diff --git a/.platform/schema b/.platform/schema index e440e5c8..bf0d87ab 100644 --- a/.platform/schema +++ b/.platform/schema @@ -1 +1 @@ -3 \ No newline at end of file +4 \ No newline at end of file diff --git a/composer.lock b/composer.lock index 8ce70921..ea13df34 100644 --- a/composer.lock +++ b/composer.lock @@ -3812,16 +3812,16 @@ }, { "name": "drupal/hdbt", - "version": "6.0.7", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/City-of-Helsinki/drupal-hdbt.git", - "reference": "870d15251457e0b01c0a71a73197d93f20e65fc1" + "reference": "23f88b1560240d61ca7c2a644d0856679a778ebf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/City-of-Helsinki/drupal-hdbt/zipball/870d15251457e0b01c0a71a73197d93f20e65fc1", - "reference": "870d15251457e0b01c0a71a73197d93f20e65fc1", + "url": "https://api.github.com/repos/City-of-Helsinki/drupal-hdbt/zipball/23f88b1560240d61ca7c2a644d0856679a778ebf", + "reference": "23f88b1560240d61ca7c2a644d0856679a778ebf", "shasum": "" }, "require": { @@ -3839,10 +3839,10 @@ "Drupal" ], "support": { - "source": "https://github.com/City-of-Helsinki/drupal-hdbt/tree/6.0.7", + "source": "https://github.com/City-of-Helsinki/drupal-hdbt/tree/6.1.0", "issues": "https://github.com/City-of-Helsinki/drupal-hdbt/issues" }, - "time": "2023-11-30T11:36:34+00:00" + "time": "2023-12-01T12:38:54+00:00" }, { "name": "drupal/hdbt_admin", diff --git a/docker/openshift/Dockerfile b/docker/openshift/Dockerfile index 25b26fa5..6f82194d 100644 --- a/docker/openshift/Dockerfile +++ b/docker/openshift/Dockerfile @@ -9,6 +9,7 @@ RUN composer install --no-progress --profile --prefer-dist --no-interaction --no COPY docker/openshift/entrypoints/ /entrypoints RUN chmod +x /entrypoints/* +COPY docker/openshift/init.sh / # Copy cron scripts RUN mkdir /crons diff --git a/docker/openshift/crons/migrate-status.php b/docker/openshift/crons/migrate-status.php deleted file mode 100644 index 8cb5aaa2..00000000 --- a/docker/openshift/crons/migrate-status.php +++ /dev/null @@ -1,82 +0,0 @@ -format('U'); - } - catch (\Exception $e) { - } - return 0; -} - -if (php_sapi_name() !== 'cli') { - throw new RuntimeException(); -} - -if (!isset($argv[2], $argv[1])) { - throw new RuntimeException('Missing argument.'); -} - -$migrations = explode(',', $argv[1]); -$data = $argv[2]; -// Default to 6 hours. -$time = $argv[3] ?? 21600; - -if (is_file($data)) { - $data = file_get_contents($data); -} - -if (!($json = json_decode($data)) || !is_array($json)) { - throw new RuntimeException('Given argument is not a valid json'); -} - -$reset_status = []; -$skip_migrate = []; - -foreach ($json as $migration) { - if (!in_array($migration->id, $migrations)) { - continue; - } - // Reset migration status. - if ($migration->status !== 'Idle') { - $reset_status[] = $migration->id; - } - - $last_imported = unix_time($migration->last_imported) + $time; - - // Skip migration. - if ($last_imported && $last_imported > time()) { - $skip_migrate[] = $migration->id; - } -} - -output_variable('RESET_STATUS', implode(' ', $reset_status)); -output_variable('SKIP_MIGRATE', implode(' ', $skip_migrate)); diff --git a/docker/openshift/crons/migrate-tpr.sh b/docker/openshift/crons/migrate-tpr.sh index 08006f13..780bcbbf 100644 --- a/docker/openshift/crons/migrate-tpr.sh +++ b/docker/openshift/crons/migrate-tpr.sh @@ -1,68 +1,12 @@ #!/bin/bash -function populate_variables { - # Generate variables used to control which migrates needs - # to be reset and which ones needs to be skipped based on - # migrate status - MIGRATE_STATUS=$(drush migrate:status --format=json) - php ./docker/openshift/crons/migrate-status.php \ - tpr_unit,tpr_service,tpr_errand_service,tpr_service_channel \ - "$MIGRATE_STATUS" > /tmp/migrate-tpr-source.sh \ - $1 - - # Contains variables: - # - $RESET_STATUS - # - $SKIP_MIGRATE - # Both contains a space separated list of migrates - source /tmp/migrate-tpr-source.sh -} - -function reset_status { - # Reset status of stuck migrations. - for ID in $RESET_STATUS; do - drush migrate:reset-status $ID - done -} - -function run_migrate { - for ID in $SKIP_MIGRATE; do - if [ "$ID" == "$1" ]; then - return 1 - fi - done - return 0 -} - -# Populate variables for the first run after deploy and -# default migrate interval to 6 hours. -populate_variables 21600 - while true do - # Reset stuck migrates. - reset_status - - if run_migrate "tpr_unit"; then - echo "Running TPR Unit migrate: $(date)" - PARTIAL_MIGRATE=1 drush migrate:import tpr_unit --no-progress - fi - if run_migrate "tpr_service"; then - echo "Running TPR Service migrate: $(date)" - PARTIAL_MIGRATE=1 drush migrate:import tpr_service --no-progress - fi - if run_migrate "tpr_errand_service"; then - echo "Running TPR Errand Service migrate: $(date)" - PARTIAL_MIGRATE=1 drush migrate:import tpr_errand_service --no-progress - fi - if run_migrate "tpr_service_channel"; then - echo "Running TPR Service Channel migrate: $(date)" - PARTIAL_MIGRATE=1 drush migrate:import tpr_service_channel --no-progress - fi - # Reset migrate status if migrate has been running for more - # than 12 hours. - populate_variables 43200 - # Never skip migrate after first time. - SKIP_MIGRATE= + # Allow migrations to be run every 3 hours and reset stuck migrations every 12 hours. + drush migrate:import tpr_unit --no-progress --reset-threshold 43200 --interval 10800 + drush migrate:import tpr_service --no-progress --reset-threshold 43200 --interval 10800 + drush migrate:import tpr_errand_service --no-progress --reset-threshold 43200 --interval 10800 + drush migrate:import tpr_service_channel --no-progress --reset-threshold 43200 --interval 10800 # Sleep for 6 hours. sleep 21600 done diff --git a/docker/openshift/entrypoints/10-preflight.sh b/docker/openshift/entrypoints/10-preflight.sh new file mode 100644 index 00000000..5cd45c01 --- /dev/null +++ b/docker/openshift/entrypoints/10-preflight.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +source /init.sh + +if [ -f "../docker/openshift/preflight/preflight.php" ]; then + echo "Running preflight checks ..." + php ../docker/openshift/preflight/preflight.php +fi + diff --git a/docker/openshift/entrypoints/20-deploy.sh b/docker/openshift/entrypoints/20-deploy.sh index c4051265..6a098241 100644 --- a/docker/openshift/entrypoints/20-deploy.sh +++ b/docker/openshift/entrypoints/20-deploy.sh @@ -1,25 +1,11 @@ #!/bin/bash -cd /var/www/html/public +source /init.sh -function output_error_message { - echo ${1} - php ../docker/openshift/notify.php "${1}" || true -} - -# Make sure we have active Drupal configuration. -if [ ! -f "../conf/cmi/system.site.yml" ]; then - output_error_message "Container start error: Codebase is not deployed properly. Exiting early." +function rollback_deployment { + output_error_message "Deployment failed: ${1}" + set_deploy_id ${2} exit 1 -fi - -if [ ! -n "$OPENSHIFT_BUILD_NAME" ]; then - output_error_message "Container start error: OPENSHIFT_BUILD_NAME is not defined. Exiting early." - exit 1 -fi - -function get_deploy_id { - echo $(drush state:get deploy_id) } # Populate twig caches. @@ -27,54 +13,42 @@ if [ ! -d "/tmp/twig" ]; then drush twig:compile || true fi -# Attempt to set deploy ID in case this is the first deploy. -if [[ -z "$(get_deploy_id)" ]]; then - drush state:set deploy_id $OPENSHIFT_BUILD_NAME -fi - -# Exit early if deploy ID is still not set. This usually means either Redis or -# something else is down. -if [[ -z "$(get_deploy_id)" ]]; then - output_error_message "Container start error: Could not fetch deploy ID. Exiting early." - exit 1 -fi +# Capture the current deploy ID so we can roll back to previous version in case +# deployment fails. +CURRENT_DEPLOY_ID=$(get_deploy_id) # This script is run every time a container is spawned and certain environments might # start more than one Drupal container. This is used to make sure we run deploy # tasks only once per deploy. -if [ "$(get_deploy_id)" != "$OPENSHIFT_BUILD_NAME" ]; then - drush state:set deploy_id $OPENSHIFT_BUILD_NAME +if [ "$CURRENT_DEPLOY_ID" != "$OPENSHIFT_BUILD_NAME" ]; then + set_deploy_id $OPENSHIFT_BUILD_NAME if [ $? -ne 0 ]; then - output_error_message "Deployment failed: Failed set deploy_id" - exit 1 + rollback_deployment "Failed to set deploy_id" $CURRENT_DEPLOY_ID fi # Put site in maintenance mode drush state:set system.maintenance_mode 1 --input-format=integer if [ $? -ne 0 ]; then - output_error_message "Deployment failed: Failed to enable maintenance_mode" - exit 1 + rollback_deployment "Failed to enable maintenance_mode" $CURRENT_DEPLOY_ID fi - # Run helfi specific pre-deploy tasks. Allow this to fail in case - # the environment is not using the 'helfi_api_base' module. - # @see https://github.com/City-of-Helsinki/drupal-module-helfi-api-base + # Run pre-deploy tasks. + # @see https://github.com/City-of-Helsinki/drupal-module-helfi-api-base/blob/main/documentation/deploy-hooks.md drush helfi:pre-deploy || true # Run maintenance tasks (config import, database updates etc) drush deploy if [ $? -ne 0 ]; then - output_error_message "Deployment failed: drush deploy failed with {$?} exit code. See logs for more information." + rollback_deployment "drush deploy failed with {$?} exit code. See logs for more information." $CURRENT_DEPLOY_ID exit 1 fi - # Run helfi specific post deploy tasks. Allow this to fail in case - # the environment is not using the 'helfi_api_base' module. - # @see https://github.com/City-of-Helsinki/drupal-module-helfi-api-base + # Run post-deploy tasks. + # @see https://github.com/City-of-Helsinki/drupal-module-helfi-api-base/blob/main/documentation/deploy-hooks.md drush helfi:post-deploy || true # Disable maintenance mode drush state:set system.maintenance_mode 0 --input-format=integer if [ $? -ne 0 ]; then - output_error_message "Deployment failure: Failed to disable maintenance_mode" + rollback_deployment "Failed to disable maintenance_mode" $CURRENT_DEPLOY_ID fi fi diff --git a/docker/openshift/init.sh b/docker/openshift/init.sh new file mode 100644 index 00000000..8bef1380 --- /dev/null +++ b/docker/openshift/init.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +cd /var/www/html/public + +function get_deploy_id { + if [ ! -f "sites/default/files/deploy.id" ]; then + touch sites/default/files/deploy.id + fi + echo $(cat sites/default/files/deploy.id) +} + +function set_deploy_id { + echo ${1} > sites/default/files/deploy.id +} + +function output_error_message { + echo ${1} + php ../docker/openshift/notify.php "${1}" || true +} + +function deployment_in_progress { + if [ "$(get_deploy_id)" != "$OPENSHIFT_BUILD_NAME" ]; then + return 0 + fi + + if [ "$(drush state:get system.maintenance_mode)" = "1" ]; then + return 0 + fi + + return 1 +} + +if [ ! -d "sites/default/files" ]; then + output_error_message "Container start error: Public file folder does not exist. Exiting early." + exit 1 +fi + +# Make sure we have active Drupal configuration. +if [ ! -f "../conf/cmi/system.site.yml" ]; then + output_error_message "Container start error: Codebase is not deployed properly. Exiting early." + exit 1 +fi + +if [ ! -n "$OPENSHIFT_BUILD_NAME" ]; then + output_error_message "Container start error: OPENSHIFT_BUILD_NAME is not defined. Exiting early." + exit 1 +fi + diff --git a/docker/openshift/preflight/preflight.php b/docker/openshift/preflight/preflight.php new file mode 100644 index 00000000..b3eb762e --- /dev/null +++ b/docker/openshift/preflight/preflight.php @@ -0,0 +1,103 @@ +#!/usr/bin/env php + [ + 'DRUPAL_ROUTES', + 'DRUPAL_DB_NAME', + 'DRUPAL_DB_PASS', + 'DRUPAL_DB_HOST', + ], + 'additionalFiles' => [], +]; + // Environment specific overrides. if (file_exists(__DIR__ . '/all.settings.php')) { // phpcs:ignore @@ -349,3 +364,4 @@ function drupal_get_env(string|array $variables) : mixed { if (empty($settings['deployment_identifier'])) { $settings['deployment_identifier'] = filemtime(__DIR__ . '/../../../composer.lock'); } +