This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new 95d3d427ecc [v3-1-test] Add `check-release-files` command to verify 
expected packages in Airflow SVN. (#58579) (#58604)
95d3d427ecc is described below

commit 95d3d427ecc8cfacecf61851668ee1a14bca1073
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sun Nov 23 22:29:11 2025 +0100

    [v3-1-test] Add `check-release-files` command to verify expected packages 
in Airflow SVN. (#58579) (#58604)
    
    This command is now better integrated into airflow `breeze` ecosystem:
    
    * auto-complete works
    * tests are run as part of breeze tests
    * release documentation is updated and PATH_TO_AIRFLOW_SVN variable is less 
ambiguous and automatically read into release-management's 
`check-release-files` command argument
    * help descriptions are upgrade
    * the `upgrade-check` that was only released at the beginning of Airflow 2 
is removed
    (cherry picked from commit 13dc31fc065d0250229bc38b0425bdd1bddcf9a9)
---
 .gitignore                                         |   4 +-
 dev/README_RELEASE_AIRFLOW.md                      |  18 +-
 dev/README_RELEASE_AIRFLOWCTL.md                   |  16 +-
 dev/README_RELEASE_PROVIDERS.md                    |  31 +-
 dev/README_RELEASE_PYTHON_CLIENT.md                |  18 +-
 dev/breeze/doc/09_release_management_tasks.rst     |  63 ++++
 .../doc/images/output_release-management.svg       |  20 +-
 .../doc/images/output_release-management.txt       |   2 +-
 ...tput_release-management_check-release-files.svg | 154 +++++++++
 ...tput_release-management_check-release-files.txt |   1 +
 .../output_setup_check-all-params-in-groups.svg    |   8 +-
 .../output_setup_check-all-params-in-groups.txt    |   2 +-
 .../output_setup_regenerate-command-images.svg     |  74 ++--
 .../output_setup_regenerate-command-images.txt     |   2 +-
 .../commands/release_management_commands.py        | 135 ++++++++
 .../commands/release_management_commands_config.py |  12 +
 .../airflow_breeze/utils/check_release_files.py    | 228 +++++++++++++
 dev/breeze/tests/test_check_release_files.py       | 222 ++++++++++++
 dev/check_files.py                                 | 378 ---------------------
 19 files changed, 928 insertions(+), 460 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1528de626bd..f255d7e01a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -233,8 +233,8 @@ pip-wheel-metadata
 .pypirc
 
 # Dev files
-/dev/packages.txt
-/dev/Dockerfile.pmc
+packages.txt
+Dockerfile.pmc
 
 # Generated UI licenses
 3rd-party-licenses/LICENSES-ui.txt
diff --git a/dev/README_RELEASE_AIRFLOW.md b/dev/README_RELEASE_AIRFLOW.md
index cfe2e48e304..70bd555df15 100644
--- a/dev/README_RELEASE_AIRFLOW.md
+++ b/dev/README_RELEASE_AIRFLOW.md
@@ -717,25 +717,23 @@ cd ..
 svn update --set-depth=infinity asf-dist/dev/airflow
 ```
 
-Set an environment variable: PATH_TO_SVN to the root of folder where you clone 
the SVN repository:
+Set an environment variable: PATH_TO_AIRFLOW_SVN to the root of folder where 
you clone the SVN repository:
 
 ```shell scrupt
 cd asf-dist/dev/airflow
-export PATH_TO_SVN=$(pwd -P)
+export PATH_TO_AIRFLOW_SVN=$(pwd -P)
 ```
 
-Optionally you can use `check_files.py` script to verify that all expected 
files are
-present in SVN. This script may help also with verifying installation of the 
packages.
+Optionally you can use the `breeze release-management check-release-files` 
command to verify that all expected files are
+present in SVN. This command may also help with verifying installation of the 
packages.
 
 ```shell script
-cd $AIRFLOW_REPO_ROOT/dev
-uv run check_files.py airflow -v ${VERSION_RC} -p ${PATH_TO_SVN}
+breeze release-management check-release-files airflow --version ${VERSION_RC}
 ```
 
 
 ```shell script
-cd $AIRFLOW_REPO_ROOT/dev
-uv run check_files.py task-sdk -v ${TASK_SDK_VERSION_RC} -p 
${PATH_TO_SVN}/task-sdk
+breeze release-management check-release-files task-sdk --version 
${TASK_SDK_VERSION_RC}
 ```
 
 ## Licence check
@@ -753,7 +751,7 @@ wget -qO- 
https://dlcdn.apache.org//creadur/apache-rat-0.17/apache-rat-0.17-bin.
 Unpack the release source archive (the `<package + version>-source.tar.gz` 
file) to a folder
 
 ```shell script
-rm -rf /tmp/apache-airflow-src && mkdir -p /tmp/apache-airflow-src && tar -xzf 
${PATH_TO_SVN}/${VERSION_RC}/apache_airflow*-source.tar.gz --strip-components 1 
-C /tmp/apache-airflow-src
+rm -rf /tmp/apache-airflow-src && mkdir -p /tmp/apache-airflow-src && tar -xzf 
${PATH_TO_AIRFLOW_SVN}/${VERSION_RC}/apache_airflow*-source.tar.gz 
--strip-components 1 -C /tmp/apache-airflow-src
 ```
 
 Run the check:
@@ -829,7 +827,7 @@ Once you have the keys, the signatures can be verified 
after switching to the di
 release packages:
 
 ```shell script
-cd ${PATH_TO_SVN}/${VERSION_RC}
+cd ${PATH_TO_AIRFLOW_SVN}/${VERSION_RC}
 ```
 
 And running this:
diff --git a/dev/README_RELEASE_AIRFLOWCTL.md b/dev/README_RELEASE_AIRFLOWCTL.md
index 609339c45a2..c8dc9bdd095 100644
--- a/dev/README_RELEASE_AIRFLOWCTL.md
+++ b/dev/README_RELEASE_AIRFLOWCTL.md
@@ -453,11 +453,11 @@ cd asf-dist/dev/airflow
 svn update .
 ```
 
-Set an environment variable: PATH_TO_SVN to the root of folder where you have 
airflow-ctl
+Set an environment variable: PATH_TO_AIRFLOW_SVN to the root of folder where 
you have airflow-ctl
 
 ```shell script
 cd asf-dist/dev/airflow
-export PATH_TO_SVN=$(pwd -P)
+export PATH_TO_AIRFLOW_SVN=$(pwd -P)
 ```
 
 TODO: implement check in ``check_files.py``
@@ -506,7 +506,7 @@ breeze release-management prepare-tarball --tarball-type 
apache_airflow_ctl --ve
 5) Switch to the folder where you checked out the SVN dev files
 
 ```shell
-cd ${PATH_TO_SVN}/airflow-ctl/${VERSION_RC}
+cd ${PATH_TO_AIRFLOW_SVN}/airflow-ctl/${VERSION_RC}
 ```
 
 6) Compare the packages in SVN to the ones you just built
@@ -524,6 +524,14 @@ You should see output similar to:
 apache_airflow_airflow_ctl-1.0.0.tar.gz:No diff found
 ```
 
+You can use the `breeze release-management check-release-files` command to 
verify that all expected files are
+present in SVN. This command may also help with verifying installation of the 
packages.
+
+```shell script
+breeze release-management check-release-files airflow-ctl --version 
${VERSION_RC}
+```
+
+
 ### Licence check
 
 This can be done with the Apache RAT tool.
@@ -539,7 +547,7 @@ wget -qO- 
https://dlcdn.apache.org//creadur/apache-rat-0.17/apache-rat-0.17-bin.
 Unpack the release source archive (the `<package + version>-source.tar.gz` 
file) to a folder
 
 ```shell script
-rm -rf /tmp/apache/airflow-src && mkdir -p /tmp/apache-airflow-src && tar -xzf 
${PATH_TO_SVN}/${VERSION_RC}/apache_airflow*-source.tar.gz --strip-components 1 
-C /tmp/apache-airflow-src
+rm -rf /tmp/apache/airflow-src && mkdir -p /tmp/apache-airflow-src && tar -xzf 
${PATH_TO_AIRFLOW_SVN}/${VERSION_RC}/apache_airflow*-source.tar.gz 
--strip-components 1 -C /tmp/apache-airflow-src
 ```
 
 Run the check:
diff --git a/dev/README_RELEASE_PROVIDERS.md b/dev/README_RELEASE_PROVIDERS.md
index be032f331d6..495d079b31d 100644
--- a/dev/README_RELEASE_PROVIDERS.md
+++ b/dev/README_RELEASE_PROVIDERS.md
@@ -807,25 +807,29 @@ cd asf-dist/dev/airflow
 svn update .
 ```
 
-Set an environment variable: PATH_TO_SVN to the root of folder where you have 
providers
+Set environment variables: PATH_TO_AIRFLOW_SVN to the root of folder where you 
have providers and RELEASE_DATE to
+the release date you are verifying.
 
 ``` shell
 cd asf-dist/dev/airflow
-export PATH_TO_SVN=$(pwd -P)
+export PATH_TO_AIRFLOW_SVN=$(pwd -P)
 ```
 
-Optionally you can use the 
[`check_files.py`](https://github.com/apache/airflow/blob/main/dev/check_files.py)
-script to verify that all expected files are present in SVN. This script will 
produce a `Dockerfile.pmc` which
+Optionally you can use the `breeze release-management check-release-files` 
command
+to verify that all expected files are present in SVN. This command will 
produce a `Dockerfile.pmc` which
 may help with verifying installation of the packages.
 
-Once you have cloned/updated the SVN repository, copy the pypi URLs shared in 
the email to a file called `packages.txt` in the $AIRFLOW_REPO_ROOT/dev
-directory and cd into it.
+Once you have cloned/updated the SVN repository, copy the PyPi URLs shared
+in the email to a file called `packages.txt` in the $AIRFLOW_REPO_ROOT/dev
+directory.
 
 ```shell script
-uv run check_files.py providers -p ${PATH_TO_SVN}
+cd ${AIRFLOW_REPO_ROOT}/dev
+# Copy packages.txt extracted from the mail sent by the release manager here
+breeze release-management check-release-files providers --release-date 
${RELEASE_DATE}
 ```
 
-After the above script completes you can build `Dockerfile.pmc` to trigger an 
installation of each provider
+After the above command completes you can build `Dockerfile.pmc` to trigger an 
installation of each provider
 package and verify the correct versions are installed:
 
 ```shell script
@@ -874,8 +878,8 @@ breeze release-management prepare-provider-distributions 
--include-removed-provi
 5) Switch to the folder where you checked out the SVN dev files
 
 ```shell
-cd ${PATH_TO_SVN}
-cd providers
+cd ${PATH_TO_AIRFLOW_SVN}
+cd providers/${RELEASE_DATE}
 ```
 
 6) Compare the packages in SVN to the ones you just built
@@ -945,7 +949,7 @@ wget -qO- 
https://dlcdn.apache.org//creadur/apache-rat-0.17/apache-rat-0.17-bin.
 Unpack the release source archive (the `<package + version>-source.tar.gz` 
file) to a folder
 
 ```shell script
-rm -rf /tmp/apache/airflow-src && mkdir -p /tmp/apache-airflow-src && tar -xzf 
${PATH_TO_SVN}/${VERSION}/apache_airflow*-source.tar.gz --strip-components 1 -C 
/tmp/apache-airflow-src
+rm -rf /tmp/apache/airflow-providers-src && mkdir -p 
/tmp/apache-airflow-providers-src && tar -xzf 
${PATH_TO_AIRFLOW_SVN}/providers/${RELEASE_DATE}/apache_airflow_providers-*-source.tar.gz
 --strip-components 1 -C /tmp/apache-airflow-providers-src
 ```
 
 Run the check:
@@ -1020,6 +1024,11 @@ gpg --keyserver keys.gnupg.net --receive-keys 
CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7
 
 Once you have the keys, the signatures can be verified by running this:
 
+```shell
+cd ${PATH_TO_AIRFLOW_SVN}
+cd providers/${RELEASE_DATE}
+```
+
 ```shell script
 for i in *.asc
 do
diff --git a/dev/README_RELEASE_PYTHON_CLIENT.md 
b/dev/README_RELEASE_PYTHON_CLIENT.md
index 98475f110a5..f9cc93b23fd 100644
--- a/dev/README_RELEASE_PYTHON_CLIENT.md
+++ b/dev/README_RELEASE_PYTHON_CLIENT.md
@@ -408,10 +408,10 @@ cd ..
 [ -d asf-dist ] || svn checkout --depth=immediates 
https://dist.apache.org/repos/dist asf-dist
 svn update --set-depth=infinity asf-dist/dev/airflow/clients/python
 
-export PATH_TO_SVN="${PWD}/asf-dist/dev/airflow/clients/python/${VERSION_RC}"
+export PATH_TO_AIRFLOW_SVN="${PWD}/asf-dist/dev/airflow/"
 
 # Then compare the packages
-cd ${PATH_TO_SVN}
+cd ${PATH_TO_AIRFLOW_SVN}/clients/python/${VERSION_RC}
 for i in ${AIRFLOW_REPO_ROOT}/dist/*
 do
   echo "Checking if $(basename $i) is the same as $i"
@@ -426,6 +426,14 @@ In case the files are different, you should see:
 Binary files apache_airflow-client-2.9.0.tar.gz and 
.../apache_airflow-2.9.0.tar.gz differ
 ```
 
+You can use the `breeze release-management check-release-files` command to 
verify that all expected files are
+present in SVN. This command may also help with verifying installation of the 
packages.
+
+```shell script
+breeze release-management check-release-files python-client --version 
${VERSION_RC}
+```
+
+
 ### Licence check
 
 This can be done with the Apache RAT tool.
@@ -441,7 +449,7 @@ wget -qO- 
https://dlcdn.apache.org//creadur/apache-rat-0.17/apache-rat-0.17-bin.
 Unpack the release source archive (the `<package + version>-source.tar.gz` 
file) to a folder
 
 ```shell script
-rm -rf /tmp/apache/airflow-python-client-src && mkdir -p 
/tmp/apache-airflow-python-client-src && tar -xzf 
${PATH_TO_SVN}/apache_airflow_python_client-*-source.tar.gz --strip-components 
1 -C /tmp/apache-airflow-python-client-src
+rm -rf /tmp/apache/airflow-python-client-src && mkdir -p 
/tmp/apache-airflow-python-client-src && tar -xzf 
${PATH_TO_AIRFLOW_SVN}/clients/python/${VERSION_RC}/apache_airflow_python_client-*-source.tar.gz
 --strip-components 1 -C /tmp/apache-airflow-python-client-src
 ```
 
 Run the check:
@@ -515,7 +523,7 @@ gpg --keyserver keys.gnupg.net --receive-keys 
CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7
 Once you have the keys, the signatures can be verified by running this:
 
 ```shell script
-cd ${PATH_TO_SVN}
+cd ${PATH_TO_AIRFLOW_SVN}/clients/python/${VERSION_RC}
 for i in *.asc
 do
    echo -e "Checking $i\n"; gpg --verify $i
@@ -555,7 +563,7 @@ Primary key fingerprint: 1271 7556 040E EF2E EAF1  B9C2 
75FC CD0A 25FA 0E4B
 Run this:
 
 ```shell script
-cd ${PATH_TO_SVN}
+cd ${PATH_TO_AIRFLOW_SVN}/clients/python/${VERSION_RC}
 for i in *.sha512
 do
     echo "Checking $i"; shasum -a 512 `basename $i .sha512 ` | diff - $i
diff --git a/dev/breeze/doc/09_release_management_tasks.rst 
b/dev/breeze/doc/09_release_management_tasks.rst
index 4169f8e2a7e..287acbd610d 100644
--- a/dev/breeze/doc/09_release_management_tasks.rst
+++ b/dev/breeze/doc/09_release_management_tasks.rst
@@ -904,6 +904,69 @@ These are all available flags of ``workflow-run 
publish-docs`` command:
   :width: 100%
   :alt: Breeze workflow-run publish-docs
 
+Checking release files
+""""""""""""""""""""""
+
+To verify that all expected packages and artifacts are present in the Apache 
Airflow SVN release directory,
+you can use the ``breeze release-management check-release-files`` command. 
This is useful for release
+managers and PMC members to validate that all required files (including .asc 
signatures and .sha512
+checksums) are present when voting for release.
+
+The command supports checking files for different release types:
+
+**Checking Airflow release files:**
+
+.. code-block:: bash
+
+     breeze release-management check-release-files airflow 
--path-to-airflow-svn ~/code/asf-dist/dev/airflow --version 2.8.1rc2
+
+**Checking Task SDK release files:**
+
+.. code-block:: bash
+
+     breeze release-management check-release-files task-sdk 
--path-to-airflow-svn ~/code/asf-dist/dev/airflow --version 1.0.0rc1
+
+**Checking Airflow CTL release files:**
+
+.. code-block:: bash
+
+     breeze release-management check-release-files airflow-ctl 
--path-to-airflow-svn ~/code/asf-dist/dev/airflow --version 0.1.0rc1
+
+**Checking Python client release files:**
+
+.. code-block:: bash
+
+     breeze release-management check-release-files python-client 
--path-to-airflow-svn ~/code/asf-dist/dev/airflow --version 2.10.0rc1
+
+**Checking Provider release files:**
+
+.. code-block:: bash
+
+     breeze release-management check-release-files providers 
--path-to-airflow-svn ~/code/asf-dist/dev/airflow --release-date 2024-01-01
+
+For providers, you can specify a custom packages file (default is 
``packages.txt``):
+
+.. code-block:: bash
+
+     breeze release-management check-release-files providers 
--path-to-airflow-svn ~/code/asf-dist/dev/airflow --release-date 2024-01-01 
--packages-file my-packages.txt
+
+The command checks for the presence of:
+
+* Source distributions (``.tar.gz``)
+* Wheel distributions (``.whl``)
+* ASF signatures (``.asc``)
+* SHA512 checksums (``.sha512``)
+
+If any expected files are missing, the command will report them and exit with 
a non-zero status code.
+If all files are present, it will also provide a Dockerfile snippet you can 
use to test the installation.
+
+These are all available flags of ``release-management check-release-files`` 
command:
+
+.. image:: ./images/output_release-management_check-release-files.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_release-management_check-release-files.svg
+  :width: 100%
+  :alt: Breeze check-release-files
+
 Constraints version check
 """""""""""""""""""""""""
 
diff --git a/dev/breeze/doc/images/output_release-management.svg 
b/dev/breeze/doc/images/output_release-management.svg
index abfe13210a4..a58d6ee577c 100644
--- a/dev/breeze/doc/images/output_release-management.svg
+++ b/dev/breeze/doc/images/output_release-management.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1270.0" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1294.3999999999999" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -42,7 +42,7 @@
 
     <defs>
     <clipPath id="breeze-release-management-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="1219.0" />
+      <rect x="0" y="0" width="1463.0" height="1243.3999999999999" />
     </clipPath>
     <clipPath id="breeze-release-management-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -191,9 +191,12 @@
 <clipPath id="breeze-release-management-line-48">
     <rect x="0" y="1172.7" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-release-management-line-49">
+    <rect x="0" y="1197.1" 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="1268" rx="8"/><text 
class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" 
x="740" y="27">Command:&#160;release-management</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1292.4" rx="8"/><text 
class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" 
x="740" y="27">Command:&#160;release-management</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -248,11 +251,12 @@
 </text><text class="breeze-release-management-r5" x="0" y="1044.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-42)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1044.8" textLength="292.8" 
clip-path="url(#breeze-release-management-line-42)">generate-constraints&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1044.8" textLength="1098" 
clip-path="url(#breeze-release-management-line-42)">Generates&#160;pinned&#160;c
 [...]
 </text><text class="breeze-release-management-r5" x="0" y="1069.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-43)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1069.2" textLength="292.8" 
clip-path="url(#breeze-release-management-line-43)">update-constraints&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1069.2" textLength="1098" 
clip-path="url(#breeze-release-management-line-43)">Update&#160;releas [...]
 </text><text class="breeze-release-management-r5" x="0" y="1093.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-44)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1093.6" textLength="292.8" 
clip-path="url(#breeze-release-management-line-44)">publish-docs-to-s3&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1093.6" textLength="1098" 
clip-path="url(#breeze-release-management-line-44)">Publishes&#160;doc [...]
-</text><text class="breeze-release-management-r5" x="0" y="1118" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-45)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1118" textLength="12.2" 
clip-path="url(#breeze-release-management-line-45)">
-</text><text class="breeze-release-management-r5" x="0" y="1142.4" 
textLength="24.4" 
clip-path="url(#breeze-release-management-line-46)">╭─</text><text 
class="breeze-release-management-r5" x="24.4" y="1142.4" textLength="122" 
clip-path="url(#breeze-release-management-line-46)">&#160;Commands&#160;</text><text
 class="breeze-release-management-r5" x="146.4" y="1142.4" textLength="1293.2" 
clip-path="url(#breeze-release-management-line-46)">───────────────────────────────────────────────────
 [...]
-</text><text class="breeze-release-management-r5" x="0" y="1166.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-47)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1166.8" textLength="305" 
clip-path="url(#breeze-release-management-line-47)">constraints-version-check</text><text
 class="breeze-release-management-r1" x="353.8" y="1166.8" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-47)">Check&#160;constraints&#160;against&#160;releas
 [...]
-</text><text class="breeze-release-management-r5" x="0" y="1191.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-48)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1191.2" textLength="305" 
clip-path="url(#breeze-release-management-line-48)">merge-prod-images&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="353.8" y="1191.2" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-48)">Merge&# [...]
-</text><text class="breeze-release-management-r5" x="0" y="1215.6" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-49)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-release-management-line-49)">
+</text><text class="breeze-release-management-r5" x="0" y="1118" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-45)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1118" textLength="292.8" 
clip-path="url(#breeze-release-management-line-45)">check-release-files&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1118" textLength="1098" 
clip-path="url(#breeze-release-management-line-45)">Verify&#160;that&#160;all&#16
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="1142.4" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-46)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1142.4" textLength="12.2" 
clip-path="url(#breeze-release-management-line-46)">
+</text><text class="breeze-release-management-r5" x="0" y="1166.8" 
textLength="24.4" 
clip-path="url(#breeze-release-management-line-47)">╭─</text><text 
class="breeze-release-management-r5" x="24.4" y="1166.8" textLength="122" 
clip-path="url(#breeze-release-management-line-47)">&#160;Commands&#160;</text><text
 class="breeze-release-management-r5" x="146.4" y="1166.8" textLength="1293.2" 
clip-path="url(#breeze-release-management-line-47)">───────────────────────────────────────────────────
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="1191.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-48)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1191.2" textLength="305" 
clip-path="url(#breeze-release-management-line-48)">constraints-version-check</text><text
 class="breeze-release-management-r1" x="353.8" y="1191.2" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-48)">Check&#160;constraints&#160;against&#160;releas
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="1215.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-49)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1215.6" textLength="305" 
clip-path="url(#breeze-release-management-line-49)">merge-prod-images&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="353.8" y="1215.6" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-49)">Merge&# [...]
+</text><text class="breeze-release-management-r5" x="0" y="1240" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1240" textLength="12.2" 
clip-path="url(#breeze-release-management-line-50)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_release-management.txt 
b/dev/breeze/doc/images/output_release-management.txt
index ad9ca5fe69a..04d1453a712 100644
--- a/dev/breeze/doc/images/output_release-management.txt
+++ b/dev/breeze/doc/images/output_release-management.txt
@@ -1 +1 @@
-509d258b7e4d9d0bfea9f8628747d676
+eac5e457db3b3fa57c5180ad88ee7c05
diff --git 
a/dev/breeze/doc/images/output_release-management_check-release-files.svg 
b/dev/breeze/doc/images/output_release-management_check-release-files.svg
new file mode 100644
index 00000000000..3420812ec6c
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_check-release-files.svg
@@ -0,0 +1,154 @@
+<svg class="rich-terminal" viewBox="0 0 1482 611.1999999999999" 
xmlns="http://www.w3.org/2000/svg";>
+    <!-- Generated with Rich https://www.textualize.io -->
+    <style>
+
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Regular"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff";)
 format("woff");
+        font-style: normal;
+        font-weight: 400;
+    }
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Bold"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff";)
 format("woff");
+        font-style: bold;
+        font-weight: 700;
+    }
+
+    .breeze-release-management-check-release-files-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-release-management-check-release-files-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-release-management-check-release-files-r1 { fill: #c5c8c6 }
+.breeze-release-management-check-release-files-r2 { fill: #d0b344 }
+.breeze-release-management-check-release-files-r3 { fill: #c5c8c6;font-weight: 
bold }
+.breeze-release-management-check-release-files-r4 { fill: #68a0b3;font-weight: 
bold }
+.breeze-release-management-check-release-files-r5 { fill: #868887 }
+.breeze-release-management-check-release-files-r6 { fill: #cc555a }
+.breeze-release-management-check-release-files-r7 { fill: #98a84b;font-weight: 
bold }
+.breeze-release-management-check-release-files-r8 { fill: #8d7b39 }
+.breeze-release-management-check-release-files-r9 { fill: #8a4346 }
+    </style>
+
+    <defs>
+    <clipPath id="breeze-release-management-check-release-files-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="560.1999999999999" />
+    </clipPath>
+    <clipPath id="breeze-release-management-check-release-files-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-9">
+    <rect x="0" y="221.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-10">
+    <rect x="0" y="245.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-11">
+    <rect x="0" y="269.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-12">
+    <rect x="0" y="294.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-13">
+    <rect x="0" y="318.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-14">
+    <rect x="0" y="343.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-15">
+    <rect x="0" y="367.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-16">
+    <rect x="0" y="391.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-17">
+    <rect x="0" y="416.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-18">
+    <rect x="0" y="440.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-19">
+    <rect x="0" y="465.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-20">
+    <rect x="0" y="489.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-check-release-files-line-21">
+    <rect x="0" y="513.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="609.2" rx="8"/><text 
class="breeze-release-management-check-release-files-title" fill="#c5c8c6" 
text-anchor="middle" x="740" 
y="27">Command:&#160;release-management&#160;check-release-files</text>
+            <g transform="translate(26,22)">
+            <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+            <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+            <circle cx="44" cy="0" r="7" fill="#28c840"/>
+            </g>
+        
+    <g transform="translate(9, 41)" 
clip-path="url(#breeze-release-management-check-release-files-clip-terminal)">
+    
+    <g class="breeze-release-management-check-release-files-matrix">
+    <text class="breeze-release-management-check-release-files-r1" x="1464" 
y="20" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-0)">
+</text><text class="breeze-release-management-check-release-files-r2" x="12.2" 
y="44.4" textLength="878.4" 
clip-path="url(#breeze-release-management-check-release-files-line-1)">Usage:&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-release-management-check-release-files-r1" x="12.2" 
y="68.8" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-2)">[</text><text
 class="breeze-release-management-check-release-files-r4" x="24.4" y="68.8" 
textLength="85.4" 
clip-path="url(#breeze-release-management-check-release-files-line-2)">OPTIONS</text><text
 class="breeze-release-management-check-release-files-r1" x="109.8" y="68.8" 
textLength="36.6" clip-path="url(#breeze- [...]
+</text><text class="breeze-release-management-check-release-files-r1" x="1464" 
y="93.2" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-3)">
+</text><text class="breeze-release-management-check-release-files-r1" x="12.2" 
y="117.6" textLength="829.6" 
clip-path="url(#breeze-release-management-check-release-files-line-4)">Verify&#160;that&#160;all&#160;expected&#160;packages&#160;are&#160;present&#160;in&#160;Apache&#160;Airflow&#160;svn.</text><text
 class="breeze-release-management-check-release-files-r1" x="1464" y="117.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-4)">
+</text><text class="breeze-release-management-check-release-files-r1" x="1464" 
y="142" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-5)">
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="166.4" textLength="24.4" 
clip-path="url(#breeze-release-management-check-release-files-line-6)">╭─</text><text
 class="breeze-release-management-check-release-files-r5" x="24.4" y="166.4" 
textLength="329.4" 
clip-path="url(#breeze-release-management-check-release-files-line-6)">&#160;Check&#160;release&#160;files&#160;flags&#160;</text><text
 class="breeze-release-management-check-release-files-r5" x="353.8" y="1 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="190.8" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-7)">│</text><text
 class="breeze-release-management-check-release-files-r6" x="24.4" y="190.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-7)">*</text><text
 class="breeze-release-management-check-release-files-r4" x="61" y="190.8" 
textLength="256.2" clip-path="url(#breeze-release- [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="215.2" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-8)">│</text><text
 class="breeze-release-management-check-release-files-r1" x="390.4" y="215.2" 
textLength="1049.2" 
clip-path="url(#breeze-release-management-check-release-files-line-8)">~/code/asf-dist/dev/airflow)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="239.6" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-9)">│</text><text
 class="breeze-release-management-check-release-files-r8" x="390.4" y="239.6" 
textLength="1049.2" 
clip-path="url(#breeze-release-management-check-release-files-line-9)">(DIRECTORY)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="264" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-10)">│</text><text
 class="breeze-release-management-check-release-files-r9" x="390.4" y="264" 
textLength="1049.2" 
clip-path="url(#breeze-release-management-check-release-files-line-10)">[required]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="288.4" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-11)">│</text><text
 class="breeze-release-management-check-release-files-r4" x="61" y="288.4" 
textLength="109.8" 
clip-path="url(#breeze-release-management-check-release-files-line-11)">--version</text><text
 class="breeze-release-management-check-release-files-r1" x="390.4" y="288.4" 
textLength="1049.2" clip-path="url(#br [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="312.8" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-12)">│</text><text
 class="breeze-release-management-check-release-files-r1" x="390.4" y="312.8" 
textLength="1049.2" 
clip-path="url(#breeze-release-management-check-release-files-line-12)">task-sdk,&#160;airflow-ctl,&#160;and&#160;python-client.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="337.2" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-13)">│</text><text
 class="breeze-release-management-check-release-files-r8" x="390.4" y="337.2" 
textLength="1049.2" 
clip-path="url(#breeze-release-management-check-release-files-line-13)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="361.6" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-14)">│</text><text
 class="breeze-release-management-check-release-files-r4" x="61" y="361.6" 
textLength="170.8" 
clip-path="url(#breeze-release-management-check-release-files-line-14)">--release-date</text><text
 class="breeze-release-management-check-release-files-r1" x="390.4" y="361.6" 
textLength="793" clip-path="url(# [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="386" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-15)">│</text><text
 class="breeze-release-management-check-release-files-r4" x="61" y="386" 
textLength="183" 
clip-path="url(#breeze-release-management-check-release-files-line-15)">--packages-file</text><text
 class="breeze-release-management-check-release-files-r1" x="390.4" y="386" 
textLength="768.6" clip-path="url(#breez [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="410.4" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-16)">│</text><text
 class="breeze-release-management-check-release-files-r5" x="390.4" y="410.4" 
textLength="768.6" 
clip-path="url(#breeze-release-management-check-release-files-line-16)">[default:&#160;packages.txt]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="434.8" textLength="1464" 
clip-path="url(#breeze-release-management-check-release-files-line-17)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-check-release-files-r1" x="1464" y="434.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-17)">
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="459.2" textLength="24.4" 
clip-path="url(#breeze-release-management-check-release-files-line-18)">╭─</text><text
 class="breeze-release-management-check-release-files-r5" x="24.4" y="459.2" 
textLength="195.2" 
clip-path="url(#breeze-release-management-check-release-files-line-18)">&#160;Common&#160;options&#160;</text><text
 class="breeze-release-management-check-release-files-r5" x="219.6" y="459.2" 
textLength="1 [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="483.6" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-19)">│</text><text
 class="breeze-release-management-check-release-files-r4" x="24.4" y="483.6" 
textLength="109.8" 
clip-path="url(#breeze-release-management-check-release-files-line-19)">--verbose</text><text
 class="breeze-release-management-check-release-files-r7" x="158.6" y="483.6" 
textLength="24.4" clip-path="url(#br [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="508" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-20)">│</text><text
 class="breeze-release-management-check-release-files-r4" x="24.4" y="508" 
textLength="109.8" 
clip-path="url(#breeze-release-management-check-release-files-line-20)">--dry-run</text><text
 class="breeze-release-management-check-release-files-r7" x="158.6" y="508" 
textLength="24.4" clip-path="url(#breeze-r [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="532.4" textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-21)">│</text><text
 class="breeze-release-management-check-release-files-r4" x="24.4" y="532.4" 
textLength="73.2" 
clip-path="url(#breeze-release-management-check-release-files-line-21)">--help</text><text
 class="breeze-release-management-check-release-files-r7" x="158.6" y="532.4" 
textLength="24.4" clip-path="url(#breeze [...]
+</text><text class="breeze-release-management-check-release-files-r5" x="0" 
y="556.8" textLength="1464" 
clip-path="url(#breeze-release-management-check-release-files-line-22)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-check-release-files-r1" x="1464" y="556.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-check-release-files-line-22)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git 
a/dev/breeze/doc/images/output_release-management_check-release-files.txt 
b/dev/breeze/doc/images/output_release-management_check-release-files.txt
new file mode 100644
index 00000000000..9fc21be66ca
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_check-release-files.txt
@@ -0,0 +1 @@
+11b529b25ad8eac330722da830792bfb
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg 
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
index 27339818a38..63d9e5d38c9 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.svg
@@ -201,10 +201,10 @@
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="312.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="312.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:deploy-airflow&#160;|&#160;k8s:k9s&#160;|&#160;k8s:logs&#160;|&#160;k8s:run-complete-tests&#160;|&#160;k8s:setup-env&#160;|&#160;k8s:shell&#160;|&#160;&#16
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="337.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="337.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">k8s:status&#160;|&#160;k8s:tests&#160;|&#160;k8s:upload-k8s-image&#160;|&#160;prod-image&#160;|&#160;prod-image:build&#160;|&#160;prod-image:load&#160;|&#160;&
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="361.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="361.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">prod-image:pull&#160;|&#160;prod-image:save&#160;|&#160;prod-image:verify&#160;|&#160;release-management&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="386" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="386" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">release-management:add-back-references&#160;|&#160;release-management:clean-old-provider-artifacts&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="410.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="410.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">release-management:constraints-version-check&#160;|&#160;release-management:create-minor-branch&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="434.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="434.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">release-management:generate-constraints&#160;|&#160;release-management:generate-issue-content-core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="459.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="459.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">release-management:generate-issue-content-helm-chart&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="386" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="386" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">release-management:add-back-references&#160;|&#160;release-management:check-release-files&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="410.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="410.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">release-management:clean-old-provider-artifacts&#160;|&#160;release-management:constraints-version-check&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="434.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="434.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">release-management:create-minor-branch&#160;|&#160;release-management:generate-constraints&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="459.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="459.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">release-management:generate-issue-content-core&#160;|&#160;release-management:generate-issue-content-helm-chart&#160;|</text><text
 class="breeze-setup-check-al [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="483.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="483.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">release-management:generate-issue-content-providers&#160;|&#160;release-management:generate-providers-metadata&#160;|&#160;</text><text
 class="breeze-setup-che [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="508" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="508" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">release-management:install-provider-distributions&#160;|&#160;release-management:merge-prod-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="532.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="532.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">release-management:prepare-airflow-ctl-distributions&#160;|&#160;release-management:prepare-airflow-distributions</text><text
 class="breeze-setup-check-all-par [...]
diff --git a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt 
b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
index 6221820cf8a..fc679b8ef8d 100644
--- a/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
+++ b/dev/breeze/doc/images/output_setup_check-all-params-in-groups.txt
@@ -1 +1 @@
-255b0c6c08d2c819aaa7bb5c29c88315
+9fe82522ca4d19aa02f9de986fa30bb1
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg 
b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
index 4e6caeda075..e60f2a655b1 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1221.1999999999998" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1245.6" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-setup-regenerate-command-images-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="1170.1999999999998" />
+      <rect x="0" y="0" width="1463.0" height="1194.6" />
     </clipPath>
     <clipPath id="breeze-setup-regenerate-command-images-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -186,9 +186,12 @@
 <clipPath id="breeze-setup-regenerate-command-images-line-46">
     <rect x="0" y="1123.9" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-setup-regenerate-command-images-line-47">
+    <rect x="0" y="1148.3" 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="1219.2" rx="8"/><text 
class="breeze-setup-regenerate-command-images-title" fill="#c5c8c6" 
text-anchor="middle" x="740" 
y="27">Command:&#160;setup&#160;regenerate-command-images</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1243.6" rx="8"/><text 
class="breeze-setup-regenerate-command-images-title" fill="#c5c8c6" 
text-anchor="middle" x="740" 
y="27">Command:&#160;setup&#160;regenerate-command-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"/>
@@ -214,38 +217,39 @@
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="337.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-13)">k8s:deploy-airflow&#160;|&#160;k8s:k9s&#160;|&#160;k8s:logs&#160;|&#160;k8s:run-complete-tests&#160;|&#160;k8s:setup-env&#160;|&#160;k8s:shell&#160;|&#160;&#160;&#
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="361.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="361.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-14)">k8s:status&#160;|&#160;k8s:tests&#160;|&#160;k8s:upload-k8s-image&#160;|&#160;prod-image&#160;|&#160;prod-image:build&#160;|&#160;prod-image:load&#160;|&#160;&#160
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="386" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="386" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-15)">prod-image:pull&#160;|&#160;prod-image:save&#160;|&#160;prod-image:verify&#160;|&#160;release-management&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="410.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">release-management:add-back-references&#160;|&#160;release-management:clean-old-provider-artifacts&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="434.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">release-management:constraints-version-check&#160;|&#160;release-management:create-minor-branch&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="459.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:generate-constraints&#160;|&#160;release-management:generate-issue-content-core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="483.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:generate-issue-content-helm-chart&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="508" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:generate-issue-content-providers&#160;|&#160;release-management:generate-providers-metadata</text><text
 class="breeze-setup-regenerate-command-image [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="532.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">|&#160;release-management:install-provider-distributions&#160;|&#160;release-management:merge-prod-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</t
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="556.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:prepare-airflow-ctl-distributions&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="581.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">release-management:prepare-airflow-distributions&#160;|&#160;release-management:prepare-helm-chart-package&#160;|&#160;&#160;</text><text
 class="breeze-setup-regen [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="605.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">release-management:prepare-helm-chart-tarball&#160;|&#160;release-management:prepare-provider-distributions&#160;|&#160;</text><text
 class="breeze-setup-regenerate [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="630" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">release-management:prepare-provider-documentation&#160;|&#160;release-management:prepare-python-client&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="br [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="654.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="654.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">release-management:prepare-tarball&#160;|&#160;release-management:prepare-task-sdk-distributions&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="678.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">release-management:publish-docs&#160;|&#160;release-management:publish-docs-to-s3&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="703.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="727.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">release-management:start-release&#160;|&#160;release-management:tag-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="752" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">release-management:update-constraints&#160;|&#160;release-management:verify-provider-distributions&#160;|&#160;run&#160;|&#160;&#160;&#160;&#160;</text><text
 class="br [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;sbom:export-dependency-information&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="800.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;&#160;</text><text
 class [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="825.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="849.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="874" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="874" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">testing&#160;|&#160;testing:airflow-ctl-integration-tests&#160;|&#160;testing:airflow-ctl-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="898.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">testing:core-integration-tests&#160;|&#160;testing:core-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="922.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="922.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">testing:helm-tests&#160;|&#160;testing:providers-integration-tests&#160;|&#160;testing:providers-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="947.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="947.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">testing:python-api-client-tests&#160;|&#160;testing:system-tests&#160;|&#160;testing:task-sdk-integration-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</t
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="971.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">testing:task-sdk-tests&#160;|&#160;workflow-run&#160;|&#160;workflow-run:publish-docs)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="996" 
textLength="146.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">--check-only</text><text
 class="breeze-setup-regenerate-command-images-r1" x="219.6" y="996" 
textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-l [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1020.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text 
class="breeze-setup-regenerate-command-images-r1" x="219.6" y="1020.4" 
textLength="170.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">together&#160;with&#160;</text><text
 class="breeze-setup-regenerate-command-images-r4" x="390.4" y="1020.4" 
textLength="109.8" clip-path="url(#breeze-setup-rege [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1044.8" textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="1044.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1069.2" textLength="24.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">╭─</text><text 
class="breeze-setup-regenerate-command-images-r5" x="24.4" y="1069.2" 
textLength="195.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">&#160;Common&#160;options&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x="219.6" y="1069.2" 
textLength="1220" clip-path="url(#breeze-setu [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1093.6" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1093.6" 
textLength="109.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">--verbose</text><text
 class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1093.6" 
textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-im [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1118" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1118" 
textLength="109.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">--dry-run</text><text
 class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1118" 
textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-l [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1142.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1142.4" 
textLength="73.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-46)">--help</text><text
 class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1142.4" 
textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1166.8" textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-47)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="1166.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-47)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="410.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-16)">release-management:add-back-references&#160;|&#160;release-management:check-release-files&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="434.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-17)">release-management:clean-old-provider-artifacts&#160;|&#160;release-management:constraints-version-check&#160;|&#160;&#160;&#160;&#160;</text><text
 class="breeze-s [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="459.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:create-minor-branch&#160;|&#160;release-management:generate-constraints&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="483.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:generate-issue-content-core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="508" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:generate-issue-content-helm-chart&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="532.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:generate-issue-content-providers&#160;|&#160;release-management:generate-providers-metadata</text><text
 class="breeze-setup-regenerate-command-i [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="556.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">|&#160;release-management:install-provider-distributions&#160;|&#160;release-management:merge-prod-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</t
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="581.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">release-management:prepare-airflow-ctl-distributions&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="605.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">release-management:prepare-airflow-distributions&#160;|&#160;release-management:prepare-helm-chart-package&#160;|&#160;&#160;</text><text
 class="breeze-setup-regen [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="630" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">release-management:prepare-helm-chart-tarball&#160;|&#160;release-management:prepare-provider-distributions&#160;|&#160;</text><text
 class="breeze-setup-regenerate-com [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="654.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="654.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">release-management:prepare-provider-documentation&#160;|&#160;release-management:prepare-python-client&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="678.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">release-management:prepare-tarball&#160;|&#160;release-management:prepare-task-sdk-distributions&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="703.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:publish-docs&#160;|&#160;release-management:publish-docs-to-s3&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="727.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="752" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">release-management:start-release&#160;|&#160;release-management:tag-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:update-constraints&#160;|&#160;release-management:verify-provider-distributions&#160;|&#160;run&#160;|&#160;&#160;&#160;&#160;</text><text
 class [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="800.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;sbom:export-dependency-information&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="825.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;&#160;</text><text
 class [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="849.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="874" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="874" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="898.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">testing&#160;|&#160;testing:airflow-ctl-integration-tests&#160;|&#160;testing:airflow-ctl-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="922.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="922.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">testing:core-integration-tests&#160;|&#160;testing:core-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="947.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="947.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">testing:helm-tests&#160;|&#160;testing:providers-integration-tests&#160;|&#160;testing:providers-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="971.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">testing:python-api-client-tests&#160;|&#160;testing:system-tests&#160;|&#160;testing:task-sdk-integration-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</t
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="996" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">testing:task-sdk-tests&#160;|&#160;workflow-run&#160;|&#160;workflow-run:publish-docs)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1020.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1020.4" 
textLength="146.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">--check-only</text><text
 class="breeze-setup-regenerate-command-images-r1" x="219.6" y="1020.4" 
textLength="1220" clip-path="url(#breeze-setup-regenerate-command [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1044.8" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text 
class="breeze-setup-regenerate-command-images-r1" x="219.6" y="1044.8" 
textLength="170.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">together&#160;with&#160;</text><text
 class="breeze-setup-regenerate-command-images-r4" x="390.4" y="1044.8" 
textLength="109.8" clip-path="url(#breeze-setup-rege [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1069.2" textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="1069.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1093.6" textLength="24.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">╭─</text><text 
class="breeze-setup-regenerate-command-images-r5" x="24.4" y="1093.6" 
textLength="195.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">&#160;Common&#160;options&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x="219.6" y="1093.6" 
textLength="1220" clip-path="url(#breeze-setu [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1118" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1118" 
textLength="109.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">--verbose</text><text
 class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1118" 
textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-l [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1142.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1142.4" 
textLength="109.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-46)">--dry-run</text><text
 class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1142.4" 
textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-im [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1166.8" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-47)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1166.8" 
textLength="73.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-47)">--help</text><text
 class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1166.8" 
textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1191.2" textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-48)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="1191.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-48)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt 
b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
index 93c47a5ff70..a76eaaeae52 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.txt
@@ -1 +1 @@
-c014107e4161ae3eedceec12d3297658
+a08a800fc1e5beda50eddf14b8a4d851
diff --git 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
index deba972845a..c27775f138b 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -4087,3 +4087,138 @@ def version_check(
         github_token=github_token,
         github_repository=github_repository,
     )
+
+
+@release_management.command(
+    name="check-release-files",
+    help="Verify that all expected packages are present in Apache Airflow 
svn.",
+)
[email protected](
+    "--path-to-airflow-svn",
+    "-p",
+    required=True,
+    type=click.Path(exists=True, file_okay=False, dir_okay=True, 
resolve_path=True, path_type=Path),
+    envvar="PATH_TO_AIRFLOW_SVN",
+    help="Path to directory where release files are checked out from SVN 
(e.g., ~/code/asf-dist/dev/airflow)",
+)
[email protected](
+    "--version",
+    type=str,
+    help="Version of package to verify (e.g., 2.8.1rc2, 1.0.0rc1). "
+    "Required for airflow, task-sdk, airflow-ctl, and python-client.",
+)
[email protected](
+    "--release-date",
+    type=str,
+    help="Date of the release in YYYY-MM-DD format. Required for providers.",
+)
[email protected](
+    "--packages-file",
+    type=click.Path(exists=True, file_okay=True, dir_okay=False, 
resolve_path=True, path_type=Path),
+    default="packages.txt",
+    show_default=True,
+    help="File containing list of packages to check (for providers only).",
+)
[email protected](
+    "release_type",
+    type=BetterChoice(["airflow", "task-sdk", "airflow-ctl", "python-client", 
"providers"]),
+    required=True,
+)
+@option_verbose
+@option_dry_run
+def check_release_files(
+    path: Path,
+    version: str | None,
+    release_date: str | None,
+    packages_file: Path,
+    release_type: str,
+):
+    """
+    Verify that all expected packages are present in Apache Airflow svn.
+
+    In case of providers, it will generate Dockerfile.pmc that you can use
+    to verify that all packages are installable.
+
+    In case of providers, you should update `packages.txt` file with list of 
packages
+    that you expect to find (copy-paste the list from VOTE thread).
+
+    """
+    from airflow_breeze.utils.check_release_files import (
+        AIRFLOW_CTL_DOCKER,
+        AIRFLOW_DOCKER,
+        PROVIDERS_DOCKER,
+        PYTHON_CLIENT_DOCKER,
+        TASK_SDK_DOCKER,
+        check_airflow_ctl_release,
+        check_airflow_release,
+        check_providers,
+        check_python_client_release,
+        check_task_sdk_release,
+        create_docker,
+        get_packages,
+        warn_of_missing_files,
+    )
+
+    console = get_console()
+
+    # Validate required parameters based on release type
+    if release_type == "providers":
+        if not release_date:
+            console.print("[error]--release-date is required for providers[/]")
+            sys.exit(1)
+        directory = path / "providers" / release_date
+    else:
+        if not version:
+            console.print(f"[error]--version is required for 
{release_type}[/]")
+            sys.exit(1)
+
+        # Determine directory based on release type
+        if release_type == "airflow":
+            directory = path / version
+        elif release_type == "task-sdk":
+            directory = path / version
+        elif release_type == "airflow-ctl":
+            directory = path / "airflow-ctl" / version
+        elif release_type == "python-client":
+            directory = path / "clients" / "python" / version
+        else:
+            console.print(f"[error]Unknown release type: {release_type}[/]")
+            sys.exit(1)
+
+    if not directory.exists():
+        console.print(f"[error]Directory does not exist: {directory}[/]")
+        sys.exit(1)
+
+    files = os.listdir(directory)
+    dockerfile_path = AIRFLOW_ROOT_PATH / "Dockerfile.pmc"
+
+    # Check files based on release type
+    missing_files = []
+
+    if release_type == "providers":
+        packages = get_packages(packages_file)
+        missing_files = check_providers(files, release_date, packages)
+        pips = [f"{name}=={ver}" for name, ver in packages]
+        create_docker(
+            PROVIDERS_DOCKER.format("RUN uv pip install --pre --system " + " 
".join(f"'{p}'" for p in pips)),
+            dockerfile_path,
+        )
+    elif release_type == "airflow":
+        missing_files = check_airflow_release(files, version)
+        create_docker(AIRFLOW_DOCKER.format(version), dockerfile_path)
+    elif release_type == "task-sdk":
+        missing_files = check_task_sdk_release(files, version)
+        create_docker(TASK_SDK_DOCKER.format(version), dockerfile_path)
+    elif release_type == "airflow-ctl":
+        missing_files = check_airflow_ctl_release(files, version)
+        create_docker(AIRFLOW_CTL_DOCKER.format(version), dockerfile_path)
+    elif release_type == "python-client":
+        missing_files = check_python_client_release(files, version)
+        create_docker(PYTHON_CLIENT_DOCKER.format(version), dockerfile_path)
+
+    if missing_files:
+        warn_of_missing_files(missing_files, str(directory))
+        sys.exit(1)
+    else:
+        console.print("\n[success]All expected files are present![/]")
+        sys.exit(0)
diff --git 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
index 14f6cffb61e..44810eeb64c 100644
--- 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
+++ 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
@@ -75,6 +75,7 @@ RELEASE_OTHER_COMMANDS: dict[str, str | list[str]] = {
         "generate-constraints",
         "update-constraints",
         "publish-docs-to-s3",
+        "check-release-files",
     ],
 }
 
@@ -503,4 +504,15 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str, 
str | list[str]]]] = {
             ],
         },
     ],
+    "breeze release-management check-release-files": [
+        {
+            "name": "Check release files flags",
+            "options": [
+                "--path-to-airflow-svn",
+                "--version",
+                "--release-date",
+                "--packages-file",
+            ],
+        }
+    ],
 }
diff --git a/dev/breeze/src/airflow_breeze/utils/check_release_files.py 
b/dev/breeze/src/airflow_breeze/utils/check_release_files.py
new file mode 100644
index 00000000000..e5143e64b0e
--- /dev/null
+++ b/dev/breeze/src/airflow_breeze/utils/check_release_files.py
@@ -0,0 +1,228 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import itertools
+import re
+from pathlib import Path
+
+from airflow_breeze.utils.console import get_console
+
+PROVIDERS_DOCKER = """\
+FROM ghcr.io/apache/airflow/main/ci/python3.10
+RUN cd airflow-core; uv sync --no-sources
+
+# Install providers
+{}
+"""
+
+AIRFLOW_DOCKER = """\
+FROM python:3.10
+
+# Upgrade
+RUN pip install "apache-airflow=={}"
+
+"""
+
+TASK_SDK_DOCKER = """\
+FROM python:3.10
+
+# Upgrade
+RUN pip install "apache-airflow-task-sdk=={}"
+
+"""
+
+AIRFLOW_CTL_DOCKER = """\
+FROM python:3.10
+
+# Install airflow-ctl
+RUN pip install "apache-airflow-ctl=={}"
+
+"""
+
+PYTHON_CLIENT_DOCKER = """\
+FROM python:3.10
+
+# Install python-client
+RUN pip install "apache-airflow-python-client=={}"
+
+"""
+
+
+def get_packages(packages_file: Path) -> list[tuple[str, str]]:
+    """Read packages from packages.txt file."""
+    try:
+        content = packages_file.read_text()
+    except FileNotFoundError:
+        raise SystemExit(f"List of packages to check is empty. Please add 
packages to `{packages_file}`")
+
+    if not content:
+        raise SystemExit(f"List of packages to check is empty. Please add 
packages to `{packages_file}`")
+
+    # e.g. https://pypi.org/project/apache-airflow-providers-airbyte/3.1.0rc1/
+    packages = []
+    for line in content.splitlines():
+        if line:
+            _, name, version = line.rstrip("/").rsplit("/", 2)
+            packages.append((name, version))
+
+    return packages
+
+
+def create_docker(txt: str, output_file: Path):
+    """Generate Dockerfile for testing installation."""
+    output_file.write_text(txt)
+
+    console = get_console()
+    console.print("\n[bold]To check installation run:[/bold]")
+    console.print(
+        f"""\
+        docker build -f {output_file} --tag local/airflow .
+        docker run --rm --entrypoint "airflow" local/airflow info
+        docker image rm local/airflow
+        """
+    )
+
+
+def check_providers(files: list[str], release_date: str, packages: 
list[tuple[str, str]]) -> list[str]:
+    """Check if all expected provider files are present."""
+    console = get_console()
+    console.print("Checking providers from packages.txt:\n")
+    missing_list = []
+    expected_files = expand_name_variations(
+        [
+            f"apache_airflow_providers-{release_date}-source.tar.gz",
+        ]
+    )
+    missing_list.extend(check_all_files(expected_files=expected_files, 
actual_files=files))
+    for name, version_raw in packages:
+        console.print(f"Checking {name} {version_raw}")
+        version = strip_rc_suffix(version_raw)
+        expected_files = expand_name_variations(
+            [
+                f"{name.replace('-', '_')}-{version}.tar.gz",
+                f"{name.replace('-', '_')}-{version}-py3-none-any.whl",
+            ]
+        )
+
+        missing_list.extend(check_all_files(expected_files=expected_files, 
actual_files=files))
+
+    return missing_list
+
+
+def strip_rc_suffix(version: str) -> str:
+    """Remove rc suffix from version string."""
+    return re.sub(r"rc\d+$", "", version)
+
+
+def print_status(file: str, is_found: bool):
+    """Print status of a file check."""
+    console = get_console()
+    color, status = ("green", "OK") if is_found else ("red", "MISSING")
+    console.print(f"    - {file}: [{color}]{status}[/{color}]")
+
+
+def check_all_files(actual_files: list[str], expected_files: list[str]) -> 
list[str]:
+    """Check if all expected files are in actual files list."""
+    missing_list = []
+    for file in expected_files:
+        is_found = file in actual_files
+        if not is_found:
+            missing_list.append(file)
+        print_status(file=file, is_found=is_found)
+    return missing_list
+
+
+def check_airflow_release(files: list[str], version: str) -> list[str]:
+    """Check if all expected Airflow release files are present."""
+    console = get_console()
+    console.print(f"Checking airflow release for version {version}:\n")
+    version = strip_rc_suffix(version)
+
+    expected_files = expand_name_variations(
+        [
+            f"apache_airflow-{version}.tar.gz",
+            f"apache_airflow-{version}-source.tar.gz",
+            f"apache_airflow-{version}-py3-none-any.whl",
+            f"apache_airflow_core-{version}.tar.gz",
+            f"apache_airflow_core-{version}-py3-none-any.whl",
+        ]
+    )
+    return check_all_files(expected_files=expected_files, actual_files=files)
+
+
+def check_task_sdk_release(files: list[str], version: str) -> list[str]:
+    """Check if all expected task-sdk release files are present."""
+    console = get_console()
+    console.print(f"Checking task-sdk release for version {version}:\n")
+    version = strip_rc_suffix(version)
+
+    expected_files = expand_name_variations(
+        [
+            f"apache_airflow_task_sdk-{version}.tar.gz",
+            f"apache_airflow_task_sdk-{version}-py3-none-any.whl",
+        ]
+    )
+    return check_all_files(expected_files=expected_files, actual_files=files)
+
+
+def expand_name_variations(files: list[str]) -> list[str]:
+    """Expand file names to include signature and checksum variations."""
+    return sorted(base + suffix for base, suffix in itertools.product(files, 
["", ".asc", ".sha512"]))
+
+
+def check_airflow_ctl_release(files: list[str], version: str) -> list[str]:
+    """Check if all expected airflow-ctl release files are present."""
+    console = get_console()
+    console.print(f"Checking airflow-ctl release for version {version}:\n")
+    version = strip_rc_suffix(version)
+
+    expected_files = expand_name_variations(
+        [
+            f"apache_airflow_ctl-{version}-source.tar.gz",
+            f"apache_airflow_ctl-{version}.tar.gz",
+            f"apache_airflow_ctl-{version}-py3-none-any.whl",
+        ]
+    )
+    return check_all_files(expected_files=expected_files, actual_files=files)
+
+
+def check_python_client_release(files: list[str], version: str) -> list[str]:
+    """Check if all expected python-client release files are present."""
+    console = get_console()
+    console.print(f"Checking python-client release for version {version}:\n")
+    version = strip_rc_suffix(version)
+
+    expected_files = expand_name_variations(
+        [
+            f"apache_airflow_python_client-{version}-source.tar.gz",
+            f"apache_airflow_client-{version}.tar.gz",
+            f"apache_airflow_client-{version}-py3-none-any.whl",
+        ]
+    )
+    return check_all_files(expected_files=expected_files, actual_files=files)
+
+
+def warn_of_missing_files(files: list[str], directory: str):
+    """Print warning message for missing files."""
+    console = get_console()
+    console.print(
+        f"[red]Check failed. Here are the files we expected but did not find 
in {directory}:[/red]\n"
+    )
+
+    for file in files:
+        console.print(f"    - [red]{file}[/red]")
diff --git a/dev/breeze/tests/test_check_release_files.py 
b/dev/breeze/tests/test_check_release_files.py
new file mode 100644
index 00000000000..44e4269e641
--- /dev/null
+++ b/dev/breeze/tests/test_check_release_files.py
@@ -0,0 +1,222 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from pathlib import Path
+
+from airflow_breeze.utils.check_release_files import (
+    check_airflow_ctl_release,
+    check_airflow_release,
+    check_providers,
+    check_python_client_release,
+    check_task_sdk_release,
+)
+
+
+def test_check_airflow_release_pass():
+    """Passes if all files are present."""
+    files = [
+        "apache_airflow-2.8.1-py3-none-any.whl",
+        "apache_airflow-2.8.1-py3-none-any.whl.asc",
+        "apache_airflow-2.8.1-py3-none-any.whl.sha512",
+        "apache_airflow-2.8.1-source.tar.gz",
+        "apache_airflow-2.8.1-source.tar.gz.asc",
+        "apache_airflow-2.8.1-source.tar.gz.sha512",
+        "apache_airflow-2.8.1.tar.gz",
+        "apache_airflow-2.8.1.tar.gz.asc",
+        "apache_airflow-2.8.1.tar.gz.sha512",
+        "apache_airflow_core-2.8.1-py3-none-any.whl",
+        "apache_airflow_core-2.8.1-py3-none-any.whl.asc",
+        "apache_airflow_core-2.8.1-py3-none-any.whl.sha512",
+        "apache_airflow_core-2.8.1.tar.gz",
+        "apache_airflow_core-2.8.1.tar.gz.asc",
+        "apache_airflow_core-2.8.1.tar.gz.sha512",
+    ]
+    assert check_airflow_release(files, version="2.8.1rc2") == []
+
+
+def test_check_airflow_release_fail():
+    """Fails if missing one file."""
+    files = [
+        "apache_airflow-2.8.1-py3-none-any.whl",
+        "apache_airflow-2.8.1-py3-none-any.whl.asc",
+        "apache_airflow-2.8.1-py3-none-any.whl.sha512",
+        "apache_airflow-2.8.1-source.tar.gz",
+        "apache_airflow-2.8.1-source.tar.gz.asc",
+        "apache_airflow-2.8.1-source.tar.gz.sha512",
+        "apache_airflow-2.8.1.tar.gz.asc",
+        "apache_airflow-2.8.1.tar.gz.sha512",
+        "apache_airflow_core-2.8.1-py3-none-any.whl",
+        "apache_airflow_core-2.8.1-py3-none-any.whl.asc",
+        "apache_airflow_core-2.8.1-py3-none-any.whl.sha512",
+        "apache_airflow_core-2.8.1.tar.gz.asc",
+        "apache_airflow_core-2.8.1.tar.gz.sha512",
+    ]
+
+    missing_files = check_airflow_release(files, version="2.8.1rc2")
+    assert missing_files == ["apache_airflow-2.8.1.tar.gz", 
"apache_airflow_core-2.8.1.tar.gz"]
+
+
+def test_check_providers_pass(tmp_path: Path):
+    """Passes if all provider files are present."""
+    packages_file = tmp_path / "packages.txt"
+    packages_file.write_text(
+        "https://pypi.org/project/apache-airflow-providers-airbyte/3.1.0rc1/\n";
+        
"https://pypi.org/project/apache-airflow-providers-foo-bar/9.6.42rc2/\n";
+    )
+
+    packages = [
+        ("apache-airflow-providers-airbyte", "3.1.0rc1"),
+        ("apache-airflow-providers-foo-bar", "9.6.42rc2"),
+    ]
+
+    files = [
+        "apache_airflow_providers-2024-01-01-source.tar.gz",
+        "apache_airflow_providers-2024-01-01-source.tar.gz.asc",
+        "apache_airflow_providers-2024-01-01-source.tar.gz.sha512",
+        "apache_airflow_providers_airbyte-3.1.0.tar.gz",
+        "apache_airflow_providers_airbyte-3.1.0.tar.gz.asc",
+        "apache_airflow_providers_airbyte-3.1.0.tar.gz.sha512",
+        "apache_airflow_providers_airbyte-3.1.0-py3-none-any.whl",
+        "apache_airflow_providers_airbyte-3.1.0-py3-none-any.whl.asc",
+        "apache_airflow_providers_airbyte-3.1.0-py3-none-any.whl.sha512",
+        "apache_airflow_providers_foo_bar-9.6.42.tar.gz",
+        "apache_airflow_providers_foo_bar-9.6.42.tar.gz.asc",
+        "apache_airflow_providers_foo_bar-9.6.42.tar.gz.sha512",
+        "apache_airflow_providers_foo_bar-9.6.42-py3-none-any.whl",
+        "apache_airflow_providers_foo_bar-9.6.42-py3-none-any.whl.asc",
+        "apache_airflow_providers_foo_bar-9.6.42-py3-none-any.whl.sha512",
+    ]
+    assert check_providers(files, release_date="2024-01-01", 
packages=packages) == []
+
+
+def test_check_providers_failure(tmp_path: Path):
+    """Fails if provider files are missing."""
+    packages_file = tmp_path / "packages.txt"
+    
packages_file.write_text("https://pypi.org/project/apache-airflow-providers-spam-egg/1.2.3rc4/\n";)
+
+    packages = [("apache-airflow-providers-spam-egg", "1.2.3rc4")]
+
+    files = [
+        "apache_airflow_providers-2024-02-01-source.tar.gz",
+        "apache_airflow_providers-2024-02-01-source.tar.gz.asc",
+        "apache_airflow_providers-2024-02-01-source.tar.gz.sha512",
+        "apache_airflow_providers_spam_egg-1.2.3.tar.gz",
+        "apache_airflow_providers_spam_egg-1.2.3.tar.gz.sha512",
+        "apache_airflow_providers_spam_egg-1.2.3-py3-none-any.whl",
+        "apache_airflow_providers_spam_egg-1.2.3-py3-none-any.whl.asc",
+    ]
+    assert sorted(check_providers(files, release_date="2024-02-01", 
packages=packages)) == [
+        "apache_airflow_providers_spam_egg-1.2.3-py3-none-any.whl.sha512",
+        "apache_airflow_providers_spam_egg-1.2.3.tar.gz.asc",
+    ]
+
+
+def test_check_task_sdk_release_pass():
+    """Passes if all task-sdk files are present."""
+    files = [
+        "apache_airflow_task_sdk-1.0.0-py3-none-any.whl",
+        "apache_airflow_task_sdk-1.0.0-py3-none-any.whl.asc",
+        "apache_airflow_task_sdk-1.0.0-py3-none-any.whl.sha512",
+        "apache_airflow_task_sdk-1.0.0.tar.gz",
+        "apache_airflow_task_sdk-1.0.0.tar.gz.asc",
+        "apache_airflow_task_sdk-1.0.0.tar.gz.sha512",
+    ]
+    assert check_task_sdk_release(files, version="1.0.0rc1") == []
+
+
+def test_check_task_sdk_release_fail():
+    """Fails if task-sdk files are missing."""
+    files = [
+        "apache_airflow_task_sdk-1.0.0-py3-none-any.whl",
+        "apache_airflow_task_sdk-1.0.0-py3-none-any.whl.sha512",
+        "apache_airflow_task_sdk-1.0.0.tar.gz",
+        "apache_airflow_task_sdk-1.0.0.tar.gz.asc",
+    ]
+    missing_files = check_task_sdk_release(files, version="1.0.0rc1")
+    assert sorted(missing_files) == [
+        "apache_airflow_task_sdk-1.0.0-py3-none-any.whl.asc",
+        "apache_airflow_task_sdk-1.0.0.tar.gz.sha512",
+    ]
+
+
+def test_check_airflow_ctl_release_pass():
+    """Passes if all airflow-ctl files are present."""
+    files = [
+        "apache_airflow_ctl-1.2.3-py3-none-any.whl",
+        "apache_airflow_ctl-1.2.3-py3-none-any.whl.asc",
+        "apache_airflow_ctl-1.2.3-py3-none-any.whl.sha512",
+        "apache_airflow_ctl-1.2.3-source.tar.gz",
+        "apache_airflow_ctl-1.2.3-source.tar.gz.asc",
+        "apache_airflow_ctl-1.2.3-source.tar.gz.sha512",
+        "apache_airflow_ctl-1.2.3.tar.gz",
+        "apache_airflow_ctl-1.2.3.tar.gz.asc",
+        "apache_airflow_ctl-1.2.3.tar.gz.sha512",
+    ]
+    assert check_airflow_ctl_release(files, version="1.2.3rc2") == []
+
+
+def test_check_airflow_ctl_release_fail():
+    """Fails if airflow-ctl files are missing."""
+    files = [
+        "apache_airflow_ctl-1.2.3-py3-none-any.whl",
+        "apache_airflow_ctl-1.2.3-py3-none-any.whl.asc",
+        "apache_airflow_ctl-1.2.3-source.tar.gz.asc",
+        "apache_airflow_ctl-1.2.3.tar.gz",
+        "apache_airflow_ctl-1.2.3.tar.gz.sha512",
+    ]
+    missing_files = check_airflow_ctl_release(files, version="1.2.3rc2")
+    assert sorted(missing_files) == [
+        "apache_airflow_ctl-1.2.3-py3-none-any.whl.sha512",
+        "apache_airflow_ctl-1.2.3-source.tar.gz",
+        "apache_airflow_ctl-1.2.3-source.tar.gz.sha512",
+        "apache_airflow_ctl-1.2.3.tar.gz.asc",
+    ]
+
+
+def test_check_python_client_release_pass():
+    """Passes if all python-client files are present."""
+    files = [
+        "apache_airflow_client-2.5.0-py3-none-any.whl",
+        "apache_airflow_client-2.5.0-py3-none-any.whl.asc",
+        "apache_airflow_client-2.5.0-py3-none-any.whl.sha512",
+        "apache_airflow_client-2.5.0.tar.gz",
+        "apache_airflow_client-2.5.0.tar.gz.asc",
+        "apache_airflow_client-2.5.0.tar.gz.sha512",
+        "apache_airflow_python_client-2.5.0-source.tar.gz",
+        "apache_airflow_python_client-2.5.0-source.tar.gz.asc",
+        "apache_airflow_python_client-2.5.0-source.tar.gz.sha512",
+    ]
+    assert check_python_client_release(files, version="2.5.0rc3") == []
+
+
+def test_check_python_client_release_fail():
+    """Fails if python-client files are missing."""
+    files = [
+        "apache_airflow_client-2.5.0-py3-none-any.whl",
+        "apache_airflow_client-2.5.0-py3-none-any.whl.sha512",
+        "apache_airflow_client-2.5.0.tar.gz.asc",
+        "apache_airflow_python_client-2.5.0-source.tar.gz",
+        "apache_airflow_python_client-2.5.0-source.tar.gz.sha512",
+    ]
+    missing_files = check_python_client_release(files, version="2.5.0rc3")
+    assert sorted(missing_files) == [
+        "apache_airflow_client-2.5.0-py3-none-any.whl.asc",
+        "apache_airflow_client-2.5.0.tar.gz",
+        "apache_airflow_client-2.5.0.tar.gz.sha512",
+        "apache_airflow_python_client-2.5.0-source.tar.gz.asc",
+    ]
diff --git a/dev/check_files.py b/dev/check_files.py
deleted file mode 100644
index 58003d7b02b..00000000000
--- a/dev/check_files.py
+++ /dev/null
@@ -1,378 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# /// script
-# requires-python = ">=3.10"
-# dependencies = [
-#   "rich>=13.6.0",
-#   "rich-click>=1.7.1",
-# ]
-# ///
-from __future__ import annotations
-
-import itertools
-import os
-import re
-
-import rich_click as click
-from rich import print
-
-PROVIDERS_DOCKER = """\
-FROM ghcr.io/apache/airflow/main/ci/python3.10
-RUN cd airflow-core; uv sync --no-sources
-
-# Install providers
-{}
-"""
-
-AIRFLOW_DOCKER = """\
-FROM python:3.10
-
-# Upgrade
-RUN pip install "apache-airflow=={}"
-
-"""
-
-TASK_SDK_DOCKER = """\
-FROM python:3.10
-
-# Upgrade
-RUN pip install "apache-airflow-task-sdk=={}"
-
-"""
-
-
-DOCKER_UPGRADE = """\
-FROM apache/airflow:1.10.15
-
-# Install upgrade-check
-RUN pip install "apache-airflow-upgrade-check=={}"
-
-"""
-
-AIRFLOW = "AIRFLOW"
-PROVIDERS = "PROVIDERS"
-UPGRADE_CHECK = "UPGRADE_CHECK"
-
-
-def get_packages() -> list[tuple[str, str]]:
-    try:
-        with open("packages.txt") as file:
-            content = file.read()
-    except FileNotFoundError:
-        content = ""
-    if not content:
-        raise SystemExit("List of packages to check is empty. Please add 
packages to `packages.txt`")
-
-    # e.g. https://pypi.org/project/apache-airflow-providers-airbyte/3.1.0rc1/
-
-    packages = []
-    for line in content.splitlines():
-        if line:
-            _, name, version = line.rstrip("/").rsplit("/", 2)
-            packages.append((name, version))
-
-    return packages
-
-
-def create_docker(txt: str):
-    # Generate docker
-    with open("Dockerfile.pmc", "w+") as f:
-        f.write(txt)
-
-    print("\n[bold]To check installation run:[/bold]")
-    print(
-        """\
-        docker build -f Dockerfile.pmc --tag local/airflow .
-        docker run --rm --entrypoint "airflow" local/airflow info
-        docker image rm local/airflow
-        """
-    )
-
-
-def check_providers(files: list[str]):
-    print("Checking providers from packages.txt:\n")
-    missing_list = []
-    for name, version in get_packages():
-        print(f"Checking {name} {version}")
-        version = strip_rc_suffix(version)
-        expected_files = expand_name_variations(
-            [
-                f"{name.replace('-', '_')}-{version}.tar.gz",
-                f"{name.replace('-', '_')}-{version}-py3-none-any.whl",
-            ]
-        )
-
-        missing_list.extend(check_all_files(expected_files=expected_files, 
actual_files=files))
-
-    return missing_list
-
-
-def strip_rc_suffix(version):
-    return re.sub(r"rc\d+$", "", version)
-
-
-def print_status(file, is_found: bool):
-    color, status = ("green", "OK") if is_found else ("red", "MISSING")
-    print(f"    - {file}: [{color}]{status}[/{color}]")
-
-
-def check_all_files(actual_files, expected_files):
-    missing_list = []
-    for file in expected_files:
-        is_found = file in actual_files
-        if not is_found:
-            missing_list.append(file)
-        print_status(file=file, is_found=is_found)
-    return missing_list
-
-
-def check_airflow_release(files: list[str], version: str):
-    print(f"Checking airflow release for version {version}:\n")
-    version = strip_rc_suffix(version)
-
-    expected_files = expand_name_variations(
-        [
-            f"apache_airflow-{version}.tar.gz",
-            f"apache_airflow-{version}-source.tar.gz",
-            f"apache_airflow-{version}-py3-none-any.whl",
-            f"apache_airflow_core-{version}.tar.gz",
-            f"apache_airflow_core-{version}-py3-none-any.whl",
-        ]
-    )
-    return check_all_files(expected_files=expected_files, actual_files=files)
-
-
-def check_task_sdk_release(files: list[str], version: str):
-    print(f"Checking task-sdk release for version {version}:\n")
-    version = strip_rc_suffix(version)
-
-    expected_files = expand_name_variations(
-        [
-            f"apache_airflow_task_sdk-{version}.tar.gz",
-            f"apache_airflow_task_sdk-{version}-py3-none-any.whl",
-        ]
-    )
-    return check_all_files(expected_files=expected_files, actual_files=files)
-
-
-def expand_name_variations(files):
-    return sorted(base + suffix for base, suffix in itertools.product(files, 
["", ".asc", ".sha512"]))
-
-
-def check_upgrade_check(files: list[str], version: str):
-    print(f"Checking upgrade_check for version {version}:\n")
-    version = strip_rc_suffix(version)
-
-    expected_files = expand_name_variations(
-        [
-            f"apache-airflow-upgrade-check-{version}-bin.tar.gz",
-            f"apache-airflow-upgrade-check-{version}-source.tar.gz",
-            f"apache_airflow_upgrade_check-{version}-py2.py3-none-any.whl",
-        ]
-    )
-    return check_all_files(expected_files=expected_files, actual_files=files)
-
-
-def warn_of_missing_files(files):
-    print("[red]Check failed. Here are the files we expected but did not 
find:[/red]\n")
-
-    for file in files:
-        print(f"    - [red]{file}[/red]")
-
-
-path_option = click.option(
-    "--path",
-    "-p",
-    prompt="Path to files",
-    type=str,
-    help="Path to directory where are sources",
-)
-version_option = click.option(
-    "--version",
-    "-v",
-    prompt="Version",
-    type=str,
-    help="Version of package to verify. For example 1.10.15.rc1, 2021.3.17rc1",
-)
-
-
[email protected]()
-def cli():
-    """
-    Use this tool to verify that all expected packages are present in Apache 
Airflow svn.
-    In case of providers, it will generate Dockerfile.pmc that you can use
-    to verify that all packages are installable.
-
-    In case of providers, you should update `packages.txt` file with list of 
packages
-    that you expect to find (copy-paste the list from VOTE thread).
-
-    Example usages:
-    python check_files.py airflow -p ~/code/airflow_svn -v 1.10.15rc1
-    python check_files.py upgrade_check -p ~/code/airflow_svn -v 1.3.0rc2
-    python check_files.py providers -p ~/code/airflow_svn
-    """
-
-
[email protected]()
-@path_option
[email protected]_context
-def providers(ctx, path: str):
-    files = os.listdir(os.path.join(path, "providers"))
-    pips = [f"{name}=={version}" for name, version in get_packages()]
-    missing_files = check_providers(files)
-    create_docker(
-        PROVIDERS_DOCKER.format("RUN uv pip install --pre --system " + " 
".join(f"'{p}'" for p in pips))
-    )
-    if missing_files:
-        warn_of_missing_files(missing_files)
-
-
[email protected]()
-@path_option
-@version_option
[email protected]_context
-def airflow(ctx, path: str, version: str):
-    files = os.listdir(os.path.join(path, version))
-    missing_files = check_airflow_release(files, version)
-    create_docker(AIRFLOW_DOCKER.format(version))
-    if missing_files:
-        warn_of_missing_files(missing_files)
-    return
-
-
[email protected](name="task-sdk")
-@path_option
-@version_option
[email protected]_context
-def task_sdk(ctx, path: str, version: str):
-    files = os.listdir(os.path.join(path, version))
-    missing_files = check_task_sdk_release(files, version)
-    create_docker(TASK_SDK_DOCKER.format(version))
-    if missing_files:
-        warn_of_missing_files(missing_files)
-    return
-
-
[email protected]()
-@path_option
-@version_option
[email protected]_context
-def upgrade_check(ctx, path: str, version: str):
-    files = os.listdir(os.path.join(path, "upgrade-check", version))
-    missing_files = check_upgrade_check(files, version)
-
-    create_docker(DOCKER_UPGRADE.format(version))
-    if missing_files:
-        warn_of_missing_files(missing_files)
-    return
-
-
-cli.add_command(providers)
-cli.add_command(airflow)
-cli.add_command(task_sdk)
-cli.add_command(upgrade_check)
-
-if __name__ == "__main__":
-    cli()
-
-
-def test_check_release_pass():
-    """Passes if all present"""
-    files = [
-        "apache_airflow-2.8.1-py3-none-any.whl",
-        "apache_airflow-2.8.1-py3-none-any.whl.asc",
-        "apache_airflow-2.8.1-py3-none-any.whl.sha512",
-        "apache_airflow-2.8.1-source.tar.gz",
-        "apache_airflow-2.8.1-source.tar.gz.asc",
-        "apache_airflow-2.8.1-source.tar.gz.sha512",
-        "apache_airflow-2.8.1.tar.gz",
-        "apache_airflow-2.8.1.tar.gz.asc",
-        "apache_airflow-2.8.1.tar.gz.sha512",
-        "apache_airflow_core-2.8.1-py3-none-any.whl",
-        "apache_airflow_core-2.8.1-py3-none-any.whl.asc",
-        "apache_airflow_core-2.8.1-py3-none-any.whl.sha512",
-        "apache_airflow_core-2.8.1.tar.gz",
-        "apache_airflow_core-2.8.1.tar.gz.asc",
-        "apache_airflow_core-2.8.1.tar.gz.sha512",
-    ]
-    assert check_airflow_release(files, version="2.8.1rc2") == []
-
-
-def test_check_release_fail():
-    """Fails if missing one"""
-    files = [
-        "apache_airflow-2.8.1-py3-none-any.whl",
-        "apache_airflow-2.8.1-py3-none-any.whl.asc",
-        "apache_airflow-2.8.1-py3-none-any.whl.sha512",
-        "apache_airflow-2.8.1-source.tar.gz",
-        "apache_airflow-2.8.1-source.tar.gz.asc",
-        "apache_airflow-2.8.1-source.tar.gz.sha512",
-        "apache_airflow-2.8.1.tar.gz.asc",
-        "apache_airflow-2.8.1.tar.gz.sha512",
-        "apache_airflow_core-2.8.1-py3-none-any.whl",
-        "apache_airflow_core-2.8.1-py3-none-any.whl.asc",
-        "apache_airflow_core-2.8.1-py3-none-any.whl.sha512",
-        "apache_airflow_core-2.8.1.tar.gz.asc",
-        "apache_airflow_core-2.8.1.tar.gz.sha512",
-    ]
-
-    missing_files = check_airflow_release(files, version="2.8.1rc2")
-    assert missing_files == ["apache_airflow-2.8.1.tar.gz", 
"apache_airflow_core-2.8.1.tar.gz"]
-
-
-def test_check_providers_pass(monkeypatch, tmp_path):
-    """Passes if all present"""
-    monkeypatch.chdir(tmp_path)
-    (tmp_path / "packages.txt").write_text(
-        "https://pypi.org/project/apache-airflow-providers-airbyte/3.1.0rc1/\n";
-        
"https://pypi.org/project/apache-airflow-providers-foo-bar/9.6.42rc2/\n";
-    )
-
-    files = [
-        "apache_airflow_providers_airbyte-3.1.0.tar.gz",
-        "apache_airflow_providers_airbyte-3.1.0.tar.gz.asc",
-        "apache_airflow_providers_airbyte-3.1.0.tar.gz.sha512",
-        "apache_airflow_providers_airbyte-3.1.0-py3-none-any.whl",
-        "apache_airflow_providers_airbyte-3.1.0-py3-none-any.whl.asc",
-        "apache_airflow_providers_airbyte-3.1.0-py3-none-any.whl.sha512",
-        "apache_airflow_providers_foo_bar-9.6.42.tar.gz",
-        "apache_airflow_providers_foo_bar-9.6.42.tar.gz.asc",
-        "apache_airflow_providers_foo_bar-9.6.42.tar.gz.sha512",
-        "apache_airflow_providers_foo_bar-9.6.42-py3-none-any.whl",
-        "apache_airflow_providers_foo_bar-9.6.42-py3-none-any.whl.asc",
-        "apache_airflow_providers_foo_bar-9.6.42-py3-none-any.whl.sha512",
-    ]
-    assert check_providers(files) == []
-
-
-def test_check_providers_failure(monkeypatch, tmp_path):
-    """Passes if all present"""
-    monkeypatch.chdir(tmp_path)
-    (tmp_path / "packages.txt").write_text(
-        
"https://pypi.org/project/apache-airflow-providers-spam-egg/1.2.3rc4/\n";
-    )
-
-    files = [
-        "apache_airflow_providers_spam_egg-1.2.3.tar.gz",
-        "apache_airflow_providers_spam_egg-1.2.3.tar.gz.sha512",
-        "apache_airflow_providers_spam_egg-1.2.3-py3-none-any.whl",
-        "apache_airflow_providers_spam_egg-1.2.3-py3-none-any.whl.asc",
-    ]
-    assert sorted(check_providers(files)) == [
-        "apache_airflow_providers_spam_egg-1.2.3-py3-none-any.whl.sha512",
-        "apache_airflow_providers_spam_egg-1.2.3.tar.gz.asc",
-    ]

Reply via email to