[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
Open
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
magento:cron:stoprunscron:removefrom{{previous_release}}, but Magento keys each crontab block to the base path the command is run from, so that only removes the live block whenprevious_releasehappens to be the live release.previous_releaseisreleases_list[1](recipe/deploy/release.php), the second-newest release directory. That stops being thecurrentsymlink 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()appendshash('sha256', BP)to the block marker, so a block belongs to exactly one base path. Verified against a live crontab:6ca66aa6…=sha256("/home/magento/releases/20260814081733")2a8e9eee…=sha256("/home/magento/releases/20260827044137")Steps to reproduce
currentpoints at release A, and the crontab holds one block keyed to A.deploy:symlink, leaving B on disk.currentis still A.previous_releasenow resolves to B, not A.magento:cron:stoprunscron:removefrom B, which removes B's block. There is no B block, so nothing is removed.magento:cron:installadds a block for C.Expected
One
cron:runentry, 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:removefrom{{current_path}}.magento:cron:stopruns beforedeploy:symlink, socurrentis still the live release at that point, which is the block that actually needs removing.__DIR__resolves the symlink, soBPis the real release path and the hash matches. Thetestguard keeps the first deploy working, wherecurrentdoes not yet exist, and replaces the existingprevious_releaseguard from #4230, which this supersedes for the same failure mode.