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

uranusjr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 41623bc01fe Publish schema files with doc publishing workflow (#68976)
41623bc01fe is described below

commit 41623bc01fe73330e9a3dbc64f7e5c023ce8d2d9
Author: Tzu-ping Chung <[email protected]>
AuthorDate: Thu Jun 25 22:51:45 2026 +0800

    Publish schema files with doc publishing workflow (#68976)
---
 .github/workflows/publish-docs-to-s3.yml           |  62 +++++++++
 dev/breeze/doc/09_release_management_tasks.rst     |  33 +++++
 dev/breeze/doc/images/output-commands.svg          |   2 +-
 .../doc/images/output_release-management.svg       |  24 ++--
 .../doc/images/output_release-management.txt       |   2 +-
 ...ut_release-management_publish-schemas-to-s3.svg | 139 +++++++++++++++++++++
 ...ut_release-management_publish-schemas-to-s3.txt |   1 +
 .../output_setup_check-all-params-in-groups.svg    |   6 +-
 .../output_setup_check-all-params-in-groups.txt    |   2 +-
 .../output_setup_regenerate-command-images.svg     |  30 ++---
 .../output_setup_regenerate-command-images.txt     |   2 +-
 .../commands/release_management_commands.py        |  62 +++++++++
 .../commands/release_management_commands_config.py |  13 ++
 dev/breeze/src/airflow_breeze/global_constants.py  |   5 +
 .../src/airflow_breeze/utils/publish_docs_to_s3.py | 122 ++++++++++++++++++
 15 files changed, 473 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/publish-docs-to-s3.yml 
b/.github/workflows/publish-docs-to-s3.yml
index 27cf7394cb5..cebcdafac87 100644
--- a/.github/workflows/publish-docs-to-s3.yml
+++ b/.github/workflows/publish-docs-to-s3.yml
@@ -94,6 +94,8 @@ jobs:
       extra-build-options: ${{ steps.parameters.outputs.extra-build-options }}
       airflow-base-version: ${{ steps.parameters.outputs.airflow-base-version 
}}
       airflow-version: ${{ steps.parameters.outputs.airflow-version }}
+      publish-execution-api-schema: ${{ 
steps.parameters.outputs.publish-execution-api-schema }}
+      publish-supervisor-schema: ${{ 
steps.parameters.outputs.publish-supervisor-schema }}
       # yamllint disable rule:line-length
       skip-write-to-stable-folder: ${{ inputs.skip-write-to-stable-folder && 
'--skip-write-to-stable-folder' || '' }}
       default-python-version: "3.10"
@@ -211,6 +213,17 @@ jobs:
              echo "airflow-version=no-airflow" >> ${GITHUB_OUTPUT}
              echo "airflow-base-version=no-airflow" >> ${GITHUB_OUTPUT}
           fi
+          PUBLISH_EXEC="false"
+          PUBLISH_SUP="false"
+          if [[ "${INCLUDE_DOCS}" == "all" || "${INCLUDE_DOCS}" == "" ]]; then
+             PUBLISH_EXEC="true"
+             PUBLISH_SUP="true"
+          else
+             [[ " ${INCLUDE_DOCS} " == *" apache-airflow "* ]] && 
PUBLISH_EXEC="true"
+             [[ " ${INCLUDE_DOCS} " == *" task-sdk "* ]] && PUBLISH_SUP="true"
+          fi
+          echo "publish-execution-api-schema=${PUBLISH_EXEC}" >> 
${GITHUB_OUTPUT}
+          echo "publish-supervisor-schema=${PUBLISH_SUP}" >> ${GITHUB_OUTPUT}
 
   build-docs:
     needs: [build-info]
@@ -323,6 +336,31 @@ jobs:
           key: cache-docs-inventory-v1
           if-no-files-found: 'error'
           retention-days: '2'
+      - name: "Generate Execution API schema artifact"
+        if: needs.build-info.outputs.publish-execution-api-schema == 'true'
+        env:
+          # Building the in-process app runs its lifespan, which constructs the
+          # JWT validator and requires a secret. The value is never used.
+          AIRFLOW__API_AUTH__JWT_SECRET: "schema-generation-not-a-real-secret"
+        run: |
+          mkdir -p schemas
+          uv run --frozen --project airflow-core -s \
+            scripts/ci/prek/generate_execution_api_schema.py > 
schemas/execution-api.json
+      - name: "Generate Supervisor schema artifact"
+        if: needs.build-info.outputs.publish-supervisor-schema == 'true'
+        run: |
+          mkdir -p schemas
+          uv run --frozen --project task-sdk -s \
+            scripts/ci/prek/dump_supervisor_schemas.py > 
schemas/supervisor-schema.json
+      - name: "Upload schema artifacts"
+        if: needs.build-info.outputs.publish-execution-api-schema == 'true' || 
needs.build-info.outputs.publish-supervisor-schema == 'true'
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a 
 # v7.0.1
+        with:
+          name: airflow-schemas
+          path: schemas/
+          retention-days: '7'
+          if-no-files-found: 'error'
+          overwrite: 'true'
       - name: "Store stable versions"
         run: uv run /tmp/store_stable_versions.py
       - name: "Saving build docs folder"
@@ -522,6 +560,30 @@ jobs:
           breeze release-management publish-docs-to-s3 --source-dir-path 
${SOURCE_DIR_PATH} \
           --destination-location ${DESTINATION_LOCATION} --stable-versions \
           --exclude-docs "${EXCLUDE_DOCS}" --overwrite 
${SKIP_WRITE_TO_STABLE_FOLDER}
+      - name: "Download schema artifacts"
+        if: needs.build-info.outputs.publish-execution-api-schema == 'true' || 
needs.build-info.outputs.publish-supervisor-schema == 'true'
+        uses: 
actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
+        with:
+          name: airflow-schemas
+          path: schemas
+      - name: "Publish schemas to S3"
+        if: needs.build-info.outputs.publish-execution-api-schema == 'true' || 
needs.build-info.outputs.publish-supervisor-schema == 'true'
+        env:
+          DESTINATION_LOCATION: "${{ 
needs.build-info.outputs.destination-location }}"
+          PUBLISH_EXEC: "${{ 
needs.build-info.outputs.publish-execution-api-schema }}"
+          PUBLISH_SUP: "${{ needs.build-info.outputs.publish-supervisor-schema 
}}"
+        run: |
+          # Reuse the docs bucket but publish under the schemas/ prefix.
+          SCHEMAS_DESTINATION="${DESTINATION_LOCATION%docs/}schemas/"
+          args=()
+          if [[ "${PUBLISH_EXEC}" == "true" ]]; then
+             args+=(--execution-api schemas/execution-api.json)
+          fi
+          if [[ "${PUBLISH_SUP}" == "true" ]]; then
+             args+=(--supervisor schemas/supervisor-schema.json)
+          fi
+          breeze release-management publish-schemas-to-s3 \
+            --destination-location "${SCHEMAS_DESTINATION}" "${args[@]}"
 
   update-registry:
     needs: [publish-docs-to-s3, build-info]
diff --git a/dev/breeze/doc/09_release_management_tasks.rst 
b/dev/breeze/doc/09_release_management_tasks.rst
index 63d69195087..70453de37db 100644
--- a/dev/breeze/doc/09_release_management_tasks.rst
+++ b/dev/breeze/doc/09_release_management_tasks.rst
@@ -1080,6 +1080,39 @@ These are all available flags of ``workflow-run 
publish-docs`` command:
   :width: 100%
   :alt: Breeze workflow-run publish-docs
 
+Publishing the schema files to S3
+"""""""""""""""""""""""""""""""""
+
+Alongside the documentation, the ``Publish Docs to S3`` workflow also 
publishes two generated schema artifacts
+to the same docs bucket, under the ``schemas/`` prefix (served at 
``https://airflow.apache.org/schemas/``):
+
+* The Execution API OpenAPI spec ``schemas/execution-api/<version>.json``
+* The Supervisor JSON Schema ``schemas/supervisor-schema/<version>.json``
+
+Each dated file is immutable, so the command uploads individual objects and 
skips a date that already exists
+unless ``--overwrite`` is given. Publishing is gated on the package set. The 
schema files are only published
+when ``apache-airflow`` or ``task-sdk`` is built.
+
+To publish the schema files to S3, use the ``release-management 
publish-schemas-to-s3`` command:
+
+.. code-block:: bash
+
+     breeze release-management publish-schemas-to-s3 \
+       --execution-api execution-api.json \
+       --supervisor supervisor-schema.json \
+       --destination-location s3://live-docs-airflow-apache-org/schemas/
+
+``--destination-location`` is the ``s3://<bucket>/schemas/`` location to 
publish under; each schema is
+written to ``<location>/<schema-type>/<version>.json``. Pass at least one of
+``--execution-api`` / ``--supervisor``.
+
+These are all available flags of ``release-management publish-schemas-to-s3`` 
command:
+
+.. image:: ./images/output_release-management_publish-schemas-to-s3.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.svg
+  :width: 100%
+  :alt: Breeze release-management publish-schemas-to-s3
+
 Checking release files
 """"""""""""""""""""""
 
diff --git a/dev/breeze/doc/images/output-commands.svg 
b/dev/breeze/doc/images/output-commands.svg
index 4891c30ed51..6dfe7e09c52 100644
--- a/dev/breeze/doc/images/output-commands.svg
+++ b/dev/breeze/doc/images/output-commands.svg
@@ -367,7 +367,7 @@
     
     <g class="breeze-help-matrix">
     <text class="breeze-help-r1" x="1464" y="20" textLength="12.2" 
clip-path="url(#breeze-help-line-0)">
-</text><text class="breeze-help-r2" x="12.2" y="44.4" textLength="73.2" 
clip-path="url(#breeze-help-line-1)">Usage:</text><text class="breeze-help-r3" 
x="97.6" y="44.4" textLength="73.2" 
clip-path="url(#breeze-help-line-1)">breeze</text><text class="breeze-help-r1" 
x="183" y="44.4" textLength="12.2" 
clip-path="url(#breeze-help-line-1)">[</text><text class="breeze-help-r4" 
x="195.2" y="44.4" textLength="85.4" 
clip-path="url(#breeze-help-line-1)">OPTIONS</text><text class="breeze-help-r1" 
 [...]
+</text><text class="breeze-help-r2" x="12.2" y="44.4" textLength="73.2" 
clip-path="url(#breeze-help-line-1)">Usage:</text><text class="breeze-help-r3" 
x="97.6" y="44.4" textLength="73.2" 
clip-path="url(#breeze-help-line-1)">breeze</text><text class="breeze-help-r1" 
x="183" y="44.4" textLength="12.2" 
clip-path="url(#breeze-help-line-1)">[</text><text class="breeze-help-r4" 
x="195.2" y="44.4" textLength="85.4" 
clip-path="url(#breeze-help-line-1)">OPTIONS</text><text class="breeze-help-r1" 
 [...]
 </text><text class="breeze-help-r1" x="1464" y="68.8" textLength="12.2" 
clip-path="url(#breeze-help-line-2)">
 </text><text class="breeze-help-r5" x="0" y="93.2" textLength="24.4" 
clip-path="url(#breeze-help-line-3)">╭─</text><text class="breeze-help-r5" 
x="24.4" y="93.2" textLength="195.2" 
clip-path="url(#breeze-help-line-3)">&#160;Common&#160;options&#160;</text><text
 class="breeze-help-r5" x="219.6" y="93.2" textLength="1220" 
clip-path="url(#breeze-help-line-3)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
 class="breeze-help-r [...]
 </text><text class="breeze-help-r5" x="0" y="117.6" textLength="12.2" 
clip-path="url(#breeze-help-line-4)">│</text><text class="breeze-help-r4" 
x="24.4" y="117.6" textLength="109.8" 
clip-path="url(#breeze-help-line-4)">--answer&#160;</text><text 
class="breeze-help-r6" x="158.6" y="117.6" textLength="24.4" 
clip-path="url(#breeze-help-line-4)">-a</text><text class="breeze-help-r1" 
x="207.4" y="117.6" textLength="329.4" 
clip-path="url(#breeze-help-line-4)">Force&#160;answer&#160;to&#160;que [...]
diff --git a/dev/breeze/doc/images/output_release-management.svg 
b/dev/breeze/doc/images/output_release-management.svg
index 309ebac51d6..01900bf07f6 100644
--- a/dev/breeze/doc/images/output_release-management.svg
+++ b/dev/breeze/doc/images/output_release-management.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1660.3999999999999" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1684.8" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -42,7 +42,7 @@
 
     <defs>
     <clipPath id="breeze-release-management-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="1609.3999999999999" />
+      <rect x="0" y="0" width="1463.0" height="1633.8" />
     </clipPath>
     <clipPath id="breeze-release-management-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -239,9 +239,12 @@
 <clipPath id="breeze-release-management-line-64">
     <rect x="0" y="1563.1" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-release-management-line-65">
+    <rect x="0" y="1587.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="1658.4" rx="8"/><text 
class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" 
x="740" y="27">Command:&#160;release-management</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1682.8" rx="8"/><text 
class="breeze-release-management-title" fill="#c5c8c6" text-anchor="middle" 
x="740" y="27">Command:&#160;release-management</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -310,13 +313,14 @@
 </text><text class="breeze-release-management-r5" x="0" y="1386.4" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-56)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1386.4" textLength="292.8" 
clip-path="url(#breeze-release-management-line-56)">generate-constraints&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1386.4" textLength="1098" 
clip-path="url(#breeze-release-management-line-56)">Generates&#160;pinned&#160;c
 [...]
 </text><text class="breeze-release-management-r5" x="0" y="1410.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-57)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1410.8" textLength="292.8" 
clip-path="url(#breeze-release-management-line-57)">update-constraints&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1410.8" textLength="1098" 
clip-path="url(#breeze-release-management-line-57)">Update&#160;releas [...]
 </text><text class="breeze-release-management-r5" x="0" y="1435.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-58)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1435.2" textLength="292.8" 
clip-path="url(#breeze-release-management-line-58)">publish-docs-to-s3&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1435.2" textLength="1098" 
clip-path="url(#breeze-release-management-line-58)">Publishes&#160;doc [...]
-</text><text class="breeze-release-management-r5" x="0" y="1459.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-59)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1459.6" textLength="292.8" 
clip-path="url(#breeze-release-management-line-59)">verify-rc-by-pmc&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1459.6" textLength="1098" 
clip-path="url(#breeze-release-management-line-59)">[EXPERIM [...]
-</text><text class="breeze-release-management-r5" x="0" y="1484" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-60)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1484" textLength="292.8" 
clip-path="url(#breeze-release-management-line-60)">check-release-files&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1484" textLength="1098" 
clip-path="url(#breeze-release-management-line-60)">Verify&#160;that&#160;all&#16
 [...]
-</text><text class="breeze-release-management-r5" x="0" y="1508.4" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-61)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1508.4" textLength="12.2" 
clip-path="url(#breeze-release-management-line-61)">
-</text><text class="breeze-release-management-r5" x="0" y="1532.8" 
textLength="24.4" 
clip-path="url(#breeze-release-management-line-62)">╭─</text><text 
class="breeze-release-management-r5" x="24.4" y="1532.8" textLength="122" 
clip-path="url(#breeze-release-management-line-62)">&#160;Commands&#160;</text><text
 class="breeze-release-management-r5" x="146.4" y="1532.8" textLength="1293.2" 
clip-path="url(#breeze-release-management-line-62)">───────────────────────────────────────────────────
 [...]
-</text><text class="breeze-release-management-r5" x="0" y="1557.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-63)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1557.2" textLength="305" 
clip-path="url(#breeze-release-management-line-63)">constraints-version-check</text><text
 class="breeze-release-management-r1" x="353.8" y="1557.2" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-63)">Check&#160;constraints&#160;against&#160;releas
 [...]
-</text><text class="breeze-release-management-r5" x="0" y="1581.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-64)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1581.6" textLength="305" 
clip-path="url(#breeze-release-management-line-64)">merge-prod-images&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="353.8" y="1581.6" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-64)">Merge&# [...]
-</text><text class="breeze-release-management-r5" x="0" y="1606" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-65)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1606" textLength="12.2" 
clip-path="url(#breeze-release-management-line-65)">
+</text><text class="breeze-release-management-r5" x="0" y="1459.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-59)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1459.6" textLength="292.8" 
clip-path="url(#breeze-release-management-line-59)">publish-schemas-to-s3&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1459.6" textLength="1098" 
clip-path="url(#breeze-release-management-line-59)">Publishes&#160;generated&#160;JSO
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="1484" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-60)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1484" textLength="292.8" 
clip-path="url(#breeze-release-management-line-60)">verify-rc-by-pmc&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1484" textLength="1098" 
clip-path="url(#breeze-release-management-line-60)">[EXPERIMENTAL] [...]
+</text><text class="breeze-release-management-r5" x="0" y="1508.4" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-61)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1508.4" textLength="292.8" 
clip-path="url(#breeze-release-management-line-61)">check-release-files&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="1508.4" textLength="1098" 
clip-path="url(#breeze-release-management-line-61)">Verify&#160;that&#160;a 
[...]
+</text><text class="breeze-release-management-r5" x="0" y="1532.8" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-62)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1532.8" textLength="12.2" 
clip-path="url(#breeze-release-management-line-62)">
+</text><text class="breeze-release-management-r5" x="0" y="1557.2" 
textLength="24.4" 
clip-path="url(#breeze-release-management-line-63)">╭─</text><text 
class="breeze-release-management-r5" x="24.4" y="1557.2" textLength="122" 
clip-path="url(#breeze-release-management-line-63)">&#160;Commands&#160;</text><text
 class="breeze-release-management-r5" x="146.4" y="1557.2" textLength="1293.2" 
clip-path="url(#breeze-release-management-line-63)">───────────────────────────────────────────────────
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="1581.6" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-64)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1581.6" textLength="305" 
clip-path="url(#breeze-release-management-line-64)">constraints-version-check</text><text
 class="breeze-release-management-r1" x="353.8" y="1581.6" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-64)">Check&#160;constraints&#160;against&#160;releas
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="1606" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-65)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="1606" textLength="305" 
clip-path="url(#breeze-release-management-line-65)">merge-prod-images&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="353.8" y="1606" textLength="1085.8" 
clip-path="url(#breeze-release-management-line-65)">Merge&#160;pr [...]
+</text><text class="breeze-release-management-r5" x="0" y="1630.4" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-66)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1630.4" textLength="12.2" 
clip-path="url(#breeze-release-management-line-66)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_release-management.txt 
b/dev/breeze/doc/images/output_release-management.txt
index 88669f75b59..bed6316d48f 100644
--- a/dev/breeze/doc/images/output_release-management.txt
+++ b/dev/breeze/doc/images/output_release-management.txt
@@ -1 +1 @@
-1588da1100c6c55691550abd5da329b0
+016eb82c476bc36ac2bcb754d3e87919
diff --git 
a/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.svg 
b/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.svg
new file mode 100644
index 00000000000..1f4a0c7ee77
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.svg
@@ -0,0 +1,139 @@
+<svg class="rich-terminal" viewBox="0 0 1482 513.5999999999999" 
xmlns="http://www.w3.org/2000/svg";>
+    <!-- Generated with Rich https://www.textualize.io -->
+    <style>
+
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Regular"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff";)
 format("woff");
+        font-style: normal;
+        font-weight: 400;
+    }
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Bold"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff";)
 format("woff");
+        font-style: bold;
+        font-weight: 700;
+    }
+
+    .breeze-release-management-publish-schemas-to-s3-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-release-management-publish-schemas-to-s3-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-release-management-publish-schemas-to-s3-r1 { fill: #c5c8c6 }
+.breeze-release-management-publish-schemas-to-s3-r2 { fill: #d0b344 }
+.breeze-release-management-publish-schemas-to-s3-r3 { fill: 
#c5c8c6;font-weight: bold }
+.breeze-release-management-publish-schemas-to-s3-r4 { fill: 
#68a0b3;font-weight: bold }
+.breeze-release-management-publish-schemas-to-s3-r5 { fill: #868887 }
+.breeze-release-management-publish-schemas-to-s3-r6 { fill: #8d7b39 }
+.breeze-release-management-publish-schemas-to-s3-r7 { fill: #cc555a }
+.breeze-release-management-publish-schemas-to-s3-r8 { fill: 
#d0b344;font-weight: bold }
+.breeze-release-management-publish-schemas-to-s3-r9 { fill: #8a4346 }
+.breeze-release-management-publish-schemas-to-s3-r10 { fill: 
#98a84b;font-weight: bold }
+    </style>
+
+    <defs>
+    <clipPath 
id="breeze-release-management-publish-schemas-to-s3-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="462.59999999999997" />
+    </clipPath>
+    <clipPath id="breeze-release-management-publish-schemas-to-s3-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-9">
+    <rect x="0" y="221.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-10">
+    <rect x="0" y="245.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-11">
+    <rect x="0" y="269.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-12">
+    <rect x="0" y="294.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-13">
+    <rect x="0" y="318.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-14">
+    <rect x="0" y="343.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-15">
+    <rect x="0" y="367.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-16">
+    <rect x="0" y="391.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-publish-schemas-to-s3-line-17">
+    <rect x="0" y="416.3" width="1464" height="24.65"/>
+            </clipPath>
+    </defs>
+
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="511.6" rx="8"/><text 
class="breeze-release-management-publish-schemas-to-s3-title" fill="#c5c8c6" 
text-anchor="middle" x="740" 
y="27">Command:&#160;release-management&#160;publish-schemas-to-s3</text>
+            <g transform="translate(26,22)">
+            <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+            <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+            <circle cx="44" cy="0" r="7" fill="#28c840"/>
+            </g>
+        
+    <g transform="translate(9, 41)" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-clip-terminal)">
+    
+    <g class="breeze-release-management-publish-schemas-to-s3-matrix">
+    <text class="breeze-release-management-publish-schemas-to-s3-r1" x="1464" 
y="20" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-0)">
+</text><text class="breeze-release-management-publish-schemas-to-s3-r2" 
x="12.2" y="44.4" textLength="73.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-1)">Usage:</text><text
 class="breeze-release-management-publish-schemas-to-s3-r3" x="97.6" y="44.4" 
textLength="573.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-1)">breeze&#160;release-management&#160;publish-schemas-to-s3</text><text
 class="breeze-release-management-publish-schemas-to-s [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r1" 
x="1464" y="68.8" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-2)">
+</text><text class="breeze-release-management-publish-schemas-to-s3-r1" 
x="12.2" y="93.2" textLength="927.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-3)">Publishes&#160;generated&#160;JSON&#160;schema&#160;artifacts&#160;(Execution&#160;API,&#160;Supervisor)&#160;to&#160;S3.</text><text
 class="breeze-release-management-publish-schemas-to-s3-r1" x="1464" y="93.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-3)">
+</text><text class="breeze-release-management-publish-schemas-to-s3-r1" 
x="1464" y="117.6" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-4)">
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="142" textLength="24.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-5)">╭─</text><text
 class="breeze-release-management-publish-schemas-to-s3-r5" x="24.4" y="142" 
textLength="280.6" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-5)">&#160;Publish&#160;schemas&#160;to&#160;S3&#160;</text><text
 class="breeze-release-management-publish-schemas-to-s3-r5" x="305" y="1 [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="166.4" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-6)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r4" x="61" y="166.4" 
textLength="268.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-6)">--execution-api&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-publish-schemas-to-s3-r1" x= [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="190.8" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-7)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r4" x="61" y="190.8" 
textLength="268.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-7)">--supervisor&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-publish-schem [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="215.2" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-8)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r7" x="24.4" y="215.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-8)">*</text><text
 class="breeze-release-management-publish-schemas-to-s3-r4" x="61" y="215.2" 
textLength="268.4" clip-path="url(#breez [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="239.6" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-9)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r1" x="353.8" y="239.6" 
textLength="1085.8" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-9)">s3://live-docs-airflow-apache-org/schemas/.&#160;Each&#160;schema&#160;is&#160;written&#160;to&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="264" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-10)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r8" x="353.8" y="264" 
textLength="122" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-10)">&lt;location&gt;</text><text
 class="breeze-release-management-publish-schemas-to-s3-r1" x="475.8" y="264" 
textLength="12.2" clip-pat [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="288.4" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-11)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r6" x="353.8" y="288.4" 
textLength="561.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-11)">(s3://live-docs-airflow-apache-org/schemas/&#160;|&#160;</text><text
 class="breeze-release-management-publish-schemas-to-s3-r5 [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="312.8" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-12)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r6" x="353.8" y="312.8" 
textLength="561.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-12)">s3://staging-docs-airflow-apache-org/schemas/)</text><text
 class="breeze-release-management-publish-schemas-to-s3-r5" x="1451. [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="337.2" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-13)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r4" x="61" y="337.2" 
textLength="268.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-13)">--overwrite&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-publis [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="361.6" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-14)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r4" x="61" y="361.6" 
textLength="268.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-14)">--dry-run&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-managem [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="386" textLength="1464" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-15)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-publish-schemas-to-s3-r1" x="1464" y="386" 
textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-15)">
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="410.4" textLength="24.4" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-16)">╭─</text><text
 class="breeze-release-management-publish-schemas-to-s3-r5" x="24.4" y="410.4" 
textLength="195.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-16)">&#160;Common&#160;options&#160;</text><text
 class="breeze-release-management-publish-schemas-to-s3-r5" x="219.6" y="410.4" 
tex [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="434.8" textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-17)">│</text><text
 class="breeze-release-management-publish-schemas-to-s3-r4" x="24.4" y="434.8" 
textLength="73.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-17)">--help</text><text
 class="breeze-release-management-publish-schemas-to-s3-r10" x="122" y="434.8" 
textLength="24.4" clip-path="ur [...]
+</text><text class="breeze-release-management-publish-schemas-to-s3-r5" x="0" 
y="459.2" textLength="1464" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-publish-schemas-to-s3-r1" x="1464" y="459.2" 
textLength="12.2" 
clip-path="url(#breeze-release-management-publish-schemas-to-s3-line-18)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git 
a/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.txt 
b/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.txt
new file mode 100644
index 00000000000..3217f6210b9
--- /dev/null
+++ b/dev/breeze/doc/images/output_release-management_publish-schemas-to-s3.txt
@@ -0,0 +1 @@
+60c42737a26b1a9363f13b85d7589a47
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 a94f436f33f..1daa6048546 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
@@ -227,9 +227,9 @@
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="654.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="654.4" 
textLength="1159" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">release-management:prepare-provider-documentation&#160;|&#160;release-management:prepare-python-client&#160;|&#160;</text><text
 class="breeze-setup-check-all-p [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="678.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="678.8" 
textLength="1085.8" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">release-management:prepare-tarball&#160;|&#160;release-management:prepare-task-sdk-distributions&#160;|&#160;</text><text
 class="breeze-setup-check-all-param [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="703.2" 
textLength="902.8" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">release-management:publish-docs&#160;|&#160;release-management:publish-docs-to-s3&#160;|&#160;</text><text
 class="breeze-setup-check-all-params-in-groups-r5"  [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="727.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="727.6" 
textLength="963.8" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#160;|&#160;</text><text
 class="breeze-setup-check-all-params-in-groups [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="752" 
textLength="854" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">release-management:start-release&#160;|&#160;release-management:tag-providers&#160;|&#160;</text><text
 class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="776.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="776.4" 
textLength="1110.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">release-management:update-constraints&#160;|&#160;release-management:update-providers-next-version&#160;|&#160;</text><text
 class="breeze-setup-check-all-par [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="727.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="727.6" 
textLength="1024.8" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">release-management:publish-schemas-to-s3&#160;|&#160;release-management:release-prod-images&#160;|&#160;</text><text
 class="breeze-setup-check-all-params-in- [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="752" 
textLength="1281" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#160;|&#160;release-management:tag-providers</text><text
 class="breeze-setup-check [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="776.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="776.4" 
textLength="1134.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">|&#160;release-management:update-constraints&#160;|&#160;release-management:update-providers-next-version&#160;|&#160;</text><text
 class="breeze-setup-check- [...]
 </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="158.6" y="800.8" 
textLength="1244.4" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">release-management:verify-provider-distributions&#160;|&#160;release-management:verify-rc-by-pmc&#160;|&#160;run&#160;|&#160;sbom&#160;|&#160;</text><text
 cl [...]
 </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="158.6" y="825.2" 
textLength="1281" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">sbom:build-all-airflow-images&#160;|&#160;sbom:export-dependency-information&#160;|&#160;sbom:generate-providers-requirements</text><text
 class="breeze-setup-c [...]
 </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="158.6" y="849.6" 
textLength="1183.4" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;</text><text
 cl [...]
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 f6155ca71eb..027ee1753bd 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 @@
-ab7f4fb815bf503631f336876c24e2b1
+561b619130079265ef547620b63f72cd
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 0e07ebb3f1e..72911001bb6 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -247,21 +247,21 @@
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="703.2" 
textLength="1244.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:prepare-provider-distributions&#160;|&#160;release-management:prepare-provider-documentation&#160;</text><text
 class="breeze-setup-regenerate- [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="727.6" 
textLength="1000.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">|&#160;release-management:prepare-python-client&#160;|&#160;release-management:prepare-tarball&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-im [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="752" 
textLength="1049.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">release-management:prepare-task-sdk-distributions&#160;|&#160;release-management:publish-docs&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images- [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="776.4" 
textLength="988.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:publish-docs-to-s3&#160;|&#160;release-management:release-prod-images&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="800.8" 
textLength="890.6" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x="145 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="825.2" 
textLength="915" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">release-management:tag-providers&#160;|&#160;release-management:update-constraints&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x="145 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="849.6" 
textLength="1244.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">release-management:update-providers-next-version&#160;|&#160;release-management:verify-provider-distributions&#160;|&#160;</text><text
 class="breeze-setup-regene [...]
-</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="195.2" y="874" 
textLength="1012.6" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">release-management:verify-rc-by-pmc&#160;|&#160;run&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;</text><text
 class="breeze-setup-regenerat [...]
-</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="195.2" y="898.4" 
textLength="927.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">sbom:export-dependency-information&#160;|&#160;sbom:generate-providers-requirements&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x=" [...]
-</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="195.2" y="922.8" 
textLength="1159" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;</text><text
 class="breeze-s [...]
-</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="195.2" y="947.2" 
textLength="1244.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|</text><text
 class="bree [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="971.6" 
textLength="1098" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;testing&#160;|&#160;testing:airflow-ctl-integration-tests&#160;|&#160;</text><text
 class="bre [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="996" 
textLength="1085.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">testing:airflow-ctl-tests&#160;|&#160;testing:airflow-e2e-tests&#160;|&#160;testing:core-integration-tests&#160;|&#160;</text><text
 class="breeze-setup-regenerate-co [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1020.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1020.4" 
textLength="890.6" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">testing:core-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-image [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1044.8" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1044.8" 
textLength="1195.6" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">testing:providers-integration-tests&#160;|&#160;testing:providers-tests&#160;|&#160;testing:python-api-client-tests&#160;|&#160;</text><text
 class="breeze-setu [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1069.2" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1069.2" 
textLength="1037" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">testing:system-tests&#160;|&#160;testing:task-sdk-integration-tests&#160;|&#160;testing:task-sdk-tests&#160;|&#160;</text><text
 class="breeze-setup-regenerate-co [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1093.6" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1093.6" 
textLength="1207.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">testing:ui-e2e-tests&#160;|&#160;ui&#160;|&#160;ui:check-translation-completeness&#160;|&#160;ui:compile-assets&#160;|&#160;workflow-run&#160;|&#160;</text><te
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1118" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1118" 
textLength="317.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">workflow-run:publish-docs)</text><text
 class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1118" 
textLength="12.2" clip-path="url(#breeze-setup-regenera [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="776.4" 
textLength="1012.6" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:publish-docs-to-s3&#160;|&#160;release-management:publish-schemas-to-s3&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="800.8" 
textLength="963.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5"  [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="825.2" 
textLength="854" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">release-management:start-release&#160;|&#160;release-management:tag-providers&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x="1451.8"  [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="849.6" 
textLength="1110.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">release-management:update-constraints&#160;|&#160;release-management:update-providers-next-version&#160;|&#160;</text><text
 class="breeze-setup-regenerate-comman [...]
+</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="195.2" y="874" 
textLength="1244.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">release-management:verify-provider-distributions&#160;|&#160;release-management:verify-rc-by-pmc&#160;|&#160;run&#160;|&#160;sbom&#160;|&#160;</text><text
 class="bre [...]
+</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="195.2" y="898.4" 
textLength="841.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">sbom:build-all-airflow-images&#160;|&#160;sbom:export-dependency-information&#160;|&#160;</text><text
 class="breeze-setup-regenerate-command-images-r5" x="1451.8" [...]
+</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="195.2" y="922.8" 
textLength="1207.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-37)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;</text><text
 class="br [...]
+</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="195.2" y="947.2" 
textLength="1244.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-38)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade</text><text
 class="breeze-se [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="971.6" 
textLength="1037" 
clip-path="url(#breeze-setup-regenerate-command-images-line-39)">|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;testing&#160;|&#160;</text><text
 class="bre [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="996" 
textLength="1171.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-40)">testing:airflow-ctl-integration-tests&#160;|&#160;testing:airflow-ctl-tests&#160;|&#160;testing:airflow-e2e-tests&#160;|&#160;</text><text
 class="breeze-setup-regene [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1020.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1020.4" 
textLength="1037" 
clip-path="url(#breeze-setup-regenerate-command-images-line-41)">testing:core-integration-tests&#160;|&#160;testing:core-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;</text><text
 class="breeze-setup-regenerate-co [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1044.8" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1044.8" 
textLength="1037" 
clip-path="url(#breeze-setup-regenerate-command-images-line-42)">testing:helm-tests&#160;|&#160;testing:providers-integration-tests&#160;|&#160;testing:providers-tests&#160;|&#160;</text><text
 class="breeze-setup-regenerate-co [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1069.2" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1069.2" 
textLength="1146.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-43)">testing:python-api-client-tests&#160;|&#160;testing:system-tests&#160;|&#160;testing:task-sdk-integration-tests&#160;|&#160;</text><text
 class="breeze-setup-re [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1093.6" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1093.6" 
textLength="1085.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-44)">testing:task-sdk-tests&#160;|&#160;testing:ui-e2e-tests&#160;|&#160;ui&#160;|&#160;ui:check-translation-completeness&#160;|&#160;</text><text
 class="breeze-set [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1118" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1118" 
textLength="744.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-45)">ui:compile-assets&#160;|&#160;workflow-run&#160;|&#160;workflow-run:publish-docs)</text><text
 class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1118"  [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1142.4" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1142.4" 
textLength="146.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-46)">--check-only</text><text
 class="breeze-setup-regenerate-command-images-r1" x="195.2" y="1142.4" 
textLength="1244.4" clip-path="url(#breeze-setup-regenerate-comma [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1166.8" textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-47)">│</text><text 
class="breeze-setup-regenerate-command-images-r1" x="195.2" y="1166.8" 
textLength="170.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-47)">together&#160;with&#160;</text><text
 class="breeze-setup-regenerate-command-images-r4" x="366" y="1166.8" 
textLength="109.8" clip-path="url(#breeze-setup-regene [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" 
y="1191.2" textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-48)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="1191.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-48)">
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 328bd526239..860ef216136 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 @@
-3a1ef6b761c61aa0fa09fe849e948a0e
+bce2b4cc3d1512b690164cbfaa4bd2f6
diff --git 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
index 146b3ba180c..1556cf037b8 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -100,6 +100,7 @@ from airflow_breeze.global_constants import (
     DEFAULT_PYTHON_MAJOR_MINOR_VERSION_FOR_IMAGES,
     DESTINATION_LOCATIONS,
     MULTI_PLATFORM,
+    SCHEMA_DESTINATION_LOCATIONS,
     UV_VERSION,
     get_airflow_version,
     get_airflowctl_version,
@@ -4833,6 +4834,67 @@ def publish_docs_to_s3(
         sys.exit(1)
 
 
+@release_management_group.command(
+    name="publish-schemas-to-s3",
+    help="Publishes generated JSON schema artifacts (Execution API, 
Supervisor) to S3.",
+)
[email protected](
+    "--execution-api",
+    help="Path to the generated Execution API OpenAPI JSON file.",
+    type=click.Path(exists=True, dir_okay=False, path_type=Path),
+)
[email protected](
+    "--supervisor",
+    help="Path to the generated Supervisor schema JSON file.",
+    type=click.Path(exists=True, dir_okay=False, path_type=Path),
+)
[email protected](
+    "--destination-location",
+    help="S3 location to publish the schemas under, e.g. "
+    "s3://live-docs-airflow-apache-org/schemas/. Each schema is written to "
+    "<location>/<schema-type>/<version>.json.",
+    type=NotVerifiedBetterChoice(SCHEMA_DESTINATION_LOCATIONS),
+    required=True,
+)
[email protected](
+    "--overwrite",
+    is_flag=True,
+    help="Overwrite the dated schema file if it already exists in S3.",
+)
[email protected](
+    "--dry-run",
+    is_flag=True,
+    help="Dry run - only print what would be done.",
+)
+def publish_schemas_to_s3(
+    execution_api: Path | None,
+    supervisor: Path | None,
+    destination_location: str,
+    overwrite: bool,
+    dry_run: bool,
+):
+    from airflow_breeze.utils.publish_docs_to_s3 import publish_schemas_to_s3 
as _publish_schemas_to_s3
+
+    if not execution_api and not supervisor:
+        console_print("[error]Provide at least one of --execution-api or 
--supervisor[/]")
+        sys.exit(1)
+
+    console_print("[info]Publishing schemas to S3[/]")
+    console_print(f"[info]Destination bucket location: 
{destination_location}[/]")
+    if execution_api:
+        console_print(f"[info]Execution API schema: {execution_api}[/]")
+    if supervisor:
+        console_print(f"[info]Supervisor schema: {supervisor}[/]")
+
+    _publish_schemas_to_s3(
+        destination_location=destination_location.rstrip("/"),
+        execution_api_schema=execution_api,
+        supervisor_schema=supervisor,
+        overwrite=overwrite,
+        dry_run=dry_run,
+    )
+
+
 @release_management_group.command(
     name="constraints-version-check", help="Check constraints against released 
versions of packages."
 )
diff --git 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
index 2b4c8073b88..2acad7f44f8 100644
--- 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
+++ 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
@@ -86,6 +86,7 @@ RELEASE_OTHER_COMMANDS: dict[str, str | list[str]] = {
         "generate-constraints",
         "update-constraints",
         "publish-docs-to-s3",
+        "publish-schemas-to-s3",
         "verify-rc-by-pmc",
         "check-release-files",
     ],
@@ -563,6 +564,18 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str, 
str | list[str]]]] = {
             ],
         }
     ],
+    "breeze release-management publish-schemas-to-s3": [
+        {
+            "name": "Publish schemas to S3",
+            "options": [
+                "--execution-api",
+                "--supervisor",
+                "--destination-location",
+                "--overwrite",
+                "--dry-run",
+            ],
+        }
+    ],
     "breeze release-management constraints-version-check": [
         {
             "name": "Constraints options.",
diff --git a/dev/breeze/src/airflow_breeze/global_constants.py 
b/dev/breeze/src/airflow_breeze/global_constants.py
index ba46fcef3e5..14b5752784d 100644
--- a/dev/breeze/src/airflow_breeze/global_constants.py
+++ b/dev/breeze/src/airflow_breeze/global_constants.py
@@ -313,6 +313,11 @@ DESTINATION_LOCATIONS = [
     "s3://staging-docs-airflow-apache-org/docs/",
 ]
 
+SCHEMA_DESTINATION_LOCATIONS = [
+    "s3://live-docs-airflow-apache-org/schemas/",
+    "s3://staging-docs-airflow-apache-org/schemas/",
+]
+
 PACKAGES_METADATA_EXCLUDE_NAMES = ["docker-stack", "apache-airflow-providers"]
 
 
diff --git a/dev/breeze/src/airflow_breeze/utils/publish_docs_to_s3.py 
b/dev/breeze/src/airflow_breeze/utils/publish_docs_to_s3.py
index 756913e690c..df70049353c 100644
--- a/dev/breeze/src/airflow_breeze/utils/publish_docs_to_s3.py
+++ b/dev/breeze/src/airflow_breeze/utils/publish_docs_to_s3.py
@@ -18,6 +18,7 @@ from __future__ import annotations
 
 import json
 import os
+import pathlib
 import subprocess
 import sys
 from functools import cached_property
@@ -388,3 +389,124 @@ class S3DocsPublish:
             Body=html_body,
             ContentType="text/html",
         )
+
+
+# Maps the published schema sub-directory to the field in the generated JSON
+# document that carries the version date (``YYYY-MM-DD``).
+SCHEMA_VERSION_FIELDS: dict[str, str] = {
+    "execution-api": "info.version",
+    "supervisor-schema": "api_version",
+}
+
+
+def _read_nested_field(payload: dict, dotted_field: str) -> str:
+    value: object = payload
+    for part in dotted_field.split("."):
+        if not isinstance(value, dict):
+            raise KeyError(dotted_field)
+        value = value[part]
+    return str(value)
+
+
+def _publish_single_schema(
+    *,
+    destination_location: str,
+    schema_type: str,
+    schema_path: pathlib.Path,
+    overwrite: bool,
+    dry_run: bool,
+) -> bool:
+    """
+    Publish a single dated schema file under *destination_location*.
+
+    :returns: A boolean representing whether something was actually uploaded.
+    """
+    if not schema_path.exists():
+        console_print(f"[error]Schema file not found: {schema_path}\n")
+        sys.exit(1)
+
+    with schema_path.open() as f:
+        payload = json.load(f)
+    version = _read_nested_field(payload, SCHEMA_VERSION_FIELDS[schema_type])
+
+    destination = 
f"{destination_location.rstrip('/')}/{schema_type}/{version}.json"
+    bucket, key = S3DocsPublish.get_bucket_key(destination)
+
+    already_published = s3_client.list_objects_v2(Bucket=bucket, 
Prefix=key).get("KeyCount", 0) > 0
+    if already_published and not overwrite:
+        console_print(
+            f"[info]Skipping {destination} — version {version} already 
published "
+            "(pass --overwrite to replace it).\n"
+        )
+        return False
+
+    if dry_run:
+        console_print(f"[info]Dry run: would upload {schema_path} to 
{destination}\n")
+        return False
+
+    console_print(f"[info]Publishing {schema_type} version {version} to 
{destination}\n")
+    s3_client.put_object(
+        Bucket=bucket,
+        Key=key,
+        Body=schema_path.read_bytes(),
+        ContentType="application/json",
+    )
+    console_print(f"[success]Published {destination}\n")
+    return True
+
+
+def _invalidate_schemas_cache(destination_location: str) -> None:
+    distribution_id = get_cloudfront_distribution(destination_location)
+    _, base_prefix = 
S3DocsPublish.get_bucket_key(destination_location.rstrip("/"))
+    invalidation_path = f"/{base_prefix}/*"
+    console_print(
+        f"[info]Invalidating CloudFront cache for {invalidation_path}: 
distribution id {distribution_id}\n"
+    )
+    cloudfront_client.create_invalidation(
+        DistributionId=distribution_id,
+        InvalidationBatch={
+            "Paths": {"Quantity": 1, "Items": [invalidation_path]},
+            "CallerReference": f"schemas-{os.environ.get('GITHUB_RUN_ID', 
'0')}",
+        },
+    )
+    console_print(f"[success]CloudFront cache invalidation requested: 
{distribution_id}\n")
+
+
+def publish_schemas_to_s3(
+    *,
+    destination_location: str,
+    execution_api_schema: pathlib.Path | None,
+    supervisor_schema: pathlib.Path | None,
+    overwrite: bool = False,
+    dry_run: bool = False,
+) -> None:
+    """Publish generated schema artifacts under *destination_location*.
+
+    ``destination_location`` is an ``s3://<bucket>/<prefix>/`` location (e.g.
+    ``s3://live-docs-airflow-apache-org/schemas/``); each schema is written to
+    ``<prefix>/<schema-type>/<version>.json`` and the ``<prefix>`` is 
invalidated
+    in CloudFront afterwards.
+    """
+    to_publish: list[tuple[str, pathlib.Path]] = []
+    if execution_api_schema:
+        to_publish.append(("execution-api", execution_api_schema))
+    if supervisor_schema:
+        to_publish.append(("supervisor-schema", supervisor_schema))
+
+    if not to_publish:
+        console_print("[error]No schema files provided. Pass --execution-api 
and/or --supervisor.\n")
+        sys.exit(1)
+
+    uploaded_any = False
+    for schema_type, schema_path in to_publish:
+        uploaded = _publish_single_schema(
+            destination_location=destination_location,
+            schema_type=schema_type,
+            schema_path=schema_path,
+            overwrite=overwrite,
+            dry_run=dry_run,
+        )
+        uploaded_any = uploaded_any or uploaded
+
+    if uploaded_any and not dry_run:
+        _invalidate_schemas_cache(destination_location)

Reply via email to