This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch mirror-hardened-images-more-often
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to
refs/heads/mirror-hardened-images-more-often by this push:
new 1f37210cb59 Dispatch the mirror from a job of its own in the upgrade
check
1f37210cb59 is described below
commit 1f37210cb59f5926b280da4e2ebb21bc4d446310
Author: Jarek Potiuk <[email protected]>
AuthorDate: Fri Oct 30 13:33:11 2026 +0100
Dispatch the mirror from a job of its own in the upgrade check
The upgrade job runs the third-party tools and hooks it upgrades, with a
token that may push. Giving that token "actions: write" as well would let
any of that code dispatch, re-run or cancel workflows. A separate job that
only dispatches the mirror holds that permission now, and the upgrade job
waits for it.
Generated-by: Claude Opus 5
---
.github/workflows/scheduled-upgrade-check-main.yml | 2 +-
.../scheduled-upgrade-check-v3-4-test.yml | 2 +-
.github/workflows/upgrade-check.yml | 37 +++++++++++++++++++---
dev/breeze/doc/09_release_management_tasks.rst | 7 ++--
.../output_workflow-run_mirror-base-images.svg | 32 +++++++++++++++----
.../output_workflow-run_mirror-base-images.txt | 2 +-
.../airflow_breeze/commands/workflow_commands.py | 11 +++++--
.../commands/workflow_commands_config.py | 9 +++++-
dev/breeze/tests/test_workflow_commands.py | 13 ++++++--
9 files changed, 93 insertions(+), 22 deletions(-)
diff --git a/.github/workflows/scheduled-upgrade-check-main.yml
b/.github/workflows/scheduled-upgrade-check-main.yml
index 198bb856f53..ee0ab72a15a 100644
--- a/.github/workflows/scheduled-upgrade-check-main.yml
+++ b/.github/workflows/scheduled-upgrade-check-main.yml
@@ -25,7 +25,7 @@ on: # yamllint disable-line rule:truthy
permissions:
contents: write
pull-requests: write
- # Dispatches the "Mirror hardened base images" workflow before the upgrade
pins its images.
+ # Only the job of upgrade-check.yml that dispatches the "Mirror hardened
base images" workflow gets it.
actions: write
jobs:
upgrade-main:
diff --git a/.github/workflows/scheduled-upgrade-check-v3-4-test.yml
b/.github/workflows/scheduled-upgrade-check-v3-4-test.yml
index 753cde39c86..9d51e87cec4 100644
--- a/.github/workflows/scheduled-upgrade-check-v3-4-test.yml
+++ b/.github/workflows/scheduled-upgrade-check-v3-4-test.yml
@@ -25,7 +25,7 @@ on: # yamllint disable-line rule:truthy
permissions:
contents: write
pull-requests: write
- # Dispatches the "Mirror hardened base images" workflow before the upgrade
pins its images.
+ # Only the job of upgrade-check.yml that dispatches the "Mirror hardened
base images" workflow gets it.
actions: write
jobs:
upgrade-v3-4-test:
diff --git a/.github/workflows/upgrade-check.yml
b/.github/workflows/upgrade-check.yml
index b6693bb620b..88591e5cc6a 100644
--- a/.github/workflows/upgrade-check.yml
+++ b/.github/workflows/upgrade-check.yml
@@ -30,20 +30,48 @@ on: # yamllint disable-line rule:truthy
description: "Slack bot token for notifications"
required: true
permissions:
- contents: write
- pull-requests: write
- # Dispatches the "Mirror hardened base images" workflow before the upgrade
pins its images.
- actions: write
+ contents: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
TARGET_BRANCH: ${{ inputs.target-branch }}
jobs:
+ # A job of its own, so the token that may dispatch workflows never reaches
the upgrade job, which
+ # runs the third-party tools and hooks it upgrades.
+ mirror-base-images:
+ timeout-minutes: 30
+ name: >-
+ [${{ inputs.target-branch }}] Mirror hardened base images
+ runs-on: ["ubuntu-22.04"]
+ permissions:
+ actions: write
+ contents: read
+ steps:
+ - name: >-
+ [${{ inputs.target-branch }}] Checkout main
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #
v7.0.1
+ with:
+ ref: main
+ persist-credentials: false
+ - name: >-
+ [${{ inputs.target-branch }}] Install Breeze
+ uses: ./.github/actions/breeze
+ # The upgrade for main is the one the mirror would otherwise start a
second time.
+ - name: >-
+ [${{ inputs.target-branch }}] Mirror the base images and wait for
the run
+ env:
+ TRIGGER_UPGRADE_CHECK_FLAG: >-
+ ${{ inputs.target-branch == 'main' && '--no-trigger-upgrade-check'
|| '--trigger-upgrade-check' }}
+ run: breeze workflow-run mirror-base-images
"${TRIGGER_UPGRADE_CHECK_FLAG}"
createupgrade-check:
timeout-minutes: 45
name: >-
[${{ inputs.target-branch }}] Upgrade checks and PR
runs-on: ["ubuntu-22.04"]
+ needs: [mirror-base-images]
+ permissions:
+ contents: write
+ pull-requests: write
steps:
- name: >-
[${{ inputs.target-branch }}] Cleanup repo
@@ -87,6 +115,7 @@ jobs:
--switch-to-base
--no-k8s-schema-sync
--latest-package-managers
+ --no-mirror-base-images
--answer yes
- name: >-
[${{ inputs.target-branch }}] Find upgrade PR
diff --git a/dev/breeze/doc/09_release_management_tasks.rst
b/dev/breeze/doc/09_release_management_tasks.rst
index 273ed9808b0..cd638c2cbcf 100644
--- a/dev/breeze/doc/09_release_management_tasks.rst
+++ b/dev/breeze/doc/09_release_management_tasks.rst
@@ -1168,9 +1168,10 @@ These are all available flags of ``workflow-run
mirror-base-images`` command:
:alt: Breeze workflow-run mirror-base-images
``breeze workflow-run upgrade-check`` runs the upgrade check for a branch, by
default the branch breeze
-comes from. The check mirrors the base images first - ``breeze ci upgrade``
does that before it upgrades
-the important versions, locally as well as in CI, unless
``--no-mirror-base-images`` is passed. When
-anything moved, it opens an upgrade PR against the branch.
+comes from. The check mirrors the base images first: in CI a job of its own
does it, so the token that may
+dispatch workflows never reaches the job running the upgraded tools, and a
local ``breeze ci upgrade`` does
+it before it upgrades the important versions, unless
``--no-mirror-base-images`` is passed. When anything
+moved, it opens an upgrade PR against the branch.
These are all available flags of ``workflow-run upgrade-check`` command:
diff --git a/dev/breeze/doc/images/output_workflow-run_mirror-base-images.svg
b/dev/breeze/doc/images/output_workflow-run_mirror-base-images.svg
index c5804aa80ea..9c61d5dd5f0 100644
--- a/dev/breeze/doc/images/output_workflow-run_mirror-base-images.svg
+++ b/dev/breeze/doc/images/output_workflow-run_mirror-base-images.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 245.2"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 367.2"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -42,7 +42,7 @@
<defs>
<clipPath id="breeze-workflow-run-mirror-base-images-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="194.2" />
+ <rect x="0" y="0" width="1463.0" height="316.2" />
</clipPath>
<clipPath id="breeze-workflow-run-mirror-base-images-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -65,9 +65,24 @@
<clipPath id="breeze-workflow-run-mirror-base-images-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-workflow-run-mirror-base-images-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-workflow-run-mirror-base-images-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-workflow-run-mirror-base-images-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-workflow-run-mirror-base-images-line-10">
+ <rect x="0" y="245.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-workflow-run-mirror-base-images-line-11">
+ <rect x="0" y="269.9" width="1464" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="243.2" rx="8"/><text
class="breeze-workflow-run-mirror-base-images-title" fill="#c5c8c6"
text-anchor="middle" x="740"
y="27">Command: workflow-run mirror-base-images</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="365.2" rx="8"/><text
class="breeze-workflow-run-mirror-base-images-title" fill="#c5c8c6"
text-anchor="middle" x="740"
y="27">Command: workflow-run mirror-base-images</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -82,9 +97,14 @@
</text><text class="breeze-workflow-run-mirror-base-images-r1" x="1464"
y="68.8" textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-2)">
</text><text class="breeze-workflow-run-mirror-base-images-r1" x="12.2"
y="93.2" textLength="878.4"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-3)">Mirror the latest hardened base images and wait until they are mirrored.</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="1464" y="93.2"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-3)">
</text><text class="breeze-workflow-run-mirror-base-images-r1" x="1464"
y="117.6" textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-4)">
-</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="142"
textLength="24.4"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-5)">╭─</text><text
class="breeze-workflow-run-mirror-base-images-r5" x="24.4" y="142"
textLength="195.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-5)"> Common options </text><text
class="breeze-workflow-run-mirror-base-images-r5" x="219.6" y="142"
textLength="1220" clip-path="url(#breeze-workflow-run-mi [...]
-</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="166.4"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-6)">│</text><text
class="breeze-workflow-run-mirror-base-images-r4" x="24.4" y="166.4"
textLength="73.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-6)">--help</text><text
class="breeze-workflow-run-mirror-base-images-r6" x="122" y="166.4"
textLength="24.4" clip-path="url(#breeze-workflow-run-mirror-base-images-line-6
[...]
-</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="190.8"
textLength="1464"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-7)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="1464" y="190.8"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-7)">
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="142"
textLength="24.4"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-5)">╭─</text><text
class="breeze-workflow-run-mirror-base-images-r5" x="24.4" y="142"
textLength="170.8"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-5)"> Mirror flags </text><text
class="breeze-workflow-run-mirror-base-images-r5" x="195.2" y="142"
textLength="1244.4" clip-path="url(#breeze-workflow-run-mi [...]
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="166.4"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-6)">│</text><text
class="breeze-workflow-run-mirror-base-images-r4" x="24.4" y="166.4"
textLength="280.6"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-6)">--trigger-upgrade-check</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="305" y="166.4"
textLength="12.2" clip-path="url(#breeze-workflow-run-mirror- [...]
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="190.8"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-7)">│</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="658.8" y="190.8"
textLength="780.8"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-7)">its pin. Turn it off when the main upgrade check is what runs   </text><text
class="breez [...]
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="215.2"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-8)">│</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="658.8" y="215.2"
textLength="146.4"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-8)">the mirror. </text><text
class="breeze-workflow-run-mirror-base-images-r5" x="805.2" y="215.2"
textLength="390.4" clip-path="url(#breeze-workflow-run-mirr [...]
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="239.6"
textLength="1464"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-9)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="1464" y="239.6"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-9)">
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="264"
textLength="24.4"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-10)">╭─</text><text
class="breeze-workflow-run-mirror-base-images-r5" x="24.4" y="264"
textLength="195.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-10)"> Common options </text><text
class="breeze-workflow-run-mirror-base-images-r5" x="219.6" y="264"
textLength="1220" clip-path="url(#breeze-workflow-run- [...]
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="288.4"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-11)">│</text><text
class="breeze-workflow-run-mirror-base-images-r4" x="24.4" y="288.4"
textLength="73.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-11)">--help</text><text
class="breeze-workflow-run-mirror-base-images-r6" x="122" y="288.4"
textLength="24.4" clip-path="url(#breeze-workflow-run-mirror-base-images-line
[...]
+</text><text class="breeze-workflow-run-mirror-base-images-r5" x="0" y="312.8"
textLength="1464"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-workflow-run-mirror-base-images-r1" x="1464" y="312.8"
textLength="12.2"
clip-path="url(#breeze-workflow-run-mirror-base-images-line-12)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_workflow-run_mirror-base-images.txt
b/dev/breeze/doc/images/output_workflow-run_mirror-base-images.txt
index 826f1ebb0cf..35b73c90d6e 100644
--- a/dev/breeze/doc/images/output_workflow-run_mirror-base-images.txt
+++ b/dev/breeze/doc/images/output_workflow-run_mirror-base-images.txt
@@ -1 +1 @@
-4f364945d4e9ce6e6e7bf01b2e1dc0b1
+ff6777b06b1340e4e0d47c58e828aae6
diff --git a/dev/breeze/src/airflow_breeze/commands/workflow_commands.py
b/dev/breeze/src/airflow_breeze/commands/workflow_commands.py
index 0495511670b..76b7f5d8632 100644
--- a/dev/breeze/src/airflow_breeze/commands/workflow_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/workflow_commands.py
@@ -499,8 +499,15 @@ def workflow_run_release_constraints(version: str, ref:
str, workflow_branch: st
name="mirror-base-images",
help="Mirror the latest hardened base images and wait until they are
mirrored.",
)
-def workflow_run_mirror_base_images():
- mirror_hardened_base_images(APACHE_AIRFLOW_REPO)
[email protected](
+ "--trigger-upgrade-check/--no-trigger-upgrade-check",
+ default=True,
+ show_default=True,
+ help="Let the mirror run the main upgrade check when a tag moves past its
pin. Turn it off when the "
+ "main upgrade check is what runs the mirror.",
+)
+def workflow_run_mirror_base_images(trigger_upgrade_check: bool):
+ mirror_hardened_base_images(APACHE_AIRFLOW_REPO,
trigger_upgrade_check=trigger_upgrade_check)
@workflow_run_group.command(
diff --git a/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py
b/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py
index 0475958adbd..5b4eb705780 100644
--- a/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py
@@ -88,4 +88,11 @@ WORKFLOW_RUN_PARAMETERS["breeze workflow-run upgrade-check"]
= [
],
},
]
-WORKFLOW_RUN_PARAMETERS["breeze workflow-run mirror-base-images"] = []
+WORKFLOW_RUN_PARAMETERS["breeze workflow-run mirror-base-images"] = [
+ {
+ "name": "Mirror flags",
+ "options": [
+ "--trigger-upgrade-check",
+ ],
+ },
+]
diff --git a/dev/breeze/tests/test_workflow_commands.py
b/dev/breeze/tests/test_workflow_commands.py
index 467b7316321..088a36777c0 100644
--- a/dev/breeze/tests/test_workflow_commands.py
+++ b/dev/breeze/tests/test_workflow_commands.py
@@ -394,12 +394,19 @@ class TestSyncStagingToMain:
assert mock_trigger.call_count == 2
[email protected](
+ ("args", "trigger_upgrade_check"),
+ [
+ pytest.param([], True, id="default"),
+ pytest.param(["--no-trigger-upgrade-check"], False,
id="called-by-the-main-upgrade"),
+ ],
+)
@patch("airflow_breeze.commands.workflow_commands.mirror_hardened_base_images",
autospec=True)
-def test_mirror_base_images_runs_the_mirror(mock_mirror):
- result = CliRunner().invoke(workflow_run_mirror_base_images, [],
catch_exceptions=False)
+def test_mirror_base_images_runs_the_mirror(mock_mirror, args,
trigger_upgrade_check):
+ result = CliRunner().invoke(workflow_run_mirror_base_images, args,
catch_exceptions=False)
assert result.exit_code == 0
- mock_mirror.assert_called_once_with("apache/airflow")
+ mock_mirror.assert_called_once_with("apache/airflow",
trigger_upgrade_check=trigger_upgrade_check)
@pytest.mark.parametrize(