Refresh the image registry cache in a workflow that cannot be cancelled - #71171
Merged
Conversation
A branch built on push refreshed its registry cache from inside the CI run, which cancels in progress on the next push. With no cache the build runs cold, which widens the window the next push cancels in, which leaves the cache missing -- v3-3-test held only the default Python version's amd64 cache because that was the one matrix entry that finished in time. The refresh also has to cover every Python version: a version with no cache entry builds from scratch on every run, and selective checks narrows the list on a text-only push.
The manual constraints refresh shared a workflow with the automatic uv.lock push, so it was filtered by that workflow's paths and buried under its name in the Actions list. The documented procedures pointed at local builds -- refresh_images.sh for the image cache, breeze commands for the constraints -- which need a buildx/qemu setup, a committer login to ghcr.io, and enough bandwidth to push the layers. The workflows need none of that, and unlike a local run they always cover every Python version and every constraint flavour.
A push-triggered refresh should give way to the next one -- it is building the cache of a commit that is no longer the tip. A manual run should not: it is started because the branch has no cache and the push runs are the thing that keeps getting cancelled.
potiuk
requested review from
amoghrajesh,
ashb,
bugraoz93,
choo121600,
ephraimbuddy,
gopidesupavan,
jason810496,
jedcunningham,
jscheffl and
vatsrahul1001
as code owners
August 5, 2026 10:33
vatsrahul1001
approved these changes
Aug 5, 2026
Member
Author
|
OK Yolo :) |
Contributor
Backport failed to create: v3-3-test. View the failure log Run detailsNote: As of Merging PRs targeted for Airflow 3.X In matter of doubt please ask in #release-management Slack channel.
You can attempt to backport this manually by running: cherry_picker e69c188 v3-3-testThis should apply the commit to the v3-3-test branch and leave the commit in conflict state marking After you have resolved the conflicts, you can continue the backport process by running: cherry_picker --continueIf you don't have cherry-picker installed, see the installation guide. |
Merged
1 task
potiuk
added a commit
that referenced
this pull request
Aug 5, 2026
…ed (#71171) (#71173) * Refresh the image registry cache in a workflow that cannot be cancelled A branch built on push refreshed its registry cache from inside the CI run, which cancels in progress on the next push. With no cache the build runs cold, which widens the window the next push cancels in, which leaves the cache missing -- v3-3-test held only the default Python version's amd64 cache because that was the one matrix entry that finished in time. The refresh also has to cover every Python version: a version with no cache entry builds from scratch on every run, and selective checks narrows the list on a text-only push. * Refresh constraints from a workflow of its own, covering every flavour The manual constraints refresh shared a workflow with the automatic uv.lock push, so it was filtered by that workflow's paths and buried under its name in the Actions list. The documented procedures pointed at local builds -- refresh_images.sh for the image cache, breeze commands for the constraints -- which need a buildx/qemu setup, a committer login to ghcr.io, and enough bandwidth to push the layers. The workflows need none of that, and unlike a local run they always cover every Python version and every constraint flavour. * Exempt a manually started cache refresh from the push cancellation A push-triggered refresh should give way to the next one -- it is building the cache of a commit that is no longer the tip. A manual run should not: it is started because the branch has no cache and the push runs are the thing that keeps getting cancelled. (cherry picked from commit e69c188) Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
vatsrahul1001
added a commit
that referenced
this pull request
Aug 5, 2026
…ed (#71171) (#71173) * Refresh the image registry cache in a workflow that cannot be cancelled A branch built on push refreshed its registry cache from inside the CI run, which cancels in progress on the next push. With no cache the build runs cold, which widens the window the next push cancels in, which leaves the cache missing -- v3-3-test held only the default Python version's amd64 cache because that was the one matrix entry that finished in time. The refresh also has to cover every Python version: a version with no cache entry builds from scratch on every run, and selective checks narrows the list on a text-only push. * Refresh constraints from a workflow of its own, covering every flavour The manual constraints refresh shared a workflow with the automatic uv.lock push, so it was filtered by that workflow's paths and buried under its name in the Actions list. The documented procedures pointed at local builds -- refresh_images.sh for the image cache, breeze commands for the constraints -- which need a buildx/qemu setup, a committer login to ghcr.io, and enough bandwidth to push the layers. The workflows need none of that, and unlike a local run they always cover every Python version and every constraint flavour. * Exempt a manually started cache refresh from the push cancellation A push-triggered refresh should give way to the next one -- it is building the cache of a commit that is no longer the tip. A manual run should not: it is started because the branch has no cache and the push runs are the thing that keeps getting cancelled. (cherry picked from commit e69c188) Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
dabla
pushed a commit
to dabla/airflow
that referenced
this pull request
Aug 14, 2026
…ed (apache#71171) * Refresh the image registry cache in a workflow that cannot be cancelled A branch built on push refreshed its registry cache from inside the CI run, which cancels in progress on the next push. With no cache the build runs cold, which widens the window the next push cancels in, which leaves the cache missing -- v3-3-test held only the default Python version's amd64 cache because that was the one matrix entry that finished in time. The refresh also has to cover every Python version: a version with no cache entry builds from scratch on every run, and selective checks narrows the list on a text-only push. * Refresh constraints from a workflow of its own, covering every flavour The manual constraints refresh shared a workflow with the automatic uv.lock push, so it was filtered by that workflow's paths and buried under its name in the Actions list. The documented procedures pointed at local builds -- refresh_images.sh for the image cache, breeze commands for the constraints -- which need a buildx/qemu setup, a committer login to ghcr.io, and enough bandwidth to push the layers. The workflows need none of that, and unlike a local run they always cover every Python version and every constraint flavour. * Exempt a manually started cache refresh from the push cancellation A push-triggered refresh should give way to the next one -- it is building the cache of a commit that is no longer the tip. A manual run should not: it is started because the branch has no cache and the push runs are the thing that keeps getting cancelled.
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.
v3-3-testbuilds itslinux/amd64CI images from scratch, ~20 minutes per Python version, because the registry has no cache for them:The registry holds
cache-linux-amd64for Python 3.10 alone on that branch, whilecache-linux-arm64exists for all five.Why
A branch built on
pushrefreshed its cache from inside the CI run, which cancels in progress on the next push. With no cache the build runs cold, which widens the window the next push cancels in, which leaves the cache missing. Run30973271401is the loop in one screenshot:The next push landed at 05:17:26 and killed four of the five, fifteen seconds after the first finished. Of the last 60 AMD runs on that branch, 45 were cancelled and 14 failed — so the Regular cache push in
finalize-tests.yml, which sits behind the whole test matrix, never runs there either.A job cannot opt out of its run being cancelled, so the refresh has to be a workflow of its own.
What this does
refresh-image-registry-cache.yml— refreshes the CI cache for both platforms, onworkflow_dispatchand onpushto release-prep / providers branches. Push runs are never cancelled (a newer one queues behind); manual runs are grouped separately, so a merge cannot cancel one, and re-firing it replaces the run in flight.Every Python version, both paths. Selective checks narrows
python-versionsto the default one on a push where only text files changed (_should_run_all_tests_and_versions), which is a second, independent way a branch ends up with cache for one version. The workflow forces theall versionslabel; a new test intest_selective_checks.pypins that.The early cache push is removed from the regular build. It is what this workflow replaces, so
additional-ci-image-checks.ymlloses that job and the sevenworkflow_callinputs only it consumed (removed from both wrappers identically, socheck-ci-workflows-in-syncstays green).mainis unaffected: it is not built on push, and its Push Image Cache job at the end of the scheduled canary runs to completion.refresh-constraints.yml— the manual constraints refresh, split out ofupdate-constraints-on-push.ymlso it is not filtered by that workflow'spaths: uv.lockand appears under its own name. It calls that workflow rather than copying it, and refreshes all three flavours — source-providers, no-providers and PyPI — since refreshing only PyPI leaves CI and Breeze on the older pins.release-constraints.ymlis untouched.Docs — both procedures in
dev/MANUALLY_GENERATING_IMAGE_CACHE_AND_CONSTRAINTS.mdnow lead with the workflows; the local buildx / qemu /refresh_images.shroute is kept but demoted to a fallback. The automated-CI section no longer describes the early cache push this PR deletes.Also fixed in
dev/MANUALLY_BUILDING_IMAGES.md: the merge step was documented asdocker release-management merge-prod-imagesin both the regular and slim variants — it is abreezesubcommand, so the documented command fails as written.Follow-ups this does not do
v3-3-testneeds the workflow backported before its cache can be refreshed there —workflow_dispatchruns the file from the branch you select.dev/MANUALLY_BUILDING_IMAGES.mdcontradicts itself on the buildx version (a warning says "at least 0.13", the prose says 0.23 is needed fordocker-container). Left alone rather than guessed at.Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Opus 5) following the guidelines