You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by po...@apache.org on 2024/01/22 23:54:59 UTC
(airflow) branch main updated: Make Helm artifacts reproducible (#36930)
This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 48158c9967 Make Helm artifacts reproducible (#36930)
48158c9967 is described below
commit 48158c9967c14acf65264e338b8dea60af3f25e1
Author: Jarek Potiuk <ja...@potiuk.com>
AuthorDate: Tue Jan 23 00:54:52 2024 +0100
Make Helm artifacts reproducible (#36930)
Following #36726, #36744, #36763, #36819 this PR adds the feature of
making source tarball that we release as an official release of
the ASF for Helm Chart into reproducible tarball. This means that
anyone should be able to produce such tarball using the sources
of airflow and verify that he tarball pushed to SVN by the
release manager is built from our source repositories.
We also do the same with Helm package. It turns out that gpg signing
of the package does not modify the .tgz file - it just adds .prov file
containing checksum and signature, so we can safely re-pack the .tar.gz
package in a reproducible way, this way we have both reproduciblity and
provenance check nicely working together.
There are few changes in this PR that are related:
* Bumped Helm version in our environment to use the latest one and
using the `breeze k8s setup-env` environment to run all the release
commands - this way we can be sure same helm version is used to build
the package, further making it more reproducible.
* The reproducible packaging utility we have has been refeactored now -
we take "source" archive as parameter rather than directory and simply
repack it in reproducible way.
* The tool also applies group/other ownership removal on its own,
because helm package has no option to umask the generated files.
* In this change we also ignore subcharts from being exported to the source
tarball package as we shoudl not include source files from postgres in
our source package..
* Both - the tarball and helm package are generated in `dist` folder similarly as
all our other packages.
* Documentation for releasing the packages and verifying them is updated.
* CI jobs are updated to use the new commands and generated packages are
produced as artifacts so that we can be sure the commands continue
working and produce the right output.
---
.gitattributes | 1 +
.github/workflows/ci.yml | 52 ++++
.pre-commit-config.yaml | 6 +-
CI.rst | 2 +
CI_DIAGRAMS.md | 4 +
chart/reproducible_build.yaml | 2 +
dev/README_RELEASE_HELM_CHART.md | 329 +++++++++++++--------
dev/breeze/README.md | 2 +-
.../doc/images/output_release-management.svg | 54 ++--
.../doc/images/output_release-management.txt | 2 +-
...lease-management_prepare-helm-chart-package.svg | 112 +++++++
...lease-management_prepare-helm-chart-package.txt | 1 +
...lease-management_prepare-helm-chart-tarball.svg | 166 +++++++++++
...lease-management_prepare-helm-chart-tarball.txt | 1 +
.../output_setup_check-all-params-in-groups.svg | 42 +--
.../output_setup_check-all-params-in-groups.txt | 2 +-
.../output_setup_regenerate-command-images.svg | 46 +--
.../output_setup_regenerate-command-images.txt | 2 +-
dev/breeze/pyproject.toml | 2 +-
.../commands/release_candidate_command.py | 97 +++---
.../commands/release_management_commands.py | 274 ++++++++++++++++-
.../commands/release_management_commands_config.py | 30 ++
.../src/airflow_breeze/configure_rich_click.py | 2 +
dev/breeze/src/airflow_breeze/global_constants.py | 2 +-
dev/breeze/src/airflow_breeze/utils/path_utils.py | 2 +
.../src/airflow_breeze/utils/reproducible.py | 77 +++--
docker_tests/requirements.txt | 2 +-
scripts/ci/kubernetes/k8s_requirements.txt | 7 +-
.../pre_commit_update_source_date_epoch.py | 29 +-
29 files changed, 1067 insertions(+), 283 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index 28d55db9c2..6fc521e5d6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9,6 +9,7 @@ manifests export-ignore
newsfragments export-ignore
scripts export-ignore
tests export-ignore
+chart/charts/** export-ignore
Dockerfile.ci export-ignore
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 518723c431..9b2e758300 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1048,6 +1048,58 @@ jobs:
- name: "Helm Unit Tests: ${{ matrix.helm-test-package }}"
run: breeze testing helm-tests --helm-test-package "${{ matrix.helm-test-package }}"
+ tests-helm-release:
+ timeout-minutes: 80
+ name: "Release Helm"
+ runs-on: ${{fromJSON(needs.build-info.outputs.runs-on)}}
+ needs: [build-info]
+ env:
+ RUNS_ON: "${{needs.build-info.outputs.runs-on}}"
+ PYTHON_MAJOR_MINOR_VERSION: "${{needs.build-info.outputs.default-python-version}}"
+ if: >
+ needs.build-info.outputs.needs-helm-tests == 'true' && needs.build-info.outputs.default-branch == 'main'
+ steps:
+ - name: Cleanup repo
+ run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm -rf /workspace/*"
+ - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ - name: "Install Breeze"
+ uses: ./.github/actions/breeze
+ - name: Setup git for tagging
+ run: |
+ git config --global user.email "name@example.com"
+ git config --global user.name "Your Name"
+ - name: "Remove old artifacts"
+ run: rm -rf dist/*
+ - name: "Setup k8s/helm environment"
+ run: breeze k8s setup-env
+ - name: "Install helm gpg plugin"
+ run: >
+ breeze k8s shell -c "helm plugin install https://github.com/technosophos/helm-gpg
+ --version 6303407eb63deaeb1b2f24de611e3468a27ec05b"
+ - name: "Helm release tarball"
+ run: >
+ breeze release-management prepare-helm-chart-tarball --ignore-version-check --override-tag
+ --skip-tag-signing --version 0.0.0 --version-suffix dev0
+ - name: Generate GPG key for signing
+ run: gpg --batch --passphrase '' --quick-gen-key dev@airflow.apache.org default default
+ - name: "Helm release package"
+ run: >
+ breeze release-management prepare-helm-chart-package --sign-email dev@airflow.apache.org
+ - name: "Sign artifacts for ASF distribution"
+ run: ./dev/sign.sh dist/airflow-*.tgz dist/airflow-*-source.tar.gz
+ env:
+ SIGN_WITH: dev@airflow.apache.org
+ - name: "Upload Helm artifacts"
+ uses: actions/upload-artifact@v3
+ with:
+ name: Helm artifacts
+ path: ./dist/airflow-*
+ retention-days: 7
+ if-no-files-found: error
+
tests-postgres:
timeout-minutes: 130
name: >
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index c6ee8604dc..2024caa647 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -135,7 +135,7 @@ repos:
- --fuzzy-match-generates-todo
- id: insert-license
name: Add license for all YAML files except Helm templates
- exclude: ^\.github/.*$|^.*/.*_vendor/|^chart/templates/.*|^airflow/reproducible_build.yaml$
+ exclude: ^\.github/.*$|^.*/.*_vendor/|^chart/templates/.*|.*/reproducible_build.yaml$
types: [yaml]
files: \.ya?ml$
args:
@@ -254,7 +254,7 @@ repos:
name: Check YAML files with yamllint
entry: yamllint -c yamllint-config.yml --strict
types: [yaml]
- exclude: ^.*airflow\.template\.yaml$|^.*init_git_sync\.template\.yaml$|^.*/.*_vendor/|^chart/(?:templates|files)/.*\.yaml$|openapi/.*\.yaml$|^\.pre-commit-config\.yaml$|^airflow/reproducible_build.yaml$
+ exclude: ^.*airflow\.template\.yaml$|^.*init_git_sync\.template\.yaml$|^.*/.*_vendor/|^chart/(?:templates|files)/.*\.yaml$|openapi/.*\.yaml$|^\.pre-commit-config\.yaml$|^.*/reproducible_build.yaml$
- repo: https://github.com/ikamensh/flynt
rev: '1.0.1'
hooks:
@@ -833,7 +833,7 @@ repos:
name: Update Source Date Epoch for reproducible builds
language: python
entry: ./scripts/ci/pre_commit/pre_commit_update_source_date_epoch.py
- files: ^RELEASE_NOTES.rst$
+ files: ^RELEASE_NOTES.rst$|^chart/RELEASE_NOTES.rst$
additional_dependencies: ['rich>=12.4.4', 'pyyaml']
pass_filenames: false
require_serial: true
diff --git a/CI.rst b/CI.rst
index ea4d0d3fa9..5800ba138c 100644
--- a/CI.rst
+++ b/CI.rst
@@ -397,6 +397,8 @@ This workflow is a regular workflow that performs all checks of Airflow code.
+---------------------------------+----------------------------------------------------------+----------+----------+-----------+-------------------+
| Helm tests | Run the Helm integration tests | Yes | Yes | Yes | - |
+---------------------------------+----------------------------------------------------------+----------+----------+-----------+-------------------+
+| Helm release tests | Run the tests for Helm releasing | Yes | Yes | Yes | - |
++---------------------------------+----------------------------------------------------------+----------+----------+-----------+-------------------+
| Summarize warnings | Summarizes warnings from all other tests | Yes | Yes | Yes | Yes |
+---------------------------------+----------------------------------------------------------+----------+----------+-----------+-------------------+
| Wait for PROD Images | Waits for and verify PROD Images | Yes (2) | Yes (2) | Yes (2) | Yes (2) |
diff --git a/CI_DIAGRAMS.md b/CI_DIAGRAMS.md
index cbd1d54d88..a06160d4b1 100644
--- a/CI_DIAGRAMS.md
+++ b/CI_DIAGRAMS.md
@@ -62,6 +62,8 @@ sequenceDiagram
Note over Tests: React WWW tests
and
Note over Tests: Test git clone on Windows
+ and
+ Note over Tests: Helm release tests
and
opt
Note over Tests: Run basic <br>static checks
@@ -216,6 +218,8 @@ sequenceDiagram
Note over Tests: Test examples<br>PROD image building
and
Note over Tests: Test git clone on Windows
+ and
+ Note over Tests: Helm release tests
and
opt
Note over Tests: Run basic <br>static checks
diff --git a/chart/reproducible_build.yaml b/chart/reproducible_build.yaml
new file mode 100644
index 0000000000..992d725355
--- /dev/null
+++ b/chart/reproducible_build.yaml
@@ -0,0 +1,2 @@
+release-notes-hash: 46313503ae418af0ecad2c5504a97a43
+source-date-epoch: 1705774629
diff --git a/dev/README_RELEASE_HELM_CHART.md b/dev/README_RELEASE_HELM_CHART.md
index 7e0f65f9bc..804c530f73 100644
--- a/dev/README_RELEASE_HELM_CHART.md
+++ b/dev/README_RELEASE_HELM_CHART.md
@@ -22,12 +22,15 @@
- [Prepare the Apache Airflow Helm Chart Release Candidate](#prepare-the-apache-airflow-helm-chart-release-candidate)
- [Pre-requisites](#pre-requisites)
+ - [Set environment variables](#set-environment-variables)
+ - [Setup k8s environment (mainly helm chart)](#setup-k8s-environment-mainly-helm-chart)
- [Build Release Notes](#build-release-notes)
- [Build RC artifacts](#build-rc-artifacts)
- [Prepare issue for testing status of rc](#prepare-issue-for-testing-status-of-rc)
- [Prepare Vote email on the Apache Airflow release candidate](#prepare-vote-email-on-the-apache-airflow-release-candidate)
- [Verify the release candidate by PMCs](#verify-the-release-candidate-by-pmcs)
- [SVN check](#svn-check)
+ - [Source tarball reproducibility check](#source-tarball-reproducibility-check)
- [Licence check](#licence-check)
- [Signature check](#signature-check)
- [SHA512 sum check](#sha512-sum-check)
@@ -59,7 +62,52 @@ details the steps for releasing Helm Chart.
## Pre-requisites
-- Helm version >= 3.5.4
+- Helm version == 3.14.0
+- towncrier version == 23.11.0
+- The `helm gpg` plugin to sign the chart. It can be found at: https://github.com/technosophos/helm-gpg
+
+Instructions for installing the pre-requisites are explained in the steps below.
+
+## Set environment variables
+
+- Set environment variables
+
+```shell
+# Set Version
+export VERSION=1.0.1
+export VERSION_SUFFIX=rc1
+
+# Set AIRFLOW_REPO_ROOT to the path of your git repo
+export AIRFLOW_REPO_ROOT=$(pwd -P)
+
+# Example after cloning
+git clone https://github.com/apache/airflow.git airflow
+cd airflow
+export AIRFLOW_REPO_ROOT=$(pwd -P)
+```
+
+## Setup k8s environment (mainly helm chart)
+
+This will install Helm in the recent version and enter the environment where you can run `helm` commands
+and installs the necessary python dependencies (including `towncrier` in the k8s virtual environment).
+
+```shell
+breeze k8s setup-env
+breeze k8s shell
+```
+
+Install the helm-gpg plugin, if you have not installed it already. This command will install the plugin
+using commit sha of version of the plugin that is known to work with latest openssl and reviewed by us.
+
+```shell
+helm plugin install https://github.com/technosophos/helm-gpg --version 6303407eb63deaeb1b2f24de611e3468a27ec05b
+```
+
+You can also update/uninstall/list the plugin with other `helm plugin` commands. For more information, run:
+
+```shell
+helm plugin --help
+```
## Build Release Notes
@@ -68,7 +116,7 @@ Before creating the RC, you need to build and commit the release notes for the r
Preview with:
```shell script
-towncrier build --draft --version=${VERSION_WITHOUT_RC} --date=2021-12-15 --dir chart --config chart/newsfragments/config.toml
+towncrier build --draft --version=${VERSION} --date=2021-12-15 --dir chart --config chart/newsfragments/config.toml
```
Then remove the `--draft` flag to have towncrier build the release notes for real.
@@ -95,6 +143,16 @@ annotations:
url: https://github.com/apache/airflow/pull/19263
```
+Make sure that all the release notes changes are submitted as PR and merged. Changes in release notes should
+also automatically (via `pre-commit` trigger updating of the [reproducible_build.yaml](../chart/reproducible_build.yaml))
+file which is uses to reproducibly build the chart package and source tarball.
+
+You can leave the k8s environment now:
+
+```shell
+exit
+```
+
## Build RC artifacts
The Release Candidate artifacts we vote upon should be the exact ones we vote against,
@@ -103,101 +161,55 @@ the same between voted release candidate and final release.
Because of this the version in the built artifacts that will become the
official Apache releases must not include the rcN suffix.
-- Set environment variables
-
- ```shell
- # Set Version
- export VERSION=1.0.1rc1
- export VERSION_WITHOUT_RC=${VERSION%rc?}
-
- # Set AIRFLOW_REPO_ROOT to the path of your git repo
- export AIRFLOW_REPO_ROOT=$(pwd)
+Make sure you have `apache` remote set up pointing to the apache git repo.
+If needed, add it with:
- # Example after cloning
- git clone https://github.com/apache/airflow.git airflow
- cd airflow
- export AIRFLOW_REPO_ROOT=$(pwd)
- ```
+```shell
+git remote add apache git@github.com:apache/airflow.git
+git fetch apache
+```
- We currently release Helm Chart from `main` branch:
- ```shell
- git checkout main
- ```
-
-- Clean the checkout: the sdist step below will
-
- ```shell
- git clean -fxd
- ```
-
-- Update Helm Chart version in `Chart.yaml`, example: `version: 1.0.0` (without
- the RC tag). If the default version of Airflow is different from `appVersion` change it.
-
-- Add and commit the version change.
-
- ```shell
- git add chart
- git commit -m "Chart: Bump version to $VERSION_WITHOUT_RC"
- ```
-
- Note: You will tag this commit, you do not need to open a PR for it.
-
-- Tag your release
-
- ```shell
- git tag -s helm-chart/${VERSION} -m "Apache Airflow Helm Chart $VERSION"
- ```
-
-- Tarball the repo
-
- NOTE: Make sure your checkout is clean at this stage - any untracked or changed files will otherwise be included
- in the file produced.
-
- ```shell
- git archive --format=tar.gz helm-chart/${VERSION} --prefix=airflow-chart-${VERSION_WITHOUT_RC}/ \
- -o airflow-chart-${VERSION_WITHOUT_RC}-source.tar.gz chart .rat-excludes
- ```
+```shell
+git checkout apache/main
+```
-- Generate chart binary
+- Clean the checkout: (note that this step will also clean any IDE settings you might have so better to
+ do it in a checked out version you only use for releasing)
+```shell
+git clean -fxd
+rm -rf dist/*
+```
- ```shell
- helm package chart --dependency-update
- ```
+- Generate the source tarball:
-- Sign the chart binary
+```shell
+breeze release-management prepare-helm-chart-tarball --version ${VERSION} --version-suffix ${VERSION_SUFFIX}
+```
- In the following command, replace the email address with your email address or your KEY ID
- so GPG uses the right key to sign the chart.
- (If you have not generated a key yet, generate it by following instructions on
- http://www.apache.org/dev/openpgp.html#key-gen-generate-key)
+- Generate the binary Helm Chart release:
- ```shell
- helm gpg sign -u jedcunningham@apache.org airflow-${VERSION_WITHOUT_RC}.tgz
- ```
+```shell
+breeze release-management prepare-helm-chart-packagte --sig jedcunningham@apache.org
+```
- Warning: you need the `helm gpg` plugin to sign the chart. It can be found at: https://github.com/technosophos/helm-gpg
+Warning: you need the `helm gpg` plugin to sign the chart (instructions to install it above)
- This should also generate a provenance file (Example: `airflow-1.0.0.tgz.prov`) as described in
- https://helm.sh/docs/topics/provenance/, which can be used to verify integrity of the Helm chart.
+This should generate two files:
- Verify the signed chart (with example output shown):
+- `dist/airflow-${VERSION}.tgz`
+- `dist/airflow-${VERSION}.tgz.prov`
- ```shell
- $ helm gpg verify airflow-${VERSION_WITHOUT_RC}.tgz
- gpg: Signature made Thu Jan 6 21:33:35 2022 MST
- gpg: using RSA key E1A1E984F55B8F280BD9CBA20BB7163892A2E48E
- gpg: Good signature from "Jed Cunningham <je...@apache.org>" [ultimate]
- plugin: Chart SHA verified. sha256:b33eac716e0416a18af89fb4fa1043fcfcf24f9f903cda3912729815213525df
- ```
+The second one is a provenance file as described in
+https://helm.sh/docs/topics/provenance/. It can be used to verify integrity of the Helm chart.
- Generate SHA512/ASC
- ```shell
- ${AIRFLOW_REPO_ROOT}/dev/sign.sh airflow-chart-${VERSION_WITHOUT_RC}-source.tar.gz
- ${AIRFLOW_REPO_ROOT}/dev/sign.sh airflow-${VERSION_WITHOUT_RC}.tgz
- ```
+```shell
+${AIRFLOW_REPO_ROOT}/dev/sign.sh dist/airflow-*.tgz dist/airflow-*-source.tar.gz
+```
- Move the artifacts to ASF dev dist repo, Generate convenience `index.yaml` & Publish them
@@ -207,12 +219,12 @@ official Apache releases must not include the rcN suffix.
# Create new folder for the release
cd airflow-dev/helm-chart
- svn mkdir ${VERSION}
+ svn mkdir ${VERSION}${VERSION_SUFFIX}
# Move the artifacts to svn folder
- mv ${AIRFLOW_REPO_ROOT}/airflow-${VERSION_WITHOUT_RC}.tgz* ${VERSION}/
- mv ${AIRFLOW_REPO_ROOT}/airflow-chart-${VERSION_WITHOUT_RC}-source.tar.gz* ${VERSION}/
- cd ${VERSION}
+ mv ${AIRFLOW_REPO_ROOT}/dist/airflow-${VERSION}.tgz* ${VERSION}${VERSION_SUFFIX}/
+ mv ${AIRFLOW_REPO_ROOT}/dist/airflow-chart-${VERSION}-source.tar.gz* ${VERSION}${VERSION_SUFFIX}/
+ cd ${VERSION}${VERSION_SUFFIX}
###### Generate index.yaml file - Start
# Download the latest index.yaml on Airflow Website
@@ -223,29 +235,29 @@ official Apache releases must not include the rcN suffix.
sed -i 's|https://downloads.apache.org/airflow/helm-chart/|https://archive.apache.org/dist/airflow/helm-chart/|' index.yaml
# Generate / Merge the new version with existing index.yaml
- helm repo index --merge ./index.yaml . --url "https://dist.apache.org/repos/dist/dev/airflow/helm-chart/${VERSION}"
+ helm repo index --merge ./index.yaml . --url "https://dist.apache.org/repos/dist/dev/airflow/helm-chart/${VERSION}${VERSION_SUFFIX}"
###### Generate index.yaml file - End
# Commit the artifacts
svn add *
- svn commit -m "Add artifacts for Helm Chart ${VERSION}"
+ svn commit -m "Add artifacts for Helm Chart ${VERSION}${VERSION_SUFFIX}"
```
- Remove old Helm Chart versions from the dev repo
```shell
cd ..
- export PREVIOUS_VERSION=1.0.0rc1
- svn rm ${PREVIOUS_VERSION}
- svn commit -m "Remove old Helm Chart release: ${PREVIOUS_VERSION}"
+ export PREVIOUS_VERSION_WITH_SUFFIX=1.0.0rc1
+ svn rm ${PREVIOUS_VERSION_WITH_SUFFIX}
+ svn commit -m "Remove old Helm Chart release: ${PREVIOUS_VERSION_WITH_SUFFIX}"
```
- Push Tag for the release candidate
```shell
cd ${AIRFLOW_REPO_ROOT}
- git push origin tag helm-chart/${VERSION}
+ git push apache tag helm-chart/${VERSION}${VERSION_SUFFIX}
```
## Prepare issue for testing status of rc
@@ -255,7 +267,7 @@ Create an issue for testing status of the RC (PREVIOUS_RELEASE should be the pre
```shell script
cat <<EOF
-Status of testing of Apache Airflow Helm Chart ${VERSION}
+Status of testing of Apache Airflow Helm Chart ${VERSION}${VERSION_SUFFIX}
EOF
```
@@ -263,7 +275,7 @@ Content is generated with:
```shell
./dev/prepare_release_issue.py generate-issue-content --previous-release helm-chart/<PREVIOUS_RELEASE> \
- --current-release helm-chart/${VERSION} --is-helm-chart
+ --current-release helm-chart/${VERSION}${VERSION_SUFFIX} --is-helm-chart
```
@@ -277,7 +289,7 @@ Subject:
```shell
cat <<EOF
-[VOTE] Release Apache Airflow Helm Chart ${VERSION_WITHOUT_RC} based on ${VERSION}
+[VOTE] Release Apache Airflow Helm Chart ${VERSION} based on ${VERSION}${VERSION_SUFFIX}
EOF
```
@@ -292,25 +304,25 @@ Body:
cat <<EOF
Hello Apache Airflow Community,
-This is a call for the vote to release Helm Chart version ${VERSION_WITHOUT_RC}.
+This is a call for the vote to release Helm Chart version ${VERSION}.
The release candidate is available at:
-https://dist.apache.org/repos/dist/dev/airflow/helm-chart/$VERSION/
+https://dist.apache.org/repos/dist/dev/airflow/helm-chart/${VERSION}${VERSION_SUFFIX}/
-airflow-chart-${VERSION_WITHOUT_RC}-source.tar.gz - is the "main source release" that comes with INSTALL instructions.
-airflow-${VERSION_WITHOUT_RC}.tgz - is the binary Helm Chart release.
+airflow-chart-${VERSION}-source.tar.gz - is the "main source release" that comes with INSTALL instructions.
+airflow-${VERSION}.tgz - is the binary Helm Chart release.
Public keys are available at: https://www.apache.org/dist/airflow/KEYS
For convenience "index.yaml" has been uploaded (though excluded from voting), so you can also run the below commands.
-helm repo add apache-airflow-dev https://dist.apache.org/repos/dist/dev/airflow/helm-chart/$VERSION/
+helm repo add apache-airflow-dev https://dist.apache.org/repos/dist/dev/airflow/helm-chart/${VERSION}${VERSION_SUFFIX}/
helm repo update
helm install airflow apache-airflow-dev/airflow
-airflow-${VERSION_WITHOUT_RC}.tgz.prov - is also uploaded for verifying Chart Integrity, though not strictly required for releasing the artifact based on ASF Guidelines.
+airflow-${VERSION}.tgz.prov - is also uploaded for verifying Chart Integrity, though not strictly required for releasing the artifact based on ASF Guidelines.
-$ helm gpg verify airflow-${VERSION_WITHOUT_RC}.tgz
+$ helm gpg verify airflow-${VERSION}.tgz
gpg: Signature made Thu Jan 6 21:33:35 2022 MST
gpg: using RSA key E1A1E984F55B8F280BD9CBA20BB7163892A2E48E
gpg: Good signature from "Jed Cunningham <je...@apache.org>" [ultimate]
@@ -333,12 +345,12 @@ Consider this my (binding) +1.
For license checks, the .rat-excludes files is included, so you can run the following to verify licenses (just update your path to rat):
-tar -xvf airflow-chart-${VERSION_WITHOUT_RC}-source.tar.gz
-cd airflow-chart-${VERSION_WITHOUT_RC}
+tar -xvf airflow-chart-${VERSION}-source.tar.gz
+cd airflow-chart-${VERSION}
java -jar apache-rat-0.13.jar chart -E .rat-excludes
Please note that the version number excludes the \`rcX\` string, so it's now
-simply ${VERSION_WITHOUT_RC}. This will allow us to rename the artifact without modifying
+simply ${VERSION}. This will allow us to rename the artifact without modifying
the artifact checksums when we actually release it.
The status of testing the Helm Chart by the community is kept here:
@@ -375,9 +387,9 @@ The files should be present in the sub-folder of
The following files should be present (7 files):
-* `airflow-chart-${VERSION_WITHOUT_RC}-source.tar.gz` + .asc + .sha512
-* `airflow-{VERSION_WITHOUT_RC}.tgz` + .asc + .sha512
-* `airflow-{VERSION_WITHOUT_RC}.tgz.prov`
+* `airflow-chart-${VERSION}-source.tar.gz` + .asc + .sha512
+* `airflow-{VERSION}.tgz` + .asc + .sha512
+* `airflow-{VERSION}.tgz.prov`
As a PMC you should be able to clone the SVN repository:
@@ -391,6 +403,67 @@ Or update it if you already checked it out:
svn update .
```
+While in the directory, save the path to the repository root:
+
+```shell
+SVN_REPO_ROOT=$(pwd -P)
+```
+
+## Source tarball reproducibility check
+
+The source tarball should be reproducible. This means that if you build it twice, you should get
+the same result. This is important for security reasons, as it ensures that the source code
+has not been tampered with.
+
+1. Go to airflow repository root (for example if you cloned it to `../airflow` then `cd ../airflow`)
+
+```shell
+cd ../airflow
+AIRFLOW_REPO_ROOT=$(pwd -P)
+```
+
+2. Set the version of the release you are checking
+
+```shell
+VERSION=12.0.1
+VERSION_SUFFIX=rc1
+```
+
+3. Check-out the branch from which the release was made and cleanup dist folder:
+
+```shell
+git checkout helm-chart/${VERSION}${VERSION_SUFFIX}
+rm -rf dist/*
+```
+
+4. Build the source tarball and package. Since you are not releasing the package, you should ignore version
+ check and skip tagging. There is no need to specify version as it is stored in Chart.yaml of the rc tag.
+
+```shell
+breeze release-management prepare-helm-chart-tarball --version-suffix rc1 --ignore-version-check --skip-tagging
+breeze release-management prepare-helm-chart-package
+```
+
+5. Compare the produced tarball binary with ones in SVN:
+
+```shell
+
+diff ${AIRFLOW_REPO_ROOT}/dist/airflow-chart-${VERSION}-source.tar.gz ${SVN_REPO_ROOT}/airflow-chart/${VERSION}${VERSION_SUFFIX}/airflow-chart-${VERSION}-source.tar.gz
+diff ${AIRFLOW_REPO_ROOT}/dist/airflow-${VERSION}.tar.gz ${SVN_REPO_ROOT}/airflow-chart/${VERSION}${VERSION_SUFFIX}/airflow-${VERSION}.tar.gz
+```
+
+There should be no differences reported. If you see "binary files differ" message, it means that
+the source tarball is not reproducible. This is not a blocker for the release, you can unpack the sources
+of the tarball and compare the two tarballs and check the differences for example
+with `diff -R <DIR1> <DIR2>`. It could be that our reproducible build script is not working correctly yet,
+and we need to fix it (so checking the differences would be helpful also to find out what is wrong).
+
+Before proceeding next you want to go to the SVN directory
+
+```shell
+cd ${SVN_REPO_ROOT}/helm-chart/${VERSION}${VERSION_SUFFIX}
+```
+
## Licence check
This can be done with the Apache RAT tool.
@@ -401,7 +474,7 @@ This can be done with the Apache RAT tool.
* Enter the sources folder run the check
```shell
-java -jar $PATH_TO_RAT/apache-rat-0.13/apache-rat-0.13.jar chart -E .rat-excludes
+java -jar ${PATH_TO_RAT}/apache-rat-0.13/apache-rat-0.13.jar chart -E .rat-excludes
```
where `.rat-excludes` is the file in the root of Chart source code.
@@ -562,20 +635,20 @@ the binaries again, and gives a clearer history in the svn commit logs):
```shell
# First clone the repo
-export RC=1.0.1rc1
-export VERSION=${RC/rc?/}
+export VERSION=1.0.1
+export VERSION_SUFFIX=rc1
svn checkout https://dist.apache.org/repos/dist/release/airflow airflow-release
# Create new folder for the release
cd airflow-release/helm-chart
-export AIRFLOW_SVN_RELEASE_HELM=$(pwd)
+export AIRFLOW_SVN_RELEASE_HELM=$(pwd -P)
svn mkdir ${VERSION}
cd ${VERSION}
# Move the artifacts to svn folder & commit (don't copy or copy & remove - index.yaml)
-for f in ../../../airflow-dev/helm-chart/$RC/*; do svn cp $f ${$(basename $f)/}; done
+for f in ../../../airflow-dev/helm-chart/${VERSION}${VERSION_SUFFIX}/*; do svn cp $f ${$(basename $f)/}; done
svn rm index.yaml
-svn commit -m "Release Airflow Helm Chart Check ${VERSION} from ${RC}"
+svn commit -m "Release Airflow Helm Chart Check ${VERSION} from ${VERSION}${VERSION_SUFFIX}"
```
@@ -587,9 +660,9 @@ Create and push the release tag:
```shell
cd "${AIRFLOW_REPO_ROOT}"
-git checkout helm-chart/${RC}
+git checkout helm-chart/${VERSION}${VERSION_SUFFIX}
git tag -s helm-chart/${VERSION} -m "Apache Airflow Helm Chart ${VERSION}"
-git push origin helm-chart/${VERSION}
+git push apache helm-chart/${VERSION}
```
## Publish documentation
@@ -605,7 +678,7 @@ between the two repositories to be able to build the documentation.
git clone https://github.com/apache/airflow-site.git airflow-site
cd airflow-site
git checkout -b helm-${VERSION}-docs
- export AIRFLOW_SITE_DIRECTORY="$(pwd)"
+ export AIRFLOW_SITE_DIRECTORY="$(pwd -P)"
```
- Then you can go to the directory and build the necessary documentation packages
@@ -634,9 +707,9 @@ between the two repositories to be able to build the documentation.
```shell
breeze release-management add-back-references helm-chart
- curl https://dist.apache.org/repos/dist/dev/airflow/helm-chart/$RC/index.yaml -o index.yaml
+ curl https://dist.apache.org/repos/dist/dev/airflow/helm-chart/${VERSION}${VERSION_SUFFIX}/index.yaml -o index.yaml
cp ${AIRFLOW_SVN_RELEASE_HELM}/${VERSION}/airflow-${VERSION}.tgz .
- helm repo index --merge ./index.yaml . --url "https://downloads.apache.org/airflow/helm-chart/$VERSION"
+ helm repo index --merge ./index.yaml . --url "https://downloads.apache.org/airflow/helm-chart/${VERSION}"
rm airflow-${VERSION}.tgz
mv index.yaml landing-pages/site/static/index.yaml
```
@@ -669,15 +742,15 @@ Body:
cat <<EOF
Dear Airflow community,
-I am pleased to announce that we have released Apache Airflow Helm chart $VERSION 🎉 🎊
+I am pleased to announce that we have released Apache Airflow Helm chart ${VERSION} 🎉 🎊
The source release, as well as the "binary" Helm Chart release, are available:
-📦 Official Sources: https://airflow.apache.org/docs/helm-chart/$VERSION/installing-helm-chart-from-sources.html
+📦 Official Sources: https://airflow.apache.org/docs/helm-chart/${VERSION}/installing-helm-chart-from-sources.html
📦 ArtifactHub: https://artifacthub.io/packages/helm/apache-airflow/airflow
-📚 Docs: https://airflow.apache.org/docs/helm-chart/$VERSION/
-🚀 Quick Start Installation Guide: https://airflow.apache.org/docs/helm-chart/$VERSION/quick-start.html
-🛠️ Release Notes: https://airflow.apache.org/docs/helm-chart/$VERSION/release_notes.html
+📚 Docs: https://airflow.apache.org/docs/helm-chart/${VERSION}/
+🚀 Quick Start Installation Guide: https://airflow.apache.org/docs/helm-chart/${VERSION}/quick-start.html
+🛠️ Release Notes: https://airflow.apache.org/docs/helm-chart/${VERSION}/release_notes.html
Thanks to all the contributors who made this possible.
@@ -740,9 +813,9 @@ cat <<EOF
We've just released Apache Airflow Helm Chart ${VERSION} 🎉
📦 ArtifactHub: https://artifacthub.io/packages/helm/apache-airflow/airflow
-📚 Docs: https://airflow.apache.org/docs/helm-chart/$VERSION/
-🚀 Quick Start Installation Guide: https://airflow.apache.org/docs/helm-chart/$VERSION/quick-start.html
-🛠 Release Notes: https://airflow.apache.org/docs/helm-chart/$VERSION/release_notes.html
+📚 Docs: https://airflow.apache.org/docs/helm-chart/${VERSION}/
+🚀 Quick Start Installation Guide: https://airflow.apache.org/docs/helm-chart/${VERSION}/quick-start.html
+🛠 Release Notes: https://airflow.apache.org/docs/helm-chart/${VERSION}/release_notes.html
Thanks to all the contributors who made this possible.
EOF
@@ -766,11 +839,11 @@ Tweet and post on Linkedin about the release:
```shell
cat <<EOF
-We've just released Apache Airflow Helm chart $VERSION 🎉
+We've just released Apache Airflow Helm chart ${VERSION} 🎉
📦 ArtifactHub: https://artifacthub.io/packages/helm/apache-airflow/airflow
-📚 Docs: https://airflow.apache.org/docs/helm-chart/$VERSION/
-🛠️ Release Notes: https://airflow.apache.org/docs/helm-chart/$VERSION/release_notes.html
+📚 Docs: https://airflow.apache.org/docs/helm-chart/${VERSION}/
+🛠️ Release Notes: https://airflow.apache.org/docs/helm-chart/${VERSION}/release_notes.html
Thanks to all the contributors who made this possible.
EOF
diff --git a/dev/breeze/README.md b/dev/breeze/README.md
index 0786647629..52bbaaa4ae 100644
--- a/dev/breeze/README.md
+++ b/dev/breeze/README.md
@@ -66,6 +66,6 @@ PLEASE DO NOT MODIFY THE HASH BELOW! IT IS AUTOMATICALLY UPDATED BY PRE-COMMIT.
---------------------------------------------------------------------------------------------------------
-Package config hash: 5253de328868bc7e725254e1efe2daa57e7b1faee1b0be68aa8609569e47d08a1e0be4760bf889f422c4ce5c2884577c1300cd2f2292f2cb4677b1d1d160916c
+Package config hash: f22d0c615925c3accb40fc1cf0ca5dc9ca57719968df55f12e96383bc5072113aef6d785565ae33f2f73889388ba2a2136a010f5dbfe12fe3cb90bc88c058bcb
---------------------------------------------------------------------------------------------------------
diff --git a/dev/breeze/doc/images/output_release-management.svg b/dev/breeze/doc/images/output_release-management.svg
index 34ce075ae3..9d1efaaac4 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 830.8" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 928.4" 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="779.8" />
+ <rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="breeze-release-management-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -137,9 +137,21 @@
<clipPath id="breeze-release-management-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-release-management-line-31">
+ <rect x="0" y="757.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-line-32">
+ <rect x="0" y="782.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-line-33">
+ <rect x="0" y="806.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-line-34">
+ <rect x="0" y="831.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="828.8" rx="8"/><text class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: release-management</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: 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"/>
@@ -165,22 +177,26 @@
</text><text class="breeze-release-management-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-release-management-line-13)">│</text><text class="breeze-release-management-r4" x="24.4" y="337.2" textLength="353.8" clip-path="url(#breeze-release-management-line-13)">start-release                </text><text class="breeze-release-management-r1" x="402.6" y="337.2" textLength="1037" clip-path="url(#br [...]
</text><text class="breeze-release-management-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-release-management-line-14)">│</text><text class="breeze-release-management-r4" x="24.4" y="361.6" textLength="353.8" clip-path="url(#breeze-release-management-line-14)">release-prod-images          </text><text class="breeze-release-management-r1" x="402.6" y="361.6" textLength="1037" clip-path="url(#breeze-release-management-line-1 [...]
</text><text class="breeze-release-management-r5" x="0" y="386" textLength="1464" clip-path="url(#breeze-release-management-line-15)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-release-management-line-15)">
-</text><text class="breeze-release-management-r5" x="0" y="410.4" textLength="24.4" clip-path="url(#breeze-release-management-line-16)">╭─</text><text class="breeze-release-management-r5" x="24.4" y="410.4" textLength="341.6" clip-path="url(#breeze-release-management-line-16)"> Providers release commands </text><text class="breeze-release-management-r5" x="366" y="410.4" textLength="1073.6" clip-path="url(#breeze-release-management-line-16)">────────────────────────── [...]
-</text><text class="breeze-release-management-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-line-17)">│</text><text class="breeze-release-management-r4" x="24.4" y="434.8" textLength="439.2" clip-path="url(#breeze-release-management-line-17)">prepare-provider-documentation      </text><text class="breeze-release-management-r1" x="488" y="434.8" textLength="951.6" clip-path="url(#breeze-release-management-line-17)">Prepare [...]
-</text><text class="breeze-release-management-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-line-18)">│</text><text class="breeze-release-management-r4" x="24.4" y="459.2" textLength="439.2" clip-path="url(#breeze-release-management-line-18)">prepare-provider-packages           </text><text class="breeze-release-management-r1" x="488" y="459.2" textLength="951.6" clip-path="url(#breeze-release-manage [...]
-</text><text class="breeze-release-management-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-release-management-line-19)">│</text><text class="breeze-release-management-r4" x="24.4" y="483.6" textLength="439.2" clip-path="url(#breeze-release-management-line-19)">install-provider-packages           </text><text class="breeze-release-management-r1" x="488" y="483.6" textLength="951.6" clip-path="url(#breeze-release-manage [...]
-</text><text class="breeze-release-management-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-release-management-line-20)">│</text><text class="breeze-release-management-r4" x="24.4" y="508" textLength="439.2" clip-path="url(#breeze-release-management-line-20)">verify-provider-packages            </text><text class="breeze-release-management-r1" x="488" y="508" textLength="951.6" clip-path="url(#breeze-release-managem [...]
-</text><text class="breeze-release-management-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-release-management-line-21)">│</text><text class="breeze-release-management-r4" x="24.4" y="532.4" textLength="439.2" clip-path="url(#breeze-release-management-line-21)">generate-providers-metadata         </text><text class="breeze-release-management-r1" x="488" y="532.4" textLength="951.6" clip-path="url(#breeze-release-management-line- [...]
-</text><text class="breeze-release-management-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-release-management-line-22)">│</text><text class="breeze-release-management-r4" x="24.4" y="556.8" textLength="439.2" clip-path="url(#breeze-release-management-line-22)">generate-issue-content-providers    </text><text class="breeze-release-management-r1" x="488" y="556.8" textLength="951.6" clip-path="url(#breeze-release-management-line-22)">Generates conte [...]
-</text><text class="breeze-release-management-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-line-23)">│</text><text class="breeze-release-management-r4" x="24.4" y="581.2" textLength="439.2" clip-path="url(#breeze-release-management-line-23)">clean-old-provider-artifacts        </text><text class="breeze-release-management-r1" x="488" y="581.2" textLength="951.6" clip-path="url(#breeze-release-management-line-23)"> [...]
-</text><text class="breeze-release-management-r5" x="0" y="605.6" textLength="1464" clip-path="url(#breeze-release-management-line-24)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-release-management-line-24)">
-</text><text class="breeze-release-management-r5" x="0" y="630" textLength="24.4" clip-path="url(#breeze-release-management-line-25)">╭─</text><text class="breeze-release-management-r5" x="24.4" y="630" textLength="292.8" clip-path="url(#breeze-release-management-line-25)"> Other release commands </text><text class="breeze-release-management-r5" x="317.2" y="630" textLength="1122.4" clip-path="url(#breeze-release-management-line-25)">────────────────────────────────── [...]
-</text><text class="breeze-release-management-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">│</text><text class="breeze-release-management-r4" x="24.4" y="654.4" textLength="292.8" clip-path="url(#breeze-release-management-line-26)">add-back-references     </text><text class="breeze-release-management-r1" x="341.6" y="654.4" textLength="1098" clip-path="url(#breeze-release-management-line-26)">Command to add&# [...]
-</text><text class="breeze-release-management-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">│</text><text class="breeze-release-management-r4" x="24.4" y="678.8" textLength="292.8" clip-path="url(#breeze-release-management-line-27)">prepare-python-client   </text><text class="breeze-release-management-r1" x="341.6" y="678.8" textLength="1098" clip-path="url(#breeze-release-management-line-27)">Prepares python client [...]
-</text><text class="breeze-release-management-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">│</text><text class="breeze-release-management-r4" x="24.4" y="703.2" textLength="292.8" clip-path="url(#breeze-release-management-line-28)">publish-docs            </text><text class="breeze-release-management-r1" x="341.6" y="703.2" textLength="1098" clip-path="url(#breeze-release-management-l [...]
-</text><text class="breeze-release-management-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-release-management-line-29)">│</text><text class="breeze-release-management-r4" x="24.4" y="727.6" textLength="292.8" clip-path="url(#breeze-release-management-line-29)">generate-constraints    </text><text class="breeze-release-management-r1" x="341.6" y="727.6" textLength="1098" clip-path="url(#breeze-release-management-line-29)">Generates pinned cons [...]
-</text><text class="breeze-release-management-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-release-management-line-30)">│</text><text class="breeze-release-management-r4" x="24.4" y="752" textLength="292.8" clip-path="url(#breeze-release-management-line-30)">update-constraints      </text><text class="breeze-release-management-r1" x="341.6" y="752" textLength="1098" clip-path="url(#breeze-release-management-line-30)">Update released c [...]
-</text><text class="breeze-release-management-r5" x="0" y="776.4" textLength="1464" clip-path="url(#breeze-release-management-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-release-management-line-31)">
+</text><text class="breeze-release-management-r5" x="0" y="410.4" textLength="24.4" clip-path="url(#breeze-release-management-line-16)">╭─</text><text class="breeze-release-management-r5" x="24.4" y="410.4" textLength="280.6" clip-path="url(#breeze-release-management-line-16)"> Helm release commands </text><text class="breeze-release-management-r5" x="305" y="410.4" textLength="1134.6" clip-path="url(#breeze-release-management-line-16)">─────────────────────────────── [...]
+</text><text class="breeze-release-management-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-line-17)">│</text><text class="breeze-release-management-r4" x="24.4" y="434.8" textLength="671" clip-path="url(#breeze-release-management-line-17)">prepare-helm-chart-tarball                             </text><text clas [...]
+</text><text class="breeze-release-management-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-line-18)">│</text><text class="breeze-release-management-r4" x="24.4" y="459.2" textLength="671" clip-path="url(#breeze-release-management-line-18)">prepare-helm-chart-package                             </text><text clas [...]
+</text><text class="breeze-release-management-r5" x="0" y="483.6" textLength="1464" clip-path="url(#breeze-release-management-line-19)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-release-management-line-19)">
+</text><text class="breeze-release-management-r5" x="0" y="508" textLength="24.4" clip-path="url(#breeze-release-management-line-20)">╭─</text><text class="breeze-release-management-r5" x="24.4" y="508" textLength="341.6" clip-path="url(#breeze-release-management-line-20)"> Providers release commands </text><text class="breeze-release-management-r5" x="366" y="508" textLength="1073.6" clip-path="url(#breeze-release-management-line-20)">──────────────────────────────── [...]
+</text><text class="breeze-release-management-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-release-management-line-21)">│</text><text class="breeze-release-management-r4" x="24.4" y="532.4" textLength="439.2" clip-path="url(#breeze-release-management-line-21)">prepare-provider-documentation      </text><text class="breeze-release-management-r1" x="488" y="532.4" textLength="951.6" clip-path="url(#breeze-release-management-line-21)">Prepare [...]
+</text><text class="breeze-release-management-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-release-management-line-22)">│</text><text class="breeze-release-management-r4" x="24.4" y="556.8" textLength="439.2" clip-path="url(#breeze-release-management-line-22)">prepare-provider-packages           </text><text class="breeze-release-management-r1" x="488" y="556.8" textLength="951.6" clip-path="url(#breeze-release-manage [...]
+</text><text class="breeze-release-management-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-line-23)">│</text><text class="breeze-release-management-r4" x="24.4" y="581.2" textLength="439.2" clip-path="url(#breeze-release-management-line-23)">install-provider-packages           </text><text class="breeze-release-management-r1" x="488" y="581.2" textLength="951.6" clip-path="url(#breeze-release-manage [...]
+</text><text class="breeze-release-management-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-release-management-line-24)">│</text><text class="breeze-release-management-r4" x="24.4" y="605.6" textLength="439.2" clip-path="url(#breeze-release-management-line-24)">verify-provider-packages            </text><text class="breeze-release-management-r1" x="488" y="605.6" textLength="951.6" clip-path="url(#breeze-release-m [...]
+</text><text class="breeze-release-management-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-release-management-line-25)">│</text><text class="breeze-release-management-r4" x="24.4" y="630" textLength="439.2" clip-path="url(#breeze-release-management-line-25)">generate-providers-metadata         </text><text class="breeze-release-management-r1" x="488" y="630" textLength="951.6" clip-path="url(#breeze-release-management-line-25)">G [...]
+</text><text class="breeze-release-management-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-release-management-line-26)">│</text><text class="breeze-release-management-r4" x="24.4" y="654.4" textLength="439.2" clip-path="url(#breeze-release-management-line-26)">generate-issue-content-providers    </text><text class="breeze-release-management-r1" x="488" y="654.4" textLength="951.6" clip-path="url(#breeze-release-management-line-26)">Generates conte [...]
+</text><text class="breeze-release-management-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-release-management-line-27)">│</text><text class="breeze-release-management-r4" x="24.4" y="678.8" textLength="439.2" clip-path="url(#breeze-release-management-line-27)">clean-old-provider-artifacts        </text><text class="breeze-release-management-r1" x="488" y="678.8" textLength="951.6" clip-path="url(#breeze-release-management-line-27)"> [...]
+</text><text class="breeze-release-management-r5" x="0" y="703.2" textLength="1464" clip-path="url(#breeze-release-management-line-28)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-release-management-line-28)">
+</text><text class="breeze-release-management-r5" x="0" y="727.6" textLength="24.4" clip-path="url(#breeze-release-management-line-29)">╭─</text><text class="breeze-release-management-r5" x="24.4" y="727.6" textLength="292.8" clip-path="url(#breeze-release-management-line-29)"> Other release commands </text><text class="breeze-release-management-r5" x="317.2" y="727.6" textLength="1122.4" clip-path="url(#breeze-release-management-line-29)">──────────────────────────── [...]
+</text><text class="breeze-release-management-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-release-management-line-30)">│</text><text class="breeze-release-management-r4" x="24.4" y="752" textLength="292.8" clip-path="url(#breeze-release-management-line-30)">add-back-references     </text><text class="breeze-release-management-r1" x="341.6" y="752" textLength="1098" clip-path="url(#breeze-release-management-line-30)">Command to add ba [...]
+</text><text class="breeze-release-management-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-release-management-line-31)">│</text><text class="breeze-release-management-r4" x="24.4" y="776.4" textLength="292.8" clip-path="url(#breeze-release-management-line-31)">prepare-python-client   </text><text class="breeze-release-management-r1" x="341.6" y="776.4" textLength="1098" clip-path="url(#breeze-release-management-line-31)">Prepares python client [...]
+</text><text class="breeze-release-management-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-release-management-line-32)">│</text><text class="breeze-release-management-r4" x="24.4" y="800.8" textLength="292.8" clip-path="url(#breeze-release-management-line-32)">publish-docs            </text><text class="breeze-release-management-r1" x="341.6" y="800.8" textLength="1098" clip-path="url(#breeze-release-management-l [...]
+</text><text class="breeze-release-management-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#breeze-release-management-line-33)">│</text><text class="breeze-release-management-r4" x="24.4" y="825.2" textLength="292.8" clip-path="url(#breeze-release-management-line-33)">generate-constraints    </text><text class="breeze-release-management-r1" x="341.6" y="825.2" textLength="1098" clip-path="url(#breeze-release-management-line-33)">Generates pinned cons [...]
+</text><text class="breeze-release-management-r5" x="0" y="849.6" textLength="12.2" clip-path="url(#breeze-release-management-line-34)">│</text><text class="breeze-release-management-r4" x="24.4" y="849.6" textLength="292.8" clip-path="url(#breeze-release-management-line-34)">update-constraints      </text><text class="breeze-release-management-r1" x="341.6" y="849.6" textLength="1098" clip-path="url(#breeze-release-management-line-34)">Update released& [...]
+</text><text class="breeze-release-management-r5" x="0" y="874" textLength="1464" clip-path="url(#breeze-release-management-line-35)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-r1" x="1464" y="874" textLength="12.2" clip-path="url(#breeze-release-management-line-35)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_release-management.txt b/dev/breeze/doc/images/output_release-management.txt
index 4a66a02926..a54617592f 100644
--- a/dev/breeze/doc/images/output_release-management.txt
+++ b/dev/breeze/doc/images/output_release-management.txt
@@ -1 +1 @@
-8de953c7706d780e6598d34b93a65714
+7e7d82328d7a6d8862d663b4a0a25767
diff --git a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.svg b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.svg
new file mode 100644
index 0000000000..d50a3adc23
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.svg
@@ -0,0 +1,112 @@
+<svg class="rich-terminal" viewBox="0 0 1482 367.2" xmlns="http://www.w3.org/2000/svg">
+ <!-- Generated with Rich https://www.textualize.io -->
+ <style>
+
+ @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-prepare-helm-chart-package-matrix {
+ font-family: Fira Code, monospace;
+ font-size: 20px;
+ line-height: 24.4px;
+ font-variant-east-asian: full-width;
+ }
+
+ .breeze-release-management-prepare-helm-chart-package-title {
+ font-size: 18px;
+ font-weight: bold;
+ font-family: arial;
+ }
+
+ .breeze-release-management-prepare-helm-chart-package-r1 { fill: #c5c8c6 }
+.breeze-release-management-prepare-helm-chart-package-r2 { fill: #d0b344 }
+.breeze-release-management-prepare-helm-chart-package-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-release-management-prepare-helm-chart-package-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-release-management-prepare-helm-chart-package-r5 { fill: #868887 }
+.breeze-release-management-prepare-helm-chart-package-r6 { fill: #8d7b39 }
+.breeze-release-management-prepare-helm-chart-package-r7 { fill: #98a84b;font-weight: bold }
+ </style>
+
+ <defs>
+ <clipPath id="breeze-release-management-prepare-helm-chart-package-clip-terminal">
+ <rect x="0" y="0" width="1463.0" height="316.2" />
+ </clipPath>
+ <clipPath id="breeze-release-management-prepare-helm-chart-package-line-0">
+ <rect x="0" y="1.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-1">
+ <rect x="0" y="25.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-2">
+ <rect x="0" y="50.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-3">
+ <rect x="0" y="74.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-4">
+ <rect x="0" y="99.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-5">
+ <rect x="0" y="123.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-6">
+ <rect x="0" y="147.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-10">
+ <rect x="0" y="245.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-package-line-11">
+ <rect x="0" y="269.9" width="1464" height="24.65"/>
+ </clipPath>
+ </defs>
+
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="365.2" rx="8"/><text class="breeze-release-management-prepare-helm-chart-package-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: release-management prepare-helm-chart-package</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-prepare-helm-chart-package-clip-terminal)">
+
+ <g class="breeze-release-management-prepare-helm-chart-package-matrix">
+ <text class="breeze-release-management-prepare-helm-chart-package-r1" x="1464" y="20" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-0)">
+</text><text class="breeze-release-management-prepare-helm-chart-package-r2" x="12.2" y="44.4" textLength="73.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-1)">Usage:</text><text class="breeze-release-management-prepare-helm-chart-package-r3" x="97.6" y="44.4" textLength="634.4" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-1)">breeze release-management prepare-helm-chart-package</text><text class="breeze-release-manage [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-2)">
+</text><text class="breeze-release-management-prepare-helm-chart-package-r1" x="12.2" y="93.2" textLength="341.6" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-3)">Prepares helm chart package.</text><text class="breeze-release-management-prepare-helm-chart-package-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-3)">
+</text><text class="breeze-release-management-prepare-helm-chart-package-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-4)">
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="142" textLength="24.4" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-5)">╭─</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="24.4" y="142" textLength="183" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-5)"> Package flags </text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="207. [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-6)">│</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="24.4" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-6)">-</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="36.6" y="166.4" textLength="6 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="190.8" textLength="1464" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-7)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-helm-chart-package-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package- [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="215.2" textLength="24.4" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-8)">╭─</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="24.4" y="215.2" textLength="195.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-8)"> Common options </text><text class="breeze-release-management-prepare-helm-chart-package-r5" [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-9)">│</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="24.4" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-9)">-</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="36.6" y="239.6" textLength="4 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-10)">│</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="24.4" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-10)">-</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="36.6" y="264" textLength="97.6" [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-11)">│</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="24.4" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-11)">-</text><text class="breeze-release-management-prepare-helm-chart-package-r4" x="36.6" y="288.4" textLength= [...]
+</text><text class="breeze-release-management-prepare-helm-chart-package-r5" x="0" y="312.8" textLength="1464" clip-path="url(#breeze-release-management-prepare-helm-chart-package-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-helm-chart-package-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-package [...]
+</text>
+ </g>
+ </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt
new file mode 100644
index 0000000000..a0c9091169
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-package.txt
@@ -0,0 +1 @@
+8c3be9f78286641f5657f890745ef936
diff --git a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.svg b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.svg
new file mode 100644
index 0000000000..f4055c7d56
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.svg
@@ -0,0 +1,166 @@
+<svg class="rich-terminal" viewBox="0 0 1482 684.4" 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-prepare-helm-chart-tarball-matrix {
+ font-family: Fira Code, monospace;
+ font-size: 20px;
+ line-height: 24.4px;
+ font-variant-east-asian: full-width;
+ }
+
+ .breeze-release-management-prepare-helm-chart-tarball-title {
+ font-size: 18px;
+ font-weight: bold;
+ font-family: arial;
+ }
+
+ .breeze-release-management-prepare-helm-chart-tarball-r1 { fill: #c5c8c6 }
+.breeze-release-management-prepare-helm-chart-tarball-r2 { fill: #d0b344 }
+.breeze-release-management-prepare-helm-chart-tarball-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-release-management-prepare-helm-chart-tarball-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-release-management-prepare-helm-chart-tarball-r5 { fill: #868887 }
+.breeze-release-management-prepare-helm-chart-tarball-r6 { fill: #8d7b39 }
+.breeze-release-management-prepare-helm-chart-tarball-r7 { fill: #cc555a }
+.breeze-release-management-prepare-helm-chart-tarball-r8 { fill: #8a4346 }
+.breeze-release-management-prepare-helm-chart-tarball-r9 { fill: #98a84b;font-weight: bold }
+ </style>
+
+ <defs>
+ <clipPath id="breeze-release-management-prepare-helm-chart-tarball-clip-terminal">
+ <rect x="0" y="0" width="1463.0" height="633.4" />
+ </clipPath>
+ <clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-0">
+ <rect x="0" y="1.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-1">
+ <rect x="0" y="25.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-2">
+ <rect x="0" y="50.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-3">
+ <rect x="0" y="74.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-4">
+ <rect x="0" y="99.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-5">
+ <rect x="0" y="123.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-6">
+ <rect x="0" y="147.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-10">
+ <rect x="0" y="245.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-11">
+ <rect x="0" y="269.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-12">
+ <rect x="0" y="294.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-13">
+ <rect x="0" y="318.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-14">
+ <rect x="0" y="343.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-15">
+ <rect x="0" y="367.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-16">
+ <rect x="0" y="391.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-17">
+ <rect x="0" y="416.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-18">
+ <rect x="0" y="440.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-19">
+ <rect x="0" y="465.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-20">
+ <rect x="0" y="489.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-21">
+ <rect x="0" y="513.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-22">
+ <rect x="0" y="538.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-23">
+ <rect x="0" y="562.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-release-management-prepare-helm-chart-tarball-line-24">
+ <rect x="0" y="587.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="682.4" rx="8"/><text class="breeze-release-management-prepare-helm-chart-tarball-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: release-management prepare-helm-chart-tarball</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-prepare-helm-chart-tarball-clip-terminal)">
+
+ <g class="breeze-release-management-prepare-helm-chart-tarball-matrix">
+ <text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="1464" y="20" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-0)">
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r2" x="12.2" y="44.4" textLength="73.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-1)">Usage:</text><text class="breeze-release-management-prepare-helm-chart-tarball-r3" x="97.6" y="44.4" textLength="634.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-1)">breeze release-management prepare-helm-chart-tarball</text><text class="breeze-release-manage [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-2)">
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="12.2" y="93.2" textLength="341.6" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-3)">Prepares helm chart tarball.</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-3)">
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-4)">
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="142" textLength="24.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-5)">╭─</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="24.4" y="142" textLength="183" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-5)"> Package flags </text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="207. [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-6)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="61" y="166.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-6)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="73.2" y="166.4" textLength="97. [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-7)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="378.2" y="190.8" textLength="280.6" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-7)">Chart.yaml, unless the </text><text class="breeze-release-management-prepare-helm-chart-tarba [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-8)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r6" x="378.2" y="215.2" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-8)">(TEXT)                  [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-9)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r7" x="24.4" y="239.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-9)">*</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="61" y="239.6" textLength="12. [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-10)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="378.2" y="264" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-10)">archive using release candidate tag.          [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-11)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r6" x="378.2" y="288.4" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-11)">(TEXT)                 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-12)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r8" x="378.2" y="312.8" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-12)">[required]                 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-13)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="61" y="337.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-13)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="73.2" y="337.2" textLength="8 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-14)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="378.2" y="361.6" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-14)">is correctly set in the Chart.yaml.        [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-15)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="61" y="386" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-15)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="73.2" y="386" textLength="109.8" [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-16)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="378.2" y="410.4" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-16)">when youtest the breeze command locally.       [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-17)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="61" y="434.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-17)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="73.2" y="434.8" textLength="6 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-18)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="378.2" y="459.2" textLength="1061.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-18)">chart.                 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-19)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="61" y="483.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-19)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="73.2" y="483.6" textLength="6 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="508" textLength="1464" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-20)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-20)">
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="532.4" textLength="24.4" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-21)">╭─</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="24.4" y="532.4" textLength="195.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-21)"> Common options </text><text class="breeze-release-management-prepare-helm-chart-tarball-r5 [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-22)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="24.4" y="556.8" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-22)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="36.6" y="556.8" textLength= [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-23)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="24.4" y="581.2" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-23)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="36.6" y="581.2" textLength= [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-24)">│</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="24.4" y="605.6" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-24)">-</text><text class="breeze-release-management-prepare-helm-chart-tarball-r4" x="36.6" y="605.6" textLength= [...]
+</text><text class="breeze-release-management-prepare-helm-chart-tarball-r5" x="0" y="630" textLength="1464" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-25)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-release-management-prepare-helm-chart-tarball-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-release-management-prepare-helm-chart-tarball-line-25)">
+</text>
+ </g>
+ </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt
new file mode 100644
index 0000000000..9f7304e817
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_prepare-helm-chart-tarball.txt
@@ -0,0 +1 @@
+d57dc8d296addbea3fd3285e2063c102
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 ae38c42e96..eab9041eff 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
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 879.5999999999999" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 904.0" xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-setup-check-all-params-in-groups-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="828.5999999999999" />
+ <rect x="0" y="0" width="1463.0" height="853.0" />
</clipPath>
<clipPath id="breeze-setup-check-all-params-in-groups-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -144,9 +144,12 @@
<clipPath id="breeze-setup-check-all-params-in-groups-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-setup-check-all-params-in-groups-line-33">
+ <rect x="0" y="806.7" 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="877.6" rx="8"/><text class="breeze-setup-check-all-params-in-groups-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup check-all-params-in-groups</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="902" rx="8"/><text class="breeze-setup-check-all-params-in-groups-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup check-all-params-in-groups</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -174,22 +177,23 @@
</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:generate-constraints | release-management:generate-issue-content-providers |        </tex [...]
</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:generate-providers-metadata | release-management:install-provider-packages |        < [...]
</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:prepare-airflow-package | release-management:prepare-airflow-tarball |         & [...]
-</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:prepare-provider-documentation | release-management:prepare-provider-packages |     </text><text cla [...]
-</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:prepare-python-client | release-management:publish-docs |           &# [...]
-</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:release-prod-images | release-management:start-rc-process |            [...]
-</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:start-release | release-management:update-constraints |            [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="556.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:verify-provider-packages | sbom | sbom:build-all-airflow-images |        &# [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="581.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">sbom:generate-providers-requirements | sbom:update-sbom-information | setup | setup:autocomplete |    &# [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="605.6" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">setup:check-all-params-in-groups | setup:config | setup:regenerate-command-images | setup:self-upgrade </text><text class="b [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="630" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">| setup:synchronize-local-mounts | setup:version | shell | start-airflow | static-checks | testing | [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="654.4" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">testing:db-tests | testing:docker-compose-tests | testing:helm-tests | testing:integration-tests |    &# [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="678.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">testing:non-db-tests | testing:tests)                   [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="703.2" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="727.6" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="727.6" textLength="195.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)"> Common options </text><text class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="727.6" textLength="1220" clip-path="url(#breeze-se [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="752" textLength="97.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30) [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="776.4" textLength="48.8" clip-path="url(#breeze-setup-check-all-params-in-groups-li [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="800.8" textLength="61" clip-path="url(#breeze-setup-check-all-params-in-groups-line [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="825.2" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">
+</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:prepare-helm-chart-package | release-management:prepare-helm-chart-tarball |        < [...]
+</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:prepare-provider-documentation | release-management:prepare-provider-packages |     </text><text cla [...]
+</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:prepare-python-client | release-management:publish-docs |             [...]
+</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:release-prod-images | release-management:start-rc-process |            [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="556.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:start-release | release-management:update-constraints |            [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="581.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">release-management:verify-provider-packages | sbom | sbom:build-all-airflow-images |        &# [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="605.6" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">sbom:generate-providers-requirements | sbom:update-sbom-information | setup | setup:autocomplete |    &# [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="630" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">setup:check-all-params-in-groups | setup:config | setup:regenerate-command-images | setup:self-upgrade </text><text class="breez [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="654.4" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">| setup:synchronize-local-mounts | setup:version | shell | start-airflow | static-checks | testing  [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="678.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">testing:db-tests | testing:docker-compose-tests | testing:helm-tests | testing:integration-tests |    &# [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="183" y="703.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">testing:non-db-tests | testing:tests)                   [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="727.6" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="752" textLength="195.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)"> Common options </text><text class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="752" textLength="1220" clip-path="url(#breeze-setup-ch [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="776.4" textLength="97.6" clip-path="url(#breeze-setup-check-all-params-in-groups-li [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="800.8" textLength="48.8" clip-path="url(#breeze-setup-check-all-params-in-groups-li [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">-</text><text class="breeze-setup-check-all-params-in-groups-r4" x="36.6" y="825.2" textLength="61" clip-path="url(#breeze-setup-check-all-params-in-groups-line [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="849.6" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">
</text>
</g>
</g>
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 bc749d3570..a8b551c86c 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 @@
-0ca4a64e910acc7ff95e90385b3c1540
+c460ad112eb9edf1a3bf7246b024dfcc
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 11bca82b2d..7c51079230 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 952.8" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 977.1999999999999" 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="901.8" />
+ <rect x="0" y="0" width="1463.0" height="926.1999999999999" />
</clipPath>
<clipPath id="breeze-setup-regenerate-command-images-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -153,9 +153,12 @@
<clipPath id="breeze-setup-regenerate-command-images-line-35">
<rect x="0" y="855.5" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-setup-regenerate-command-images-line-36">
+ <rect x="0" y="879.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="950.8" rx="8"/><text class="breeze-setup-regenerate-command-images-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup regenerate-command-images</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="975.2" rx="8"/><text class="breeze-setup-regenerate-command-images-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup 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"/>
@@ -184,24 +187,25 @@
</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:generate-constraints | release-management:generate-issue-content-providers |     </text><text class="bre [...]
</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:generate-providers-metadata | release-management:install-provider-packages |     </text><text class="bre [...]
</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:prepare-airflow-package | release-management:prepare-airflow-tarball |           [...]
-</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:prepare-provider-documentation | release-management:prepare-provider-packages |  </text><text class="breeze-setup-regen [...]
-</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:prepare-python-client | release-management:publish-docs |             [...]
-</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:release-prod-images | release-management:start-rc-process |            [...]
-</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:start-release | release-management:update-constraints |            &# [...]
-</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:verify-provider-packages | sbom | sbom:build-all-airflow-images |          [...]
-</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)">sbom:generate-providers-requirements | sbom:update-sbom-information | setup | setup:autocomplete |  </text><text class [...]
-</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)">setup:check-all-params-in-groups | setup:config | setup:regenerate-command-images |           [...]
-</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)">setup:self-upgrade | setup:synchronize-local-mounts | setup:version | shell | start-airflow |    & [...]
-</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)">static-checks | testing | testing:db-tests | testing:docker-compose-tests | testing:helm-tests |    [...]
-</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)">testing:integration-tests | testing:non-db-tests | testing:tests)              [...]
-</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-r4" x="24.4" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="727.6" textLength="73.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29) [...]
-</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-r1" x="219.6" y="752" textLength="170.8" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">together with </text><text class="breeze-setup-regenerate-command-images-r4" x="390.4" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-com [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">╭─</text><text class="breeze-setup-regenerate-command-images-r5" x="24.4" y="800.8" textLength="195.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)"> Common options </text><text class="breeze-setup-regenerate-command-images-r5" x="219.6" y="800.8" textLength="1220" clip-path="url(#breeze-setup-r [...]
-</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-r4" x="24.4" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="825.2" textLength="97.6" clip-path="url(#breeze-setup-regenerate-command-images-line-33) [...]
-</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-r4" x="24.4" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="849.6" textLength="48.8" clip-path="url(#breeze-setup-regenerate-command-images-line-34) [...]
-</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-r4" x="24.4" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="874" textLength="61" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">-help< [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">
+</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:prepare-helm-chart-package | release-management:prepare-helm-chart-tarball |     </text><text class="bre [...]
+</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:prepare-provider-documentation | release-management:prepare-provider-packages |  </text><text class="breeze-setup-regenerat [...]
+</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:prepare-python-client | release-management:publish-docs |             [...]
+</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:release-prod-images | release-management:start-rc-process |            [...]
+</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:start-release | release-management:update-constraints |            &# [...]
+</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:verify-provider-packages | sbom | sbom:build-all-airflow-images |          [...]
+</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)">sbom:generate-providers-requirements | sbom:update-sbom-information | setup | setup:autocomplete |  </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)">setup:check-all-params-in-groups | setup:config | setup:regenerate-command-images |         & [...]
+</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)">setup:self-upgrade | setup:synchronize-local-mounts | setup:version | shell | start-airflow |    & [...]
+</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)">static-checks | testing | testing:db-tests | testing:docker-compose-tests | testing:helm-tests |    [...]
+</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)">testing:integration-tests | testing:non-db-tests | testing:tests)              [...]
+</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-r4" x="24.4" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="752" textLength="73.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">-che [...]
+</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-r1" x="219.6" y="776.4" textLength="170.8" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">together with </text><text class="breeze-setup-regenerate-command-images-r4" x="390.4" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenera [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">╭─</text><text class="breeze-setup-regenerate-command-images-r5" x="24.4" y="825.2" textLength="195.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)"> Common options </text><text class="breeze-setup-regenerate-command-images-r5" x="219.6" y="825.2" textLength="1220" clip-path="url(#breeze-setup-r [...]
+</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-r4" x="24.4" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="849.6" textLength="97.6" clip-path="url(#breeze-setup-regenerate-command-images-line-34) [...]
+</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-r4" x="24.4" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="874" textLength="48.8" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">-dry [...]
+</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-r4" x="24.4" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">-</text><text class="breeze-setup-regenerate-command-images-r4" x="36.6" y="898.4" textLength="61" clip-path="url(#breeze-setup-regenerate-command-images-line-36)"> [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="922.8" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">
</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 396d3494bb..255ecb40ff 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 @@
-2cd063e443a03f8dbacff6674a27dfe8
+0ae4af7ff2065325e7442c444a83d8e3
diff --git a/dev/breeze/pyproject.toml b/dev/breeze/pyproject.toml
index 438719faa7..6984f829be 100644
--- a/dev/breeze/pyproject.toml
+++ b/dev/breeze/pyproject.toml
@@ -60,7 +60,7 @@ dependencies = [
"psutil>=5.9.6",
"pygithub>=2.1.1",
"pytest-xdist>=3.3.1",
- "pytest>=7.4.0",
+ "pytest>=7.4.4",
"pyyaml>=6.0.1",
"requests>=2.31.0",
"rich-click>=1.7.1",
diff --git a/dev/breeze/src/airflow_breeze/commands/release_candidate_command.py b/dev/breeze/src/airflow_breeze/commands/release_candidate_command.py
index 0b35b8821d..a7b14234fe 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_candidate_command.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_candidate_command.py
@@ -25,8 +25,8 @@ from airflow_breeze.commands.common_options import option_answer
from airflow_breeze.commands.release_management_group import release_management
from airflow_breeze.utils.confirm import confirm_action
from airflow_breeze.utils.console import console_print
-from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT
-from airflow_breeze.utils.reproducible import archive_deterministically, get_source_date_epoch
+from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT, DIST_DIR, OUT_DIR
+from airflow_breeze.utils.reproducible import get_source_date_epoch, repack_deterministically
from airflow_breeze.utils.run_utils import run_command
CI = os.environ.get("CI")
@@ -71,53 +71,41 @@ def git_clean():
console_print("[success]Git repo cleaned")
-DIST_DIR = AIRFLOW_SOURCES_ROOT / "dist"
-OUT_DIR = AIRFLOW_SOURCES_ROOT / "out"
-REPRODUCIBLE_DIR = OUT_DIR / "reproducible"
-
-
def tarball_release(version: str, version_without_rc: str, source_date_epoch: int):
- if confirm_action("Create tarball?"):
- console_print(f"[info]Creating tarball for Airflow {version}")
- shutil.rmtree(OUT_DIR, ignore_errors=True)
- DIST_DIR.mkdir(exist_ok=True)
- OUT_DIR.mkdir(exist_ok=True)
- REPRODUCIBLE_DIR.mkdir(exist_ok=True)
- archive_name = f"apache-airflow-{version_without_rc}-source.tar.gz"
- temporary_archive = OUT_DIR / archive_name
- run_command(
- [
- "git",
- "-c",
- "tar.umask=0077",
- "archive",
- "--format=tar.gz",
- f"{version}",
- f"--prefix=apache-airflow-{version_without_rc}/",
- "-o",
- temporary_archive.as_posix(),
- ],
- check=True,
- )
- run_command(
- [
- "tar",
- "-xf",
- temporary_archive.as_posix(),
- "-C",
- REPRODUCIBLE_DIR.as_posix(),
- "--strip",
- "1",
- ]
- )
- final_archive = DIST_DIR / archive_name
- archive_deterministically(
- dir_to_archive=REPRODUCIBLE_DIR.as_posix(),
- dest_archive=final_archive.as_posix(),
- prepend_path=None,
- timestamp=source_date_epoch,
- )
- console_print(f"[success]Tarball created in {final_archive}")
+ console_print(f"[info]Creating tarball for Airflow {version}")
+ shutil.rmtree(OUT_DIR, ignore_errors=True)
+ DIST_DIR.mkdir(exist_ok=True)
+ OUT_DIR.mkdir(exist_ok=True)
+ archive_name = f"apache-airflow-{version_without_rc}-source.tar.gz"
+ temporary_archive = OUT_DIR / archive_name
+ result = run_command(
+ [
+ "git",
+ "-c",
+ "tar.umask=0077",
+ "archive",
+ "--format=tar.gz",
+ f"{version}",
+ f"--prefix=apache-airflow-{version_without_rc}/",
+ "-o",
+ temporary_archive.as_posix(),
+ ],
+ check=False,
+ )
+ if result.returncode != 0:
+ console_print(f"[error]Failed to create tarball {temporary_archive} for Airflow {version}")
+ exit(result.returncode)
+ final_archive = DIST_DIR / archive_name
+ result = repack_deterministically(
+ source_archive=temporary_archive,
+ dest_archive=final_archive,
+ prepend_path=None,
+ timestamp=source_date_epoch,
+ )
+ if result.returncode != 0:
+ console_print(f"[error]Failed to create tarball {temporary_archive} for Airflow {version}")
+ exit(result.returncode)
+ console_print(f"[success]Tarball created in {final_archive}")
def create_artifacts_with_hatch(source_date_epoch: int):
@@ -327,7 +315,7 @@ def prepare_airflow_tarball(version: str):
airflow_version = Version(version)
if not airflow_version.is_prerelease:
exit("--version value must be a pre-release")
- source_date_epoch = get_source_date_epoch()
+ source_date_epoch = get_source_date_epoch(AIRFLOW_SOURCES_ROOT / "airflow")
version_without_rc = airflow_version.base_version
# Create the tarball
tarball_release(
@@ -387,12 +375,13 @@ def publish_release_candidate(version, previous_version, github_token):
# # Tag & clean the repo
git_tag(version)
git_clean()
- source_date_epoch = get_source_date_epoch()
+ source_date_epoch = get_source_date_epoch(AIRFLOW_SOURCES_ROOT / "airflow")
shutil.rmtree(DIST_DIR, ignore_errors=True)
- # Create the tarball
- tarball_release(
- version=version, version_without_rc=version_without_rc, source_date_epoch=source_date_epoch
- )
+ if confirm_action("Create tarball?"):
+ # Create the tarball
+ tarball_release(
+ version=version, version_without_rc=version_without_rc, source_date_epoch=source_date_epoch
+ )
# Create the artifacts
if confirm_action("Use docker to create artifacts?"):
create_artifacts_with_docker()
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 3592220e92..c4516d9af2 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -133,6 +133,7 @@ from airflow_breeze.utils.path_utils import (
CONSTRAINTS_CACHE_DIR,
DIST_DIR,
GENERATED_PROVIDER_PACKAGES_DIR,
+ OUT_DIR,
PROVIDER_METADATA_JSON_FILE_PATH,
cleanup_python_generated_files,
)
@@ -142,7 +143,7 @@ from airflow_breeze.utils.provider_dependencies import (
get_related_providers,
)
from airflow_breeze.utils.python_versions import get_python_version_list
-from airflow_breeze.utils.reproducible import get_source_date_epoch
+from airflow_breeze.utils.reproducible import get_source_date_epoch, repack_deterministically
from airflow_breeze.utils.run_utils import (
run_command,
)
@@ -389,7 +390,7 @@ def prepare_airflow_packages(
perform_environment_checks()
fix_ownership_using_docker()
cleanup_python_generated_files()
- source_date_epoch = get_source_date_epoch()
+ source_date_epoch = get_source_date_epoch(AIRFLOW_SOURCES_ROOT / "airflow")
if use_local_hatch:
_build_airflow_packages_with_hatch(
package_format=package_format,
@@ -2394,3 +2395,272 @@ def prepare_python_client(
finally:
if version_suffix_for_pypi:
VERSION_FILE.write_text(original_version)
+
+
+CHART_DIR = AIRFLOW_SOURCES_ROOT / "chart"
+CHART_YAML_FILE = CHART_DIR / "Chart.yaml"
+VALUES_YAML_FILE = CHART_DIR / "values.yaml"
+
+
+@release_management.command(name="prepare-helm-chart-tarball", help="Prepares helm chart tarball.")
+@click.option(
+ "--version",
+ help="Version used for helm chart. This version has to be set and has to match the version in "
+ "Chart.yaml, unless the --ignore-version-check flag is used.",
+ envvar="VERSION",
+)
+@click.option(
+ "--version-suffix",
+ help="Version suffix used to publish the package. Needs to be present as we always build "
+ "archive using release candidate tag.",
+ required=True,
+ envvar="VERSION_SUFFIX",
+)
+@click.option(
+ "--ignore-version-check",
+ is_flag=True,
+ help="Ignores result of version update check. Produce tarball regardless of "
+ "whether version is correctly set in the Chart.yaml.",
+)
+@click.option(
+ "--skip-tagging",
+ is_flag=True,
+ help="Skip tagging the chart. Useful if the tag is already created, or when you verify the chart.",
+)
+@click.option(
+ "--skip-tag-signing",
+ is_flag=True,
+ help="Skip signing the tag. Useful for CI where we just tag without signing the tag.",
+)
+@click.option(
+ "--override-tag",
+ is_flag=True,
+ help="Override tag if it already exists. Useful when you want to re-create the tag, usually when you"
+ "test the breeze command locally.",
+)
+@option_dry_run
+@option_verbose
+def prepare_helm_chart_tarball(
+ version: str | None,
+ version_suffix: str,
+ ignore_version_check: bool,
+ override_tag: bool,
+ skip_tagging: bool,
+ skip_tag_signing: bool,
+) -> None:
+ import yaml
+
+ chart_yaml_file_content = CHART_YAML_FILE.read_text()
+ chart_yaml_dict = yaml.safe_load(chart_yaml_file_content)
+ version_in_chart = chart_yaml_dict["version"]
+ airflow_version_in_chart = chart_yaml_dict["appVersion"]
+ values_content = yaml.safe_load(VALUES_YAML_FILE.read_text())
+ airflow_version_in_values = values_content["airflowVersion"]
+ default_airflow_tag_in_values = values_content["defaultAirflowTag"]
+ if ignore_version_check:
+ if not version:
+ version = version_in_chart
+ else:
+ if not version or not version_suffix:
+ get_console().print(
+ "[error]You need to provide --version and --version-suffix parameter unless you "
+ "use --ignore-version-check[/]"
+ )
+ sys.exit(1)
+ get_console().print(f"[info]Airflow version in values.yaml: {airflow_version_in_values}[/]")
+ get_console().print(f"[info]Default Airflow Tag in values.yaml: {default_airflow_tag_in_values}[/]")
+ get_console().print(f"[info]Airflow version in Chart.yaml: {airflow_version_in_chart}[/]")
+ if airflow_version_in_values != default_airflow_tag_in_values:
+ get_console().print(
+ f"[error]Airflow version ({airflow_version_in_values}) does not match the "
+ f"defaultAirflowTag ({default_airflow_tag_in_values}) in values.yaml[/]"
+ )
+ sys.exit(1)
+ updating = False
+ if version_in_chart != version:
+ get_console().print(
+ f"[warning]Version in chart.yaml ({version_in_chart}) does not match the version "
+ f"passed as parameter ({version}). Updating[/]"
+ )
+ updating = True
+ chart_yaml_file_content = chart_yaml_file_content.replace(
+ f"version: {version_in_chart}", f"version: {version}"
+ )
+ else:
+ get_console().print(f"[success]Version in chart.yaml is good: {version}[/]")
+ if airflow_version_in_values != airflow_version_in_chart:
+ get_console().print(
+ f"[warning]Airflow version in Chart.yaml ({airflow_version_in_chart}) does not match the "
+ f"airflow version ({airflow_version_in_values}) in values.yaml. Updating[/]"
+ )
+ updating = True
+ chart_yaml_file_content = chart_yaml_file_content.replace(
+ f"appVersion: {airflow_version_in_chart}", f"appVersion: {airflow_version_in_values}"
+ )
+ else:
+ get_console().print(
+ f"[success]Airflow version in chart.yaml matches the airflow version in values.yaml: "
+ f"({airflow_version_in_values})[/]"
+ )
+ if updating:
+ CHART_YAML_FILE.write_text(chart_yaml_file_content)
+ get_console().print("\n[warning]Versions of the chart has been updated[/]\n")
+ if ignore_version_check:
+ get_console().print(
+ "[warning]Ignoring the version check. "
+ "The tarball will be created but it should not be published[/]"
+ )
+ else:
+ get_console().print(
+ "\n[info]Please create a PR with that change, get it merged, and try again.[/]\n"
+ )
+ sys.exit(1)
+ tag_with_suffix = f"helm-chart/{version}{version_suffix}"
+ if not skip_tagging:
+ get_console().print(f"[info]Tagging the chart with {tag_with_suffix}[/]")
+ tag_command = [
+ "git",
+ "tag",
+ tag_with_suffix,
+ "-m",
+ f"Apache Airflow Helm Chart {version}{version_suffix}",
+ ]
+ if override_tag:
+ tag_command.append("--force")
+ if not skip_tag_signing:
+ tag_command.append("--sign")
+ result = run_command(tag_command, check=False)
+ if result.returncode != 0:
+ get_console().print(f"[error]Error tagging the chart with {tag_with_suffix}.\n")
+ get_console().print(
+ "[warning]If you are sure the tag is set correctly, you can add --skip-tagging"
+ " flag to the command[/]"
+ )
+ sys.exit(result.returncode)
+ else:
+ get_console().print(f"[warning]Skipping tagging the chart with {tag_with_suffix}[/]")
+ get_console().print(f"[info]Creating tarball for Helm Chart {tag_with_suffix}[/]")
+ archive_name = f"airflow-chart-{version}-source.tar.gz"
+ OUT_DIR.mkdir(parents=True, exist_ok=True)
+ source_archive = OUT_DIR / archive_name
+ source_archive.unlink(missing_ok=True)
+ result = run_command(
+ [
+ "git",
+ "-c",
+ "tar.umask=0077",
+ "archive",
+ "--format=tar.gz",
+ tag_with_suffix,
+ f"--prefix=airflow-chart-{version}/",
+ "-o",
+ source_archive.as_posix(),
+ "chart",
+ ".rat-excludes",
+ ],
+ check=False,
+ )
+ if result.returncode != 0:
+ get_console().print(f"[error]Error running git archive for Helm Chart {tag_with_suffix}[/]")
+ sys.exit(result.returncode)
+ DIST_DIR.mkdir(parents=True, exist_ok=True)
+ final_archive = DIST_DIR / archive_name
+ final_archive.unlink(missing_ok=True)
+ result = repack_deterministically(
+ source_archive=source_archive,
+ dest_archive=final_archive,
+ prepend_path=None,
+ timestamp=get_source_date_epoch(CHART_DIR),
+ )
+ if result.returncode != 0:
+ get_console().print(
+ f"[error]Error repackaging source tarball for Helm Chart from {source_archive} tp "
+ f"{tag_with_suffix}[/]"
+ )
+ sys.exit(result.returncode)
+ get_console().print(f"[success]Tarball created in {final_archive}")
+
+
+@release_management.command(name="prepare-helm-chart-package", help="Prepares helm chart package.")
+@click.option(
+ "--sign-email",
+ help="Email associated with the key used to sign the package.",
+ envvar="SIGN_EMAIL",
+ default="",
+)
+@option_dry_run
+@option_verbose
+def prepare_helm_chart_package(sign_email: str):
+ import yaml
+
+ from airflow_breeze.utils.kubernetes_utils import (
+ K8S_BIN_BASE_PATH,
+ create_virtualenv,
+ make_sure_helm_installed,
+ )
+
+ chart_yaml_dict = yaml.safe_load(CHART_YAML_FILE.read_text())
+ version = chart_yaml_dict["version"]
+ result = create_virtualenv(force_venv_setup=False)
+ if result.returncode != 0:
+ sys.exit(result.returncode)
+ make_sure_helm_installed()
+ get_console().print(f"[info]Packaging the chart for Helm Chart {version}[/]")
+ k8s_env = os.environ.copy()
+ k8s_env["PATH"] = str(K8S_BIN_BASE_PATH) + os.pathsep + k8s_env["PATH"]
+ # Tar on modern unix options requires --wildcards parameter to work with globs
+ # See https://github.com/technosophos/helm-gpg/issues/1
+ k8s_env["TAR_OPTIONS"] = "--wildcards"
+ archive_name = f"airflow-{version}.tgz"
+ OUT_DIR.mkdir(parents=True, exist_ok=True)
+ result = run_command(
+ cmd=["helm", "package", "chart", "--dependency-update", "--destination", OUT_DIR.as_posix()],
+ env=k8s_env,
+ check=False,
+ )
+ if result.returncode != 0:
+ get_console().print("[error]Error packaging the chart[/]")
+ sys.exit(result.returncode)
+ DIST_DIR.mkdir(parents=True, exist_ok=True)
+ final_archive = DIST_DIR / archive_name
+ final_archive.unlink(missing_ok=True)
+ source_archive = OUT_DIR / archive_name
+ result = repack_deterministically(
+ source_archive=source_archive,
+ dest_archive=final_archive,
+ prepend_path=None,
+ timestamp=get_source_date_epoch(CHART_DIR),
+ )
+ if result.returncode != 0:
+ get_console().print(
+ f"[error]Error repackaging package for Helm Chart from {source_archive} to {final_archive}[/]"
+ )
+ sys.exit(result.returncode)
+ else:
+ get_console().print(f"[success]Package created in {final_archive}[/]")
+ if sign_email:
+ get_console().print(f"[info]Signing the package with {sign_email}[/]")
+ prov_file = final_archive.with_suffix(".tgz.prov")
+ if prov_file.exists():
+ get_console().print(f"[warning]Removing existing {prov_file}[/]")
+ prov_file.unlink()
+ result = run_command(
+ cmd=["helm", "gpg", "sign", "-u", sign_email, archive_name],
+ cwd=DIST_DIR.as_posix(),
+ env=k8s_env,
+ check=False,
+ )
+ if result.returncode != 0:
+ get_console().print("[error]Error signing the chart[/]")
+ sys.exit(result.returncode)
+ result = run_command(
+ cmd=["helm", "gpg", "verify", archive_name],
+ cwd=DIST_DIR.as_posix(),
+ env=k8s_env,
+ check=False,
+ )
+ if result.returncode != 0:
+ get_console().print("[error]Error signing the chart[/]")
+ sys.exit(result.returncode)
+ else:
+ get_console().print(f"[success]Chart signed - the {prov_file} file created.[/]")
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 ea587fd4b1..ac7bbecb13 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
@@ -28,6 +28,14 @@ RELEASE_AIRFLOW_COMMANDS: dict[str, str | list[str]] = {
],
}
+RELEASE_HELM_COMMANDS: dict[str, str | list[str]] = {
+ "name": "Helm release commands",
+ "commands": [
+ "prepare-helm-chart-tarball",
+ "prepare-helm-chart-package",
+ ],
+}
+
RELEASE_PROVIDERS_COMMANDS: dict[str, str | list[str]] = {
"name": "Providers release commands",
"commands": [
@@ -41,6 +49,7 @@ RELEASE_PROVIDERS_COMMANDS: dict[str, str | list[str]] = {
],
}
+
RELEASE_OTHER_COMMANDS: dict[str, str | list[str]] = {
"name": "Other release commands",
"commands": [
@@ -71,6 +80,27 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = {
],
}
],
+ "breeze release-management prepare-helm-chart-tarball": [
+ {
+ "name": "Package flags",
+ "options": [
+ "--version",
+ "--version-suffix",
+ "--ignore-version-check",
+ "--override-tag",
+ "--skip-tagging",
+ "--skip-tag-signing",
+ ],
+ }
+ ],
+ "breeze release-management prepare-helm-chart-package": [
+ {
+ "name": "Package flags",
+ "options": [
+ "--sign-email",
+ ],
+ }
+ ],
"breeze release-management verify-provider-packages": [
{
"name": "Provider verification flags",
diff --git a/dev/breeze/src/airflow_breeze/configure_rich_click.py b/dev/breeze/src/airflow_breeze/configure_rich_click.py
index 271408b206..63f79d6777 100644
--- a/dev/breeze/src/airflow_breeze/configure_rich_click.py
+++ b/dev/breeze/src/airflow_breeze/configure_rich_click.py
@@ -48,6 +48,7 @@ else:
)
from airflow_breeze.commands.release_management_commands_config import (
RELEASE_AIRFLOW_COMMANDS,
+ RELEASE_HELM_COMMANDS,
RELEASE_MANAGEMENT_PARAMETERS,
RELEASE_OTHER_COMMANDS,
RELEASE_PROVIDERS_COMMANDS,
@@ -107,6 +108,7 @@ else:
"breeze setup": [SETUP_COMMANDS],
"breeze release-management": [
RELEASE_AIRFLOW_COMMANDS,
+ RELEASE_HELM_COMMANDS,
RELEASE_PROVIDERS_COMMANDS,
RELEASE_OTHER_COMMANDS,
],
diff --git a/dev/breeze/src/airflow_breeze/global_constants.py b/dev/breeze/src/airflow_breeze/global_constants.py
index 0ca07b981e..2ccd3bb0dd 100644
--- a/dev/breeze/src/airflow_breeze/global_constants.py
+++ b/dev/breeze/src/airflow_breeze/global_constants.py
@@ -403,7 +403,7 @@ DEFAULT_KUBERNETES_VERSION = CURRENT_KUBERNETES_VERSIONS[0]
DEFAULT_EXECUTOR = CURRENT_EXECUTORS[0]
KIND_VERSION = "v0.20.0"
-HELM_VERSION = "v3.9.4"
+HELM_VERSION = "v3.14.0"
# Initialize image build variables - Have to check if this has to go to ci dataclass
USE_AIRFLOW_VERSION = None
diff --git a/dev/breeze/src/airflow_breeze/utils/path_utils.py b/dev/breeze/src/airflow_breeze/utils/path_utils.py
index f6e75a9fc5..2ffdb6d24b 100644
--- a/dev/breeze/src/airflow_breeze/utils/path_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/path_utils.py
@@ -293,6 +293,8 @@ HOOKS_DIR = AIRFLOW_SOURCES_ROOT / "hooks"
KUBE_DIR = AIRFLOW_SOURCES_ROOT / ".kube"
LOGS_DIR = AIRFLOW_SOURCES_ROOT / "logs"
DIST_DIR = AIRFLOW_SOURCES_ROOT / "dist"
+OUT_DIR = AIRFLOW_SOURCES_ROOT / "out"
+REPRODUCIBLE_DIR = OUT_DIR / "reproducible"
GENERATED_PROVIDER_PACKAGES_DIR = DIST_DIR / "provider_packages"
DOCS_DIR = AIRFLOW_SOURCES_ROOT / "docs"
SCRIPTS_CI_DIR = AIRFLOW_SOURCES_ROOT / "scripts" / "ci"
diff --git a/dev/breeze/src/airflow_breeze/utils/reproducible.py b/dev/breeze/src/airflow_breeze/utils/reproducible.py
index ca272ea9ec..36a6eeea81 100644
--- a/dev/breeze/src/airflow_breeze/utils/reproducible.py
+++ b/dev/breeze/src/airflow_breeze/utils/reproducible.py
@@ -36,34 +36,38 @@ import gzip
import itertools
import locale
import os
+import shutil
import tarfile
from argparse import ArgumentParser
+from pathlib import Path
+from subprocess import CalledProcessError, CompletedProcess
-from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT
+from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT, OUT_DIR, REPRODUCIBLE_DIR
+from airflow_breeze.utils.run_utils import run_command
-def get_source_date_epoch():
+def get_source_date_epoch(path: Path):
import yaml
- reproducible_build_yaml = AIRFLOW_SOURCES_ROOT / "airflow" / "reproducible_build.yaml"
+ reproducible_build_yaml = path / "reproducible_build.yaml"
reproducible_build_dict = yaml.safe_load(reproducible_build_yaml.read_text())
source_date_epoch: int = reproducible_build_dict["source-date-epoch"]
return source_date_epoch
@contextlib.contextmanager
-def cd(new_path):
+def cd(new_path: Path):
"""Context manager for changing the current working directory"""
previous_path = os.getcwd()
try:
- os.chdir(new_path)
+ os.chdir(new_path.as_posix())
yield
finally:
os.chdir(previous_path)
@contextlib.contextmanager
-def setlocale(name):
+def setlocale(name: str):
"""Context manager for changing the current locale"""
saved_locale = locale.setlocale(locale.LC_ALL)
try:
@@ -72,8 +76,10 @@ def setlocale(name):
locale.setlocale(locale.LC_ALL, saved_locale)
-def archive_deterministically(dir_to_archive, dest_archive, prepend_path=None, timestamp=0):
- """Create a .tar.gz archive in a deterministic (reproducible) manner.
+def repack_deterministically(
+ source_archive: Path, dest_archive: Path, prepend_path=None, timestamp=0
+) -> CompletedProcess | CalledProcessError:
+ """Repack a .tar.gz archive in a deterministic (reproducible) manner.
See https://reproducible-builds.org/docs/archives/ for more details."""
@@ -84,8 +90,33 @@ def archive_deterministically(dir_to_archive, dest_archive, prepend_path=None, t
tarinfo.mtime = timestamp
return tarinfo
- dest_archive = os.path.abspath(dest_archive)
- with cd(dir_to_archive):
+ OUT_DIR.mkdir(exist_ok=True)
+ shutil.rmtree(REPRODUCIBLE_DIR, ignore_errors=True)
+ REPRODUCIBLE_DIR.mkdir(exist_ok=True)
+
+ result = run_command(
+ [
+ "tar",
+ "-xf",
+ source_archive.as_posix(),
+ "-C",
+ REPRODUCIBLE_DIR.as_posix(),
+ ],
+ check=False,
+ )
+ if result.returncode != 0:
+ return result
+ dest_archive.unlink(missing_ok=True)
+ result = run_command(
+ [
+ "chmod",
+ "-R",
+ "go=",
+ REPRODUCIBLE_DIR.as_posix(),
+ ],
+ check=False,
+ )
+ with cd(REPRODUCIBLE_DIR):
current_dir = "."
file_list = [current_dir]
for root, dirs, files in os.walk(current_dir):
@@ -101,34 +132,44 @@ def archive_deterministically(dir_to_archive, dest_archive, prepend_path=None, t
temp_file = f"{dest_archive}.temp~"
with os.fdopen(os.open(temp_file, os.O_WRONLY | os.O_CREAT, 0o644), "wb") as out_file:
with gzip.GzipFile(fileobj=out_file, mtime=0, mode="wb") as gzip_file:
- with tarfile.open(fileobj=gzip_file, mode="w:") as tar_file:
+ with tarfile.open(fileobj=gzip_file, mode="w:") as tar_file: # type: ignore
for entry in file_list:
arcname = entry
if prepend_path is not None:
arcname = os.path.normpath(os.path.join(prepend_path, arcname))
tar_file.add(entry, filter=reset, recursive=False, arcname=arcname)
os.rename(temp_file, dest_archive)
+ return result
def main():
parser = ArgumentParser()
- parser.add_argument("-d", "--dir", help="directory to archive")
+ parser.add_argument("-a", "--archive", help="archive to repack")
parser.add_argument("-o", "--out", help="archive destination")
- parser.add_argument("-p", "--prepend", help="prepend path")
+ parser.add_argument("-p", "--prepend", help="prepend path in the archive")
parser.add_argument(
- "-t", "--timestamp", help="timestamp of files", type=int, default=get_source_date_epoch()
+ "-t",
+ "--timestamp",
+ help="timestamp of files",
+ type=int,
+ default=get_source_date_epoch(AIRFLOW_SOURCES_ROOT / "airflow"),
)
args = parser.parse_args()
- if not args.dir or not args.out:
+ if not args.archive or not args.out:
error = (
- "You should provide a directory to archive, and the "
- f"archive file name, not {repr((args.dir, args.out))}"
+ "You should provide an archive to repack, and the target "
+ f"archive file name, not {repr((args.archoive, args.out))}"
)
raise ValueError(error)
- archive_deterministically(args.dir, args.out, args.prepend, args.timestamp)
+ repack_deterministically(
+ source_archive=Path(args.archive),
+ dest_archive=Path(args.out),
+ prepend_path=args.prepend,
+ timestamp=args.timestamp,
+ )
if __name__ == "__main__":
diff --git a/docker_tests/requirements.txt b/docker_tests/requirements.txt
index c156378a5a..9a06256663 100644
--- a/docker_tests/requirements.txt
+++ b/docker_tests/requirements.txt
@@ -1,3 +1,3 @@
-pytest>=7.1
+pytest>=7.4.4
pytest-xdist
requests
diff --git a/scripts/ci/kubernetes/k8s_requirements.txt b/scripts/ci/kubernetes/k8s_requirements.txt
index bba6871b51..ebef4fa0f4 100644
--- a/scripts/ci/kubernetes/k8s_requirements.txt
+++ b/scripts/ci/kubernetes/k8s_requirements.txt
@@ -1,6 +1 @@
--e .[cncf.kubernetes]
-pytest
-pytest-cov
-pytest-instafail
-pytest-timeouts
-pytest-xdist
+-e .[devel-devscripts,devel-tests,cncf.kubernetes] --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-3.8.txt"
diff --git a/scripts/ci/pre_commit/pre_commit_update_source_date_epoch.py b/scripts/ci/pre_commit/pre_commit_update_source_date_epoch.py
index 6bd15d8bd3..a78026388d 100755
--- a/scripts/ci/pre_commit/pre_commit_update_source_date_epoch.py
+++ b/scripts/ci/pre_commit/pre_commit_update_source_date_epoch.py
@@ -28,18 +28,35 @@ sys.path.insert(0, str(Path(__file__).parent.resolve())) # make sure common_pre
from common_precommit_utils import AIRFLOW_SOURCES_ROOT_PATH
-RELEASE_NOTES_FILE_PATH = AIRFLOW_SOURCES_ROOT_PATH / "RELEASE_NOTES.rst"
-REPRODUCIBLE_BUILD_FILE = AIRFLOW_SOURCES_ROOT_PATH / "airflow" / "reproducible_build.yaml"
+CHART_DIR = AIRFLOW_SOURCES_ROOT_PATH / "chart"
-if __name__ == "__main__":
+AIRFLOW_RELEASE_NOTES_FILE_PATH = AIRFLOW_SOURCES_ROOT_PATH / "RELEASE_NOTES.rst"
+AIRFLOW_REPRODUCIBLE_BUILD_FILE = AIRFLOW_SOURCES_ROOT_PATH / "airflow" / "reproducible_build.yaml"
+
+CHART_RELEASE_NOTES_FILE_PATH = CHART_DIR / "RELEASE_NOTES.rst"
+CHART_REPRODUCIBLE_BUILD_FILE = CHART_DIR / "reproducible_build.yaml"
+
+
+def write_reproducible_build_file(release_notes_path: Path, reproducible_build_path: Path):
hash_md5 = md5()
- hash_md5.update(RELEASE_NOTES_FILE_PATH.read_bytes())
+ hash_md5.update(release_notes_path.read_bytes())
release_notes_hash = hash_md5.hexdigest()
- reproducible_build_text = REPRODUCIBLE_BUILD_FILE.read_text()
+ reproducible_build_text = reproducible_build_path.read_text()
reproducible_build = yaml.safe_load(reproducible_build_text)
old_hash = reproducible_build["release-notes-hash"]
if release_notes_hash != old_hash:
# Replace the hash in the file
reproducible_build["release-notes-hash"] = release_notes_hash
reproducible_build["source-date-epoch"] = int(time())
- REPRODUCIBLE_BUILD_FILE.write_text(yaml.dump(reproducible_build))
+ reproducible_build_path.write_text(yaml.dump(reproducible_build))
+
+
+if __name__ == "__main__":
+ write_reproducible_build_file(
+ release_notes_path=AIRFLOW_RELEASE_NOTES_FILE_PATH,
+ reproducible_build_path=AIRFLOW_REPRODUCIBLE_BUILD_FILE,
+ )
+ write_reproducible_build_file(
+ release_notes_path=CHART_RELEASE_NOTES_FILE_PATH,
+ reproducible_build_path=CHART_REPRODUCIBLE_BUILD_FILE,
+ )