Skip to content

[Magento] cron:stop removes the wrong crontab block when previous_release is not the live release - #4251

Open
TuVanDev wants to merge 1 commit into
deployphp:masterfrom
TuVanDev:fix/magento-cron-stop-uses-live-release
Open

[Magento] cron:stop removes the wrong crontab block when previous_release is not the live release#4251
TuVanDev wants to merge 1 commit into
deployphp:masterfrom
TuVanDev:fix/magento-cron-stop-uses-live-release

Conversation

@TuVanDev

Copy link
Copy Markdown

magento:cron:stop runs cron:remove from {{previous_release}}, but Magento keys each crontab block to the base path the command is run from, so that only removes the live block when previous_release happens to be the live release.

previous_release is releases_list[1] (recipe/deploy/release.php), the second-newest release directory. That stops being the current symlink target as soon as a failed deploy leaves a release behind.

Environment

Deployer master (also reproduced on v7.5.12), Magento 2.4.6-p15, PHP 8.2, Linux.

Mechanism

Magento\Framework\Crontab\CrontabManager::getTasksBlockStart() appends hash('sha256', BP) to the block marker, so a block belongs to exactly one base path. Verified against a live crontab:

  • block 6ca66aa6… = sha256("/home/magento/releases/20260814081733")
  • block 2a8e9eee… = sha256("/home/magento/releases/20260827044137")

Steps to reproduce

  1. Deploy successfully. current points at release A, and the crontab holds one block keyed to A.
  2. Run a deploy that creates release B and fails before deploy:symlink, leaving B on disk. current is still A.
  3. Deploy again, creating release C. previous_release now resolves to B, not A.
  4. magento:cron:stop runs cron:remove from B, which removes B's block. There is no B block, so nothing is removed.
  5. magento:cron:install adds a block for C.

Expected

One cron:run entry, for the release being deployed.

Actual

Two entries: A and C. A keeps running every minute against the previous release's code, so cron continues to execute code that is no longer live. On the affected host this ran undetected until the crontab was inspected by hand.

Fix

Run cron:remove from {{current_path}}. magento:cron:stop runs before deploy:symlink, so current is still the live release at that point, which is the block that actually needs removing. __DIR__ resolves the symlink, so BP is the real release path and the hash matches. The test guard keeps the first deploy working, where current does not yet exist, and replaces the existing previous_release guard from #4230, which this supersedes for the same failure mode.

cron:remove only removes the crontab block of the installation it is run from, because
CrontabManager keys the block on hash('sha256', BP). previous_release is releases_list[1], which
stops being the live release once a failed deploy leaves a release directory behind, so the live
block survives and magento:cron:install then adds a second one. Two cron:run entries then execute
every minute, one of them against the previous release's code.

current_path is still the live release at this point, since the task runs before deploy:symlink.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant