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

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


The following commit(s) were added to refs/heads/v3-0-test by this push:
     new fe2aa6c8fc3 [v3-0-test] Backport gh docs publish breeze workflows 
(#51286)
fe2aa6c8fc3 is described below

commit fe2aa6c8fc3ab853fdc6e092d8de4e9ed775ef21
Author: GPK <[email protected]>
AuthorDate: Mon Jun 2 10:04:40 2025 +0100

    [v3-0-test] Backport gh docs publish breeze workflows (#51286)
    
    * Add breeze commands for gh workflow docs publish (#51036)
    
    * Add breeze commands for gh workflow docs publish
    
    * Add breeze commands for gh workflow docs publish
    
    * Add sync s3 to github workflow trigger
    
    * Update dev/breeze/src/airflow_breeze/utils/gh_workflow_utils.py
    
    Co-authored-by: Bugra Ozturk <[email protected]>
    
    ---------
    
    Co-authored-by: Bugra Ozturk <[email protected]>
    
    * Update GH cli bool inputs to convert to string format in breeze and input 
branch to refresh site and sync s3 to github (#51093)
    
    * Update GH cli bool inputs to convert to string format in breeze
    
    * Update branch name to airflow-site-archive trigger
    
    * DOCS: Remove site-refresh/sync-s3-to-github and Update release 
documentation instructions (#51259)
    
    * Remove refres sit and sync s3 to github docs args
    
    * Update release readme files
    
    * Update release readme files
    
    ---------
    
    Co-authored-by: Bugra Ozturk <[email protected]>
---
 dev/README_RELEASE_AIRFLOW.md                      | 158 +++++++++---
 dev/README_RELEASE_PROVIDERS.md                    | 280 ++++++++++++---------
 dev/breeze/doc/09_release_management_tasks.rst     | 155 +++++++++---
 dev/breeze/doc/images/output-commands.svg          |  20 +-
 .../output_setup_check-all-params-in-groups.svg    |   2 +-
 .../output_setup_check-all-params-in-groups.txt    |   2 +-
 .../output_setup_regenerate-command-images.svg     |   2 +-
 .../output_setup_regenerate-command-images.txt     |   2 +-
 dev/breeze/doc/images/output_workflow-run.svg      | 103 ++++++++
 dev/breeze/doc/images/output_workflow-run.txt      |   1 +
 .../images/output_workflow-run_publish-docs.svg    | 166 ++++++++++++
 .../images/output_workflow-run_publish-docs.txt    |   1 +
 dev/breeze/src/airflow_breeze/breeze.py            |   2 +
 .../airflow_breeze/commands/workflow_commands.py   | 155 ++++++++++++
 .../commands/workflow_commands_config.py           |  36 +++
 .../src/airflow_breeze/configure_rich_click.py     |   5 +-
 .../src/airflow_breeze/utils/gh_workflow_utils.py  | 184 ++++++++++++++
 17 files changed, 1067 insertions(+), 207 deletions(-)

diff --git a/dev/README_RELEASE_AIRFLOW.md b/dev/README_RELEASE_AIRFLOW.md
index cd695e78d6a..32cf8999290 100644
--- a/dev/README_RELEASE_AIRFLOW.md
+++ b/dev/README_RELEASE_AIRFLOW.md
@@ -23,10 +23,12 @@
 - [Selecting what to put into the 
release](#selecting-what-to-put-into-the-release)
   - [Selecting what to cherry-pick](#selecting-what-to-cherry-pick)
   - [Making the cherry picking](#making-the-cherry-picking)
+  - [Collapse Cadwyn Migrations](#collapse-cadwyn-migrations)
   - [Reviewing cherry-picked PRs and assigning 
labels](#reviewing-cherry-picked-prs-and-assigning-labels)
 - [Prepare the Apache Airflow Package 
RC](#prepare-the-apache-airflow-package-rc)
   - [Update the milestone](#update-the-milestone)
   - [Build RC artifacts](#build-rc-artifacts)
+  - [Publish release candidate documentation 
(staging)](#publish-release-candidate-documentation-staging)
   - [Prepare production Docker Image RC](#prepare-production-docker-image-rc)
   - [Prepare Vote email on the Apache Airflow release 
candidate](#prepare-vote-email-on-the-apache-airflow-release-candidate)
 - [Verify the release candidate by PMC 
members](#verify-the-release-candidate-by-pmc-members)
@@ -42,8 +44,7 @@
   - [Publish release to SVN](#publish-release-to-svn)
   - [Manually prepare production Docker 
Image](#manually-prepare-production-docker-image)
   - [Verify production images](#verify-production-images)
-  - [Publish documentation](#publish-documentation)
-  - [Wait and make sure documentation is published on the website before 
proceeding](#wait-and-make-sure-documentation-is-published-on-the-website-before-proceeding)
+  - [Publish final documentation](#publish-final-documentation)
   - [Notify developers of release](#notify-developers-of-release)
   - [Send announcements about security issues fixed in the 
release](#send-announcements-about-security-issues-fixed-in-the-release)
   - [Add release data to Apache Committee Report 
Helper](#add-release-data-to-apache-committee-report-helper)
@@ -140,6 +141,15 @@ to keep a reference to the original commit we cherry 
picked from. ("cherry picke
 git cherry-pick <hash-commit> -x
 ```
 
+## Collapse Cadwyn Migrations
+
+Before cutting an RC, bump the HEAD date of Cadwyn versioned API (execution 
api for now: `airflow-core/src/airflow/api_fastapi/execution_api`)
+to reflect the tentative release date of Airflow. All the Cadwyn migrations in 
between the tentative release date and last release date
+should be collapsed.
+
+Refer https://github.com/apache/airflow/pull/49116 as a good example.
+
+
 ## Reviewing cherry-picked PRs and assigning labels
 
 We have the tool that allows to review cherry-picked PRs and assign the labels
@@ -331,6 +341,66 @@ pipx install -e ./dev/breeze
     --current-release ${VERSION}
     ```
 
+## Publish release candidate documentation (staging)
+
+Documentation is an essential part of the product and should be made available 
to users.
+In our cases, documentation for the pre-release versions is published in 
`staging` S3 bucket.
+The documentation source code and build tools are available in the 
`apache/airflow` repository, so
+you need to run several workflows to publish the documentation. More details 
about it can be found in
+[Docs README](../docs/README.md) showing the architecture and workflows 
including manual workflows for
+emergency cases.
+
+We have two options publishing the documentation 1. Using breeze commands 2. 
Manually using GitHub Actions.:
+
+### Using breeze commands
+
+You can use the `breeze` command to publish the documentation.
+The command does the following:
+
+1. Triggers [Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
+2. Triggers workflow in apache/airflow-site to refresh
+3. Triggers S3 to GitHub Sync
+
+```shell script
+  breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
+```
+
+The `--ref` parameter should be the tag of the release candidate you are 
publishing.
+
+The `--site-env` parameter should be set to `staging` for pre-release versions 
or `live` for final releases. the default option is `auto`
+if the tag is rc it publishes to `staging` bucket, otherwise it publishes to 
`live` bucket.
+
+Other available parameters can be found with:
+
+```shell script
+breeze workflow-run publish-docs --help
+```
+
+### Manually using GitHub Actions
+
+There are two steps to publish the documentation:
+
+1. Publish the documentation to the `staging` S3 bucket.
+
+The release manager publishes the documentation using GitHub Actions workflow
+[Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
 By default `auto` selection should publish to the `staging` bucket - based on
+the tag you use - pre-release tags go to staging. But you can also override it 
and specify the destination
+manually to be `live` or `staging`.
+
+You should specify 'apache-airflow docker-stack' passed as packages to be
+built.
+
+After that step, the provider documentation should be available under 
https://airflow.stage.apache.org//
+URL (RC PyPI packages are build with the staging urls) but stable links and 
drop-down boxes are not updated yet.
+
+2. Invalidate Fastly cache, update version drop-down and stable links with the 
new versions of the documentation.
+
+In order to do it, you need to run the [Build 
docs](https://github.com/apache/airflow-site/actions/workflows/build.yml)
+workflow in `airflow-site` repository - but make sure to use `staging` branch.
+
+After that workflow completes, the new version should be available in the 
drop-down list and stable links
+should be updated, also Fastly cache will be updated
+
 ## Prepare production Docker Image RC
 
 Production Docker images should be manually prepared and pushed by the release 
manager or another committer
@@ -816,57 +886,65 @@ docker pull apache/airflow:${VERSION}
 breeze prod-image verify --image-name apache/airflow:${VERSION}
 ```
 
-## Publish documentation
+## Publish final documentation
 
 Documentation is an essential part of the product and should be made available 
to users.
-In our cases, documentation for the released versions is published in a 
separate repository - 
[`apache/airflow-site`](https://github.com/apache/airflow-site), but the 
documentation source code and build tools are available in the `apache/airflow` 
repository, so you have to coordinate between the two repositories to be able 
to build the documentation.
+In our cases, documentation for the released versions is published in the 
`live` S3 bucket, and the site is
+kept in a separate repository - 
[`apache/airflow-site`](https://github.com/apache/airflow-site),
+but the documentation source code and build tools are available in the 
`apache/airflow` repository, so
+you need to run several workflows to publish the documentation. More details 
about it can be found in
+[Docs README](../docs/README.md) showing the architecture and workflows 
including manual workflows for
+emergency cases.
 
-Documentation for providers can be found in the ``/docs/apache-airflow`` 
directory.
+We have two options publishing the documentation 1. Using breeze commands 2. 
Manually using GitHub Actions.:
 
-- First, copy the airflow-site repository and set the environment variable 
``AIRFLOW_SITE_DIRECTORY``.
+### Using breeze commands
 
-    ```shell script
-    git clone https://github.com/apache/airflow-site.git airflow-site
-    cd airflow-site
-    git checkout -b ${VERSION}-docs
-    export AIRFLOW_SITE_DIRECTORY="$(pwd)"
-    ```
+You can use the `breeze` command to publish the documentation.
+The command does the following:
 
-- Then you can go to the directory and build the necessary documentation 
packages
+1. Triggers [Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
+2. Triggers workflow in apache/airflow-site to refresh
+3. Triggers S3 to GitHub Sync
 
-    ```shell script
-    cd "${AIRFLOW_REPO_ROOT}"
-    breeze build-docs apache-airflow docker-stack --clean-build
-    ```
+```shell script
+  breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
+```
 
-- Now you can preview the documentation.
+The `--ref` parameter should be the tag of the final candidate you are 
publishing.
 
-    ```shell script
-    ./docs/start_doc_server.sh
-    ```
+The `--site-env` parameter should be set to `staging` for pre-release versions 
or `live` for final releases. the default option is `auto`
+if the tag is rc it publishes to `staging` bucket, otherwise it publishes to 
`live` bucket.
 
-- Copy the documentation to the ``airflow-site`` repository, create commit, 
push changes, open a PR and merge it when the build is green.
+Other available parameters can be found with:
 
-    ```shell script
-    breeze release-management publish-docs apache-airflow docker-stack
-    breeze release-management add-back-references apache-airflow 
--airflow-site-directory "${AIRFLOW_SITE_DIRECTORY}"
-    breeze sbom update-sbom-information --airflow-version ${VERSION} 
--airflow-site-directory ${AIRFLOW_SITE_DIRECTORY} --force --all-combinations 
--run-in-parallel
-    cd "${AIRFLOW_SITE_DIRECTORY}"
-    git add .
-    git commit -m "Add documentation for Apache Airflow ${VERSION}"
-    git push
-    # and finally open a PR
-    ```
+```shell
+breeze workflow-run publish-docs --help
+```
+
+### Manually using GitHub Actions
+
+There are two steps to publish the documentation:
+
+1. Publish the documentation to S3 bucket.
+
+The release manager publishes the documentation using GitHub Actions workflow
+[Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
 By
+default `auto` selection should publish to the `live` bucket - based on
+the tag you use - pre-release tags go to staging. But you can also override it 
and specify the destination
+manually to be `live` or `staging`.
 
-The `--run-in-parallel` switch allows to speed up SBOM generation 
significantly, but it might take a lot
-of memory - if you are running into memory issues you can limit parallelism by 
setting `--parallelism N`
-where N is a number of parallel `cdxgen` servers that should be started.
+After that step, the provider documentation should be available under the 
https://airflow.apache.org/ URL
+(also linked directly from the PyPI packages) but stable links and drop-down 
boxes should not be yet updated.
+That allows the Release Manager to verify if the documentation is published.
 
-## Wait and make sure documentation is published on the website before 
proceeding
+2. Invalidate Fastly Cache, update version drop-down and stable links with the 
new versions of the documentation.
 
-This is important as it takes time for the documentation to be published. You 
should exercise some patient
-here before proceeding with the next steps.
+In order to do it, you need to run the [Build 
docs](https://github.com/apache/airflow-site/actions/workflows/build.yml)
+workflow in `airflow-site` repository. Make sure to use `main` as the branch 
to run the workflow.
 
+After that workflow completes, the new version should be available in the 
drop-down list and stable links
+should be updated, also Fastly cache will be invalidated.
 
 ## Notify developers of release
 
@@ -1007,7 +1085,7 @@ This includes:
 - For major/minor release, update version in `airflow/__init__.py` and 
`docs/docker-stack/` to the next likely minor version release.
 - Sync `RELEASE_NOTES.rst` (including deleting relevant `newsfragments`) and 
`README.md` changes.
 - Updating `Dockerfile` with the new version.
-- Updating `airflow_bug_report.yml` issue template in 
`.github/ISSUE_TEMPLATE/` with the new version.
+- Updating `1-airflow_bug_report.yml` issue template in 
`.github/ISSUE_TEMPLATE/` with the new version.
 
 ## Update default Airflow version in the helm chart
 
@@ -1046,7 +1124,7 @@ Clients can be found here:
 ### API Clients versioning policy
 
 Clients and Core versioning are completely decoupled. Clients also follow 
SemVer and are updated when core introduce changes relevant to the clients.
-Most of the time, if the [openapi 
specification](https://github.com/apache/airflow/blob/main/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-rest-api-generated.yaml)
 has
+Most of the time, if the [openapi 
specification](https://github.com/apache/airflow/blob/main/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml)
 has
 changed, clients need to be released.
 
 To determine if you should release API clients, you can run from the airflow 
repository:
diff --git a/dev/README_RELEASE_PROVIDERS.md b/dev/README_RELEASE_PROVIDERS.md
index b98bfa5de1e..08492c7f2de 100644
--- a/dev/README_RELEASE_PROVIDERS.md
+++ b/dev/README_RELEASE_PROVIDERS.md
@@ -35,9 +35,9 @@
   - [Build Provider distributions for SVN apache 
upload](#build-provider-distributions-for-svn-apache-upload)
   - [Build and sign the source and convenience 
packages](#build-and-sign-the-source-and-convenience-packages)
   - [Commit the source packages to Apache SVN 
repo](#commit-the-source-packages-to-apache-svn-repo)
-  - [Publish the Regular convenience package to 
PyPI](#publish-the-regular-convenience-package-to-pypi)
+  - [Publish the Regular distributions to PyPI (release 
candidates)](#publish-the-regular-distributions-to-pypi-release-candidates)
   - [Add tags in git](#add-tags-in-git)
-  - [Prepare documentation](#prepare-documentation)
+  - [Prepare documentation in Staging](#prepare-documentation-in-staging)
   - [Prepare issue in GitHub to keep status of 
testing](#prepare-issue-in-github-to-keep-status-of-testing)
   - [Prepare voting email for Providers release 
candidate](#prepare-voting-email-for-providers-release-candidate)
   - [Verify the release candidate by PMC 
members](#verify-the-release-candidate-by-pmc-members)
@@ -46,8 +46,8 @@
   - [Summarize the voting for the Apache Airflow 
release](#summarize-the-voting-for-the-apache-airflow-release)
   - [Publish release to SVN](#publish-release-to-svn)
   - [Publish the packages to PyPI](#publish-the-packages-to-pypi)
-  - [Publish documentation prepared 
before](#publish-documentation-prepared-before)
   - [Add tags in git](#add-tags-in-git-1)
+  - [Publish documentation](#publish-documentation)
   - [Update providers metadata](#update-providers-metadata)
   - [Notify developers of release](#notify-developers-of-release)
   - [Send announcements about security issues fixed in the 
release](#send-announcements-about-security-issues-fixed-in-the-release)
@@ -415,7 +415,7 @@ svn rm file_name  // repeate that for every file
 svn commit -m "delete old providers"
 ```
 
-## Publish the Regular convenience package to PyPI
+## Publish the Regular distributions to PyPI (release candidates)
 
 In order to publish release candidate to PyPI you just need to build and 
release packages.
 The packages should however contain the rcN suffix in the version file name 
but not internally in the package,
@@ -486,127 +486,72 @@ If you want to disable this behaviour, set the env 
**CLEAN_LOCAL_TAGS** to false
 breeze release-management tag-providers
 ```
 
-## Prepare documentation
+## Prepare documentation in Staging
 
 Documentation is an essential part of the product and should be made available 
to users.
-In our cases, documentation  for the released versions is published in a 
separate repository -
-[`apache/airflow-site`](https://github.com/apache/airflow-site), but the 
documentation source code
-and build tools are available in the `apache/airflow` repository, so you have 
to coordinate between
-the two repositories to be able to build the documentation.
+In our cases, documentation for the released versions is published in the 
staging S3 bucket, and the site is
+kept in a separate repository - 
[`apache/airflow-site`](https://github.com/apache/airflow-site),
+but the documentation source code and build tools are available in the 
`apache/airflow` repository, so
+you need to run several workflows to publish the documentation. More details 
about it can be found in
+[Docs README](../docs/README.md) showing the architecture and workflows 
including manual workflows for
+emergency cases.
 
-Documentation for providers can be found in the 
`/docs/apache-airflow-providers` directory
-and the `/docs/apache-airflow-providers-*/` directory. The first directory 
contains the package contents
-lists and should be updated every time a new version of Provider distributions 
is released.
+We have two options publishing the documentation 1. Using breeze commands 2. 
Manually using GitHub Actions.:
 
-- First, copy the airflow-site repository and set the environment variable 
``AIRFLOW_SITE_DIRECTORY``.
+### Using breeze commands
 
-```shell script
-git clone https://github.com/apache/airflow-site.git airflow-site
-cd airflow-site
-export AIRFLOW_SITE_DIRECTORY="$(pwd -P)"
-```
-
-Note if this is not the first time you clone the repo make sure main branch is 
rebased:
-
-```shell script
-cd "${AIRFLOW_SITE_DIRECTORY}"
-git checkout main
-git pull --rebase
-```
-
-- Then you can go to the directory and build the necessary documentation 
packages
-
-```shell script
-cd "${AIRFLOW_REPO_ROOT}"
-breeze build-docs --clean-build apache-airflow-providers all-providers 
--include-removed-providers
-```
-
-Usually when we release packages we also build documentation for the 
"documentation-only" packages. This
-means that unless we release just few selected packages or if we need to 
deliberately skip some packages
-we should release documentation for all Provider distributions and the above 
command is the one to use.
-
-If we want to just release some providers you can release them using package 
names:
-
-```shell script
-cd "${AIRFLOW_REPO_ROOT}"
-breeze build-docs apache-airflow-providers cncf.kubernetes sftp --clean-build
-```
-
-Alternatively, if you have set the environment variable: `DISTRIBUTIONS_LIST` 
above, just run the command:
-
-```shell script
-cd "${AIRFLOW_REPO_ROOT}"
-breeze build-docs --clean-build
-```
+You can use the `breeze` command to publish the documentation.
+The command does the following:
 
-Or using `--distributions-list` argument:
-
-```shell script
-breeze build-docs --distributions-list PACKAGE1,PACKAGE2
-```
-
-- Now you can preview the documentation.
-
-```shell script
-./docs/start_doc_server.sh
-```
-
-If you encounter error like:
+1. Triggers [Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
+2. Triggers workflow in apache/airflow-site to refresh
+3. Triggers S3 to GitHub Sync
 
 ```shell script
-airflow git:(main) ./docs/start_doc_server.sh
-./docs/start_doc_server.sh: line 22: cd: 
/Users/eladkal/PycharmProjects/airflow/docs/_build: No such file or directory
+  breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
 ```
 
-That probably means that the doc folder is empty thus it can not build the doc 
server.
-This indicates that previous step of building the docs did not work.
-
-- Copy the documentation to the ``airflow-site`` repository
-
-All providers (including overriding documentation for doc-only changes) - note 
that publishing is
-way faster on multi-cpu machines when you are publishing multiple providers:
+The `--ref` parameter should be the tag of the release candidate you are 
publishing.
 
+The `--site-env` parameter should be set to `staging` for pre-release versions 
or `live` for final releases. the default option is `auto`
+if the tag is rc it publishes to `staging` bucket, otherwise it publishes to 
`live` bucket.
 
-```shell script
-cd "${AIRFLOW_REPO_ROOT}"
-
-breeze release-management publish-docs apache-airflow-providers all-providers 
--include-removed-providers \
-    --override-versioned --run-in-parallel
+Other available parameters can be found with:
 
-breeze release-management add-back-references all-providers
+```shell
+breeze workflow-run publish-docs --help
 ```
 
-If you have providers as list of provider ids because you just released them 
you can build them with
+### Manually using GitHub Actions
 
-```shell script
-cd "${AIRFLOW_REPO_ROOT}"
+There are two steps to publish the documentation:
 
-breeze release-management publish-docs amazon apache.beam google ....
-breeze release-management add-back-references all-providers
-```
+1. Publish the documentation to the staging S3 bucket.
 
-Alternatively, if you have set the environment variable: `DISTRIBUTIONS_LIST` 
above, just run the command:
+The release manager publishes the documentation using GitHub Actions workflow
+[Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
 
-```shell script
-breeze release-management publish-docs
-breeze release-management add-back-references all-providers
-```
+You should specify the final tag to use to build the docs and list of 
providers to publish
+(separated by spaces) or ``all-providers`` in case you want to publish all 
providers
+(optionally you can exclude some of those providers). You should use `staging` 
bucket to publish the release
+candidate documentation.
 
-Or using `--distributions-list` argument:
-
-```shell script
-breeze release-management publish-docs --distributions-list PACKAGE1,PACKAGE2
-breeze release-management add-back-references all-providers
-```
+After that step, the provider documentation should be available under the 
http://airflow.staged.apache.org URL
+(also present in the PyPI packages) but stable links and drop-down boxes 
should not be yet updated.
 
+2. Invalidate Fastly cache, update version drop-down and stable links with the 
new versions of the documentation.
 
-Review the state of removed, suspended, new packages in
+Before doing it - review the state of removed, suspended, new packages in
 [the docs 
index](https://github.com/apache/airflow-site/blob/master/landing-pages/site/content/en/docs/_index.md):
+Make sure to use `staging` branch to run the workflow.
+
+There are few special considerations when the list of provider is updated.
 
 - If you publish a new package, you must add it to the list of packages in the 
index.
-- If there are changes to suspension or removal status of a package  you must 
move it appropriate section.
+- If there are changes to suspension or removal status of a package, you must 
move it appropriate section.
 
-- Create the commit and push changes.
+- In case you need to make any changes - create the commit and push changes 
and merge it to `staging` branch.
+  in [airflow-site](https://github.com/apache/airflow-site) repository.
 
 ```shell script
 cd "${AIRFLOW_SITE_DIRECTORY}"
@@ -617,6 +562,15 @@ git commit -m "Add documentation for packages - $(date 
"+%Y-%m-%d%n")"
 git push --set-upstream origin "${branch}"
 ```
 
+Merging the PR with the index changes to `staging` will trigger site 
publishing.
+
+If you do not need to merge a PR, you should manually run the
+[Build 
docs](https://github.com/apache/airflow-site/actions/workflows/build.yml)
+workflow in `airflow-site` repository to refresh indexes and drop-downs.
+
+After that build from PR or workflow completes, the new version should be 
available in the drop-down
+list and stable links should be updated, also Fastly cache will be invalidated.
+
 ## Prepare issue in GitHub to keep status of testing
 
 Create a GitHub issue with the content generated via manual execution of the 
command below. You will use
@@ -681,12 +635,20 @@ Make sure the packages are in 
https://dist.apache.org/repos/dist/dev/airflow/pro
 Send out a vote to the [email protected] mailing list. Here you can 
prepare text of the
 email.
 
-subject:
+```shell script
+export VOTE_DURATION_IN_HOURS=72
+export IS_SHORTEN_VOTE=$([ $VOTE_DURATION_IN_HOURS -ge 72 ] && echo "false" || 
echo "true")
+export SHORTEN_VOTE_TEXT="This is a shortened ($VOTE_DURATION_IN_HOURS hours 
vote) as agreed by policy set it 
https://lists.apache.org/thread/cv194w1fqqykrhswhmm54zy9gnnv6kgm";
+export VOTE_END_TIME=$(LANG=en_US.UTF-8 TZ=UTC date 
-v+"${VOTE_DURATION_IN_HOURS}"H "+%B %d, %Y %H:%M %p")
+export RELEASE_MANAGER_NAME="Elad Kalif"
+export GITHUB_ISSUE_LINK="LINK_TO_GITHUB_ISSUE"
+```
 
+subject:
 
 ```shell script
 cat <<EOF
-[VOTE] Airflow Providers prepared on $(date "+%B %d, %Y")
+[VOTE] Airflow Providers prepared on $(LANG=en_US.UTF-8 TZ=UTC date "+%B %d, 
%Y")
 EOF
 ```
 
@@ -695,8 +657,8 @@ cat <<EOF
 Hey all,
 
 I have just cut the new wave Airflow Providers packages. This email is calling 
a vote on the release,
-which will last for 72 hours - which means that it will end on $(TZ=UTC date 
-v+3d "+%B %d, %Y %H:%M %p" ) UTC and until 3 binding +1 votes have been 
received.
-
+which will last for $VOTE_DURATION_IN_HOURS hours - which means that it will 
end on $VOTE_END_TIME UTC and until 3 binding +1 votes have been received.
+$([ "$IS_SHORTEN_VOTE" = "true" ] && echo "${SHORTEN_VOTE_TEXT}" || echo "")
 
 Consider this my (binding) +1.
 
@@ -735,7 +697,7 @@ This will allow us to rename the artifact without modifying
 the artifact checksums when we actually release.
 
 The status of testing the providers by the community is kept here:
-<TODO COPY LINK TO THE ISSUE CREATED>
+$GITHUB_ISSUE_LINK
 
 The issue is also the easiest way to see important PRs included in the RC 
candidates.
 Detailed changelog for the providers will be published in the documentation 
after the
@@ -746,7 +708,7 @@ You can find the RC packages in PyPI following these links:
 <PASTE TWINE UPLOAD LINKS HERE. SORT THEM BEFORE!>
 
 Cheers,
-<TODO: Your Name>
+$RELEASE_MANAGER_NAME
 
 EOF
 ```
@@ -1253,21 +1215,6 @@ Copy links to updated packages, sort it alphabetically 
and save it on the side.
 
 * Again, confirm that the packages are available under the links printed.
 
-## Publish documentation prepared before
-
-Merge the PR that you prepared before with the documentation.
-
-If you decided to remove some packages from the release make sure to do amend 
the commit in this way:
-
-* find the packages you removed in 
`docs-archive/apache-airflow-providers-<PROVIDER>`
-* remove the latest version (the one you were releasing)
-* update `stable.txt` to the previous version
-* in the (unlikely) event you are removing first version of package:
-   * remove whole `docs-archive/apache-airflow-providers-<PROVIDER>` folder
-   * remove package from 
`docs-archive/apache-airflow-providers/core-extensions/index.html` (2 places)
-   * remove package from 
`docs-archive/apache-airflow-providers/core-extensions/connections.html` (2 
places)
-   * remove package from 
`docs-archive/apache-airflow-providers/core-extensions/extra-links.html` (2 
places)
-   * remove package from 
`docs-archive/apache-airflow-providers/core-extensions/packages-ref.html` (5 
places)
 
 ## Add tags in git
 
@@ -1283,12 +1230,103 @@ If you want to disable this behaviour, set the env 
**CLEAN_LOCAL_TAGS** to false
 breeze release-management tag-providers
 ```
 
+## Publish documentation
+
+Documentation is an essential part of the product and should be made available 
to users.
+In our cases, documentation for the released versions is published in the 
`live` S3 bucket, and the site is
+kept in a separate repository - 
[`apache/airflow-site`](https://github.com/apache/airflow-site),
+but the documentation source code and build tools are available in the 
`apache/airflow` repository, so
+you need to run several workflows to publish the documentation. More details 
about it can be found in
+[Docs README](../docs/README.md) showing the architecture and workflows 
including manual workflows for
+emergency cases.
+
+We have two options publishing the documentation 1. Using breeze commands 2. 
Manually using GitHub Actions.:
+
+### Using breeze commands
+
+You can use the `breeze` command to publish the documentation.
+The command does the following:
+
+1. Triggers [Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
+2. Triggers workflow in apache/airflow-site to refresh
+3. Triggers S3 to GitHub Sync
+
+```shell script
+  breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
+```
+
+The `--ref` parameter should be the tag of the final candidate you are 
publishing.
+
+The `--site-env` parameter should be set to `staging` for pre-release versions 
or `live` for final releases. the default option is `auto`
+if the tag is rc it publishes to `staging` bucket, otherwise it publishes to 
`live` bucket.
+
+Other available parameters can be found with:
+
+```shell
+breeze workflow-run publish-docs --help
+```
+
+### Manually using GitHub Actions
+
+There are two steps to publish the documentation:
+
+1. Publish the documentation to the live S3 bucket.
+
+The release manager publishes the documentation using GitHub Actions workflow
+[Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
+
+You should specify the final tag to use to build the docs and list of 
providers to publish
+(separated by spaces) or ``all-providers`` in case you want to publish all 
providers
+(optionally you can exclude some of those providers).
+
+The release manager publishes the documentation using GitHub Actions workflow
+[Publish Docs to 
S3](https://github.com/apache/airflow/actions/workflows/publish-docs-to-s3.yml).
+By default `auto` selection should publish to the `live` bucket - based on
+the tag you use - pre-release tags go to staging. But you can also override it 
and specify the destination
+manually to be `live` or `staging`.
+
+After that step, the provider documentation should be available under the 
http://airflow.apache.org URL
+(also present in the PyPI packages) but stable links and drop-down boxes 
should not be yet updated.
+
+2. Invalidate Fastly cache, update version drop-down and stable links with the 
new versions of the documentation.
+
+Before doing it - review the state of removed, suspended, new packages in
+[the docs 
index](https://github.com/apache/airflow-site/blob/master/landing-pages/site/content/en/docs/_index.md):
+Make sure to use `main` branch to run the workflow.
+
+There are few special considerations when the list of provider is updated.
+
+- If you publish a new package, you must add it to the list of packages in the 
index.
+- If there are changes to suspension or removal status of a package, you must 
move it appropriate section.
+- In case you need to make any changes - create the commit and push changes 
and merge it to `main` branch.
+  in [airflow-site](https://github.com/apache/airflow-site) repository.
+
+```shell script
+cd airflow-site
+export AIRFLOW_SITE_DIRECTORY="$(pwd -P)"
+cd "${AIRFLOW_SITE_DIRECTORY}"
+branch="add-documentation-$(date "+%Y-%m-%d%n")"
+git checkout -b "${branch}"
+git add .
+git commit -m "Add documentation for packages - $(date "+%Y-%m-%d%n")"
+git push --set-upstream origin "${branch}"
+```
+
+Merging the PR with the index changes to `main` will trigger site publishing.
+
+If you do not need to merge a PR, you should manually run the
+[Build 
docs](https://github.com/apache/airflow-site/actions/workflows/build.yml)
+workflow in `airflow-site` repository to refresh indexes and drop-downs.
+
+After that build from PR or workflow completes, the new version should be 
available in the drop-down
+list and stable links should be updated, also Fastly cache will be invalidated.
+
 ## Update providers metadata
 
 ```shell script
 cd ${AIRFLOW_REPO_ROOT}
 git checkout main
-git pull
+git pull apache main
 current_date=$(date '+%Y-%m-%d%n')
 branch="update-providers-metadata-${current_date}"
 git checkout -b "${branch}"
diff --git a/dev/breeze/doc/09_release_management_tasks.rst 
b/dev/breeze/doc/09_release_management_tasks.rst
index b83e6e17302..f6d7bbbebc3 100644
--- a/dev/breeze/doc/09_release_management_tasks.rst
+++ b/dev/breeze/doc/09_release_management_tasks.rst
@@ -33,21 +33,21 @@ Those are all of the available release management commands:
 Airflow release commands
 ........................
 
-Running airflow release commands is part of the release procedure performed by 
the release managers
+Running Airflow release commands is part of the release procedure performed by 
the release managers
 and it is described in detail in `dev <dev/README_RELEASE_AIRFLOW.md>`_ .
 
-Preparing airflow distributions
+Preparing Airflow distributions
 """"""""""""""""""""""""""
 
-You can prepare airflow distributions using Breeze:
+You can prepare Airflow distributions using Breeze:
 
 .. code-block:: bash
 
      breeze release-management prepare-airflow-distributions
 
-This prepares airflow .whl package in the dist folder.
+This prepares Airflow .whl package in the dist folder.
 
-Again, you can specify optional ``--distribution-format`` flag to build 
selected formats of airflow distributions,
+Again, you can specify optional ``--distribution-format`` flag to build 
selected formats of Airflow distributions,
 default is to build ``both`` type of distributions ``sdist`` and ``wheel``.
 
 .. code-block:: bash
@@ -60,10 +60,10 @@ default is to build ``both`` type of distributions 
``sdist`` and ``wheel``.
   :alt: Breeze release-management prepare-airflow-distributions
 
 
-Preparing airflow tarball
+Preparing Airflow tarball
 """""""""""""""""""""""""
 
-You can prepare airflow source tarball using Breeze:
+You can prepare Airflow source tarball using Breeze:
 
 .. code-block:: bash
 
@@ -127,10 +127,10 @@ When we prepare final release, we automate some of the 
steps we need to do.
   :width: 100%
   :alt: Breeze release-management start-rc-process
 
-Generating airflow core Issue
+Generating Airflow core Issue
 """""""""""""""""""""""""
 
-You can use Breeze to generate a airflow core issue when you release new 
airflow.
+You can use Breeze to generate a Airflow core issue when you release new 
airflow.
 
 .. image:: 
./images/output_release-management_generate-issue-content-providers.svg
   :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_release-management_generate-issue-content-core.svg
@@ -266,7 +266,7 @@ The images are also aliased in dockerhub as appropriate.
 Adding git tags for providers
 """""""""""""""""""""""""""""
 
-This command can be utilized to manage git tags for providers within the 
airflow remote repository during provider releases.
+This command can be utilized to manage git tags for providers within the 
Airflow remote repository during provider releases.
 Sometimes in cases when there is a connectivity issue to GitHub, it might be 
possible that local tags get created and lead to annoying errors.
 The default behaviour would be to clean such local tags up.
 
@@ -376,7 +376,7 @@ Preparing providers
 You can use Breeze to prepare providers.
 
 The distributions are prepared in ``dist`` folder. Note, that this command 
cleans up the ``dist`` folder
-before running, so you should run it before generating airflow package below 
as it will be removed.
+before running, so you should run it before generating Airflow package below 
as it will be removed.
 
 The below example builds providers in the wheel format.
 
@@ -406,7 +406,7 @@ You can see all providers available by running this command:
 Installing providers
 """"""""""""""""""""
 
-In some cases we want to just see if the providers generated can be installed 
with airflow without
+In some cases we want to just see if the providers generated can be installed 
with Airflow without
 verifying them. This happens automatically on CI for sdist pcackages but you 
can also run it manually if you
 just prepared providers and they are present in ``dist`` folder.
 
@@ -414,7 +414,7 @@ just prepared providers and they are present in ``dist`` 
folder.
 
      breeze release-management install-provider-distributions
 
-You can also run the verification with an earlier airflow version to check for 
compatibility.
+You can also run the verification with an earlier Airflow version to check for 
compatibility.
 
 .. code-block:: bash
 
@@ -438,7 +438,7 @@ just prepared providers and they are present in ``dist`` 
folder.
 
      breeze release-management verify-provider-distributions
 
-You can also run the verification with an earlier airflow version to check for 
compatibility.
+You can also run the verification with an earlier Airflow version to check for 
compatibility.
 
 .. code-block:: bash
 
@@ -455,7 +455,7 @@ Generating Providers Metadata
 """""""""""""""""""""""""""""
 
 The release manager can generate providers metadata per provider version - 
information about provider versions
-including the associated Airflow version for the provider version (i.e first 
airflow version released after the
+including the associated Airflow version for the provider version (i.e first 
Airflow version released after the
 provider has been released) and date of the release of the provider version.
 
 These are all of the available flags for the ``generate-providers-metadata`` 
command:
@@ -520,17 +520,17 @@ all or selected python version and single constraint mode 
like this:
 
 Constraints are generated separately for each python version and there are 
separate constraints modes:
 
-* 'constraints' - those are constraints generated by matching the current 
airflow version from sources
+* 'constraints' - those are constraints generated by matching the current 
Airflow version from sources
    and providers that are installed from PyPI. Those are constraints used by 
the users who want to
-   install airflow with pip.
+   install Airflow with pip.
 
 * "constraints-source-providers" - those are constraints generated by using 
providers installed from
   current sources. While adding new providers their dependencies might change, 
so this set of providers
-  is the current set of the constraints for airflow and providers from the 
current main sources.
+  is the current set of the constraints for Airflow and providers from the 
current main sources.
   Those providers are used by CI system to keep "stable" set of constraints.
 
 * "constraints-no-providers" - those are constraints generated from only 
Apache Airflow, without any
-  providers. If you want to manage airflow separately and then add providers 
individually, you can
+  providers. If you want to manage Airflow separately and then add providers 
individually, you can
   use those.
 
 These are all available flags of ``generate-constraints`` command:
@@ -615,7 +615,7 @@ while publishing the documentation.
      breeze release-management publish-docs --airflow-site-directory
 
 You can also use shorthand names as arguments instead of using the full names
-for airflow providers. To find the short hand names, follow the instructions 
in :ref:`generating_short_form_names`.
+for Airflow providers. To find the short hand names, follow the instructions 
in :ref:`generating_short_form_names`.
 
 The flag ``--airflow-site-directory`` takes the path of the cloned 
``airflow-site``. The command will
 not proceed if this is an invalid path.
@@ -635,7 +635,7 @@ Adding back referencing HTML for the documentation
 
 To add back references to the documentation generated by ``build-docs`` in 
Breeze to ``airflow-site``,
 use the ``release-management add-back-references`` command. This is important 
to support backward compatibility
-the airflow documentation.
+the Airflow documentation.
 
 You have to specify which distributions you run it on. For example you can run 
it for all providers:
 
@@ -690,7 +690,7 @@ Generating Provider requirements
 
 In order to generate SBOM information for providers, we need to generate 
requirements for them. This is
 done by the ``generate-providers-requirements`` command. This command 
generates requirements for the
-selected provider and python version, using the airflow version specified.
+selected provider and python version, using the Airflow version specified.
 
 .. image:: ./images/output_sbom_generate-providers-requirements.svg
   :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_sbom_generate-providers-requirements.svg
@@ -712,17 +712,17 @@ These are all of the available flags for the 
``update-sbom-information`` command
   :width: 100%
   :alt: Breeze update sbom information
 
-Build all airflow images
+Build all Airflow images
 """"""""""""""""""""""""
 
-In order to generate providers requirements, we need docker images with all 
airflow versions pre-installed,
+In order to generate providers requirements, we need docker images with all 
Airflow versions pre-installed,
 such images are built with the ``build-all-airflow-images`` command.
-This command will build one docker image per python version, with all the 
airflow versions >=2.0.0 compatible.
+This command will build one docker image per python version, with all the 
Airflow versions >=2.0.0 compatible.
 
 .. image:: ./images/output_sbom_build-all-airflow-images.svg
   :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_sbom_build-all-airflow-images.svg
   :width: 100%
-  :alt: Breeze build all airflow images
+  :alt: Breeze build all Airflow images
 
 
 Exporting SBOM information
@@ -741,16 +741,16 @@ properties of the dependencies. This is done by the 
``export-dependency-informat
 Next step: Follow the `Advanced Breeze topics 
<10_advanced_breeze_topics.rst>`_ to
 learn more about Breeze internals.
 
-Preparing airflow Task SDK distributions
+Preparing Airflow Task SDK distributions
 """""""""""""""""""""""""""""""""""
 
-You can prepare airflow distributions using Breeze:
+You can prepare Airflow distributions using Breeze:
 
 .. code-block:: bash
 
      breeze release-management prepare-task-sdk-distributions
 
-This prepares airflow Task SDK .whl package in the dist folder.
+This prepares Airflow Task SDK .whl package in the dist folder.
 
 Again, you can specify optional ``--distribution-format`` flag to build 
selected formats of the Task SDK distributions,
 default is to build ``both`` type of distributions ``sdist`` and ``wheel``.
@@ -765,18 +765,18 @@ default is to build ``both`` type of distributions 
``sdist`` and ``wheel``.
   :alt: Breeze release-management prepare-task-sdk-distributions
 
 
-Preparing airflow ctl distributions
+Preparing Airflow ctl distributions
 """""""""""""""""""""""""""""""""""
 
-You can prepare airflow distributions using Breeze:
+You can prepare Airflow distributions using Breeze:
 
 .. code-block:: bash
 
      breeze release-management prepare-airflow-ctl-distributions
 
-This prepares airflow Task SDK .whl package in the dist folder.
+This prepares Airflow Task SDK .whl package in the dist folder.
 
-Again, you can specify optional ``--distribution-format`` flag to build 
selected formats of the airflow ctl distributions,
+Again, you can specify optional ``--distribution-format`` flag to build 
selected formats of the Airflow ctl distributions,
 default is to build ``both`` type of distributions ``sdist`` and ``wheel``.
 
 .. code-block:: bash
@@ -787,3 +787,92 @@ default is to build ``both`` type of distributions 
``sdist`` and ``wheel``.
   :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_release-management_prepare-airflow-ctl-distributions.svg
   :width: 100%
   :alt: Breeze release-management prepare-airflow-ctl-distributions
+
+Publishing the documentation to S3
+""""""""""""""""""""""""""""""""""
+
+To publish the documentation generated by ``build-docs`` in Breeze to ``S3``,
+use the ``release-management publish-docs-to-s3`` command:
+
+.. code-block:: bash
+
+     breeze release-management publish-docs-to-s3
+
+The documentation publish to S3 should be done after the ``breeze 
release-management publish-docs`` command.
+Once documentation is available in ``docs-archive`` directory of airflow-site, 
it can be published to S3.
+
+The publishing documentation to S3 consists of the following steps:
+
+.. code-block:: bash
+
+     breeze release-management publish-docs --source-dir-path <> 
--destination-location <>
+
+Where ``--source-dir-path`` is a doc-archive location path and 
``--destination-location`` is the S3 bucket path.
+
+.. code-block:: bash
+
+     breeze release-management publish-docs --source-dir-path 
/User/pavan/airflow-site/docs-archive
+     --destination-location s3://airflow-docs/docs
+
+To exclude any documentation from publishing to S3, you can use the 
``--exclude`` flag.
+
+.. code-block:: bash
+
+     breeze release-management publish-docs --source-dir-path 
/User/pavan/airflow-site/docs-archive
+     --destination-location s3://airflow-docs/docs --exclude 
"amazon,apache.kafka"
+
+To override the versioned directories while publishing the documentation to 
S3, you can use the ``--overwrite`` flag.
+
+.. code-block:: bash
+
+     breeze release-management publish-docs --source-dir-path 
/User/pavan/airflow-site/docs-archive
+     --destination-location s3://airflow-docs/docs --overwrite
+
+To check what documents will be published to S3, you can use the ``--dry-run`` 
flag.
+
+.. code-block:: bash
+
+     breeze release-management publish-docs --source-dir-path 
/User/pavan/airflow-site/docs-archive
+     --destination-location s3://airflow-docs/docs --dry-run
+
+These are all available flags of ``release-management publish-docs-to-s3`` 
command:
+
+.. image:: ./images/output_release-management_publish-docs.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_release-management_publish-docs-to-s3.svg
+  :width: 100%
+  :alt: Breeze Publish documentation to S3
+
+
+Trigger GitHub Actions docs publish workflow
+"""""""""""""""""""""""""""""""""""""""""""""
+To trigger the GitHub Actions workflow that publishes the documentation to S3, 
you can use the
+``breeze workflow-run publish-docs`` command.
+
+These are all available flags of ``workflow-run`` command:
+
+.. image:: ./images/output_workflow-run.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_workflow-run.svg
+  :width: 100%
+  :alt: Workflow run command
+
+
+.. code-block:: bash
+
+     breeze workflow-run publish-docs --ref <ref> --exclude-docs 
<exclude-docs> --site-env <site-env> --refresh-site 
--skip-write-to-stable-folder <docs_packages>
+
+     example:
+      breeze workflow-run publish-docs --ref providers-amazon/1.0.0 --site-env 
live --refresh-site --skip-write-to-stable-folder amazon apache.kafka
+
+``--ref`` specifies the Git reference tag checkout and build docs.
+``--exclude-docs`` specifies the documentation packages to exclude from the 
publish process.
+``--site-env`` specifies the environment to use for the site (e.g., auto, 
live, staging). the default is auto, based on the ref it decides live or 
staging.
+``--refresh-site`` specifies whether to refresh the site after publishing the 
documentation. This triggers workflow on apache/airflow-site repository to 
refresh the site.
+``--skip-write-to-stable-folder`` specifies the documentation packages to skip 
writing to the stable folder.
+
+
+These are all available flags of ``workflow-run publish-docs`` command:
+
+.. image:: ./images/output_workflow-run_publish-docs.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_workflow-run_publish-docs.svg
+  :width: 100%
+  :alt: Breeze workflow-run publish-docs
diff --git a/dev/breeze/doc/images/output-commands.svg 
b/dev/breeze/doc/images/output-commands.svg
index 2d9668f5a21..030caaeb7d5 100644
--- a/dev/breeze/doc/images/output-commands.svg
+++ b/dev/breeze/doc/images/output-commands.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 2148.4" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 2172.7999999999997" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-help-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="2097.4" />
+      <rect x="0" y="0" width="1463.0" height="2121.7999999999997" />
     </clipPath>
     <clipPath id="breeze-help-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -300,9 +300,12 @@
 <clipPath id="breeze-help-line-84">
     <rect x="0" y="2051.1" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-help-line-85">
+    <rect x="0" y="2075.5" 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="2146.4" rx="8"/><text 
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Breeze&#160;commands</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="2170.8" rx="8"/><text 
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Breeze&#160;commands</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -393,11 +396,12 @@
 </text><text class="breeze-help-r5" x="0" y="1923.2" textLength="24.4" 
clip-path="url(#breeze-help-line-78)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="1923.2" textLength="353.8" 
clip-path="url(#breeze-help-line-78)">&#160;Release&#160;management&#160;commands&#160;</text><text
 class="breeze-help-r5" x="378.2" y="1923.2" textLength="1061.4" 
clip-path="url(#breeze-help-line-78)">───────────────────────────────────────────────────────────────────────────────────────</text><text
 clas [...]
 </text><text class="breeze-help-r5" x="0" y="1947.6" textLength="12.2" 
clip-path="url(#breeze-help-line-79)">│</text><text class="breeze-help-r4" 
x="24.4" y="1947.6" textLength="280.6" 
clip-path="url(#breeze-help-line-79)">release-management&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1947.6" textLength="1110.2" 
clip-path="url(#breeze-help-line-79)">Tools&#160;that&#160;release&#160;managers&#160;can&#160;use&#160;to&#160;prepare&#160;and&#160;manage&#16
 [...]
 </text><text class="breeze-help-r5" x="0" y="1972" textLength="12.2" 
clip-path="url(#breeze-help-line-80)">│</text><text class="breeze-help-r4" 
x="24.4" y="1972" textLength="280.6" 
clip-path="url(#breeze-help-line-80)">sbom&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1972" textLength="1110.2" 
clip-path="url(#breeze-help-line-80)">Tools&#160;that&#160;release&#160;managers
 [...]
-</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="1464" 
clip-path="url(#breeze-help-line-81)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="1996.4" textLength="12.2" 
clip-path="url(#breeze-help-line-81)">
-</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="24.4" 
clip-path="url(#breeze-help-line-82)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="2020.8" textLength="195.2" 
clip-path="url(#breeze-help-line-82)">&#160;Other&#160;commands&#160;</text><text
 class="breeze-help-r5" x="219.6" y="2020.8" textLength="1220" 
clip-path="url(#breeze-help-line-82)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
-</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="12.2" 
clip-path="url(#breeze-help-line-83)">│</text><text class="breeze-help-r4" 
x="24.4" y="2045.2" textLength="122" 
clip-path="url(#breeze-help-line-83)">setup&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2045.2" textLength="1268.8" 
clip-path="url(#breeze-help-line-83)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;configure&#160;Breeze&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="12.2" 
clip-path="url(#breeze-help-line-84)">│</text><text class="breeze-help-r4" 
x="24.4" y="2069.6" textLength="122" 
clip-path="url(#breeze-help-line-84)">ci&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2069.6" textLength="1268.8" 
clip-path="url(#breeze-help-line-84)">Tools&#160;that&#160;CI&#160;workflows&#160;use&#160;to&#160;cleanup/manage&#160;CI&#160;environment&#160;
 [...]
-</text><text class="breeze-help-r5" x="0" y="2094" textLength="1464" 
clip-path="url(#breeze-help-line-85)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2094" textLength="12.2" 
clip-path="url(#breeze-help-line-85)">
+</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="12.2" 
clip-path="url(#breeze-help-line-81)">│</text><text class="breeze-help-r4" 
x="24.4" y="1996.4" textLength="280.6" 
clip-path="url(#breeze-help-line-81)">workflow-run&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="329.4" y="1996.4" textLength="1110.2" 
clip-path="url(#breeze-help-line-81)">Tools&#160;to&#160;manage&#160;Airflow&#160;repository&#160;workflows&#160;&
 [...]
+</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="1464" 
clip-path="url(#breeze-help-line-82)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2020.8" textLength="12.2" 
clip-path="url(#breeze-help-line-82)">
+</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="24.4" 
clip-path="url(#breeze-help-line-83)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="2045.2" textLength="195.2" 
clip-path="url(#breeze-help-line-83)">&#160;Other&#160;commands&#160;</text><text
 class="breeze-help-r5" x="219.6" y="2045.2" textLength="1220" 
clip-path="url(#breeze-help-line-83)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="bree [...]
+</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="12.2" 
clip-path="url(#breeze-help-line-84)">│</text><text class="breeze-help-r4" 
x="24.4" y="2069.6" textLength="122" 
clip-path="url(#breeze-help-line-84)">setup&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2069.6" textLength="1268.8" 
clip-path="url(#breeze-help-line-84)">Tools&#160;that&#160;developers&#160;can&#160;use&#160;to&#160;configure&#160;Breeze&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-help-r5" x="0" y="2094" textLength="12.2" 
clip-path="url(#breeze-help-line-85)">│</text><text class="breeze-help-r4" 
x="24.4" y="2094" textLength="122" 
clip-path="url(#breeze-help-line-85)">ci&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-help-r1" x="170.8" y="2094" textLength="1268.8" 
clip-path="url(#breeze-help-line-85)">Tools&#160;that&#160;CI&#160;workflows&#160;use&#160;to&#160;cleanup/manage&#160;CI&#160;environment&#160;&#160;
 [...]
+</text><text class="breeze-help-r5" x="0" y="2118.4" textLength="1464" 
clip-path="url(#breeze-help-line-86)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-help-r1" x="1464" y="2118.4" textLength="12.2" 
clip-path="url(#breeze-help-line-86)">
 </text>
     </g>
     </g>
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 c61da6940de..118c0c3d4e2 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
@@ -215,7 +215,7 @@
 </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-r6" x="183" y="800.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">testing:airflow-ctl-tests&#160;|&#160;testing:core-integration-tests&#160;|&#160;testing:core-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
 </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-r6" x="183" y="825.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;testing:providers-integration-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="849.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="849.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">testing:providers-tests&#160;|&#160;testing:python-api-client-tests&#160;|&#160;testing:system-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="874" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="874" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">testing:task-sdk-tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="874" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="874" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">testing:task-sdk-tests&#160;|&#160;workflow-run&#160;|&#160;workflow-run:publish-docs)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="898.4" textLength="1464" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="898.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="922.8" textLength="24.4" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">╭─</text><text
 class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="922.8" 
textLength="195.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">&#160;Common&#160;options&#160;</text><text
 class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="922.8" 
textLength="1220" clip-path="url(#breeze-se [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="947.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="947.2" 
textLength="109.8" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">--verbose</text><text
 class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="947.2" 
textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in [...]
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 f28b4e6f51e..2b4291e68d2 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 @@
-41e8d5cb0d997969ca1b6b079446488e
+281648f2acfd40a2d6c72d8b935f7211
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 0ee7112ff35..b810ff7beab 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -233,7 +233,7 @@
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="874" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="874" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">static-checks&#160;|&#160;testing&#160;|&#160;testing:airflow-ctl-tests&#160;|&#160;testing:core-integration-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="898.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">testing:core-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="922.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="922.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">testing:providers-integration-tests&#160;|&#160;testing:providers-tests&#160;|&#160;testing:python-api-client-tests&#160;|&#160;&#160;&#160;</text><text
 class="bre [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="947.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="947.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">testing:system-tests&#160;|&#160;testing:task-sdk-tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="947.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="947.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">testing:system-tests&#160;|&#160;testing:task-sdk-tests&#160;|&#160;workflow-run&#160;|&#160;workflow-run:publish-docs)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="971.6" 
textLength="146.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">--check-only</text><text
 class="breeze-setup-regenerate-command-images-r1" x="219.6" y="971.6" 
textLength="1220" clip-path="url(#breeze-setup-regenerate-command-im [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text 
class="breeze-setup-regenerate-command-images-r1" x="219.6" y="996" 
textLength="170.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">together&#160;with&#160;</text><text
 class="breeze-setup-regenerate-command-images-r4" x="390.4" y="996" 
textLength="109.8" clip-path="url(#breeze-setup-regenerate-co [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1020.4" textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="1020.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">
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 825aefbbf35..f48a094c49d 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 @@
-170493c744c7a901f3f1c4ffb1e1c89b
+5661481e019525eae03f87ee1efeb6ee
diff --git a/dev/breeze/doc/images/output_workflow-run.svg 
b/dev/breeze/doc/images/output_workflow-run.svg
new file mode 100644
index 00000000000..af211f19a8e
--- /dev/null
+++ b/dev/breeze/doc/images/output_workflow-run.svg
@@ -0,0 +1,103 @@
+<svg class="rich-terminal" viewBox="0 0 1482 318.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-workflow-run-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-workflow-run-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-workflow-run-r1 { fill: #c5c8c6 }
+.breeze-workflow-run-r2 { fill: #d0b344 }
+.breeze-workflow-run-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-workflow-run-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-workflow-run-r5 { fill: #868887 }
+.breeze-workflow-run-r6 { fill: #98a84b;font-weight: bold }
+    </style>
+
+    <defs>
+    <clipPath id="breeze-workflow-run-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="267.4" />
+    </clipPath>
+    <clipPath id="breeze-workflow-run-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-line-9">
+    <rect x="0" y="221.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="316.4" rx="8"/><text 
class="breeze-workflow-run-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;workflow-run</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-workflow-run-clip-terminal)">
+    
+    <g class="breeze-workflow-run-matrix">
+    <text class="breeze-workflow-run-r1" x="1464" y="20" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-0)">
+</text><text class="breeze-workflow-run-r2" x="12.2" y="44.4" 
textLength="73.2" 
clip-path="url(#breeze-workflow-run-line-1)">Usage:</text><text 
class="breeze-workflow-run-r3" x="97.6" y="44.4" textLength="231.8" 
clip-path="url(#breeze-workflow-run-line-1)">breeze&#160;workflow-run</text><text
 class="breeze-workflow-run-r1" x="341.6" y="44.4" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-1)">[</text><text 
class="breeze-workflow-run-r4" x="353.8" y="44.4" textLength="85.4" cli [...]
+</text><text class="breeze-workflow-run-r1" x="1464" y="68.8" 
textLength="12.2" clip-path="url(#breeze-workflow-run-line-2)">
+</text><text class="breeze-workflow-run-r1" x="12.2" y="93.2" 
textLength="536.8" 
clip-path="url(#breeze-workflow-run-line-3)">Tools&#160;to&#160;manage&#160;Airflow&#160;repository&#160;workflows</text><text
 class="breeze-workflow-run-r1" x="1464" y="93.2" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-3)">
+</text><text class="breeze-workflow-run-r1" x="1464" y="117.6" 
textLength="12.2" clip-path="url(#breeze-workflow-run-line-4)">
+</text><text class="breeze-workflow-run-r5" x="0" y="142" textLength="24.4" 
clip-path="url(#breeze-workflow-run-line-5)">╭─</text><text 
class="breeze-workflow-run-r5" x="24.4" y="142" textLength="195.2" 
clip-path="url(#breeze-workflow-run-line-5)">&#160;Common&#160;options&#160;</text><text
 class="breeze-workflow-run-r5" x="219.6" y="142" textLength="1220" 
clip-path="url(#breeze-workflow-run-line-5)">────────────────────────────────────────────────────────────────────────────────────────
 [...]
+</text><text class="breeze-workflow-run-r5" x="0" y="166.4" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-6)">│</text><text 
class="breeze-workflow-run-r4" x="24.4" y="166.4" textLength="73.2" 
clip-path="url(#breeze-workflow-run-line-6)">--help</text><text 
class="breeze-workflow-run-r6" x="122" y="166.4" textLength="24.4" 
clip-path="url(#breeze-workflow-run-line-6)">-h</text><text 
class="breeze-workflow-run-r1" x="170.8" y="166.4" textLength="329.4" 
clip-path="url(#breeze-wor [...]
+</text><text class="breeze-workflow-run-r5" x="0" y="190.8" textLength="1464" 
clip-path="url(#breeze-workflow-run-line-7)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-workflow-run-r1" x="1464" y="190.8" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-7)">
+</text><text class="breeze-workflow-run-r5" x="0" y="215.2" textLength="24.4" 
clip-path="url(#breeze-workflow-run-line-8)">╭─</text><text 
class="breeze-workflow-run-r5" x="24.4" y="215.2" textLength="512.4" 
clip-path="url(#breeze-workflow-run-line-8)">&#160;Airflow&#160;github&#160;actions&#160;workflow&#160;commands&#160;</text><text
 class="breeze-workflow-run-r5" x="536.8" y="215.2" textLength="902.8" 
clip-path="url(#breeze-workflow-run-line-8)">────────────────────────────────────────
 [...]
+</text><text class="breeze-workflow-run-r5" x="0" y="239.6" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-9)">│</text><text 
class="breeze-workflow-run-r4" x="24.4" y="239.6" textLength="366" 
clip-path="url(#breeze-workflow-run-line-9)">publish-docs&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-workflow-run-r1" x="414.8" y="239.6" textLength="1024.8" 
clip-path="url(#breeze-workflow-run-lin [...]
+</text><text class="breeze-workflow-run-r5" x="0" y="264" textLength="1464" 
clip-path="url(#breeze-workflow-run-line-10)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-workflow-run-r1" x="1464" y="264" textLength="12.2" 
clip-path="url(#breeze-workflow-run-line-10)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_workflow-run.txt 
b/dev/breeze/doc/images/output_workflow-run.txt
new file mode 100644
index 00000000000..7c0345e43fc
--- /dev/null
+++ b/dev/breeze/doc/images/output_workflow-run.txt
@@ -0,0 +1 @@
+bff0ef03c469cfda50f0383a9d1986aa
diff --git a/dev/breeze/doc/images/output_workflow-run_publish-docs.svg 
b/dev/breeze/doc/images/output_workflow-run_publish-docs.svg
new file mode 100644
index 00000000000..135199a1465
--- /dev/null
+++ b/dev/breeze/doc/images/output_workflow-run_publish-docs.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-workflow-run-publish-docs-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-workflow-run-publish-docs-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-workflow-run-publish-docs-r1 { fill: #c5c8c6 }
+.breeze-workflow-run-publish-docs-r2 { fill: #d0b344 }
+.breeze-workflow-run-publish-docs-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-workflow-run-publish-docs-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-workflow-run-publish-docs-r5 { fill: #868887 }
+.breeze-workflow-run-publish-docs-r6 { fill: #cc555a }
+.breeze-workflow-run-publish-docs-r7 { fill: #8d7b39 }
+.breeze-workflow-run-publish-docs-r8 { fill: #8a4346 }
+.breeze-workflow-run-publish-docs-r9 { fill: #98a84b;font-weight: bold }
+    </style>
+
+    <defs>
+    <clipPath id="breeze-workflow-run-publish-docs-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="633.4" />
+    </clipPath>
+    <clipPath id="breeze-workflow-run-publish-docs-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-9">
+    <rect x="0" y="221.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-10">
+    <rect x="0" y="245.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-11">
+    <rect x="0" y="269.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-12">
+    <rect x="0" y="294.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-13">
+    <rect x="0" y="318.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-14">
+    <rect x="0" y="343.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-15">
+    <rect x="0" y="367.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-16">
+    <rect x="0" y="391.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-17">
+    <rect x="0" y="416.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-18">
+    <rect x="0" y="440.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-19">
+    <rect x="0" y="465.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-20">
+    <rect x="0" y="489.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-21">
+    <rect x="0" y="513.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-22">
+    <rect x="0" y="538.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-line-23">
+    <rect x="0" y="562.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-workflow-run-publish-docs-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-workflow-run-publish-docs-title" fill="#c5c8c6" 
text-anchor="middle" x="740" 
y="27">Command:&#160;workflow-run&#160;publish-docs</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-workflow-run-publish-docs-clip-terminal)">
+    
+    <g class="breeze-workflow-run-publish-docs-matrix">
+    <text class="breeze-workflow-run-publish-docs-r1" x="1464" y="20" 
textLength="12.2" clip-path="url(#breeze-workflow-run-publish-docs-line-0)">
+</text><text class="breeze-workflow-run-publish-docs-r2" x="12.2" y="44.4" 
textLength="1439.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-1)">Usage:&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-workflow-run-publish-docs-r3" x="12.2" y="68.8" 
textLength="1439.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-2)">breeze&#160;workflow-run&#160;publish-docs&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-workflow-run-publish-docs-r1" x="12.2" y="93.2" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-3)">[</text><text 
class="breeze-workflow-run-publish-docs-r4" x="24.4" y="93.2" textLength="85.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-3)">OPTIONS</text><text 
class="breeze-workflow-run-publish-docs-r1" x="109.8" y="93.2" 
textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-3)">]&#160;[</text><text 
class="br [...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="117.6" 
textLength="73.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-4)">apache</text><text 
class="breeze-workflow-run-publish-docs-r1" x="85.4" y="117.6" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-4)">.</text><text 
class="breeze-workflow-run-publish-docs-r4" x="97.6" y="117.6" 
textLength="109.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-4)">cassandra</text><text 
class= [...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="142" 
textLength="73.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-5)">apache</text><text 
class="breeze-workflow-run-publish-docs-r1" x="85.4" y="142" textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-5)">.</text><text 
class="breeze-workflow-run-publish-docs-r4" x="97.6" y="142" textLength="73.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-5)">impala</text><text 
class="breeze-wo [...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="166.4" 
textLength="97.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-6)">arangodb</text><text 
class="breeze-workflow-run-publish-docs-r1" x="109.8" y="166.4" 
textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-6)">&#160;|&#160;</text><text
 class="breeze-workflow-run-publish-docs-r4" x="146.4" y="166.4" 
textLength="61" 
clip-path="url(#breeze-workflow-run-publish-docs-line-6)">asana</text><te [...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="190.8" 
textLength="73.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-7)">common</text><text 
class="breeze-workflow-run-publish-docs-r1" x="85.4" y="190.8" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-7)">.</text><text 
class="breeze-workflow-run-publish-docs-r4" x="97.6" y="190.8" 
textLength="109.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-7)">messaging</text><text 
class= [...]
+</text><text class="breeze-workflow-run-publish-docs-r1" x="12.2" y="215.2" 
textLength="24.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-8)">|&#160;</text><text 
class="breeze-workflow-run-publish-docs-r4" x="36.6" y="215.2" 
textLength="158.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-8)">elasticsearch</text><text
 class="breeze-workflow-run-publish-docs-r1" x="195.2" y="215.2" 
textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-8)">&#160;|&#160;< [...]
+</text><text class="breeze-workflow-run-publish-docs-r1" x="12.2" y="239.6" 
textLength="24.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-9)">|&#160;</text><text 
class="breeze-workflow-run-publish-docs-r4" x="36.6" y="239.6" 
textLength="97.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-9)">influxdb</text><text 
class="breeze-workflow-run-publish-docs-r1" x="134.2" y="239.6" 
textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-9)">&#160;|&#160;</text> 
[...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="264" 
textLength="61" 
clip-path="url(#breeze-workflow-run-publish-docs-line-10)">neo4j</text><text 
class="breeze-workflow-run-publish-docs-r1" x="73.2" y="264" textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-10)">&#160;|&#160;</text><text
 class="breeze-workflow-run-publish-docs-r4" x="109.8" y="264" 
textLength="48.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-10)">odbc</text><text 
class [...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="288.4" 
textLength="97.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-11)">pinecone</text><text 
class="breeze-workflow-run-publish-docs-r1" x="109.8" y="288.4" 
textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-11)">&#160;|&#160;</text><text
 class="breeze-workflow-run-publish-docs-r4" x="146.4" y="288.4" 
textLength="97.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-11)">postgres</ [...]
+</text><text class="breeze-workflow-run-publish-docs-r4" x="12.2" y="312.8" 
textLength="48.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-12)">smtp</text><text 
class="breeze-workflow-run-publish-docs-r1" x="61" y="312.8" textLength="36.6" 
clip-path="url(#breeze-workflow-run-publish-docs-line-12)">&#160;|&#160;</text><text
 class="breeze-workflow-run-publish-docs-r4" x="97.6" y="312.8" 
textLength="109.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-12)">snowflake</text>< 
[...]
+</text><text class="breeze-workflow-run-publish-docs-r1" x="12.2" y="337.2" 
textLength="24.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-13)">|&#160;</text><text 
class="breeze-workflow-run-publish-docs-r4" x="36.6" y="337.2" 
textLength="85.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-13)">zendesk</text><text 
class="breeze-workflow-run-publish-docs-r1" x="122" y="337.2" 
textLength="1329.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-13)">]...&#160;&#160;&# 
[...]
+</text><text class="breeze-workflow-run-publish-docs-r1" x="1464" y="361.6" 
textLength="12.2" clip-path="url(#breeze-workflow-run-publish-docs-line-14)">
+</text><text class="breeze-workflow-run-publish-docs-r1" x="12.2" y="386" 
textLength="427" 
clip-path="url(#breeze-workflow-run-publish-docs-line-15)">Trigger&#160;publish&#160;docs&#160;to&#160;S3&#160;workflow</text><text
 class="breeze-workflow-run-publish-docs-r1" x="1464" y="386" textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-15)">
+</text><text class="breeze-workflow-run-publish-docs-r1" x="1464" y="410.4" 
textLength="12.2" clip-path="url(#breeze-workflow-run-publish-docs-line-16)">
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="434.8" 
textLength="24.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-17)">╭─</text><text 
class="breeze-workflow-run-publish-docs-r5" x="24.4" y="434.8" 
textLength="378.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-17)">&#160;Trigger&#160;publish&#160;docs&#160;workflow&#160;</text><text
 class="breeze-workflow-run-publish-docs-r5" x="402.6" y="434.8" 
textLength="1037" clip-path="url(#breeze-workflow-run [...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="459.2" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-18)">│</text><text 
class="breeze-workflow-run-publish-docs-r6" x="24.4" y="459.2" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-18)">*</text><text 
class="breeze-workflow-run-publish-docs-r4" x="61" y="459.2" textLength="61" 
clip-path="url(#breeze-workflow-run-publish-docs-line-18)">--ref</text><text 
class="breeze-workfl [...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="483.6" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-19)">│</text><text 
class="breeze-workflow-run-publish-docs-r4" x="61" y="483.6" textLength="170.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-19)">--exclude-docs</text><text
 class="breeze-workflow-run-publish-docs-r1" x="463.6" y="483.6" 
textLength="805.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-19)">Comma&#160;separated 
[...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="508" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-20)">│</text><text 
class="breeze-workflow-run-publish-docs-r4" x="61" y="508" textLength="122" 
clip-path="url(#breeze-workflow-run-publish-docs-line-20)">--site-env</text><text
 class="breeze-workflow-run-publish-docs-r1" x="463.6" y="508" textLength="671" 
clip-path="url(#breeze-workflow-run-publish-docs-line-20)">S3&#160;bucket&#160;to&#160;which&
 [...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="532.4" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-21)">│</text><text 
class="breeze-workflow-run-publish-docs-r4" x="61" y="532.4" textLength="353.8" 
clip-path="url(#breeze-workflow-run-publish-docs-line-21)">--skip-write-to-stable-folder</text><text
 class="breeze-workflow-run-publish-docs-r1" x="463.6" y="532.4" 
textLength="366" 
clip-path="url(#breeze-workflow-run-publish-docs-line-21)">Skip&#1 [...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="556.8" 
textLength="1464" 
clip-path="url(#breeze-workflow-run-publish-docs-line-22)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-workflow-run-publish-docs-r1" x="1464" y="556.8" 
textLength="12.2" clip-path="url(#breeze-workflow-run-publish-docs-line-22)">
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="581.2" 
textLength="24.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-23)">╭─</text><text 
class="breeze-workflow-run-publish-docs-r5" x="24.4" y="581.2" 
textLength="195.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-23)">&#160;Common&#160;options&#160;</text><text
 class="breeze-workflow-run-publish-docs-r5" x="219.6" y="581.2" 
textLength="1220" clip-path="url(#breeze-workflow-run-publish-docs-line-23)">─ 
[...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="605.6" 
textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-24)">│</text><text 
class="breeze-workflow-run-publish-docs-r4" x="24.4" y="605.6" 
textLength="73.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-24)">--help</text><text 
class="breeze-workflow-run-publish-docs-r9" x="122" y="605.6" textLength="24.4" 
clip-path="url(#breeze-workflow-run-publish-docs-line-24)">-h</text><text 
class="breeze-w [...]
+</text><text class="breeze-workflow-run-publish-docs-r5" x="0" y="630" 
textLength="1464" 
clip-path="url(#breeze-workflow-run-publish-docs-line-25)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-workflow-run-publish-docs-r1" x="1464" y="630" textLength="12.2" 
clip-path="url(#breeze-workflow-run-publish-docs-line-25)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_workflow-run_publish-docs.txt 
b/dev/breeze/doc/images/output_workflow-run_publish-docs.txt
new file mode 100644
index 00000000000..ccebd4389d3
--- /dev/null
+++ b/dev/breeze/doc/images/output_workflow-run_publish-docs.txt
@@ -0,0 +1 @@
+9ee2e8e8aa91886504c2d859b4e6bc49
diff --git a/dev/breeze/src/airflow_breeze/breeze.py 
b/dev/breeze/src/airflow_breeze/breeze.py
index ed651457009..fab25baba1d 100755
--- a/dev/breeze/src/airflow_breeze/breeze.py
+++ b/dev/breeze/src/airflow_breeze/breeze.py
@@ -18,6 +18,7 @@
 from __future__ import annotations
 
 from airflow_breeze.commands.main_command import main
+from airflow_breeze.commands.workflow_commands import workflow_run
 from airflow_breeze.utils.path_utils import (
     create_directories_and_files,
     find_airflow_root_path_to_operate_on,
@@ -50,6 +51,7 @@ main.add_command(prod_image)
 main.add_command(setup)
 main.add_command(release_management)
 main.add_command(sbom)
+main.add_command(workflow_run)
 
 if __name__ == "__main__":
     main()
diff --git a/dev/breeze/src/airflow_breeze/commands/workflow_commands.py 
b/dev/breeze/src/airflow_breeze/commands/workflow_commands.py
new file mode 100644
index 00000000000..5f1225ad93f
--- /dev/null
+++ b/dev/breeze/src/airflow_breeze/commands/workflow_commands.py
@@ -0,0 +1,155 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import json
+import re
+import sys
+
+import click
+
+from airflow_breeze.commands.common_options import argument_doc_packages
+from airflow_breeze.utils.click_utils import BreezeGroup
+from airflow_breeze.utils.console import get_console
+from airflow_breeze.utils.custom_param_types import BetterChoice
+from airflow_breeze.utils.gh_workflow_utils import trigger_workflow_and_monitor
+from airflow_breeze.utils.run_utils import run_command
+
+WORKFLOW_NAME_MAPS = {
+    "publish-docs": "publish-docs-to-s3.yml",
+    "airflow-refresh-site": "build.yml",
+    "sync-s3-to-github": "s3-to-github.yml",
+}
+
+APACHE_AIRFLOW_REPO = "apache/airflow"
+APACHE_AIRFLOW_SITE_REPO = "apache/airflow-site"
+APACHE_AIRFLOW_SITE_ARCHIVE_REPO = "apache/airflow-site-archive"
+
+
[email protected](cls=BreezeGroup, name="workflow-run", help="Tools to manage 
Airflow repository workflows ")
+def workflow_run():
+    pass
+
+
+@workflow_run.command(name="publish-docs", help="Trigger publish docs to S3 
workflow")
[email protected](
+    "--ref",
+    help="Git reference tag to checkout to build documentation.",
+    required=True,
+)
[email protected](
+    "--exclude-docs",
+    help="Comma separated list of docs packages to exclude from the publish.",
+    default="no-docs-excluded",
+)
[email protected](
+    "--site-env",
+    help="S3 bucket to which the documentation will be published.",
+    default="auto",
+    type=BetterChoice(["auto", "live", "staging"]),
+)
[email protected](
+    "--skip-write-to-stable-folder",
+    help="Skip writing to stable folder.",
+    is_flag=True,
+)
+@argument_doc_packages
+def workflow_run_publish(
+    ref: str,
+    exclude_docs: str,
+    site_env: str,
+    doc_packages: tuple[str, ...],
+    skip_write_to_stable_folder: bool = False,
+):
+    get_console().print(
+        f"[blue]Validating ref: {ref}[/blue]",
+    )
+
+    tag_result = run_command(
+        ["gh", "api", f"repos/apache/airflow/git/refs/tags/{ref}"],
+        capture_output=True,
+        check=False,
+    )
+
+    stdout = tag_result.stdout.decode("utf-8")
+    tag_respo = json.loads(stdout)
+
+    if not tag_respo.get("ref"):
+        get_console().print(
+            f"[red]Error: Ref {ref} is not exists in repo apache/airflow 
.[/red]",
+        )
+        sys.exit(1)
+
+    get_console().print(
+        f"[blue]Triggering workflow {WORKFLOW_NAME_MAPS['publish-docs']}: at 
{APACHE_AIRFLOW_REPO}[/blue]",
+    )
+
+    workflow_fields = {
+        "ref": ref,
+        "destination": site_env,
+        "include-docs": " ".join(doc_packages),
+        "exclude-docs": exclude_docs,
+        "skip-write-to-stable-folder": skip_write_to_stable_folder,
+    }
+
+    trigger_workflow_and_monitor(
+        workflow_name=WORKFLOW_NAME_MAPS["publish-docs"],
+        repo=APACHE_AIRFLOW_REPO,
+        branch="main",
+        **workflow_fields,
+    )
+
+    if site_env == "auto":
+        pattern = re.compile(r"^.*[0-9]+\.[0-9]+\.[0-9]+$")
+        if pattern.match(ref):
+            site_env = "live"
+        else:
+            site_env = "staging"
+
+    branch = "main" if site_env == "live" else "staging"
+
+    get_console().print(
+        f"[blue]Refreshing site at {APACHE_AIRFLOW_SITE_REPO}[/blue]",
+    )
+    wf_name = WORKFLOW_NAME_MAPS["airflow-refresh-site"]
+
+    get_console().print(
+        f"[blue]Triggering workflow {wf_name}: at 
{APACHE_AIRFLOW_SITE_REPO}[/blue]",
+    )
+
+    trigger_workflow_and_monitor(
+        workflow_name=wf_name,
+        repo=APACHE_AIRFLOW_SITE_REPO,
+        branch=branch,
+    )
+
+    get_console().print(
+        f"[blue]Refreshing completed workflow {wf_name}: at 
{APACHE_AIRFLOW_SITE_REPO}[/blue]",
+    )
+
+    workflow_fields = {"source": site_env}
+
+    get_console().print(
+        f"[blue]Syncing S3 docs to GitHub repository at 
{APACHE_AIRFLOW_SITE_ARCHIVE_REPO}[/blue]",
+    )
+    trigger_workflow_and_monitor(
+        workflow_name=WORKFLOW_NAME_MAPS["sync-s3-to-github"],
+        repo=APACHE_AIRFLOW_SITE_ARCHIVE_REPO,
+        branch=branch,
+        **workflow_fields,
+        monitor=False,
+    )
diff --git a/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py
new file mode 100644
index 00000000000..6a5025dcf9b
--- /dev/null
+++ b/dev/breeze/src/airflow_breeze/commands/workflow_commands_config.py
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+WORKFLOW_RUN_COMMANDS: dict[str, str | list[str]] = {
+    "name": "Airflow github actions workflow commands",
+    "commands": ["publish-docs"],
+}
+
+WORKFLOW_RUN_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = {
+    "breeze workflow-run publish-docs": [
+        {
+            "name": "Trigger publish docs workflow",
+            "options": [
+                "--ref",
+                "--exclude-docs",
+                "--site-env",
+                "--skip-write-to-stable-folder",
+            ],
+        },
+    ],
+}
diff --git a/dev/breeze/src/airflow_breeze/configure_rich_click.py 
b/dev/breeze/src/airflow_breeze/configure_rich_click.py
index a7a147a04e5..a5b1df980c8 100644
--- a/dev/breeze/src/airflow_breeze/configure_rich_click.py
+++ b/dev/breeze/src/airflow_breeze/configure_rich_click.py
@@ -17,6 +17,7 @@
 from __future__ import annotations
 
 from airflow_breeze.commands.sbom_commands_config import SBOM_COMMANDS, 
SBOM_PARAMETERS
+from airflow_breeze.commands.workflow_commands_config import 
WORKFLOW_RUN_COMMANDS, WORKFLOW_RUN_PARAMETERS
 
 from airflow_breeze.utils import recording  # isort:skip  # noqa: F401
 
@@ -76,6 +77,7 @@ else:
         **CI_PARAMETERS,
         **RELEASE_MANAGEMENT_PARAMETERS,
         **SBOM_PARAMETERS,
+        **WORKFLOW_RUN_PARAMETERS,
     }
     click.rich_click.COMMAND_GROUPS = {
         "breeze": [
@@ -90,7 +92,7 @@ else:
             },
             {
                 "name": "Release management commands",
-                "commands": ["release-management", "sbom"],
+                "commands": ["release-management", "sbom", "workflow-run"],
             },
             {
                 "name": "Other commands",
@@ -114,4 +116,5 @@ else:
         ],
         "breeze sbom": [SBOM_COMMANDS],
         "breeze ci": [CI_COMMANDS],
+        "breeze workflow-run": [WORKFLOW_RUN_COMMANDS],
     }
diff --git a/dev/breeze/src/airflow_breeze/utils/gh_workflow_utils.py 
b/dev/breeze/src/airflow_breeze/utils/gh_workflow_utils.py
new file mode 100644
index 00000000000..30659b363b0
--- /dev/null
+++ b/dev/breeze/src/airflow_breeze/utils/gh_workflow_utils.py
@@ -0,0 +1,184 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import json
+import sys
+import time
+
+from airflow_breeze.utils.console import get_console
+from airflow_breeze.utils.run_utils import run_command
+
+
+def tigger_workflow(workflow_name: str, repo: str, branch: str = "main", 
**kwargs):
+    """
+    Trigger a GitHub Actions workflow using the `gh` CLI.
+
+    :param workflow_name: The name of the workflow to trigger.
+    :param repo: Workflow repository example: 'apache/airflow'
+    :param branch: The branch to run the workflow on.
+    :param kwargs: Additional parameters to pass to the workflow.
+    """
+    command = ["gh", "workflow", "run", workflow_name, "--ref", branch, 
"--repo", repo]
+
+    # These are the input parameters to workflow
+    for key, value in kwargs.items():
+        # GH cli requires bool inputs to be converted to string format
+        if isinstance(value, bool):
+            value = "true" if value else "false"
+
+        command.extend(["-f", f"{key}={value}"])
+
+    get_console().print(f"[blue]Running command: {' '.join(command)}[/blue]")
+    result = run_command(command, capture_output=True, check=False)
+
+    if result.returncode != 0:
+        get_console().print(f"[red]Error running workflow: 
{result.stderr}[/red]")
+        sys.exit(1)
+
+    # Wait for a few seconds to start the workflow run
+    time.sleep(5)
+
+
+def get_workflow_run_id(workflow_name: str, repo: str) -> int:
+    """
+    Get the latest workflow run ID for a given workflow name and repository.
+
+    :param workflow_name: The name of the workflow to check.
+    :param repo: The repository in the format 'owner/repo'.
+    """
+    command = [
+        "gh",
+        "run",
+        "list",
+        "--workflow",
+        workflow_name,
+        "--repo",
+        repo,
+        "--limit",
+        "1",
+        "--json",
+        "databaseId",
+    ]
+
+    result = run_command(command, capture_output=True, check=False)
+    if result.returncode != 0:
+        get_console().print(f"[red]Error fetching workflow run ID: 
{result.stderr}[/red]")
+        sys.exit(1)
+
+    runs_data = result.stdout.strip()
+    if not runs_data:
+        get_console().print("[red]No workflow runs found.[/red]")
+        sys.exit(1)
+
+    return json.loads(runs_data)[0]["databaseId"]
+
+
+def get_workflow_run_info(run_id: str, repo: str, fields: str) -> dict:
+    """
+    Get the workflow information for a specific run ID and return the 
specified fields.
+
+    :param run_id: The ID of the workflow run to check.
+    :param repo: Workflow repository example: 'apache/airflow'
+    :param fields: Comma-separated fields to retrieve from the workflow run to 
fetch. eg: "status,conclusion,name,jobs"
+    """
+    command = ["gh", "run", "view", run_id, "--json", fields, "--repo", repo]
+
+    result = run_command(command, capture_output=True, check=False)
+    if result.returncode != 0:
+        get_console().print(f"[red]Error fetching workflow run status: 
{result.stderr}[/red]")
+        sys.exit(1)
+
+    return json.loads(result.stdout.strip())
+
+
+def monitor_workflow_run(run_id: str, repo: str):
+    """
+    Monitor the status of a workflow run until it completes.
+
+    :param run_id: The ID of the workflow run to monitor.
+    :param repo: Workflow repository example: 'apache/airflow'
+    """
+
+    completed_jobs = []
+
+    while True:
+        jobs_data = get_workflow_run_info(run_id, repo, "jobs")
+
+        for job in jobs_data.get("jobs", []):
+            name = job["name"]
+            status = job["status"]
+            conclusion = job["conclusion"]
+
+            if name not in completed_jobs and status != "completed":
+                get_console().print(
+                    f"[yellow]- Job: {name} | Status: {status} | Conclusion: 
{conclusion}[/yellow]"
+                )
+                continue
+
+            if name not in completed_jobs:
+                get_console().print(
+                    f"[green]- Job: {name} | Status: {status} | Conclusion: 
{conclusion}[/green]"
+                )
+                completed_jobs.append(name)
+
+        workflow_run_status_conclusion = get_workflow_run_info(run_id, repo, 
"status,conclusion,name")
+
+        status = workflow_run_status_conclusion.get("status")
+        conclusion = workflow_run_status_conclusion.get("conclusion")
+        name = workflow_run_status_conclusion.get("name")
+
+        if status == "completed":
+            if conclusion == "success":
+                get_console().print(f"[green]Workflow {name} run {run_id} 
completed successfully.[/green]")
+            elif conclusion == "failure":
+                get_console().print(
+                    f"[red]Workflow {name} run {run_id} failed, see for more 
info: https://github.com/{repo}/actions/runs/{run_id}[/red]";
+                )
+                sys.exit(1)
+            break
+
+        # Check status of jobs every 30 seconds
+        time.sleep(30)
+
+
+def trigger_workflow_and_monitor(
+    workflow_name: str, repo: str, branch: str = "main", monitor=True, 
**workflow_fields
+):
+    tigger_workflow(
+        workflow_name=workflow_name,
+        repo=repo,
+        branch=branch,
+        **workflow_fields,
+    )
+
+    workflow_run_id = get_workflow_run_id(
+        workflow_name=workflow_name,
+        repo=repo,
+    )
+
+    get_console().print(
+        f"[blue]Workflow run ID: {workflow_run_id}[/blue]",
+    )
+
+    if not monitor:
+        return
+
+    monitor_workflow_run(
+        run_id=str(workflow_run_id),
+        repo=repo,
+    )

Reply via email to