diff --git a/.vortex/docs/content/development/variables.mdx b/.vortex/docs/content/development/variables.mdx index 1997995e3..49b07f9e0 100644 --- a/.vortex/docs/content/development/variables.mdx +++ b/.vortex/docs/content/development/variables.mdx @@ -387,6 +387,7 @@ The list below is automatically generated with [Shellvar](https://github.com/ale | `VORTEX_NOTIFY_WEBHOOK_URL` | Webhook URL to send notifications to. | `UNDEFINED` | `.env`, `scripts/vortex/notify-webhook.sh`, `ACQUIA ENVIRONMENT`, `LAGOON ENVIRONMENT` | | `VORTEX_PROJECT` | Project name.

Drives internal naming within the codebase. Does not affect the names of containers and development URL - those depend on the project directory and can be overridden with [`$COMPOSE_PROJECT_NAME`](#compose_project_name). | `your_site` | `.env`, `scripts/vortex/info.sh` | | `VORTEX_PROVISION_ACQUIA_SKIP` | Skip Drupal site provisioning in Acquia environment. | `UNDEFINED` | `ACQUIA ENVIRONMENT` | +| `VORTEX_PROVISION_CACHE_REBUILD_AFTER_DB_UPDATE_SKIP` | Skip cache rebuild after database updates. | `0` | `scripts/vortex/provision.sh` | | `VORTEX_PROVISION_DB` | Provision database dump file. If not set, it will be auto-discovered from the VORTEX_DB_DIR directory using the VORTEX_DB_FILE name. | `UNDEFINED` | `scripts/vortex/provision.sh` | | `VORTEX_PROVISION_DB_DIR` | Directory with database dump file. | `./.data` | `scripts/vortex/provision.sh` | | `VORTEX_PROVISION_DB_FILE` | Database dump file name. | `db.sql` | `scripts/vortex/provision.sh` | diff --git a/.vortex/docs/content/drupal/provision.mdx b/.vortex/docs/content/drupal/provision.mdx index 34b8f0856..2088ba08d 100644 --- a/.vortex/docs/content/drupal/provision.mdx +++ b/.vortex/docs/content/drupal/provision.mdx @@ -136,13 +136,15 @@ section. ⑦ 💡 Verify config unchanged? ──Config changed──► 🏁 EXIT 1 (fail) ✗ │ Config unchanged (or check disabled) ▼ +⑧ 🧹 Rebuild caches after DB updates (skippable) + ▼ ⬇️ Import configuration (if config files present) ▼ 🧹 Rebuild caches ▼ 🔄 Run deployment hooks ▼ -⑧ 😷 Run DB sanitization +⑨ 😷 Run DB sanitization ▼ ⚙️ Run custom scripts ▼ @@ -158,11 +160,12 @@ You can control the provisioning flow using the following environment variables: 1. `VORTEX_PROVISION_SKIP=1`
Kill-switch to completely skip provisioning. The script will exit immediately after start. Useful in emergencies when any kind of automation needs to be disabled.

2. `VORTEX_PROVISION_TYPE=profile`
Install from a Drupal `profile` instead of importing from a `database` dump. Useful for building sites without the persistent DB and/or test profile configuration installation.

3. `VORTEX_PROVISION_OVERRIDE_DB=1`
Drop an existing database before importing from dump/installing from profile. This is useful when an already provisioned environment requires a fresh database to be imported.

-4. `VORTEX_PROVISION_FALLBACK_TO_PROFILE=1`
Automatically fall back to installing from profile if the database dump file or container image is not available. Useful for distribution demos or when using recipes/profiles that can install without a pre-existing database.

+4. `VORTEX_PROVISION_FALLBACK_TO_PROFILE=1`
Automatically fall back to installing from profile if the database dump file or container image is not available. The site is installed from the configured profile, the Shield module is enabled to protect the environment, and all post-provision operations (configuration import, database updates, deployment hooks, etc.) are skipped. This provides a minimal working Drupal site when no database is available.

5. `VORTEX_PROVISION_POST_OPERATIONS_SKIP=1`
Skip configuration imports, database updates, and other post-provisioning steps. Essentially, this is `drush sql:drop` and `$(drush sql:connect) < .data/db.sql` commands. This is useful when you want to provision a site without running any additional operations.
`ahoy import-db` uses this flag to import DB and exit.

6. `VORTEX_PROVISION_USE_MAINTENANCE_MODE=1`
Enable maintenance mode right after the site is bootstrappable and disable it at the end. Useful when you want to prevent users from accessing the site while it is being provisioned.

7. `VORTEX_PROVISION_VERIFY_CONFIG_UNCHANGED_AFTER_UPDATE=1`
Verify that active configuration was not changed by database updates. When enabled and config files are present, the provision will fail if `drush updatedb` modifies active configuration, preventing `drush config:import` from silently overwriting those changes.

-8. `VORTEX_PROVISION_SANITIZE_DB_SKIP=1`
Disable database sanitization. +8. `VORTEX_PROVISION_CACHE_REBUILD_AFTER_DB_UPDATE_SKIP=1`
Skip the cache rebuild that runs between database updates and configuration import. By default, caches are rebuilt after `drush updatedb` to ensure a clean state before importing configuration.

+9. `VORTEX_PROVISION_SANITIZE_DB_SKIP=1`
Disable database sanitization. :::tip diff --git a/.vortex/tests/bats/unit/provision.bats b/.vortex/tests/bats/unit/provision.bats index 00a9eed71..b0c091ccf 100644 --- a/.vortex/tests/bats/unit/provision.bats +++ b/.vortex/tests/bats/unit/provision.bats @@ -113,6 +113,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -248,6 +253,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -384,6 +394,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -525,6 +540,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Configuration import. "Importing configuration." "@drush -y config:import" @@ -674,6 +694,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -812,6 +837,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -949,6 +979,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -1086,6 +1121,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -1253,6 +1293,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -1391,6 +1436,11 @@ assert_provision_info() { "@drush -y updatedb --no-cache-clear" "Completed running database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Cache rebuild. "Rebuilding cache." "@drush -y cache:rebuild" @@ -1476,7 +1526,6 @@ assert_provision_info() { mkdir "./.data" export VORTEX_PROVISION_FALLBACK_TO_PROFILE=1 - export VORTEX_PROVISION_POST_OPERATIONS_SKIP=1 create_global_command_wrapper "vendor/bin/drush" @@ -1493,10 +1542,11 @@ assert_provision_info() { "Existing site was not found." "Fresh site content will be imported from the database dump file." - # Fallback to profile. + # Fallback to profile: install and enable Shield. "Database dump file is not available. Falling back to profile installation." "@drush -y sql:drop" "@drush -y site:install standard --site-name=Example site --site-mail=webmaster@example.com --account-name=admin install_configure_form.enable_update_status_module=NULL install_configure_form.enable_update_status_emails=NULL" + "@drush -y pm:install shield" "Installed a site from the profile." # Should NOT see the hard failure messages. @@ -1508,7 +1558,7 @@ assert_provision_info() { "Current Drupal environment: ci" "@drush -y php:eval print \Drupal\core\Site\Settings::get('environment'); # ci" - # Post-provision operations skipped. + # Post-provision operations skipped (set internally by fallback). "Skipped running of post-provision operations as VORTEX_PROVISION_POST_OPERATIONS_SKIP is set to 1." # Installation completion. @@ -1539,7 +1589,6 @@ assert_provision_info() { touch "./.data/db.sql" export VORTEX_PROVISION_FALLBACK_TO_PROFILE=1 - export VORTEX_PROVISION_POST_OPERATIONS_SKIP=1 create_global_command_wrapper "vendor/bin/drush" @@ -1561,6 +1610,7 @@ assert_provision_info() { "Database in the container image is not available. Falling back to profile installation." "@drush -y sql:drop" "@drush -y site:install standard --site-name=Example site --site-mail=webmaster@example.com --account-name=admin install_configure_form.enable_update_status_module=NULL install_configure_form.enable_update_status_emails=NULL" + "@drush -y pm:install shield" "Installed a site from the profile." # Should NOT see the corrupted error messages or file-based provisioning. @@ -1589,6 +1639,140 @@ assert_provision_info() { popd >/dev/null || exit 1 } +@test "Provision: DB; no site; cache rebuild skip" { + pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 + + # Remove .env file to test in isolation. + rm ./.env && touch ./.env + rm -f ./scripts/custom/provision-20-migration.sh + + export VORTEX_PROVISION_SANITIZE_DB_PASSWORD="MOCK_DB_SANITIZE_PASSWORD" + export CI=1 + + mkdir "./.data" + touch "./.data/db.sql" + + export VORTEX_PROVISION_CACHE_REBUILD_AFTER_DB_UPDATE_SKIP=1 + + create_global_command_wrapper "vendor/bin/drush" + + declare -a STEPS=( + # Drush status calls. + "@drush -y --version # Drush Commandline Tool mocked_drush_version" + "@drush -y status --field=drupal-version # mocked_core_version" + "@drush -y status --fields=bootstrap # fail" + "@drush -y php:eval print realpath(\Drupal\Core\Site\Settings::get(\"config_sync_directory\")); # $(pwd)/config/default" + + # Site provisioning information. + "Provisioning site from the database dump file." + "Dump file path: $(pwd)/.data/db.sql" + "Existing site was not found." + "Fresh site content will be imported from the database dump file." + "@drush -y sql:drop" + "@drush -y sql:connect" + "Imported database from the dump file." + # Profile. + "- Provisioning site from the profile." + "- Installed a site from the profile." + + # Drupal environment information. + "Current Drupal environment: ci" + "@drush -y php:eval print \Drupal\core\Site\Settings::get('environment'); # ci" + + # Post-provision operations. + "- Skipped running of post-provision operations as VORTEX_PROVISION_POST_OPERATIONS_SKIP is set to 1." + + # Maintenance mode. + "Enabling maintenance mode." + "@drush -y maint:set 1" + "Enabled maintenance mode." + + # Deployment and configuration updates. + "- Updated site UUID from the configuration with" + "- Importing configuration." + "- Importing config_split configuration." + + # Database updates. + "Running database updates." + "@drush -y updatedb --no-cache-clear" + "Completed running database updates." + + # Cache rebuild after database updates - SKIPPED. + "Skipped cache rebuild after database updates." + "- Clearing cache after database updates." + "- Cache was cleared." + + # Cache rebuild. + "Rebuilding cache." + "@drush -y cache:rebuild" + "Cache was rebuilt." + + # Deployment hooks. + "Running deployment hooks." + "@drush -y deploy:hook" + "Completed deployment hooks." + + # Database sanitization. + "Sanitizing database." + "@drush -y sql:sanitize --sanitize-password=MOCK_DB_SANITIZE_PASSWORD --sanitize-email=user+%uid@localhost" + "Sanitized database using drush sql:sanitize." + "- Updated username with user email." + "@drush -y sql:query --file=../scripts/sanitize.sql" + "Applied custom sanitization commands from file" + "@drush -y sql:query UPDATE \`users_field_data\` SET mail = '', name = '' WHERE uid = '0';" + "@drush -y sql:query UPDATE \`users_field_data\` SET name = '' WHERE uid = '0';" + "Reset user 0 username and email." + "- Updated user 1 email." + "- Skipped database sanitization as VORTEX_PROVISION_SANITIZE_DB_SKIP is set to 1." + + # Custom post-install script. + "Running custom post-install script './scripts/custom/provision-10-example.sh'." + "@drush -y php:eval print \Drupal\core\Site\Settings::get('environment'); # ci" + " > Setting site name." + "@drush -y php:eval \Drupal::service('config.factory')->getEditable('system.site')->set('name', 'YOURSITE')->save();" + " > Installing contrib modules." + "@drush -y pm:install admin_toolbar coffee config_split config_update media environment_indicator pathauto redirect robotstxt shield stage_file_proxy xmlsitemap" + " > Installing Redis module." + "@drush -y pm:install redis" + " > Installing and configuring ClamAV." + "@drush -y pm:install clamav" + "@drush -y config-set clamav.settings mode_daemon_tcpip.hostname clamav" + " > Installing Solr search modules." + "@drush -y pm:install search_api search_api_solr" + " > Installing custom site modules." + "@drush -y pm:install ys_base" + "@drush -y pm:install ys_search" + "@drush -y pm:install ys_demo" + " > Running deployment hooks." + "@drush -y deploy:hook" + " ==> Started example operations." + " Environment: ci" + " Running example operations in non-production environment." + # Assert that VORTEX_PROVISION_OVERRIDE_DB is correctly passed to the script. + " Fresh database detected. Performing additional example operations." + "- Existing database detected. Performing additional example operations." + " ==> Finished example operations." + "Completed running of custom post-install script './scripts/custom/provision-10-example.sh'." + + # Disabling maintenance mode. + "Disabling maintenance mode." + "@drush -y maint:set 0" + "Disabled maintenance mode." + + # Installation completion. + "Finished site provisioning" + ) + + mocks="$(run_steps "setup")" + + run ./scripts/vortex/provision.sh + assert_success + + run_steps "assert" "${mocks[@]}" + + popd >/dev/null || exit 1 +} + @test "Provision: DB; no site; no fallback" { pushd "${LOCAL_REPO_DIR}" >/dev/null || exit 1 @@ -1714,6 +1898,11 @@ assert_provision_info() { "Completed running database updates." "- Configuration was changed by database updates." + # Cache rebuild after database updates. + "Clearing cache after database updates." + "@drush -y cache:rebuild" + "Cache was cleared." + # Configuration import. "Importing configuration." "@drush -y config:import" @@ -1867,6 +2056,7 @@ assert_provision_info() { # These should NOT appear (script exits before them). "- Verified that database updates did not change configuration." "- Completed running database updates." + "- Clearing cache after database updates." "- Importing configuration." "- Rebuilding cache." "- Running deployment hooks." diff --git a/.vortex/tests/phpunit/Functional/AhoyWorkflowTest.php b/.vortex/tests/phpunit/Functional/AhoyWorkflowTest.php index 1ea7a6e85..26d79756a 100644 --- a/.vortex/tests/phpunit/Functional/AhoyWorkflowTest.php +++ b/.vortex/tests/phpunit/Functional/AhoyWorkflowTest.php @@ -442,4 +442,64 @@ public function testAhoyUpdateVortexRef(): void { $this->assertFileDoesNotExist('installer.php', 'Installer script should be removed after update'); } + #[Group('p0')] + public function testAhoyWorkflowProvisionFallbackToProfile(): void { + static::$sutInstallerEnv = ['VORTEX_INSTALLER_IS_DEMO' => '1']; + $this->prepareSut(); + $this->adjustAhoyForUnmountedVolumes(); + + $this->logSubstep('Build the site with database dump'); + $this->subtestAhoyBuild(); + + $this->logSubstep('Export configuration from the provisioned site'); + $this->cmd('ahoy drush cex -y', '* ../config/default', 'Export configuration should complete successfully'); + $this->syncToHost('config'); + $this->assertFilesWildcardExists('config/default/*.yml'); + + $this->logSubstep('Remove the database dump file'); + $this->removePathHostAndContainer('.data/db.sql'); + $this->assertFileDoesNotExist('.data/db.sql', 'Database dump file should not exist after removal'); + + $this->logSubstep('Drop the database to simulate a fresh environment'); + $this->cmd('ahoy drush sql:drop -y', txt: 'Database should be dropped successfully'); + + $this->logSubstep('Provision without fallback should fail'); + $this->fileAddVar('.env', 'VORTEX_PROVISION_FALLBACK_TO_PROFILE', 0); + $this->syncToContainer(['.env']); + $this->cmdFail( + 'ahoy provision', + [ + '* Unable to import database from file', + '* does not exist', + '* Site content was not changed', + ], + 'Provision without fallback should fail when no database dump is available', + ); + + $this->logSubstep('Provision with fallback should succeed'); + $this->fileAddVar('.env', 'VORTEX_PROVISION_FALLBACK_TO_PROFILE', 1); + $this->syncToContainer(['.env']); + $this->cmd( + 'ahoy provision', + [ + '* Database dump file is not available. Falling back to profile installation', + '* Installed a site from the profile', + '* Skipped running of post-provision operations', + '! Importing configuration', + '! Running deployment hooks', + ], + 'Provision with fallback should complete successfully', + tio: 15 * 60, + ); + + $this->logSubstep('Assert that Shield module is enabled'); + $this->cmd('ahoy drush pm:list --status=enabled --type=module --format=list', '* shield', 'Shield module should be enabled after fallback provision'); + + $this->logSubstep('Assert that homepage does not contain database dump content'); + $this->assertWebpageNotContains('/', 'This demo page is sourced from the Vortex database dump file', 'Homepage should not show database dump content after fallback provision'); + + $this->logSubstep('Assert that homepage is accessible'); + $this->assertWebpageContains('/', '