Background
Part of the Vortex 2.0 epic.
Vortex currently ships bespoke post-provision shell scripts to run logic after drush deploy. Drupal/Drush's run-once hooks (hook_update_N, hook_post_update_NAME, hook_deploy_NAME) cannot express "run on every deploy" - they are recorded as completed and never repeat. Historically this required a "persistent update" hack (resetting a hook's completion marker), which is now unmaintained and an anti-pattern.
Decision
Drush already supports running logic on every drush deploy via a native pre-command / post-command annotated-command hook targeting deploy. These are not run-once tracked. No upstream change is required.
Goal
Ship a dedicated, consumer-owned module (ys_deploy) that hosts pre/post-deploy sequences via Drush command hooks. It runs identically wherever drush deploy runs (CI, local, and production hosting post-rollout), and replaces the bespoke post-provision scripts.
Scope
- New module
ys_deploy (project-prefixed) with a DeployCommands class exposing PRE_COMMAND_HOOK / POST_COMMAND_HOOK hooks on deploy, where consumers define their own repeatable, idempotent deploy sequences.
- Developer-experience helpers in this class to make common operations easy to run and to express step ordering.
- Make these sequences testable.
- Port the capabilities currently provided by the bespoke post-provision scripts into this module.
- Decommission the custom post-provision shell scripts once parity is reached.
- Document the two layers:
- Drupal-level "every deploy" -> this module's Drush command hooks (runs wherever
drush deploy runs).
- Vortex tooling-level -> pre/post provision event scripts (#1198) for orchestration outside
drush deploy (e.g. work before DB import).
- Pin the supported hook form for the Drush version in use (Drush 13.7+ nudges some hook types toward Listener classes).
Example
A post-command hook that runs after every drush deploy, with no run-once tracking:
<?php
declare(strict_types=1);
namespace Drupal\ys_deploy\Drush\Commands;
use Consolidation\AnnotatedCommand\CommandData;
use Consolidation\AnnotatedCommand\Hooks\HookManager;
use Drush\Attributes as CLI;
use Drush\Commands\DrushCommands;
/**
* Repeatable deploy-time tasks for this project.
*/
final class DeployCommands extends DrushCommands {
/**
* Runs after EVERY `drush deploy` (not recorded as done, so never skipped).
*
* The correct home for idempotent, must-run-on-every-deploy work (search
* reindex, a re-runnable migration, cache warmups). Replaces the legacy
* "persistent update" hack. Contrast hook_deploy_NAME(), which is run-once
* and tracked.
*/
#[CLI\Hook(type: HookManager::POST_COMMAND_HOOK, target: 'deploy')]
public function postDeploy(mixed $result, CommandData $commandData): void {
$this->logger()->notice(dt('Running repeatable post-deploy tasks.'));
// Project-specific idempotent commands go here, e.g.:
// drush search-api:index
// drush migrate:import --update --sync some_config_migration
}
}
HookManager::PRE_COMMAND_HOOK provides the same extension point before the deploy steps.
Acceptance criteria
- A generated project includes a
ys_deploy module with documented pre/post deploy hook extension points.
- Repeatable deploy logic runs on every deploy across CI, local, and production.
- The bespoke post-provision scripts are removed.
- Deploy sequences are covered by tests.
References
Background
Part of the Vortex 2.0 epic.
Vortex currently ships bespoke post-provision shell scripts to run logic after
drush deploy. Drupal/Drush's run-once hooks (hook_update_N,hook_post_update_NAME,hook_deploy_NAME) cannot express "run on every deploy" - they are recorded as completed and never repeat. Historically this required a "persistent update" hack (resetting a hook's completion marker), which is now unmaintained and an anti-pattern.Decision
Drush already supports running logic on every
drush deployvia a nativepre-command/post-commandannotated-command hook targetingdeploy. These are not run-once tracked. No upstream change is required.drush deploydrush-ops/drush#6302 ("Add predeploy hook") was closednot_planned- "we won't be complicating this command with a new hook".Goal
Ship a dedicated, consumer-owned module (
ys_deploy) that hosts pre/post-deploy sequences via Drush command hooks. It runs identically whereverdrush deployruns (CI, local, and production hosting post-rollout), and replaces the bespoke post-provision scripts.Scope
ys_deploy(project-prefixed) with aDeployCommandsclass exposingPRE_COMMAND_HOOK/POST_COMMAND_HOOKhooks ondeploy, where consumers define their own repeatable, idempotent deploy sequences.drush deployruns).drush deploy(e.g. work before DB import).Example
A
post-commandhook that runs after everydrush deploy, with no run-once tracking:HookManager::PRE_COMMAND_HOOKprovides the same extension point before the deploy steps.Acceptance criteria
ys_deploymodule with documented pre/post deploy hook extension points.References
drush deploydrush-ops/drush#6302 (not_planned), Implement shell hooks drush-ops/drush#3719, Shell aliases (or yml commands) drush-ops/drush#2943.