From 6b8eb88d973044276474f7f47fc9d9ce386949fe Mon Sep 17 00:00:00 2001 From: Greg Harvey Date: Thu, 17 Jul 2025 18:44:46 +0200 Subject: [PATCH 01/16] Php unix socket pr 1.x (#724) * Moving cachetool adapter setup to the installer role and adding a test. * Updating cachetool documentation. --- docs/roles/cache_clear/cache_clear-opcache.md | 9 ++----- docs/roles/cli/cachetool.md | 7 ++++++ .../cache_clear/cache_clear-opcache/README.md | 9 ++----- .../cache_clear-opcache/defaults/main.yml | 7 ------ .../cache_clear-opcache/tasks/main.yml | 18 -------------- roles/cli/cachetool/README.md | 7 ++++++ roles/cli/cachetool/defaults/main.yml | 7 ++++++ roles/cli/cachetool/tasks/main.yml | 24 +++++++++++++++++++ 8 files changed, 49 insertions(+), 39 deletions(-) diff --git a/docs/roles/cache_clear/cache_clear-opcache.md b/docs/roles/cache_clear/cache_clear-opcache.md index 267485f4..0dd8cfaf 100644 --- a/docs/roles/cache_clear/cache_clear-opcache.md +++ b/docs/roles/cache_clear/cache_clear-opcache.md @@ -1,6 +1,6 @@ # Opcache -Clear opcache. +Clear opcache. You must have run the `cli/cachetool` role to install `cachetool` first. @@ -10,16 +10,11 @@ Clear opcache. ```yaml --- cache_clear_opcache: - # Adapter string to use as argument. - # eg. - # --fcgi=127.0.0.1:9000 - # Leave blank to use /etc/cachetool.yml - # adapter: "--fcgi=127.0.0.1:9081" # Leave commented to automatically detect the adapter based on PHP version. # Bins to clear. clear_opcache: true clear_apcu: false clear_stat: true - # cachetool_bin: "/path/to/cachetool.phar" # see _init for paths if undefined + # cachetool_bin: "/path/to/cachetool.phar" # see _init for default paths if undefined ``` diff --git a/docs/roles/cli/cachetool.md b/docs/roles/cli/cachetool.md index 36d0a014..d3c5af0b 100644 --- a/docs/roles/cli/cachetool.md +++ b/docs/roles/cli/cachetool.md @@ -6,6 +6,13 @@ Installs the `drush` command-line tool for the deploy user. --- cachetool: version: "" # enter three-digit version number, e.g. "7.0.0", to install a specific version. If not specified, will be installed depending on the php version. + unix_socket: false # Set to true to use automatic detection of Unix socket as set by ce-provision + # Adapter string to use as argument. + # e.g. + # --fcgi=127.0.0.1:9000 + # --fcgi=/var/run/php-fpm.sock + # Provide an empty string to use /etc/cachetool.yml + # adapter: "--fcgi=127.0.0.1:9081" # Leave commented to automatically detect the adapter based on PHP version. ``` diff --git a/roles/cache_clear/cache_clear-opcache/README.md b/roles/cache_clear/cache_clear-opcache/README.md index 267485f4..0dd8cfaf 100644 --- a/roles/cache_clear/cache_clear-opcache/README.md +++ b/roles/cache_clear/cache_clear-opcache/README.md @@ -1,6 +1,6 @@ # Opcache -Clear opcache. +Clear opcache. You must have run the `cli/cachetool` role to install `cachetool` first. @@ -10,16 +10,11 @@ Clear opcache. ```yaml --- cache_clear_opcache: - # Adapter string to use as argument. - # eg. - # --fcgi=127.0.0.1:9000 - # Leave blank to use /etc/cachetool.yml - # adapter: "--fcgi=127.0.0.1:9081" # Leave commented to automatically detect the adapter based on PHP version. # Bins to clear. clear_opcache: true clear_apcu: false clear_stat: true - # cachetool_bin: "/path/to/cachetool.phar" # see _init for paths if undefined + # cachetool_bin: "/path/to/cachetool.phar" # see _init for default paths if undefined ``` diff --git a/roles/cache_clear/cache_clear-opcache/defaults/main.yml b/roles/cache_clear/cache_clear-opcache/defaults/main.yml index bf28c5b0..a9b9e92d 100644 --- a/roles/cache_clear/cache_clear-opcache/defaults/main.yml +++ b/roles/cache_clear/cache_clear-opcache/defaults/main.yml @@ -1,12 +1,5 @@ --- cache_clear_opcache: - # Adapter string to use as argument. - # e.g. - # --fcgi=127.0.0.1:9000 - # --fcgi=/var/run/php-fpm.sock - # Provide an empty string to use /etc/cachetool.yml - # adapter: "--fcgi=127.0.0.1:9081" # Leave commented to automatically detect the adapter based on PHP version. - unix_socket: false # Set to true to use automatic detection of Unix socket as set by ce-provision # Bins to clear. clear_opcache: true clear_apcu: false diff --git a/roles/cache_clear/cache_clear-opcache/tasks/main.yml b/roles/cache_clear/cache_clear-opcache/tasks/main.yml index 56507c4a..ddf9fd07 100644 --- a/roles/cache_clear/cache_clear-opcache/tasks/main.yml +++ b/roles/cache_clear/cache_clear-opcache/tasks/main.yml @@ -1,22 +1,4 @@ --- -- name: Get latest php installed - ansible.builtin.shell: - cmd: 'set -o pipefail && ls -1 /etc/php/ | while read ver; do if [ -d "/etc/php/$ver/fpm" ]; then echo "$ver"; fi; done | tail -1' - args: - executable: /bin/bash - register: _php_version - -- name: Set cachetool adapter specified or default to a TCP/IP port. - ansible.builtin.set_fact: - _cachetool_adapter: "{{ cache_clear_opcache.adapter | default('--fcgi=127.0.0.1:90' + _php_version.stdout | replace('.','')) }}" - -- name: Override cachetool adapter to be a Unix socket if requested. - ansible.builtin.set_fact: - _cachetool_adapter: "--fcgi=/var/run/php{{ _php_version.stdout | replace('.','') }}-fpm.sock" - when: - - cache_clear_opcache.unix_socket - - cache_clear_opcache.adapter is not defined - # cachetool_bin is set in the _init role. - name: Clear opcache. ansible.builtin.command: diff --git a/roles/cli/cachetool/README.md b/roles/cli/cachetool/README.md index 36d0a014..d3c5af0b 100644 --- a/roles/cli/cachetool/README.md +++ b/roles/cli/cachetool/README.md @@ -6,6 +6,13 @@ Installs the `drush` command-line tool for the deploy user. --- cachetool: version: "" # enter three-digit version number, e.g. "7.0.0", to install a specific version. If not specified, will be installed depending on the php version. + unix_socket: false # Set to true to use automatic detection of Unix socket as set by ce-provision + # Adapter string to use as argument. + # e.g. + # --fcgi=127.0.0.1:9000 + # --fcgi=/var/run/php-fpm.sock + # Provide an empty string to use /etc/cachetool.yml + # adapter: "--fcgi=127.0.0.1:9081" # Leave commented to automatically detect the adapter based on PHP version. ``` diff --git a/roles/cli/cachetool/defaults/main.yml b/roles/cli/cachetool/defaults/main.yml index 8b98934d..77c338ce 100644 --- a/roles/cli/cachetool/defaults/main.yml +++ b/roles/cli/cachetool/defaults/main.yml @@ -1,3 +1,10 @@ --- cachetool: version: "" # enter three-digit version number, e.g. "7.0.0", to install a specific version. If not specified, will be installed depending on the php version. + unix_socket: false # Set to true to use automatic detection of Unix socket as set by ce-provision + # Adapter string to use as argument. + # e.g. + # --fcgi=127.0.0.1:9000 + # --fcgi=/var/run/php-fpm.sock + # Provide an empty string to use /etc/cachetool.yml + # adapter: "--fcgi=127.0.0.1:9081" # Leave commented to automatically detect the adapter based on PHP version. diff --git a/roles/cli/cachetool/tasks/main.yml b/roles/cli/cachetool/tasks/main.yml index c9855743..e7035c7c 100644 --- a/roles/cli/cachetool/tasks/main.yml +++ b/roles/cli/cachetool/tasks/main.yml @@ -83,3 +83,27 @@ - deploy_operation == 'deploy' - cachetool.version is defined - cachetool.version | length > 0 + +# Set up cachetool adapter +- name: Get latest PHP version installed. + ansible.builtin.shell: + cmd: 'set -o pipefail && ls -1 /etc/php/ | while read ver; do if [ -d "/etc/php/$ver/fpm" ]; then echo "$ver"; fi; done | tail -1' + args: + executable: /bin/bash + register: _php_version + +- name: Set cachetool adapter specified or default to a TCP/IP port. + ansible.builtin.set_fact: + _cachetool_adapter: "{{ cachetool.adapter | default('--fcgi=127.0.0.1:90' + _php_version.stdout | replace('.','')) }}" + +- name: Override cachetool adapter to be a Unix socket if requested. + ansible.builtin.set_fact: + _cachetool_adapter: "--fcgi=/var/run/php{{ _php_version.stdout | replace('.','') }}-fpm.sock" + when: + - cachetool.unix_socket + - cachetool.adapter is not defined + +# We want to fail early if cachetool is broken. +- name: Ensure cachetool is working. + ansible.builtin.command: + cmd: "{{ cachetool_bin }} {{ _cachetool_adapter }} -n opcache:status" From dc7b24e3a5ec0083cb0f1ff7667941106db5f09a Mon Sep 17 00:00:00 2001 From: Greg Harvey Date: Thu, 17 Jul 2025 19:26:48 +0200 Subject: [PATCH 02/16] Php unix socket pr 1.x (#726) * Moving cachetool adapter setup to the installer role and adding a test. * Updating cachetool documentation. * Making sure _cachetool_adapter is always set. --- roles/_init/tasks/drupal7.yml | 2 +- roles/_init/tasks/drupal8.yml | 6 ++---- roles/cli/cachetool/tasks/main.yml | 25 ++++++++++++------------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/roles/_init/tasks/drupal7.yml b/roles/_init/tasks/drupal7.yml index 3053c5c4..f6919125 100644 --- a/roles/_init/tasks/drupal7.yml +++ b/roles/_init/tasks/drupal7.yml @@ -11,7 +11,7 @@ import_role: name: cli/drush -- name: Ensure we have a cachetool binary. +- name: Ensure we have a cachetool binary and configuration. ansible.builtin.import_role: name: cli/cachetool when: install_php_cachetool diff --git a/roles/_init/tasks/drupal8.yml b/roles/_init/tasks/drupal8.yml index c254ffd6..afd1217b 100644 --- a/roles/_init/tasks/drupal8.yml +++ b/roles/_init/tasks/drupal8.yml @@ -11,9 +11,7 @@ ansible.builtin.set_fact: drush_live_bin: "{{ drush_live_bin | default('{{ live_symlink_dest }}/vendor/bin/drush') }}" -- name: Ensure we have a cachetool binary. +- name: Ensure we have a cachetool binary and configuration. ansible.builtin.import_role: name: cli/cachetool - when: - - install_php_cachetool - - deploy_operation == 'deploy' + when: install_php_cachetool diff --git a/roles/cli/cachetool/tasks/main.yml b/roles/cli/cachetool/tasks/main.yml index e7035c7c..d3a21cb2 100644 --- a/roles/cli/cachetool/tasks/main.yml +++ b/roles/cli/cachetool/tasks/main.yml @@ -1,17 +1,16 @@ --- -- name: Remove previous cachetool if exists. - ansible.builtin.file: - path: "{{ cachetool_bin }}" - state: absent - when: - - deploy_operation == 'deploy' +- name: Initial housekeeping tasks. + when: deploy_operation == 'deploy' + block: + - name: Remove previous cachetool if exists. + ansible.builtin.file: + path: "{{ cachetool_bin }}" + state: absent -- name: Ensure bin directory exists. - ansible.builtin.file: - path: "{{ cachetool_bin | dirname }}" - state: directory - when: - - deploy_operation == 'deploy' + - name: Ensure bin directory exists. + ansible.builtin.file: + path: "{{ cachetool_bin | dirname }}" + state: directory - name: Download cachetool depending on latest php version installed. # If not specified manually, according to https://github.com/gordalina/cachetool#compatibility when: @@ -84,7 +83,7 @@ - cachetool.version is defined - cachetool.version | length > 0 -# Set up cachetool adapter +# Set up cachetool adapter - needs to happen on every run so _cachetool_adapter is set. - name: Get latest PHP version installed. ansible.builtin.shell: cmd: 'set -o pipefail && ls -1 /etc/php/ | while read ver; do if [ -d "/etc/php/$ver/fpm" ]; then echo "$ver"; fi; done | tail -1' From e705aeec72dd857d242a0941e694ff45aa3dcbcb Mon Sep 17 00:00:00 2001 From: drazenCE <140631110+drazenCE@users.noreply.github.com> Date: Mon, 28 Jul 2025 16:32:05 +0200 Subject: [PATCH 03/16] Optional-drush-cr-before-import (#728) --- .../database_apply/database_apply-drupal8/tasks/main.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/database_apply/database_apply-drupal8/tasks/main.yml b/roles/database_apply/database_apply-drupal8/tasks/main.yml index 1935ac79..7915d95f 100644 --- a/roles/database_apply/database_apply-drupal8/tasks/main.yml +++ b/roles/database_apply/database_apply-drupal8/tasks/main.yml @@ -108,6 +108,15 @@ msg: "{{ _drush_output }}" when: drupal.drush_verbose_output +- name: Clear cache before config import. + ansible.builtin.include_role: + name: "cache_clear/cache_clear-{{ project_type }}" + with_items: "{{ drupal.sites }}" + loop_control: + loop_var: site + when: + - drupal.clear_cache_before_config_import | default(false) + - name: Import configuration. ansible.builtin.command: cmd: "{{ drush_bin }} -l {{ site.folder }} -y {{ site.config_import_command }}" From 2aab8107949683e8066d1fe66edda298cfb1230d Mon Sep 17 00:00:00 2001 From: Filip Rupic <123341158+filiprupic@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:19:43 +0200 Subject: [PATCH 04/16] 73171 fixing cachetool checks fpm pr 1.x (#729) * skipping cachetool check when no fpm * remove empty line --------- Co-authored-by: filip --- roles/cli/cachetool/tasks/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/cli/cachetool/tasks/main.yml b/roles/cli/cachetool/tasks/main.yml index d3a21cb2..0c221115 100644 --- a/roles/cli/cachetool/tasks/main.yml +++ b/roles/cli/cachetool/tasks/main.yml @@ -106,3 +106,4 @@ - name: Ensure cachetool is working. ansible.builtin.command: cmd: "{{ cachetool_bin }} {{ _cachetool_adapter }} -n opcache:status" + when: _php_version.stdout | length > 0 From c46831754fe0676dbc7a8439aad7cf89dfd81d1c Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Fri, 22 Aug 2025 19:03:42 +0300 Subject: [PATCH 05/16] asg_management_fix_and_improve (#733) * asg_management_fix_and_improve * asg_management_fix_and_improve * asg_management_fix_and_improve * asg_management_fix_and_improve * asg_management_fix_and_improve --- roles/asg_management/defaults/main.yml | 2 + roles/asg_management/tasks/main.yml | 2 +- roles/deploy_code/tasks/cleanup.yml | 212 ++++++++++++++++--------- 3 files changed, 136 insertions(+), 80 deletions(-) diff --git a/roles/asg_management/defaults/main.yml b/roles/asg_management/defaults/main.yml index 67371acd..ab54916e 100644 --- a/roles/asg_management/defaults/main.yml +++ b/roles/asg_management/defaults/main.yml @@ -2,6 +2,8 @@ # AWS ASG variables to allow for the suspension of autoscaling during a code deployment. asg_management: name: "" # if the deploy is on an ASG put the name here + #target_group_name: "example" # matches the ASG name by default, specify if your TargetGroup name is different (for example due to the 32-char name length limit in AWS) + refresh_asg_instances: true # runs only if squashFS image unmount failed and this set to true. #profile: "example" # optional, the boto profile name to use if not the system default region: "eu-west-1" suspend_processes: "Launch Terminate HealthCheck" # space separated string, see https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-suspend-resume-processes.html diff --git a/roles/asg_management/tasks/main.yml b/roles/asg_management/tasks/main.yml index 03ee8b44..885eb564 100644 --- a/roles/asg_management/tasks/main.yml +++ b/roles/asg_management/tasks/main.yml @@ -11,7 +11,7 @@ region: "{{ asg_management.region }}" profile: "{{ asg_management.profile | default(omit) }}" names: - - "{{ asg_management.name }}" + - "{{ asg_management.target_group_name | default(asg_management.name) }}" register: _target_group - name: Loop over target instances until they are all 'healthy'. diff --git a/roles/deploy_code/tasks/cleanup.yml b/roles/deploy_code/tasks/cleanup.yml index 796854e6..9db5403f 100644 --- a/roles/deploy_code/tasks/cleanup.yml +++ b/roles/deploy_code/tasks/cleanup.yml @@ -150,93 +150,147 @@ failed_when: false register: _deploy_code_mount_check - - name: Get the current pts session. - ansible.builtin.shell: - cmd: "tty | sed 's#/dev/##'" - register: deploy_pts - - - name: "Check for active sessions in {{ deploy_base_path }}." - ansible.builtin.shell: - cmd: "ps -eo pid,tty | awk '{print $1}' | xargs -n 1 pwdx 2>&1 | grep -v 'No such process' | grep {{ deploy_base_path }} | cut -d: -f1 | xargs -n 1 ps -o tty= -p | sort | uniq" - register: sessions_in_deploy_path - become: true - - - name: Display active sessions. - ansible.builtin.debug: - msg: > - Deploy session: {{ deploy_pts.stdout | default('Unknown') }}. - Active sessions in {{ deploy_base_path }}: {{ sessions_in_deploy_path.stdout_lines | default([]) | join(', ') | default('None') }}. - - - name: Kill sessions except the current one. + - name: Mount SquashFS image if there is no mounted one. ansible.builtin.command: - cmd: "pkill -9 -t {{ item }}" - loop: "{{ sessions_in_deploy_path.stdout_lines }}" - when: - - "item != deploy_pts.stdout" - - "item is match('^pts/\\d+$')" - failed_when: false - register: kill_sessions_result - become: true - - - name: Display killed sessions. - ansible.builtin.debug: - msg: > - Sessions terminated: {{ kill_sessions_result.results | selectattr('rc', 'defined') | selectattr('rc', 'equalto', 0) | map(attribute='item') | list | join(', ') | default('None') }}. - - - name: Reload any services that might be keeping the loop device busy. - ansible.builtin.service: - name: "{{ www_service }}" - state: reloaded - with_items: "{{ deploy_code.services }}" - loop_control: - loop_var: www_service - become: true - when: - - _deploy_code_mount_check.rc == 0 - - deploy_code.service_action == "reload" - - deploy_code.services | length > 0 - - - name: Stop any services that might be keeping the loop device busy. - ansible.builtin.service: - name: "{{ www_service }}" - state: stopped - with_items: "{{ deploy_code.services }}" - loop_control: - loop_var: www_service + cmd: "mount {{ build_base_path }}/deploy.sqsh {{ deploy_base_path }} -t squashfs -o loop" become: true when: - - _deploy_code_mount_check.rc == 0 - - deploy_code.service_action == "stop" - - deploy_code.services | length > 0 + - _deploy_code_mount_check.rc != 0 - - name: Unmount existing SquashFS image. - ansible.builtin.command: - cmd: "umount {{ deploy_base_path }}" - become: true + - name: Mount new SquashFS image instead of the already mounted. when: - _deploy_code_mount_check.rc == 0 - register: task_result - retries: "{{ deploy_code.unmount_retries }}" - delay: "{{ deploy_code.unmount_delay }}" - until: task_result.rc == 0 + block: + - name: Get the current pts session. + ansible.builtin.shell: + cmd: "tty | sed 's#/dev/##'" + register: deploy_pts - - name: Mount new SquashFS image. - ansible.builtin.command: - cmd: "mount {{ build_base_path }}/deploy.sqsh {{ deploy_base_path }} -t squashfs -o loop" - become: true + - name: "Check for active sessions in {{ deploy_base_path }}." + ansible.builtin.shell: + cmd: "ps -eo pid,tty | awk '{print $1}' | xargs -n 1 pwdx 2>&1 | grep -v 'No such process' | grep {{ deploy_base_path }} | cut -d: -f1 | xargs -n 1 ps -o tty= -p | sort | uniq" + register: sessions_in_deploy_path + become: true - - name: Start any services we stopped. - ansible.builtin.service: - name: "{{ www_service }}" - state: started - with_items: "{{ deploy_code.services }}" - loop_control: - loop_var: www_service - become: true - when: - - _deploy_code_mount_check.rc == 0 - - deploy_code.service_action == "stop" - - deploy_code.services | length > 0 + - name: Display active sessions. + ansible.builtin.debug: + msg: > + Deploy session: {{ deploy_pts.stdout | default('Unknown') }}. + Active sessions in {{ deploy_base_path }}: {{ sessions_in_deploy_path.stdout_lines | default([]) | join(', ') | default('None') }}. + + - name: Kill sessions except the current one. + ansible.builtin.command: + cmd: "pkill -9 -t {{ item }}" + loop: "{{ sessions_in_deploy_path.stdout_lines }}" + when: + - "item != deploy_pts.stdout" + - "item is match('^pts/\\d+$')" + failed_when: false + register: kill_sessions_result + become: true + + - name: Display killed sessions. + ansible.builtin.debug: + msg: > + Sessions terminated: {{ kill_sessions_result.results | selectattr('rc', 'defined') | selectattr('rc', 'equalto', 0) | map(attribute='item') | list | join(', ') | default('None') }}. + + - name: Reload any services that might be keeping the loop device busy. + ansible.builtin.service: + name: "{{ www_service }}" + state: reloaded + with_items: "{{ deploy_code.services }}" + loop_control: + loop_var: www_service + become: true + when: + - deploy_code.service_action == "reload" + - deploy_code.services | length > 0 + + - name: Stop any services that might be keeping the loop device busy. + ansible.builtin.service: + name: "{{ www_service }}" + state: stopped + with_items: "{{ deploy_code.services }}" + loop_control: + loop_var: www_service + become: true + when: + - deploy_code.service_action == "stop" + - deploy_code.services | length > 0 + + - name: Unmount existing SquashFS image. + ansible.builtin.command: + cmd: "umount {{ deploy_base_path }}" + become: true + register: task_result + retries: "{{ deploy_code.unmount_retries }}" + delay: "{{ deploy_code.unmount_delay }}" + until: task_result.rc == 0 + failed_when: false + + - name: If current image unmount succeeded. + when: task_result.rc == 0 + block: + - name: Mount new SquashFS image. + ansible.builtin.command: + cmd: "mount {{ build_base_path }}/deploy.sqsh {{ deploy_base_path }} -t squashfs -o loop" + become: true + + - name: Start any services that we stopped if the image re-mounting was successful. + ansible.builtin.service: + name: "{{ www_service }}" + state: started + with_items: "{{ deploy_code.services }}" + loop_control: + loop_var: www_service + become: true + when: + - deploy_code.service_action == "stop" + - deploy_code.services | length > 0 + + - name: If current image unmount failed. + when: task_result.rc != 0 + block: + - name: Resume all autoscale processes on ASG. + amazon.aws.autoscaling_group: + name: "{{ asg_management.name }}" + region: "{{ asg_management.region }}" + profile: "{{ asg_management.profile | default(omit) }}" + suspended_processes: [] + delegate_to: localhost + run_once: true + when: + - asg_management.name | length > 0 + + - name: Run ASG instance refresh. + amazon.aws.autoscaling_instance_refresh: + name: "{{ asg_management.name }}" + region: "{{ asg_management.region }}" + profile: "{{ asg_management.profile | default(omit) }}" + strategy: Rolling + preferences: + min_healthy_percentage: 51 + instance_warmup: 100 + skip_matching: false + state: started + delegate_to: localhost + run_once: true + when: + - asg_management.name | length > 0 + - asg_management.refresh_asg_instances + + - name: Start any services we stopped if the image re-mounting failed and ASG management is disabled. + ansible.builtin.service: + name: "{{ www_service }}" + state: started + with_items: "{{ deploy_code.services }}" + loop_control: + loop_var: www_service + become: true + when: + - deploy_code.service_action == "stop" + - deploy_code.services | length > 0 + - not asg_management.refresh_asg_instances or (asg_management.name | length) == 0 # End of the squashFS block. - name: Trigger an infrastructure rebuild. From 3b852e7be280274009df8822ef91dd6f1171b557 Mon Sep 17 00:00:00 2001 From: drazenCE <140631110+drazenCE@users.noreply.github.com> Date: Thu, 28 Aug 2025 14:37:32 +0200 Subject: [PATCH 06/16] Adding-delay-opcache-status-check (#737) * Adding-delay-opcache-status-check * Removing-failed-when --- roles/cli/cachetool/defaults/main.yml | 2 ++ roles/cli/cachetool/tasks/main.yml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/roles/cli/cachetool/defaults/main.yml b/roles/cli/cachetool/defaults/main.yml index 77c338ce..5c4ccbc0 100644 --- a/roles/cli/cachetool/defaults/main.yml +++ b/roles/cli/cachetool/defaults/main.yml @@ -2,6 +2,8 @@ cachetool: version: "" # enter three-digit version number, e.g. "7.0.0", to install a specific version. If not specified, will be installed depending on the php version. unix_socket: false # Set to true to use automatic detection of Unix socket as set by ce-provision + check_retries: 5 + check_delay: 20 # Adapter string to use as argument. # e.g. # --fcgi=127.0.0.1:9000 diff --git a/roles/cli/cachetool/tasks/main.yml b/roles/cli/cachetool/tasks/main.yml index 0c221115..f765da90 100644 --- a/roles/cli/cachetool/tasks/main.yml +++ b/roles/cli/cachetool/tasks/main.yml @@ -107,3 +107,7 @@ ansible.builtin.command: cmd: "{{ cachetool_bin }} {{ _cachetool_adapter }} -n opcache:status" when: _php_version.stdout | length > 0 + register: opcache_status_check + retries: "{{ cachetool.check_retries }}" + delay: "{{ cachetool.check_delay }}" + until: opcache_status_check.rc == 0 From 34c76c0eb677d4a54dac5c87a8dd30aba65be121 Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Mon, 1 Sep 2025 18:56:47 +0300 Subject: [PATCH 07/16] fix_var_name_for_asg_management (#739) --- roles/deploy_code/tasks/cleanup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/deploy_code/tasks/cleanup.yml b/roles/deploy_code/tasks/cleanup.yml index 9db5403f..b365a876 100644 --- a/roles/deploy_code/tasks/cleanup.yml +++ b/roles/deploy_code/tasks/cleanup.yml @@ -256,7 +256,7 @@ name: "{{ asg_management.name }}" region: "{{ asg_management.region }}" profile: "{{ asg_management.profile | default(omit) }}" - suspended_processes: [] + suspend_processes: [] delegate_to: localhost run_once: true when: From 87487c7b99feff4a92045a29144634c77c053df4 Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Thu, 4 Sep 2025 18:20:58 +0300 Subject: [PATCH 08/16] replace_ansible_pause_module (#747) --- roles/asg_management/README.md | 1 + roles/asg_management/defaults/main.yml | 2 +- roles/asg_management/tasks/asg_target_health.yml | 5 +++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/roles/asg_management/README.md b/roles/asg_management/README.md index f9f4db80..e7ff0132 100644 --- a/roles/asg_management/README.md +++ b/roles/asg_management/README.md @@ -6,6 +6,7 @@ In order to manipulate an AWS Autoscaling Group (ASG) your `deploy` user must ha * `autoscaling:SuspendProcesses` * `autoscaling:DescribeScalingProcessTypes` * `autoscaling:DescribeAutoScalingGroups` +* `autoscaling:StartInstanceRefresh` Set the `asg_management.name` to the machine name of your ASG in order to automatically suspend and resume autoscaling on build. diff --git a/roles/asg_management/defaults/main.yml b/roles/asg_management/defaults/main.yml index ab54916e..0c5dbd46 100644 --- a/roles/asg_management/defaults/main.yml +++ b/roles/asg_management/defaults/main.yml @@ -7,4 +7,4 @@ asg_management: #profile: "example" # optional, the boto profile name to use if not the system default region: "eu-west-1" suspend_processes: "Launch Terminate HealthCheck" # space separated string, see https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-suspend-resume-processes.html - pause: 5 # how long in seconds to wait before polling the AWS API again for instance statuses + pause: 10 # localhost ping count, to wait before polling the AWS API again for instance statuses (instead of ansible 'pause' module which seems to be buggy and hangs sometimes) diff --git a/roles/asg_management/tasks/asg_target_health.yml b/roles/asg_management/tasks/asg_target_health.yml index 78f3b21b..26b58f97 100644 --- a/roles/asg_management/tasks/asg_target_health.yml +++ b/roles/asg_management/tasks/asg_target_health.yml @@ -1,7 +1,8 @@ --- - name: Pause so as to not hammer the AWS API. - ansible.builtin.pause: - seconds: "{{ asg_management.pause }}" + ansible.builtin.command: + cmd: "ping localhost -c {{ asg_management.pause }}" + failed_when: false - name: Empty the target list. ansible.builtin.set_fact: From 4d8e2092e2169825f572613990c7cd5a32125660 Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Fri, 5 Sep 2025 19:25:18 +0300 Subject: [PATCH 09/16] fix_asg_management_workaround_for_squashfs (#754) * fix_asg_management_workaround_for_squashfs * fix_asg_management_workaround_for_squashfs --- roles/deploy_code/tasks/cleanup.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/deploy_code/tasks/cleanup.yml b/roles/deploy_code/tasks/cleanup.yml index b365a876..e7b53e45 100644 --- a/roles/deploy_code/tasks/cleanup.yml +++ b/roles/deploy_code/tasks/cleanup.yml @@ -255,7 +255,7 @@ amazon.aws.autoscaling_group: name: "{{ asg_management.name }}" region: "{{ asg_management.region }}" - profile: "{{ asg_management.profile | default(omit) }}" + profile: "{{ asg_management.profile | default(aws_profile | default(omit)) }}" suspend_processes: [] delegate_to: localhost run_once: true @@ -266,7 +266,7 @@ amazon.aws.autoscaling_instance_refresh: name: "{{ asg_management.name }}" region: "{{ asg_management.region }}" - profile: "{{ asg_management.profile | default(omit) }}" + profile: "{{ asg_management.profile | default(aws_profile | default(omit)) }}" strategy: Rolling preferences: min_healthy_percentage: 51 From ae07a662223e2ff15ce2d18fc6e12affbb5ee6f7 Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Mon, 8 Sep 2025 15:04:30 +0300 Subject: [PATCH 10/16] fix_asg_management_workaround_task_condition (#756) --- roles/deploy_code/tasks/cleanup.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/deploy_code/tasks/cleanup.yml b/roles/deploy_code/tasks/cleanup.yml index e7b53e45..df3d1e31 100644 --- a/roles/deploy_code/tasks/cleanup.yml +++ b/roles/deploy_code/tasks/cleanup.yml @@ -260,6 +260,7 @@ delegate_to: localhost run_once: true when: + - asg_management.name is defined - asg_management.name | length > 0 - name: Run ASG instance refresh. @@ -276,6 +277,7 @@ delegate_to: localhost run_once: true when: + - asg_management.name is defined - asg_management.name | length > 0 - asg_management.refresh_asg_instances @@ -290,7 +292,7 @@ when: - deploy_code.service_action == "stop" - deploy_code.services | length > 0 - - not asg_management.refresh_asg_instances or (asg_management.name | length) == 0 + - not asg_management.refresh_asg_instances or asg_management.name is not defined # End of the squashFS block. - name: Trigger an infrastructure rebuild. From decb6fb5e2aeaf4c2ab10f47bc13d4c1b215b67e Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Tue, 9 Sep 2025 17:02:05 +0300 Subject: [PATCH 11/16] aws_profile_for_asg_management (#758) * aws_profile_for_asg_management * aws_profile_for_asg_management_case_with_default_profile_absent --- roles/asg_management/defaults/main.yml | 2 +- roles/deploy_code/tasks/cleanup.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/asg_management/defaults/main.yml b/roles/asg_management/defaults/main.yml index 0c5dbd46..09857191 100644 --- a/roles/asg_management/defaults/main.yml +++ b/roles/asg_management/defaults/main.yml @@ -4,7 +4,7 @@ asg_management: name: "" # if the deploy is on an ASG put the name here #target_group_name: "example" # matches the ASG name by default, specify if your TargetGroup name is different (for example due to the 32-char name length limit in AWS) refresh_asg_instances: true # runs only if squashFS image unmount failed and this set to true. - #profile: "example" # optional, the boto profile name to use if not the system default + profile: "{{ lookup('env','AWS_PROFILE') | trim | default(omit) }}" # the boto profile name to use if not the system default (if doesn't exist, then EC2 instance IAM profile will be used) region: "eu-west-1" suspend_processes: "Launch Terminate HealthCheck" # space separated string, see https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-suspend-resume-processes.html pause: 10 # localhost ping count, to wait before polling the AWS API again for instance statuses (instead of ansible 'pause' module which seems to be buggy and hangs sometimes) diff --git a/roles/deploy_code/tasks/cleanup.yml b/roles/deploy_code/tasks/cleanup.yml index df3d1e31..c4e918c0 100644 --- a/roles/deploy_code/tasks/cleanup.yml +++ b/roles/deploy_code/tasks/cleanup.yml @@ -255,7 +255,7 @@ amazon.aws.autoscaling_group: name: "{{ asg_management.name }}" region: "{{ asg_management.region }}" - profile: "{{ asg_management.profile | default(aws_profile | default(omit)) }}" + profile: "{{ asg_management.profile | default(omit) }}" suspend_processes: [] delegate_to: localhost run_once: true @@ -267,7 +267,7 @@ amazon.aws.autoscaling_instance_refresh: name: "{{ asg_management.name }}" region: "{{ asg_management.region }}" - profile: "{{ asg_management.profile | default(aws_profile | default(omit)) }}" + profile: "{{ asg_management.profile | default(omit) }}" strategy: Rolling preferences: min_healthy_percentage: 51 From 92cd722a1277aa15adec9ac7caebe5e971e7564e Mon Sep 17 00:00:00 2001 From: tymofiisobchenko <104431720+tymofiisobchenko@users.noreply.github.com> Date: Fri, 12 Sep 2025 18:31:46 +0300 Subject: [PATCH 12/16] =?UTF-8?q?ansible=5Fmodule=5Frequires=5Ftoo=5Fmuch?= =?UTF-8?q?=5Fperms=5Fjust=5Ffor=5Fautoscaling=5Fmanagemen=E2=80=A6=20(#76?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ansible_module_requires_too_much_perms_just_for_autoscaling_management_so_replacing_with_aws_cli_from_role * fix condition * asg_management_workaround_improve_fix_conditions * remove extra line --- roles/deploy_code/tasks/cleanup.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/roles/deploy_code/tasks/cleanup.yml b/roles/deploy_code/tasks/cleanup.yml index c4e918c0..9f58d43a 100644 --- a/roles/deploy_code/tasks/cleanup.yml +++ b/roles/deploy_code/tasks/cleanup.yml @@ -252,13 +252,8 @@ when: task_result.rc != 0 block: - name: Resume all autoscale processes on ASG. - amazon.aws.autoscaling_group: - name: "{{ asg_management.name }}" - region: "{{ asg_management.region }}" - profile: "{{ asg_management.profile | default(omit) }}" - suspend_processes: [] - delegate_to: localhost - run_once: true + ansible.builtin.include_role: + name: asg_management when: - asg_management.name is defined - asg_management.name | length > 0 @@ -279,7 +274,7 @@ when: - asg_management.name is defined - asg_management.name | length > 0 - - asg_management.refresh_asg_instances + - asg_management.refresh_asg_instances | default(true) - name: Start any services we stopped if the image re-mounting failed and ASG management is disabled. ansible.builtin.service: @@ -292,7 +287,7 @@ when: - deploy_code.service_action == "stop" - deploy_code.services | length > 0 - - not asg_management.refresh_asg_instances or asg_management.name is not defined + - asg_management.refresh_asg_instances is not defined or not asg_management.refresh_asg_instances or asg_management.name is not defined # End of the squashFS block. - name: Trigger an infrastructure rebuild. From 9c8574fa210b857593bcd0b4e80af0cdbe5fbf23 Mon Sep 17 00:00:00 2001 From: Greg Harvey Date: Tue, 16 Sep 2025 18:11:21 +0200 Subject: [PATCH 13/16] Updating 'default()' filter paths in _init as an initial test. (#766) * Updating 'default()' filter paths in _init as an initial test. * Explicitly casting integers as strings for path creation. * Over refactored the variable setting! * Fixing Drupal 7 include in _init. --- roles/_init/tasks/custom.yml | 3 +-- roles/_init/tasks/drupal7.yml | 13 +++++-------- roles/_init/tasks/drupal8.yml | 6 +++--- roles/_init/tasks/main.yml | 32 +++++++++++++------------------- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/roles/_init/tasks/custom.yml b/roles/_init/tasks/custom.yml index 6f34c92f..0ce85358 100644 --- a/roles/_init/tasks/custom.yml +++ b/roles/_init/tasks/custom.yml @@ -1,3 +1,2 @@ --- - -# Nothing to do here. \ No newline at end of file +# Nothing to do here. diff --git a/roles/_init/tasks/drupal7.yml b/roles/_init/tasks/drupal7.yml index f6919125..08df1c76 100644 --- a/roles/_init/tasks/drupal7.yml +++ b/roles/_init/tasks/drupal7.yml @@ -1,14 +1,11 @@ --- -- name: Define path to drush for this build. - set_fact: - drush_bin: "{{ drush_bin | default('{{ bin_directory }}/drush.phar') }}" - -- name: Define path to drush for currently live build. # usually the same as drush_bin for Drupal 7 - set_fact: - drush_live_bin: "{{ drush_live_bin | default('{{ bin_directory }}/drush.phar') }}" +- name: Define paths to drush for this build. + ansible.builtin.set_fact: + drush_bin: "{{ drush_bin | default(bin_directory + '/drush.phar') }}" + drush_live_bin: "{{ drush_live_bin | default(bin_directory + '/drush.phar') }}" # usually the same as drush_bin for Drupal 7 - name: Ensure we have a drush binary. - import_role: + ansible.builtin.import_role: name: cli/drush - name: Ensure we have a cachetool binary and configuration. diff --git a/roles/_init/tasks/drupal8.yml b/roles/_init/tasks/drupal8.yml index afd1217b..a0501259 100644 --- a/roles/_init/tasks/drupal8.yml +++ b/roles/_init/tasks/drupal8.yml @@ -1,15 +1,15 @@ --- - name: Define path to drush for this build. ansible.builtin.set_fact: - drush_bin: "{{ drush_bin | default('{{ deploy_path }}/vendor/bin/drush') }}" + drush_bin: "{{ drush_bin | default(deploy_path + '/vendor/bin/drush') }}" - name: Define path to drush for previous build. ansible.builtin.set_fact: - previous_drush_bin: "{{ previous_drush_bin | default('{{ previous_deploy_path }}/vendor/bin/drush') }}" + previous_drush_bin: "{{ previous_drush_bin | default(previous_deploy_path + '/vendor/bin/drush') }}" - name: Define path to drush for currently live build. ansible.builtin.set_fact: - drush_live_bin: "{{ drush_live_bin | default('{{ live_symlink_dest }}/vendor/bin/drush') }}" + drush_live_bin: "{{ drush_live_bin | default(live_symlink_dest + '/vendor/bin/drush') }}" - name: Ensure we have a cachetool binary and configuration. ansible.builtin.import_role: diff --git a/roles/_init/tasks/main.yml b/roles/_init/tasks/main.yml index b2be45d8..00b0553d 100644 --- a/roles/_init/tasks/main.yml +++ b/roles/_init/tasks/main.yml @@ -30,34 +30,28 @@ ansible.builtin.set_fact: deploy_user: "{{ deploy_user | default('deploy') }}" -- name: Define deploy base path. +- name: Define initial deploy paths. ansible.builtin.set_fact: - deploy_base_path: "{{ deploy_base_path | default('/home/{{ deploy_user }}/deploy/{{ project_name }}_{{ build_type }}') }}" + deploy_base_path: "{{ deploy_base_path | default('/home/' + deploy_user + '/deploy/' + project_name + '_' + build_type) }}" + deploy_assets_base_path: "{{ deploy_assets_base_path | default('/home/' + deploy_user + '/shared/' + project_name + '_' + build_type + '/assets') }}" + webroot: "{{ webroot | default('web') }}" -- name: Define mounted directory for assets. +- name: Define deploy_path_prefix variable. ansible.builtin.set_fact: - deploy_assets_base_path: "{{ deploy_assets_base_path | default('/home/{{ deploy_user }}/shared/{{ project_name }}_{{ build_type }}/assets') }}" + deploy_path_prefix: "{{ deploy_base_path }}/{{ project_name }}_{{ build_type }}_build_" -- name: Define webroot. +- name: Define final deploy_path variable. ansible.builtin.set_fact: - webroot: "{{ webroot | default('web') }}" + deploy_path: "{{ deploy_path | default(deploy_path_prefix + build_number|string) }}" # This is passed from caller. - name: Gather last known good build number. ansible.builtin.set_fact: previous_build_number: "{{ previous_known_build_number }}" -- name: Define build deploy path prefix. - ansible.builtin.set_fact: - deploy_path_prefix: "{{ deploy_base_path }}/{{ project_name }}_{{ build_type }}_build_" - -- name: Define build deploy path. - ansible.builtin.set_fact: - deploy_path: "{{ deploy_path | default('{{ deploy_path_prefix }}{{ build_number }}') }}" - - name: Define live_symlink dest. ansible.builtin.set_fact: - live_symlink_dest: "{{ live_symlink_dest | default('{{ deploy_base_path }}/live.{{ project_name }}_{{ build_type }}') }}" + live_symlink_dest: "{{ live_symlink_dest | default(deploy_base_path + '/live.' + project_name + '_' + build_type) }}" - name: Read the live symlink to get the path to the current build. ansible.builtin.stat: @@ -85,7 +79,7 @@ msg: "Track file ID: {{ previous_build_number }}. Build path ID: {{ _current_build_id }}. These should match, something is wrong, failing the build." when: - _current_build_path.stat.islnk - - _current_build_id | int != previous_build_number | int + - _current_build_id|int != previous_build_number|int - not skip_build_path_check - name: Define opcache cachetool path. @@ -114,11 +108,11 @@ - name: Define live_symlink dest for image builds. ansible.builtin.set_fact: - live_symlink_build_dest: "{{ live_symlink_build_dest | default('{{ build_base_path }}/live.{{ project_name }}_{{ build_type }}') }}" + live_symlink_build_dest: "{{ live_symlink_build_dest | default(build_base_path + '/live.' + project_name + '_' + build_type) }}" - name: Overwrite deploy and live_symlink paths if SquashFS deploy. ansible.builtin.set_fact: - deploy_path: "{{ build_path | default('{{ build_path_prefix }}{{ build_number }}') }}" + deploy_path: "{{ build_path | default(build_path_prefix + build_number|string) }}" - name: Overwrite cachetool path if SquashFS deploy and path not provided. ansible.builtin.set_fact: @@ -206,7 +200,7 @@ - name: Set the previous deploy's path for later use where we need to manipulate the live site. ansible.builtin.set_fact: - previous_deploy_path: "{{ previous_deploy_path | default('{{ deploy_path_prefix }}{{ previous_build_number }}') }}" + previous_deploy_path: "{{ previous_deploy_path | default(deploy_path_prefix + previous_build_number|string) }}" # Make sure the deploy target exists. - name: Ensure deploy target directory exists. From eb6078389bbd94d24031a61eee7748b7fab23ccc Mon Sep 17 00:00:00 2001 From: Greg Harvey Date: Wed, 17 Sep 2025 15:59:31 +0200 Subject: [PATCH 14/16] Ansible12 fixes pr 1.x (#769) * Updating 'default()' filter paths in _init as an initial test. * Explicitly casting integers as strings for path creation. * Over refactored the variable setting! * Fixing Drupal 7 include in _init. * Another string truthy bug for Ansible 12. --- roles/database_apply/database_apply-drupal8/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/database_apply/database_apply-drupal8/tasks/main.yml b/roles/database_apply/database_apply-drupal8/tasks/main.yml index 7915d95f..a5734a60 100644 --- a/roles/database_apply/database_apply-drupal8/tasks/main.yml +++ b/roles/database_apply/database_apply-drupal8/tasks/main.yml @@ -128,7 +128,7 @@ loop_var: site when: - previous_build_number > 0 - - site.config_import_command + - site.config_import_command | length > 0 register: _drush_output - name: Show drush output. From fec5ede1d6a9ec75e32b3b6a4bad457b7d45af95 Mon Sep 17 00:00:00 2001 From: Drazen Date: Tue, 23 Sep 2025 11:03:05 +0200 Subject: [PATCH 15/16] ALB-retries-delay --- roles/deploy_container/tasks/action-create.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/deploy_container/tasks/action-create.yml b/roles/deploy_container/tasks/action-create.yml index 3ec81194..88c144aa 100644 --- a/roles/deploy_container/tasks/action-create.yml +++ b/roles/deploy_container/tasks/action-create.yml @@ -278,6 +278,7 @@ ip_address_type: "{{ deploy_container.aws_ecs.elb_ip_address_type }}" register: _aws_ecs_cluster_alb delegate_to: localhost + wait: true - name: Create ECS service. community.aws.ecs_service: From 433ad0ef3e6451107d862e6fae5d6d008874abd5 Mon Sep 17 00:00:00 2001 From: Drazen Date: Wed, 24 Sep 2025 12:01:34 +0200 Subject: [PATCH 16/16] ALB-retries-delay-PR-devel-1.x --- roles/deploy_container/tasks/action-create.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/deploy_container/tasks/action-create.yml b/roles/deploy_container/tasks/action-create.yml index 88c144aa..9ab44402 100644 --- a/roles/deploy_container/tasks/action-create.yml +++ b/roles/deploy_container/tasks/action-create.yml @@ -276,9 +276,9 @@ listeners: "{{ _aws_ecs_cluster_listeners }}" idle_timeout: "{{ deploy_container.aws_ecs.elb_idle_timeout }}" ip_address_type: "{{ deploy_container.aws_ecs.elb_ip_address_type }}" + wait: true register: _aws_ecs_cluster_alb delegate_to: localhost - wait: true - name: Create ECS service. community.aws.ecs_service: