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

kaxilnaik 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 4cd1e7d7726 Add skeleton project for task-sdk (#42904)
4cd1e7d7726 is described below

commit 4cd1e7d7726489fb8d7f0890154d9f6030db7aa0
Author: Kaxil Naik <[email protected]>
AuthorDate: Sat Oct 12 15:40:10 2024 +0100

    Add skeleton project for task-sdk (#42904)
    
    closes https://github.com/apache/airflow/issues/42856
    
    This PR adds a skeleton project for [AIP-72 Task 
SDK](https://cwiki.apache.org/confluence/display/AIRFLOW/AIP-72+Task+Execution+Interface+aka+Task+SDK)
    
    It creates this new project, integrates them to breeze & runs it on CI.
    
    The code & tests are just placeholders at this point, we will start adding 
things needs for DAG Authors in separate PRs.
---
 .dockerignore                                      |   1 +
 .github/boring-cyborg.yml                          |   3 +
 .github/workflows/ci.yml                           |   1 +
 .github/workflows/task-sdk-tests.yml               |  91 ++++++++++++++++
 Dockerfile                                         |  11 +-
 Dockerfile.ci                                      |  12 ++-
 dev/breeze/doc/09_release_management_tasks.rst     |  23 ++++
 .../doc/images/output_release-management.svg       |  18 +++-
 .../doc/images/output_release-management.txt       |   2 +-
 ...release-management_prepare-task-sdk-package.svg | 116 +++++++++++++++++++++
 ...release-management_prepare-task-sdk-package.txt |   1 +
 .../output_setup_check-all-params-in-groups.svg    |  20 ++--
 .../output_setup_check-all-params-in-groups.txt    |   2 +-
 .../output_setup_regenerate-command-images.svg     |  20 ++--
 .../output_setup_regenerate-command-images.txt     |   2 +-
 dev/breeze/doc/images/output_shell.svg             |   4 +-
 dev/breeze/doc/images/output_shell.txt             |   2 +-
 dev/breeze/doc/images/output_testing_db-tests.svg  |   6 +-
 dev/breeze/doc/images/output_testing_db-tests.txt  |   2 +-
 .../doc/images/output_testing_non-db-tests.svg     |   6 +-
 .../doc/images/output_testing_non-db-tests.txt     |   2 +-
 dev/breeze/doc/images/output_testing_tests.svg     |   8 +-
 dev/breeze/doc/images/output_testing_tests.txt     |   2 +-
 .../commands/release_management_commands.py        | 107 ++++++++++++++++++-
 .../commands/release_management_commands_config.py |  15 +++
 dev/breeze/src/airflow_breeze/global_constants.py  |  18 ++++
 .../airflow_breeze/utils/docker_command_utils.py   |   1 +
 dev/breeze/src/airflow_breeze/utils/run_tests.py   |   1 +
 .../src/airflow_breeze/utils/selective_checks.py   |  21 +++-
 dev/breeze/tests/test_selective_checks.py          |  10 +-
 pyproject.toml                                     |   6 +-
 scripts/ci/docker-compose/local.yml                |   3 +
 scripts/ci/kubernetes/k8s_requirements.txt         |   1 +
 scripts/docker/install_airflow.sh                  |  11 +-
 task_sdk/README.md                                 |  18 ++++
 task_sdk/pyproject.toml                            |  40 +++++++
 task_sdk/src/airflow/sdk/__init__.py               |  21 ++++
 task_sdk/src/airflow/sdk/py.typed                  |  18 ++++
 task_sdk/tests/__init__.py                         |  16 +++
 task_sdk/tests/conftest.py                         |  26 +++++
 task_sdk/tests/test_hello.py                       |  23 ++++
 41 files changed, 650 insertions(+), 61 deletions(-)

diff --git a/.dockerignore b/.dockerignore
index bdbf5fb0883..2d70030fd88 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -35,6 +35,7 @@
 !docs
 !licenses
 !providers/
+!task_sdk/
 
 # Add those folders to the context so that they are available in the CI 
container
 !scripts
diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml
index 019ea900f8e..e790d65e2fe 100644
--- a/.github/boring-cyborg.yml
+++ b/.github/boring-cyborg.yml
@@ -679,6 +679,9 @@ labelPRBasedOnFilePath:
   area:system-tests:
     - tests/system/**/*
 
+  area:task-sdk:
+    - task_sdk/**/*
+
   area:db-migrations:
     - airflow/migrations/versions/*
 
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 716323cb9ac..2267154b03a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -93,6 +93,7 @@ jobs:
       run-ui-tests: ${{ steps.selective-checks.outputs.run-ui-tests }}
       run-www-tests: ${{ steps.selective-checks.outputs.run-www-tests }}
       run-kubernetes-tests: ${{ 
steps.selective-checks.outputs.run-kubernetes-tests }}
+      run-task-sdk-tests: ${{ 
steps.selective-checks.outputs.run-task-sdk-tests }}
       basic-checks-only: ${{ steps.selective-checks.outputs.basic-checks-only 
}}
       ci-image-build: ${{ steps.selective-checks.outputs.ci-image-build }}
       prod-image-build: ${{ steps.selective-checks.outputs.prod-image-build }}
diff --git a/.github/workflows/task-sdk-tests.yml 
b/.github/workflows/task-sdk-tests.yml
new file mode 100644
index 00000000000..14fae903837
--- /dev/null
+++ b/.github/workflows/task-sdk-tests.yml
@@ -0,0 +1,91 @@
+# 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.
+#
+---
+name: Task SDK tests
+on:  # yamllint disable-line rule:truthy
+  workflow_call:
+    inputs:
+      runs-on-as-json-default:
+        description: "The array of labels (in json form) determining default 
runner used for the build."
+        required: true
+        type: string
+      image-tag:
+        description: "Tag to set for the image"
+        required: true
+        type: string
+      canary-run:
+        description: "Whether this is a canary run"
+        required: true
+        type: string
+      default-python-version:
+        description: "Which version of python should be used by default"
+        required: true
+        type: string
+      python-versions:
+        description: "JSON-formatted array of Python versions to build images 
from"
+        required: true
+        type: string
+jobs:
+  task-sdk-tests:
+    timeout-minutes: 80
+    name: Task SDK:P${{ matrix.python-version }} tests
+    runs-on: ${{ fromJSON(inputs.runs-on-as-json-default) }}
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: "${{fromJSON(inputs.python-versions)}}"
+    env:
+      GITHUB_REPOSITORY: ${{ github.repository }}
+      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      GITHUB_USERNAME: ${{ github.actor }}
+      IMAGE_TAG: "${{ inputs.image-tag }}"
+      INCLUDE_NOT_READY_PROVIDERS: "true"
+      PYTHON_MAJOR_MINOR_VERSION: "${{ inputs.default-python-version }}"
+      VERBOSE: "true"
+      CLEAN_AIRFLOW_INSTALLATION: "${{ inputs.canary-run }}"
+    if: inputs.run-task-sdk-tests == 'true'
+    steps:
+      - name: "Cleanup repo"
+        shell: bash
+        run: docker run -v "${GITHUB_WORKSPACE}:/workspace" -u 0:0 bash -c "rm 
-rf /workspace/*"
+      - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
+        uses: actions/checkout@v4
+        with:
+          persist-credentials: false
+      - name: "Cleanup docker"
+        run: ./scripts/ci/cleanup_docker.sh
+      - name: "Prepare breeze & CI image: ${{ matrix.python-version }}:${{ 
inputs.image-tag }}"
+        uses: ./.github/actions/prepare_breeze_and_image
+      - name: "Cleanup dist files"
+        run: rm -fv ./dist/*
+      - name: "Prepare Task SDK packages: wheel"
+        run: >
+          breeze release-management prepare-task-sdk-package --package-format 
wheel
+      - name: "Verify wheel packages with twine"
+        run: |
+          pipx uninstall twine || true
+          pipx install twine && twine check dist/*.whl
+      - name: >
+          Run provider unit tests on
+          Airflow Task SDK:Python ${{ matrix.python-version }}
+        if: matrix.run-tests == 'true'
+        run: >
+          breeze testing tests --run-in-parallel
+          --parallel-test-types TaskSDK
+          --use-packages-from-dist
+          --package-format wheel
diff --git a/Dockerfile b/Dockerfile
index ce229c75fac..7b5fa8d0a2b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -877,13 +877,18 @@ function install_airflow() {
     # Determine the installation_command_flags based on 
AIRFLOW_INSTALLATION_METHOD method
     local installation_command_flags
     if [[ ${AIRFLOW_INSTALLATION_METHOD} == "." ]]; then
-        # We need _a _ file in there otherwise the editable install doesn't 
include anything in the .pth file
+        # We need _a_ file in there otherwise the editable install doesn't 
include anything in the .pth file
         mkdir -p ./providers/src/airflow/providers/
         touch ./providers/src/airflow/providers/__init__.py
-        trap 'rm -f ./providers/src/airflow/providers/__init__.py 2>/dev/null' 
EXIT
+
+        # Similarly we need _a_ file for task_sdk too
+        mkdir -p ./task_sdk/src/airflow/sdk/
+        touch ./task_sdk/src/airflow/__init__.py
+
+        trap 'rm -f ./providers/src/airflow/providers/__init__.py 
./task_sdk/src/airflow/__init__.py 2>/dev/null' EXIT
 
         # When installing from sources - we always use `--editable` mode
-        installation_command_flags="--editable 
.[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION} --editable ./providers"
+        installation_command_flags="--editable 
.[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION} --editable ./providers 
--editable ./task_sdk"
     elif [[ ${AIRFLOW_INSTALLATION_METHOD} == "apache-airflow" ]]; then
         
installation_command_flags="apache-airflow[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
     elif [[ ${AIRFLOW_INSTALLATION_METHOD} == apache-airflow\ @\ * ]]; then
diff --git a/Dockerfile.ci b/Dockerfile.ci
index a3e982614de..9339e9af6d6 100644
--- a/Dockerfile.ci
+++ b/Dockerfile.ci
@@ -676,13 +676,18 @@ function install_airflow() {
     # Determine the installation_command_flags based on 
AIRFLOW_INSTALLATION_METHOD method
     local installation_command_flags
     if [[ ${AIRFLOW_INSTALLATION_METHOD} == "." ]]; then
-        # We need _a _ file in there otherwise the editable install doesn't 
include anything in the .pth file
+        # We need _a_ file in there otherwise the editable install doesn't 
include anything in the .pth file
         mkdir -p ./providers/src/airflow/providers/
         touch ./providers/src/airflow/providers/__init__.py
-        trap 'rm -f ./providers/src/airflow/providers/__init__.py 2>/dev/null' 
EXIT
+
+        # Similarly we need _a_ file for task_sdk too
+        mkdir -p ./task_sdk/src/airflow/sdk/
+        touch ./task_sdk/src/airflow/__init__.py
+
+        trap 'rm -f ./providers/src/airflow/providers/__init__.py 
./task_sdk/src/airflow/__init__.py 2>/dev/null' EXIT
 
         # When installing from sources - we always use `--editable` mode
-        installation_command_flags="--editable 
.[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION} --editable ./providers"
+        installation_command_flags="--editable 
.[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION} --editable ./providers 
--editable ./task_sdk"
     elif [[ ${AIRFLOW_INSTALLATION_METHOD} == "apache-airflow" ]]; then
         
installation_command_flags="apache-airflow[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
     elif [[ ${AIRFLOW_INSTALLATION_METHOD} == apache-airflow\ @\ * ]]; then
@@ -1356,6 +1361,7 @@ RUN bash /scripts/docker/install_pipx_tools.sh
 # So in case pyproject.toml changes we can install latest dependencies 
required.
 COPY pyproject.toml ${AIRFLOW_SOURCES}/pyproject.toml
 COPY providers/pyproject.toml ${AIRFLOW_SOURCES}/providers/pyproject.toml
+COPY task_sdk/pyproject.toml ${AIRFLOW_SOURCES}/task_sdk/pyproject.toml
 COPY airflow/__init__.py ${AIRFLOW_SOURCES}/airflow/
 COPY generated/* ${AIRFLOW_SOURCES}/generated/
 COPY constraints/* ${AIRFLOW_SOURCES}/constraints/
diff --git a/dev/breeze/doc/09_release_management_tasks.rst 
b/dev/breeze/doc/09_release_management_tasks.rst
index 9feb9a5b195..9cef5d6ccd1 100644
--- a/dev/breeze/doc/09_release_management_tasks.rst
+++ b/dev/breeze/doc/09_release_management_tasks.rst
@@ -666,3 +666,26 @@ 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 packages
+"""""""""""""""""""""""""""""""""""
+
+You can prepare airflow packages using Breeze:
+
+.. code-block:: bash
+
+     breeze release-management prepare-task-sdk-package
+
+This prepares airflow Task SDK .whl package in the dist folder.
+
+Again, you can specify optional ``--package-format`` flag to build selected 
formats of the Task SDK packages,
+default is to build ``both`` type of packages ``sdist`` and ``wheel``.
+
+.. code-block:: bash
+
+     breeze release-management prepare-task-sdk-package --package-format=wheel
+
+.. image:: ./images/output_release-management_prepare-task-sdk-package.svg
+  :target: 
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/doc/images/output_release-management_prepare-airflow-package.svg
+  :width: 100%
+  :alt: Breeze release-management prepare-task-sdk-package
diff --git a/dev/breeze/doc/images/output_release-management.svg 
b/dev/breeze/doc/images/output_release-management.svg
index 3392f33e92d..2798700d8e2 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 1001.5999999999999" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1074.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="950.5999999999999" />
+      <rect x="0" y="0" width="1463.0" height="1023.8" />
     </clipPath>
     <clipPath id="breeze-release-management-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -158,9 +158,18 @@
 <clipPath id="breeze-release-management-line-37">
     <rect x="0" y="904.3" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="breeze-release-management-line-38">
+    <rect x="0" y="928.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-line-39">
+    <rect x="0" y="953.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-line-40">
+    <rect x="0" y="977.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="999.6" 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="1072.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"/>
@@ -209,6 +218,9 @@
 </text><text class="breeze-release-management-r5" x="0" y="898.4" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-36)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="898.4" textLength="292.8" 
clip-path="url(#breeze-release-management-line-36)">generate-constraints&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="898.4" textLength="1098" 
clip-path="url(#breeze-release-management-line-36)">Generates&#160;pinned&#160;cons
 [...]
 </text><text class="breeze-release-management-r5" x="0" y="922.8" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-37)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="922.8" textLength="292.8" 
clip-path="url(#breeze-release-management-line-37)">update-constraints&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="341.6" y="922.8" textLength="1098" 
clip-path="url(#breeze-release-management-line-37)">Update&#160;released& [...]
 </text><text class="breeze-release-management-r5" x="0" y="947.2" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-38)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="947.2" textLength="12.2" 
clip-path="url(#breeze-release-management-line-38)">
+</text><text class="breeze-release-management-r5" x="0" y="971.6" 
textLength="24.4" 
clip-path="url(#breeze-release-management-line-39)">╭─</text><text 
class="breeze-release-management-r5" x="24.4" y="971.6" textLength="122" 
clip-path="url(#breeze-release-management-line-39)">&#160;Commands&#160;</text><text
 class="breeze-release-management-r5" x="146.4" y="971.6" textLength="1293.2" 
clip-path="url(#breeze-release-management-line-39)">──────────────────────────────────────────────────────
 [...]
+</text><text class="breeze-release-management-r5" x="0" y="996" 
textLength="12.2" 
clip-path="url(#breeze-release-management-line-40)">│</text><text 
class="breeze-release-management-r4" x="24.4" y="996" textLength="488" 
clip-path="url(#breeze-release-management-line-40)">prepare-task-sdk-package&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-r1" x="536.8" y="996" textLength="902.8" 
clip-path="url [...]
+</text><text class="breeze-release-management-r5" x="0" y="1020.4" 
textLength="1464" 
clip-path="url(#breeze-release-management-line-41)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-r1" x="1464" y="1020.4" textLength="12.2" 
clip-path="url(#breeze-release-management-line-41)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_release-management.txt 
b/dev/breeze/doc/images/output_release-management.txt
index 4655263b2bc..a186de953f6 100644
--- a/dev/breeze/doc/images/output_release-management.txt
+++ b/dev/breeze/doc/images/output_release-management.txt
@@ -1 +1 @@
-46d2a272002ee4a7dfefba98127d1680
+dbd26a6fc8d708bcbbe450896906bef6
diff --git 
a/dev/breeze/doc/images/output_release-management_prepare-task-sdk-package.svg 
b/dev/breeze/doc/images/output_release-management_prepare-task-sdk-package.svg
new file mode 100644
index 00000000000..63bb39a5189
--- /dev/null
+++ 
b/dev/breeze/doc/images/output_release-management_prepare-task-sdk-package.svg
@@ -0,0 +1,116 @@
+<svg class="rich-terminal" viewBox="0 0 1482 391.59999999999997" 
xmlns="http://www.w3.org/2000/svg";>
+    <!-- Generated with Rich https://www.textualize.io -->
+    <style>
+
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Regular"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff";)
 format("woff");
+        font-style: normal;
+        font-weight: 400;
+    }
+    @font-face {
+        font-family: "Fira Code";
+        src: local("FiraCode-Bold"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2";)
 format("woff2"),
+                
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff";)
 format("woff");
+        font-style: bold;
+        font-weight: 700;
+    }
+
+    .breeze-release-management-prepare-task-sdk-package-matrix {
+        font-family: Fira Code, monospace;
+        font-size: 20px;
+        line-height: 24.4px;
+        font-variant-east-asian: full-width;
+    }
+
+    .breeze-release-management-prepare-task-sdk-package-title {
+        font-size: 18px;
+        font-weight: bold;
+        font-family: arial;
+    }
+
+    .breeze-release-management-prepare-task-sdk-package-r1 { fill: #c5c8c6 }
+.breeze-release-management-prepare-task-sdk-package-r2 { fill: #d0b344 }
+.breeze-release-management-prepare-task-sdk-package-r3 { fill: 
#c5c8c6;font-weight: bold }
+.breeze-release-management-prepare-task-sdk-package-r4 { fill: 
#68a0b3;font-weight: bold }
+.breeze-release-management-prepare-task-sdk-package-r5 { fill: #868887 }
+.breeze-release-management-prepare-task-sdk-package-r6 { fill: #8d7b39 }
+.breeze-release-management-prepare-task-sdk-package-r7 { fill: 
#98a84b;font-weight: bold }
+    </style>
+
+    <defs>
+    <clipPath 
id="breeze-release-management-prepare-task-sdk-package-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="340.59999999999997" />
+    </clipPath>
+    <clipPath id="breeze-release-management-prepare-task-sdk-package-line-0">
+    <rect x="0" y="1.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-1">
+    <rect x="0" y="25.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-2">
+    <rect x="0" y="50.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-3">
+    <rect x="0" y="74.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-4">
+    <rect x="0" y="99.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-5">
+    <rect x="0" y="123.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-6">
+    <rect x="0" y="147.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-7">
+    <rect x="0" y="172.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-8">
+    <rect x="0" y="196.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-9">
+    <rect x="0" y="221.1" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-10">
+    <rect x="0" y="245.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-11">
+    <rect x="0" y="269.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="breeze-release-management-prepare-task-sdk-package-line-12">
+    <rect x="0" y="294.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="389.6" rx="8"/><text 
class="breeze-release-management-prepare-task-sdk-package-title" fill="#c5c8c6" 
text-anchor="middle" x="740" 
y="27">Command:&#160;release-management&#160;prepare-task-sdk-package</text>
+            <g transform="translate(26,22)">
+            <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+            <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+            <circle cx="44" cy="0" r="7" fill="#28c840"/>
+            </g>
+        
+    <g transform="translate(9, 41)" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-clip-terminal)">
+    
+    <g class="breeze-release-management-prepare-task-sdk-package-matrix">
+    <text class="breeze-release-management-prepare-task-sdk-package-r1" 
x="1464" y="20" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-0)">
+</text><text class="breeze-release-management-prepare-task-sdk-package-r2" 
x="12.2" y="44.4" textLength="73.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-1)">Usage:</text><text
 class="breeze-release-management-prepare-task-sdk-package-r3" x="97.6" 
y="44.4" textLength="610" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-1)">breeze&#160;release-management&#160;prepare-task-sdk-package</text><text
 class="breeze-release-management-prepare [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r1" 
x="1464" y="68.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-2)">
+</text><text class="breeze-release-management-prepare-task-sdk-package-r1" 
x="12.2" y="93.2" textLength="561.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-3)">Prepare&#160;sdist/whl&#160;package&#160;of&#160;Airflow&#160;Task&#160;SDK.</text><text
 class="breeze-release-management-prepare-task-sdk-package-r1" x="1464" 
y="93.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-3)">
+</text><text class="breeze-release-management-prepare-task-sdk-package-r1" 
x="1464" y="117.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-4)">
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="142" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-5)">╭─</text><text
 class="breeze-release-management-prepare-task-sdk-package-r5" x="24.4" y="142" 
textLength="183" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-5)">&#160;Package&#160;flags&#160;</text><text
 class="breeze-release-management-prepare-task-sdk-package-r5" x="207.4" 
y="142" [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="166.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-6)">│</text><text
 class="breeze-release-management-prepare-task-sdk-package-r4" x="24.4" 
y="166.4" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-6)">--package-format</text><text
 class="breeze-release-management-prepare-task-sdk-package-r1" x="280.6" 
y="166.4" textLe [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="190.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-7)">│</text><text
 class="breeze-release-management-prepare-task-sdk-package-r4" x="24.4" 
y="190.8" textLength="207.4" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-7)">--use-local-hatch</text><text
 class="breeze-release-management-prepare-task-sdk-package-r1" x="280.6" 
y="190.8" textL [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="215.2" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-8)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-task-sdk-package-r1" x="1464" 
y="215.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-8)">
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="239.6" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-9)">╭─</text><text
 class="breeze-release-management-prepare-task-sdk-package-r5" x="24.4" 
y="239.6" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-9)">&#160;Common&#160;options&#160;</text><text
 class="breeze-release-management-prepare-task-sdk-package-r5" x="219.6"  [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="264" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-10)">│</text><text
 class="breeze-release-management-prepare-task-sdk-package-r4" x="24.4" y="264" 
textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-10)">--verbose</text><text
 class="breeze-release-management-prepare-task-sdk-package-r7" x="158.6" 
y="264" textLength="24.4" [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="288.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-11)">│</text><text
 class="breeze-release-management-prepare-task-sdk-package-r4" x="24.4" 
y="288.4" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-11)">--dry-run</text><text
 class="breeze-release-management-prepare-task-sdk-package-r7" x="158.6" 
y="288.4" textLength= [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="312.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-12)">│</text><text
 class="breeze-release-management-prepare-task-sdk-package-r4" x="24.4" 
y="312.8" textLength="73.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-12)">--help</text><text
 class="breeze-release-management-prepare-task-sdk-package-r7" x="158.6" 
y="312.8" textLength="24. [...]
+</text><text class="breeze-release-management-prepare-task-sdk-package-r5" 
x="0" y="337.2" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-13)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-task-sdk-package-r1" x="1464" 
y="337.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-task-sdk-package-line-13)">
+</text>
+    </g>
+    </g>
+</svg>
diff --git 
a/dev/breeze/doc/images/output_release-management_prepare-task-sdk-package.txt 
b/dev/breeze/doc/images/output_release-management_prepare-task-sdk-package.txt
new file mode 100644
index 00000000000..f20d3a31463
--- /dev/null
+++ 
b/dev/breeze/doc/images/output_release-management_prepare-task-sdk-package.txt
@@ -0,0 +1 @@
+adc65fd78e7040d42660aea2289d0f96
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 71feee5875a..a5f797e9cf2 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
@@ -190,16 +190,16 @@
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="483.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="483.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">release-management:prepare-airflow-tarball&#160;|&#160;release-management:prepare-helm-chart-package&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="508" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="508" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">release-management:prepare-helm-chart-tarball&#160;|&#160;release-management:prepare-provider-documentation&#160;|&#160;&#160;&#160;&#160;</text><text
 class="breez [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="532.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="532.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">release-management:prepare-provider-packages&#160;|&#160;release-management:prepare-python-client&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="556.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="556.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:publish-docs&#160;|&#160;release-management:release-prod-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="581.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="581.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#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="605.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="605.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">release-management:tag-providers&#160;|&#160;release-management:update-constraints&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="630" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="654.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="654.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">sbom:export-dependency-information&#160;|&#160;sbom:generate-providers-requirements&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="678.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="678.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="703.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;</text><text
 cla [...]
-</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="183" y="727.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;static-checks&#160;|&#160;testing&#160;|&#160;testing:db-tests&#160;|&#160;&#160;&#160;&#
 [...]
-</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="183" y="752" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;testing:integration-tests&#160;|&#160;testing:non-db-tests&#160;|&#160;</text><text
 class=" [...]
-</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="183" y="776.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">testing:tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="556.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="556.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:prepare-task-sdk-package&#160;|&#160;release-management:publish-docs&#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="581.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="581.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#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="605.6" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="605.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">release-management:start-release&#160;|&#160;release-management:tag-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="630" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">release-management:update-constraints&#160;|&#160;release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="654.4" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="654.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">sbom:build-all-airflow-images&#160;|&#160;sbom:export-dependency-information&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="678.8" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="678.8" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;&#160;&#160;&#160;&#
 [...]
+</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text 
class="breeze-setup-check-all-params-in-groups-r6" x="183" y="703.2" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;</text><text
 class="b [...]
+</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="183" y="727.6" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;static-checks&#160;|&#160;testing&#160;
 [...]
+</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="183" y="752" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">testing:db-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;testing:integration-tests&#160;|&#160;&#160;&#160;&#160;&#160;
 [...]
+</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="183" y="776.4" 
textLength="1256.6" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">testing:non-db-tests&#160;|&#160;testing:tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" 
y="800.8" textLength="1464" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-check-all-params-in-groups-r1" x="1464" 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-r5" x="0" 
y="825.2" textLength="24.4" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">╭─</text><text
 class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="825.2" 
textLength="195.2" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">&#160;Common&#160;options&#160;</text><text
 class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="825.2" 
textLength="1220" clip-path="url(#breeze-se [...]
 </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-r4" x="24.4" y="849.6" 
textLength="109.8" 
clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">--verbose</text><text
 class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="849.6" 
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 098640fbe5b..d2cab78ff8c 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 @@
-a6a4664c4cf6fdf2bc51ffaa9c0e8177
+852bdb14696f768b8a22551ba88bf061
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 83018c3d8d3..c107a1843b4 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -204,16 +204,16 @@
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="532.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:prepare-airflow-tarball&#160;|&#160;release-management:prepare-helm-chart-package&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><
 [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="556.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:prepare-helm-chart-tarball&#160;|&#160;release-management:prepare-provider-documentation&#160;|&#160;</text><text
 class="breeze-setup-regenerate [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="581.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-23)">release-management:prepare-provider-packages&#160;|&#160;release-management:prepare-python-client&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="605.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">release-management:publish-docs&#160;|&#160;release-management:release-prod-images&#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="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="630" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">release-management:start-rc-process&#160;|&#160;release-management:start-release&#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="654.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="654.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">release-management:tag-providers&#160;|&#160;release-management:update-constraints&#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="678.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="678.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;sbom:build-all-airflow-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="703.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">sbom:export-dependency-information&#160;|&#160;sbom:generate-providers-requirements&#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="727.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="727.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;setup:check-all-params-in-groups&#160;|&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="752" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts</text><text
 class="breeze-setup-rege [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;static-checks&#160;|&#160;testing&#160;|&#160;testing:db-tests&#160;|&#160;&#160;&#160
 [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="800.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;testing:integration-tests&#160;|&#160;testing:non-db-tests</text><text
 class="breeze-setup- [...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="825.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">|&#160;testing:tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="605.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-24)">release-management:prepare-task-sdk-package&#160;|&#160;release-management:publish-docs&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="630" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-25)">release-management:release-prod-images&#160;|&#160;release-management:start-rc-process&#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="654.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="654.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-26)">release-management:start-release&#160;|&#160;release-management:tag-providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="678.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-27)">release-management:update-constraints&#160;|&#160;release-management:verify-provider-packages&#160;|&#160;sbom&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="703.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">sbom:build-all-airflow-images&#160;|&#160;sbom:export-dependency-information&#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="727.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="727.6" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">sbom:generate-providers-requirements&#160;|&#160;sbom:update-sbom-information&#160;|&#160;setup&#160;|&#160;setup:autocomplete&#160;|&#160;&#160;</text><text
 class [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="752" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">setup:check-all-params-in-groups&#160;|&#160;setup:config&#160;|&#160;setup:regenerate-command-images&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">setup:self-upgrade&#160;|&#160;setup:synchronize-local-mounts&#160;|&#160;setup:version&#160;|&#160;shell&#160;|&#160;start-airflow&#160;|&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="800.8" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">static-checks&#160;|&#160;testing&#160;|&#160;testing:db-tests&#160;|&#160;testing:docker-compose-tests&#160;|&#160;testing:helm-tests&#160;|&#160;&#160;&#160;&#16
 [...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text 
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="825.2" 
textLength="1220" 
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">testing:integration-tests&#160;|&#160;testing:non-db-tests&#160;|&#160;testing:tests)&#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="849.6" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text 
class="breeze-setup-regenerate-command-images-r4" x="24.4" y="849.6" 
textLength="146.4" 
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">--check-only</text><text
 class="breeze-setup-regenerate-command-images-r1" x="219.6" y="849.6" 
textLength="1220" clip-path="url(#breeze-setup-regenerate-command-im [...]
 </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-r1" x="219.6" y="874" 
textLength="170.8" 
clip-path="url(#breeze-setup-regenerate-command-images-line-35)">together&#160;with&#160;</text><text
 class="breeze-setup-regenerate-command-images-r4" x="390.4" y="874" 
textLength="109.8" clip-path="url(#breeze-setup-regenerate-co [...]
 </text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" 
textLength="1464" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-setup-regenerate-command-images-r1" x="1464" y="898.4" 
textLength="12.2" 
clip-path="url(#breeze-setup-regenerate-command-images-line-36)">
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 b0b5b55ddd2..751b0329d71 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 @@
-4a736bf190984799f73b3bf85dc62c4c
+326695396d27b77b860202ebe9267746
diff --git a/dev/breeze/doc/images/output_shell.svg 
b/dev/breeze/doc/images/output_shell.svg
index 1e23fe528b6..19b93c0ca15 100644
--- a/dev/breeze/doc/images/output_shell.svg
+++ b/dev/breeze/doc/images/output_shell.svg
@@ -654,8 +654,8 @@
 </text><text class="breeze-shell-r5" x="0" y="2948" textLength="12.2" 
clip-path="url(#breeze-shell-line-120)">│</text><text class="breeze-shell-r7" 
x="756.4" y="2948" textLength="683.2" 
clip-path="url(#breeze-shell-line-120)">(All&#160;|&#160;Default&#160;|&#160;API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="2948" textLength="12.2" 
clip-path="url(#breeze-shell-line-120)">│</text><text class="breeze-shell-r1" 
x= [...]
 </text><text class="breeze-shell-r5" x="0" y="2972.4" textLength="12.2" 
clip-path="url(#breeze-shell-line-121)">│</text><text class="breeze-shell-r7" 
x="756.4" y="2972.4" textLength="683.2" 
clip-path="url(#breeze-shell-line-121)">BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;ExternalPython&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="2972.4" textLength="12.2" 
clip-path="url(#breeze-shell-line-121)">│</text><text  [...]
 </text><text class="breeze-shell-r5" x="0" y="2996.8" textLength="12.2" 
clip-path="url(#breeze-shell-line-122)">│</text><text class="breeze-shell-r7" 
x="756.4" y="2996.8" textLength="683.2" 
clip-path="url(#breeze-shell-line-122)">Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="2996.8" textLength="12.2" 
clip-path="url(#breeze-shell-line-122)">│</t [...]
-</text><text class="breeze-shell-r5" x="0" y="3021.2" textLength="12.2" 
clip-path="url(#breeze-shell-line-123)">│</text><text class="breeze-shell-r7" 
x="756.4" y="3021.2" textLength="683.2" 
clip-path="url(#breeze-shell-line-123)">PythonVenv&#160;|&#160;Serialization&#160;|&#160;WWW&#160;|&#160;All-Postgres&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="3021.2" textLength="12.2" 
clip-path="url(#breeze-shell-line-123)">│</text><text class [...]
-</text><text class="breeze-shell-r5" x="0" y="3045.6" textLength="12.2" 
clip-path="url(#breeze-shell-line-124)">│</text><text class="breeze-shell-r7" 
x="756.4" y="3045.6" textLength="683.2" 
clip-path="url(#breeze-shell-line-124)">All-MySQL&#160;|&#160;All-Quarantined)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="3045. [...]
+</text><text class="breeze-shell-r5" x="0" y="3021.2" textLength="12.2" 
clip-path="url(#breeze-shell-line-123)">│</text><text class="breeze-shell-r7" 
x="756.4" y="3021.2" textLength="683.2" 
clip-path="url(#breeze-shell-line-123)">PythonVenv&#160;|&#160;Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="3021.2" textLength="12.2" 
clip-path="url(#breeze-shell-line- [...]
+</text><text class="breeze-shell-r5" x="0" y="3045.6" textLength="12.2" 
clip-path="url(#breeze-shell-line-124)">│</text><text class="breeze-shell-r7" 
x="756.4" y="3045.6" textLength="683.2" 
clip-path="url(#breeze-shell-line-124)">All-Postgres&#160;|&#160;All-MySQL&#160;|&#160;All-Quarantined)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="3045.6" textLength="12.2" 
clip-path="url(#breeze-shell-line-124)">│</t [...]
 </text><text class="breeze-shell-r5" x="0" y="3070" textLength="12.2" 
clip-path="url(#breeze-shell-line-125)">│</text><text class="breeze-shell-r5" 
x="756.4" y="3070" textLength="683.2" 
clip-path="url(#breeze-shell-line-125)">[default:&#160;Default]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 cl [...]
 </text><text class="breeze-shell-r5" x="0" y="3094.4" textLength="12.2" 
clip-path="url(#breeze-shell-line-126)">│</text><text class="breeze-shell-r4" 
x="24.4" y="3094.4" textLength="256.2" 
clip-path="url(#breeze-shell-line-126)">--use-airflow-version</text><text 
class="breeze-shell-r1" x="756.4" y="3094.4" textLength="683.2" 
clip-path="url(#breeze-shell-line-126)">Use&#160;(reinstall&#160;at&#160;entry)&#160;Airflow&#160;version&#160;from&#160;PyPI.&#160;It&#160;&#160;</text><text
 class= [...]
 </text><text class="breeze-shell-r5" x="0" y="3118.8" textLength="12.2" 
clip-path="url(#breeze-shell-line-127)">│</text><text class="breeze-shell-r1" 
x="756.4" y="3118.8" textLength="683.2" 
clip-path="url(#breeze-shell-line-127)">can&#160;also&#160;be&#160;version&#160;(to&#160;install&#160;from&#160;PyPI),&#160;`none`,&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-shell-r5" x="1451.8" y="3118.8" textLength="12.2" 
clip-path="url(#breeze-shell-line-127)">│</text><text class="bre [...]
diff --git a/dev/breeze/doc/images/output_shell.txt 
b/dev/breeze/doc/images/output_shell.txt
index 51aa99ed73c..e09e77274a0 100644
--- a/dev/breeze/doc/images/output_shell.txt
+++ b/dev/breeze/doc/images/output_shell.txt
@@ -1 +1 @@
-94eabd0345df65038958fc4842a0ff4b
+10bd351167267ce16d35b96898a64b74
diff --git a/dev/breeze/doc/images/output_testing_db-tests.svg 
b/dev/breeze/doc/images/output_testing_db-tests.svg
index 708665af52d..d9d92ed40f0 100644
--- a/dev/breeze/doc/images/output_testing_db-tests.svg
+++ b/dev/breeze/doc/images/output_testing_db-tests.svg
@@ -410,15 +410,15 @@
 </text><text class="breeze-testing-db-tests-r5" x="0" y="215.2" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-8)">│</text><text 
class="breeze-testing-db-tests-r4" x="24.4" y="215.2" textLength="256.2" 
clip-path="url(#breeze-testing-db-tests-line-8)">--parallel-test-types</text><text
 class="breeze-testing-db-tests-r1" x="439.2" y="215.2" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-8)">Space&#160;separated&#160;list&#160;of&#160;test&#160;types&#160;us
 [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="239.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-9)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="239.6" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-9)">(API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="264" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-10)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="264" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-10)">ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-db-tests-r5" x="1451.8" [...]
-</text><text class="breeze-testing-db-tests-r5" x="0" y="288.4" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-11)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="288.4" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-11)">Serialization&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-testing-db-tests-r5" x="0" y="288.4" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-11)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="288.4" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-11)">Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW)&#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-testing-db-tests-r5" x="0" y="312.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-12)">│</text><text 
class="breeze-testing-db-tests-r5" x="439.2" y="312.8" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-12)">[default:&#160;API&#160;Always&#160;BranchExternalPython&#160;BranchPythonVenv&#160;CLI&#160;Core&#160;ExternalPython</text><text
 class="breeze-testing-db-tests-r5" x="1451.8" y="312.8" textLength="12.2" 
clip-path="url(#b [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="337.2" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-13)">│</text><text 
class="breeze-testing-db-tests-r5" x="439.2" y="337.2" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-13)">Operators&#160;Other&#160;PlainAsserts&#160;Providers[-amazon,google]&#160;Providers[amazon]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-db-tests-r5" x="1451.8" y="337.2"  [...]
-</text><text class="breeze-testing-db-tests-r5" x="0" y="361.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-14)">│</text><text 
class="breeze-testing-db-tests-r5" x="439.2" y="361.6" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-14)">Providers[google]&#160;PythonVenv&#160;Serialization&#160;WWW]&#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-testing-db-tests-r5" x="0" y="361.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-14)">│</text><text 
class="breeze-testing-db-tests-r5" x="439.2" y="361.6" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-14)">Providers[google]&#160;PythonVenv&#160;Serialization&#160;TaskSDK&#160;WWW]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="386" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-15)">│</text><text 
class="breeze-testing-db-tests-r4" x="24.4" y="386" textLength="244" 
clip-path="url(#breeze-testing-db-tests-line-15)">--database-isolation</text><text
 class="breeze-testing-db-tests-r1" x="439.2" y="386" textLength="475.8" 
clip-path="url(#breeze-testing-db-tests-line-15)">Run&#160;airflow&#160;in&#160;database&#160;isolation&#160;mode.</text><te
 [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="410.4" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-16)">│</text><text 
class="breeze-testing-db-tests-r4" x="24.4" y="410.4" textLength="366" 
clip-path="url(#breeze-testing-db-tests-line-16)">--excluded-parallel-test-types</text><text
 class="breeze-testing-db-tests-r1" x="439.2" y="410.4" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-16)">Space&#160;separated&#160;list&#160;of&#160;test&#160;typ
 [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="434.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-17)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="434.8" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-17)">(API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="bree [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="459.2" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-18)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="459.2" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-18)">ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-db-tests-r5" x="145 [...]
-</text><text class="breeze-testing-db-tests-r5" x="0" y="483.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-19)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="483.6" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-19)">Serialization&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-testing-db-tests-r5" x="0" y="483.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-19)">│</text><text 
class="breeze-testing-db-tests-r6" x="439.2" y="483.6" textLength="1000.4" 
clip-path="url(#breeze-testing-db-tests-line-19)">Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW)&#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-testing-db-tests-r5" x="0" y="508" 
textLength="1464" 
clip-path="url(#breeze-testing-db-tests-line-20)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-db-tests-r1" x="1464" y="508" textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-20)">
 </text><text class="breeze-testing-db-tests-r5" x="0" y="532.4" 
textLength="24.4" 
clip-path="url(#breeze-testing-db-tests-line-21)">╭─</text><text 
class="breeze-testing-db-tests-r5" x="24.4" y="532.4" textLength="170.8" 
clip-path="url(#breeze-testing-db-tests-line-21)">&#160;Test&#160;options&#160;</text><text
 class="breeze-testing-db-tests-r5" x="195.2" y="532.4" textLength="1244.4" 
clip-path="url(#breeze-testing-db-tests-line-21)">───────────────────────────────────────────────────────
 [...]
 </text><text class="breeze-testing-db-tests-r5" x="0" y="556.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-db-tests-line-22)">│</text><text 
class="breeze-testing-db-tests-r4" x="24.4" y="556.8" textLength="170.8" 
clip-path="url(#breeze-testing-db-tests-line-22)">--test-timeout</text><text 
class="breeze-testing-db-tests-r1" x="329.4" y="556.8" textLength="1110.2" 
clip-path="url(#breeze-testing-db-tests-line-22)">Test&#160;timeout&#160;in&#160;seconds.&#160;Set&#160;the&#160;pytest&#
 [...]
diff --git a/dev/breeze/doc/images/output_testing_db-tests.txt 
b/dev/breeze/doc/images/output_testing_db-tests.txt
index 6027a2d1e66..6245a387214 100644
--- a/dev/breeze/doc/images/output_testing_db-tests.txt
+++ b/dev/breeze/doc/images/output_testing_db-tests.txt
@@ -1 +1 @@
-7b406b63cd4a75aba6ac38b8c0b7431c
+690396dbea7c9b6e018704e1ee7f727d
diff --git a/dev/breeze/doc/images/output_testing_non-db-tests.svg 
b/dev/breeze/doc/images/output_testing_non-db-tests.svg
index da43621dd69..daf8061b13e 100644
--- a/dev/breeze/doc/images/output_testing_non-db-tests.svg
+++ b/dev/breeze/doc/images/output_testing_non-db-tests.svg
@@ -376,14 +376,14 @@
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="190.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-7)">│</text><text 
class="breeze-testing-non-db-tests-r4" x="24.4" y="190.8" textLength="256.2" 
clip-path="url(#breeze-testing-non-db-tests-line-7)">--parallel-test-types</text><text
 class="breeze-testing-non-db-tests-r1" x="439.2" y="190.8" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-7)">Space&#160;separated&#160;list&#160;of&#160
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="215.2" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-8)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="215.2" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-8)">(API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><te
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="239.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-9)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="239.6" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-9)">ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-non-d [...]
-</text><text class="breeze-testing-non-db-tests-r5" x="0" y="264" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-10)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="264" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-10)">Serialization&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-testing-non-db-tests-r5" x="0" y="264" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-10)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="264" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-10)">Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW)&#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-testing-non-db-tests-r5" x="0" y="288.4" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-11)">│</text><text 
class="breeze-testing-non-db-tests-r5" x="439.2" y="288.4" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-11)">[default:&#160;API&#160;Always&#160;BranchExternalPython&#160;BranchPythonVenv&#160;CLI&#160;Core&#160;ExternalPython</text><text
 class="breeze-testing-non-db-tests-r5" x="1451.8" y="288.4" textLength="12. 
[...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="312.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-12)">│</text><text 
class="breeze-testing-non-db-tests-r5" x="439.2" y="312.8" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-12)">Operators&#160;Other&#160;PlainAsserts&#160;Providers[-amazon,google]&#160;Providers[amazon]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-non-db-tests-r5" x [...]
-</text><text class="breeze-testing-non-db-tests-r5" x="0" y="337.2" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-13)">│</text><text 
class="breeze-testing-non-db-tests-r5" x="439.2" y="337.2" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-13)">Providers[google]&#160;PythonVenv&#160;Serialization&#160;WWW]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-testing-non-db-tests-r5" x="0" y="337.2" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-13)">│</text><text 
class="breeze-testing-non-db-tests-r5" x="439.2" y="337.2" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-13)">Providers[google]&#160;PythonVenv&#160;Serialization&#160;TaskSDK&#160;WWW]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="361.6" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-14)">│</text><text 
class="breeze-testing-non-db-tests-r4" x="24.4" y="361.6" textLength="366" 
clip-path="url(#breeze-testing-non-db-tests-line-14)">--excluded-parallel-test-types</text><text
 class="breeze-testing-non-db-tests-r1" x="439.2" y="361.6" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-14)">Space&#160;separated&#160;list&#1
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="386" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-15)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="386" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-15)">(API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="410.4" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-16)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="410.4" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-16)">ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-non [...]
-</text><text class="breeze-testing-non-db-tests-r5" x="0" y="434.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-17)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="434.8" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-17)">Serialization&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
+</text><text class="breeze-testing-non-db-tests-r5" x="0" y="434.8" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-17)">│</text><text 
class="breeze-testing-non-db-tests-r6" x="439.2" y="434.8" textLength="1000.4" 
clip-path="url(#breeze-testing-non-db-tests-line-17)">Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="459.2" 
textLength="1464" 
clip-path="url(#breeze-testing-non-db-tests-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-non-db-tests-r1" x="1464" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-18)">
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="483.6" 
textLength="24.4" 
clip-path="url(#breeze-testing-non-db-tests-line-19)">╭─</text><text 
class="breeze-testing-non-db-tests-r5" x="24.4" y="483.6" textLength="170.8" 
clip-path="url(#breeze-testing-non-db-tests-line-19)">&#160;Test&#160;options&#160;</text><text
 class="breeze-testing-non-db-tests-r5" x="195.2" y="483.6" textLength="1244.4" 
clip-path="url(#breeze-testing-non-db-tests-line-19)">───────────────────────────────
 [...]
 </text><text class="breeze-testing-non-db-tests-r5" x="0" y="508" 
textLength="12.2" 
clip-path="url(#breeze-testing-non-db-tests-line-20)">│</text><text 
class="breeze-testing-non-db-tests-r4" x="24.4" y="508" textLength="170.8" 
clip-path="url(#breeze-testing-non-db-tests-line-20)">--test-timeout</text><text
 class="breeze-testing-non-db-tests-r1" x="329.4" y="508" textLength="1110.2" 
clip-path="url(#breeze-testing-non-db-tests-line-20)">Test&#160;timeout&#160;in&#160;seconds.&#160;Set&#160
 [...]
diff --git a/dev/breeze/doc/images/output_testing_non-db-tests.txt 
b/dev/breeze/doc/images/output_testing_non-db-tests.txt
index 1080b5a3777..122c3b1acd1 100644
--- a/dev/breeze/doc/images/output_testing_non-db-tests.txt
+++ b/dev/breeze/doc/images/output_testing_non-db-tests.txt
@@ -1 +1 @@
-2cc222da8b9f31b93b527220b76b48a2
+dbecb30a3e03c7dffd09d46c16687e62
diff --git a/dev/breeze/doc/images/output_testing_tests.svg 
b/dev/breeze/doc/images/output_testing_tests.svg
index c20e2ef16b2..8c8c881915a 100644
--- a/dev/breeze/doc/images/output_testing_tests.svg
+++ b/dev/breeze/doc/images/output_testing_tests.svg
@@ -466,19 +466,19 @@
 </text><text class="breeze-testing-tests-r5" x="0" y="264" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-10)">│</text><text 
class="breeze-testing-tests-r1" x="439.2" y="264" textLength="134.2" 
clip-path="url(#breeze-testing-tests-line-10)">`Providers[</text><text 
class="breeze-testing-tests-r6" x="573.4" y="264" textLength="85.4" 
clip-path="url(#breeze-testing-tests-line-10)">-amazon</text><text 
class="breeze-testing-tests-r1" x="658.8" y="264" textLength="780.8" clip-path= 
[...]
 </text><text class="breeze-testing-tests-r5" x="0" y="288.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-11)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="288.4" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-11)">(All&#160;|&#160;Default&#160;|&#160;API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;&#160;&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="288.4" textL [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="312.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-12)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="312.8" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-12)">Core&#160;|&#160;ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="312.8" textLength="12.2" cl [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="337.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-13)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="337.2" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-13)">|&#160;Serialization&#160;|&#160;WWW&#160;|&#160;All-Postgres&#160;|&#160;All-MySQL&#160;|&#160;All-Quarantined)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-test [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="337.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-13)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="337.2" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-13)">|&#160;Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW&#160;|&#160;All-Postgres&#160;|&#160;All-MySQL&#160;|&#160;All-Quarantined)&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="337.2" textL [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="361.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-14)">│</text><text 
class="breeze-testing-tests-r5" x="439.2" y="361.6" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-14)">[default:&#160;Default]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="386" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-15)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="386" textLength="256.2" 
clip-path="url(#breeze-testing-tests-line-15)">--parallel-test-types</text><text
 class="breeze-testing-tests-r1" x="439.2" y="386" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-15)">Space&#160;separated&#160;list&#160;of&#160;test&#160;types&#160;used&#160;for&#160;test
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="410.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-16)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="410.4" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-16)">(API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-t [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="434.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-17)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="434.8" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-17)">ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="434.8"  [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-18)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="459.2" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-18)">Serialization&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160
 [...]
+</text><text class="breeze-testing-tests-r5" x="0" y="459.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-18)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="459.2" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-18)">Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW)&#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-testing-tests-r5" x="0" y="483.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-19)">│</text><text 
class="breeze-testing-tests-r5" x="439.2" y="483.6" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-19)">[default:&#160;API&#160;Always&#160;BranchExternalPython&#160;BranchPythonVenv&#160;CLI&#160;Core&#160;ExternalPython</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="483.6" textLength="12.2" 
clip-path="url(#breeze-testing-t [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="508" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-20)">│</text><text 
class="breeze-testing-tests-r5" x="439.2" y="508" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-20)">Operators&#160;Other&#160;PlainAsserts&#160;Providers[-amazon,google]&#160;Providers[amazon]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="508" textLength="12.2" cli [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-21)">│</text><text 
class="breeze-testing-tests-r5" x="439.2" y="532.4" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-21)">Providers[google]&#160;PythonVenv&#160;Serialization&#160;WWW]&#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-testing-tests-r5" x="0" y="532.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-21)">│</text><text 
class="breeze-testing-tests-r5" x="439.2" y="532.4" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-21)">Providers[google]&#160;PythonVenv&#160;Serialization&#160;TaskSDK&#160;WWW]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="556.8" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-22)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="556.8" textLength="366" 
clip-path="url(#breeze-testing-tests-line-22)">--excluded-parallel-test-types</text><text
 class="breeze-testing-tests-r1" x="439.2" y="556.8" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-22)">Space&#160;separated&#160;list&#160;of&#160;test&#160;types&#160;that&#160;
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="581.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-23)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="581.2" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-23)">(API&#160;|&#160;Always&#160;|&#160;BranchExternalPython&#160;|&#160;BranchPythonVenv&#160;|&#160;CLI&#160;|&#160;Core&#160;|&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-t [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="605.6" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-24)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="605.6" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-24)">ExternalPython&#160;|&#160;Operators&#160;|&#160;Other&#160;|&#160;PlainAsserts&#160;|&#160;Providers&#160;|&#160;PythonVenv&#160;|&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-testing-tests-r5" x="1451.8" y="605.6"  [...]
-</text><text class="breeze-testing-tests-r5" x="0" y="630" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-25)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="630" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-25)">Serialization&#160;|&#160;WWW)&#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-testing-tests-r5" x="0" y="630" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-25)">│</text><text 
class="breeze-testing-tests-r7" x="439.2" y="630" textLength="1000.4" 
clip-path="url(#breeze-testing-tests-line-25)">Serialization&#160;|&#160;TaskSDK&#160;|&#160;WWW)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="654.4" textLength="1464" 
clip-path="url(#breeze-testing-tests-line-26)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-testing-tests-r1" x="1464" y="654.4" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-26)">
 </text><text class="breeze-testing-tests-r5" x="0" y="678.8" textLength="24.4" 
clip-path="url(#breeze-testing-tests-line-27)">╭─</text><text 
class="breeze-testing-tests-r5" x="24.4" y="678.8" textLength="170.8" 
clip-path="url(#breeze-testing-tests-line-27)">&#160;Test&#160;options&#160;</text><text
 class="breeze-testing-tests-r5" x="195.2" y="678.8" textLength="1244.4" 
clip-path="url(#breeze-testing-tests-line-27)">─────────────────────────────────────────────────────────────────────────
 [...]
 </text><text class="breeze-testing-tests-r5" x="0" y="703.2" textLength="12.2" 
clip-path="url(#breeze-testing-tests-line-28)">│</text><text 
class="breeze-testing-tests-r4" x="24.4" y="703.2" textLength="170.8" 
clip-path="url(#breeze-testing-tests-line-28)">--test-timeout</text><text 
class="breeze-testing-tests-r1" x="353.8" y="703.2" textLength="1085.8" 
clip-path="url(#breeze-testing-tests-line-28)">Test&#160;timeout&#160;in&#160;seconds.&#160;Set&#160;the&#160;pytest&#160;setup,&#160;ex
 [...]
diff --git a/dev/breeze/doc/images/output_testing_tests.txt 
b/dev/breeze/doc/images/output_testing_tests.txt
index d19f6cf5abd..ce894444f7f 100644
--- a/dev/breeze/doc/images/output_testing_tests.txt
+++ b/dev/breeze/doc/images/output_testing_tests.txt
@@ -1 +1 @@
-15002aa129ce25039921f800fb1cf744
+c131a2a8ab980041a1a0f5e91fe58ea8
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 95ecf30144a..a56947f026f 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -338,10 +338,16 @@ class DistributionPackageInfo(NamedTuple):
 
     @classmethod
     def dist_packages(
-        cls, *, package_format: str, dist_directory: Path, build_type: 
Literal["airflow", "providers"]
+        cls,
+        *,
+        package_format: str,
+        dist_directory: Path,
+        build_type: Literal["airflow", "providers", "task-sdk"],
     ) -> tuple[DistributionPackageInfo, ...]:
         if build_type == "airflow":
             default_glob_pattern = "apache[_-]airflow-[0-9]"
+        elif build_type == "task-sdk":
+            default_glob_pattern = "apache[_-]airflow[_-]task[_-]sdk"
         else:
             default_glob_pattern = "apache[_-]airflow[_-]providers"
         dists_info = []
@@ -549,6 +555,105 @@ def prepare_airflow_packages(
     get_console().print("[success]Successfully prepared Airflow packages")
 
 
+TASK_SDK_DIR_PATH = AIRFLOW_SOURCES_ROOT / "task_sdk"
+TASK_SDK_DIST_DIR_PATH = TASK_SDK_DIR_PATH / "dist"
+
+
+@release_management.command(
+    name="prepare-task-sdk-package",
+    help="Prepare sdist/whl package of Airflow Task SDK.",
+)
+@option_package_format
+@option_use_local_hatch
+@option_verbose
+@option_dry_run
+def prepare_airflow_task_sdk_packages(
+    package_format: str,
+    use_local_hatch: bool,
+):
+    check_python_version()
+    perform_environment_checks()
+    fix_ownership_using_docker()
+    cleanup_python_generated_files()
+
+    def _build_package_with_hatch(package_format: str):
+        command = [
+            "hatch",
+            "build",
+            "-c",
+        ]
+        if package_format == "sdist" or package_format == "both":
+            command += ["-t", "sdist"]
+        if package_format == "wheel" or package_format == "both":
+            command += ["-t", "wheel"]
+        env_copy = os.environ.copy()
+        run_command(
+            cmd=command,
+            cwd=TASK_SDK_DIR_PATH,
+            env=env_copy,
+            check=True,
+        )
+        shutil.copytree(TASK_SDK_DIST_DIR_PATH, DIST_DIR, dirs_exist_ok=True)
+
+    def _build_package_with_docker(package_format: str):
+        _build_local_build_image()
+        command = "hatch build -c "
+        if package_format == "sdist" or package_format == "both":
+            command += "-t sdist "
+        if package_format == "wheel" or package_format == "both":
+            command += "-t wheel "
+        container_id = f"airflow-task-sdk-build-{random.getrandbits(64):08x}"
+        result = run_command(
+            cmd=[
+                "docker",
+                "run",
+                "--name",
+                container_id,
+                "-t",
+                "-e",
+                "HOME=/opt/airflow/files/home",
+                "-e",
+                "GITHUB_ACTIONS",
+                "-w",
+                "/opt/airflow/task_sdk",
+                AIRFLOW_BUILD_IMAGE_TAG,
+                "bash",
+                "-c",
+                command,
+            ],
+            check=False,
+        )
+        if result.returncode != 0:
+            get_console().print("[error]Error preparing Airflow Task SDK[/]")
+            fix_ownership_using_docker()
+            sys.exit(result.returncode)
+        DIST_DIR.mkdir(parents=True, exist_ok=True)
+        get_console().print()
+        # Copy all files in the dist directory in container to the host dist 
directory (note '/.' in SRC)
+        run_command(["docker", "cp", 
f"{container_id}:/opt/airflow/task_sdk/dist/.", "./dist"], check=True)
+        run_command(["docker", "rm", "--force", container_id], check=False, 
stdout=DEVNULL, stderr=DEVNULL)
+
+    if use_local_hatch:
+        _build_package_with_hatch(
+            package_format=package_format,
+        )
+        get_console().print("[info]Checking if sdist packages can be built 
into wheels[/]")
+        packages = DistributionPackageInfo.dist_packages(
+            package_format=package_format, dist_directory=DIST_DIR, 
build_type="task-sdk"
+        )
+        get_console().print()
+        _check_sdist_to_wheel_dists(packages)
+        get_console().print("\n[info]Packages available in dist:[/]\n")
+        for dist_info in packages:
+            get_console().print(str(dist_info))
+        get_console().print()
+    else:
+        _build_package_with_docker(
+            package_format=package_format,
+        )
+    get_console().print("[success]Successfully prepared Airflow Task SDK 
packages")
+
+
 def provider_action_summary(description: str, message_type: MessageType, 
packages: list[str]):
     if packages:
         get_console().print(f"{description}: {len(packages)}\n")
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 6030848444b..b232666aba7 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
@@ -52,6 +52,12 @@ RELEASE_PROVIDERS_COMMANDS: dict[str, str | list[str]] = {
     ],
 }
 
+RELEASE_AIRFLOW_TASK_SDK_COMMANDS: dict[str, str | list[str]] = {
+    "name": "Airflow Task SDK release commands",
+    "commands": [
+        "prepare-task-sdk-package",
+    ],
+}
 
 RELEASE_OTHER_COMMANDS: dict[str, str | list[str]] = {
     "name": "Other release commands",
@@ -83,6 +89,15 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str, str 
| list[str]]]] = {
             ],
         }
     ],
+    "breeze release-management prepare-task-sdk-package": [
+        {
+            "name": "Package flags",
+            "options": [
+                "--package-format",
+                "--use-local-hatch",
+            ],
+        }
+    ],
     "breeze release-management prepare-helm-chart-tarball": [
         {
             "name": "Package flags",
diff --git a/dev/breeze/src/airflow_breeze/global_constants.py 
b/dev/breeze/src/airflow_breeze/global_constants.py
index 64bf8112112..3879c121433 100644
--- a/dev/breeze/src/airflow_breeze/global_constants.py
+++ b/dev/breeze/src/airflow_breeze/global_constants.py
@@ -185,6 +185,7 @@ class SelectiveUnitTestTypes(Enum):
     PLAIN_ASSERTS = "PlainAsserts"
     PROVIDERS = "Providers"
     PYTHON_VENV = "PythonVenv"
+    TASK_SDK = "TaskSDK"
     WWW = "WWW"
 
 
@@ -218,6 +219,23 @@ ALLOWED_HELM_TEST_PACKAGES = [
     *all_helm_test_packages(),
 ]
 
+
+@cache
+def all_task_sdk_test_packages() -> list[str]:
+    return sorted(
+        [
+            candidate.name
+            for candidate in (AIRFLOW_SOURCES_ROOT / "task_sdk" / 
"tests").iterdir()
+            if candidate.is_dir() and candidate.name != "__pycache__"
+        ]
+    )
+
+
+ALLOWED_TASK_SDK_TEST_PACKAGES = [
+    "all",
+    *all_task_sdk_test_packages(),
+]
+
 ALLOWED_PACKAGE_FORMATS = ["wheel", "sdist", "both"]
 ALLOWED_INSTALLATION_PACKAGE_FORMATS = ["wheel", "sdist"]
 ALLOWED_INSTALLATION_METHODS = [".", "apache-airflow"]
diff --git a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py 
b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
index 618d064e0e4..164a1583e1f 100644
--- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
@@ -93,6 +93,7 @@ VOLUMES_FOR_SELECTED_MOUNTS = [
     ("hooks", "/opt/airflow/hooks"),
     ("logs", "/root/airflow/logs"),
     ("providers", "/opt/airflow/providers"),
+    ("task_sdk", "/opt/airflow/task_sdk"),
     ("pyproject.toml", "/opt/airflow/pyproject.toml"),
     ("scripts", "/opt/airflow/scripts"),
     ("scripts/docker/entrypoint_ci.sh", "/entrypoint"),
diff --git a/dev/breeze/src/airflow_breeze/utils/run_tests.py 
b/dev/breeze/src/airflow_breeze/utils/run_tests.py
index 23fe5b6e196..acde9d0cc4d 100644
--- a/dev/breeze/src/airflow_breeze/utils/run_tests.py
+++ b/dev/breeze/src/airflow_breeze/utils/run_tests.py
@@ -169,6 +169,7 @@ TEST_TYPE_MAP_TO_PYTEST_ARGS: dict[str, list[str]] = {
         "tests/serialization",
     ],
     "System": ["tests/system"],
+    "TaskSDK": ["task_sdk/tests"],
     "WWW": [
         "tests/www",
     ],
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 18458af5f8a..0cb69a19471 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -87,12 +87,12 @@ ALL_CI_SELECTIVE_TEST_TYPES = (
     "API Always BranchExternalPython BranchPythonVenv "
     "CLI Core ExternalPython Operators Other PlainAsserts "
     "Providers[-amazon,google] Providers[amazon] Providers[google] "
-    "PythonVenv Serialization WWW"
+    "PythonVenv Serialization TaskSDK WWW"
 )
 
 ALL_CI_SELECTIVE_TEST_TYPES_WITHOUT_PROVIDERS = (
     "API Always BranchExternalPython BranchPythonVenv CLI Core "
-    "ExternalPython Operators Other PlainAsserts PythonVenv Serialization WWW"
+    "ExternalPython Operators Other PlainAsserts PythonVenv Serialization 
TaskSDK WWW"
 )
 ALL_PROVIDERS_SELECTIVE_TEST_TYPES = "Providers[-amazon,google] 
Providers[amazon] Providers[google]"
 
@@ -112,6 +112,7 @@ class FileGroupForCi(Enum):
     LEGACY_WWW_FILES = "legacy_www_files"
     SYSTEM_TEST_FILES = "system_tests"
     KUBERNETES_FILES = "kubernetes_files"
+    TASK_SDK_FILES = "task_sdk_files"
     ALL_PYTHON_FILES = "all_python_files"
     ALL_SOURCE_FILES = "all_sources_for_tests"
     ALL_AIRFLOW_PYTHON_FILES = "all_airflow_python_files"
@@ -227,6 +228,8 @@ CI_FILE_GROUP_MATCHES = HashableDict(
             r"^chart",
             r"^providers/src/",
             r"^providers/tests/",
+            r"^task_sdk/src/",
+            r"^task_sdk/tests/",
             r"^tests",
             r"^kubernetes_tests",
         ],
@@ -243,6 +246,10 @@ CI_FILE_GROUP_MATCHES = HashableDict(
             r"^tests/utils/",
             r"^dev/tests_common/.*\.py$",
         ],
+        FileGroupForCi.TASK_SDK_FILES: [
+            r"^task_sdk/src/airflow/sdk/.*\.py$",
+            r"^task_sdk/tests/.*\.py$",
+        ],
     }
 )
 
@@ -258,6 +265,8 @@ CI_FILE_GROUP_EXCLUDES = HashableDict(
             r"^providers/tests/.*",
             r"^providers/tests/system/.*",
             r"^tests/dags/test_imports.py",
+            r"^task_sdk/src/airflow/sdk/.*\.py$",
+            r"^task_sdk/tests/.*\.py$",
         ]
     }
 )
@@ -296,6 +305,10 @@ TEST_TYPE_MATCHES = HashableDict(
             r"^airflow/serialization/",
             r"^tests/serialization/",
         ],
+        SelectiveUnitTestTypes.TASK_SDK: [
+            r"^task_sdk/src/airflow/sdk/",
+            r"^task_sdk/tests/",
+        ],
         SelectiveUnitTestTypes.PYTHON_VENV: PYTHON_OPERATOR_FILES,
         SelectiveUnitTestTypes.BRANCH_PYTHON_VENV: PYTHON_OPERATOR_FILES,
         SelectiveUnitTestTypes.EXTERNAL_PYTHON: PYTHON_OPERATOR_FILES,
@@ -700,6 +713,10 @@ class SelectiveChecks:
             or "Providers" in self.parallel_test_types_list_as_string.split(" 
")
         )
 
+    @cached_property
+    def run_task_sdk_tests(self) -> bool:
+        return self._should_be_run(FileGroupForCi.TASK_SDK_FILES)
+
     @cached_property
     def run_kubernetes_tests(self) -> bool:
         return self._should_be_run(FileGroupForCi.KUBERNETES_FILES)
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index be3922d4619..6d031f70b87 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -1140,7 +1140,7 @@ def test_full_test_needed_when_scripts_changes(files: 
tuple[str, ...], expected_
                     "separate-test-types-list-as-string": "API Always 
BranchExternalPython BranchPythonVenv "
                     "CLI Core ExternalPython Operators Other PlainAsserts "
                     + LIST_OF_ALL_PROVIDER_TESTS
-                    + " PythonVenv Serialization WWW",
+                    + " PythonVenv Serialization TaskSDK WWW",
                     "needs-mypy": "true",
                     "mypy-folders": "['airflow', 'providers', 'docs', 'dev']",
                 },
@@ -1171,10 +1171,10 @@ def test_full_test_needed_when_scripts_changes(files: 
tuple[str, ...], expected_
                     "upgrade-to-newer-dependencies": "false",
                     "parallel-test-types-list-as-string": "API Always 
BranchExternalPython "
                     "BranchPythonVenv CLI Core ExternalPython Operators Other 
PlainAsserts "
-                    "PythonVenv Serialization WWW",
+                    "PythonVenv Serialization TaskSDK WWW",
                     "separate-test-types-list-as-string": "API Always 
BranchExternalPython "
                     "BranchPythonVenv CLI Core ExternalPython Operators Other 
PlainAsserts "
-                    "PythonVenv Serialization WWW",
+                    "PythonVenv Serialization TaskSDK WWW",
                     "needs-mypy": "true",
                     "mypy-folders": "['airflow', 'docs', 'dev']",
                 },
@@ -1300,7 +1300,7 @@ def test_expected_output_full_tests_needed(
                 "upgrade-to-newer-dependencies": "false",
                 "skip-provider-tests": "true",
                 "parallel-test-types-list-as-string": "API Always 
BranchExternalPython BranchPythonVenv "
-                "CLI Core ExternalPython Operators Other PlainAsserts 
PythonVenv Serialization WWW",
+                "CLI Core ExternalPython Operators Other PlainAsserts 
PythonVenv Serialization TaskSDK WWW",
                 "needs-mypy": "true",
                 "mypy-folders": "['airflow']",
             },
@@ -1536,7 +1536,7 @@ def test_expected_output_pull_request_target(
                 "docs-list-as-string": "apache-airflow docker-stack",
                 "upgrade-to-newer-dependencies": "true",
                 "parallel-test-types-list-as-string": "API Always 
BranchExternalPython BranchPythonVenv "
-                "CLI Core ExternalPython Operators Other PlainAsserts 
PythonVenv Serialization WWW",
+                "CLI Core ExternalPython Operators Other PlainAsserts 
PythonVenv Serialization TaskSDK WWW",
                 "needs-mypy": "true",
                 "mypy-folders": "['airflow', 'docs', 'dev']",
             },
diff --git a/pyproject.toml b/pyproject.toml
index 844e1b6d3ff..6fafa7e99b0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -342,7 +342,7 @@ section-order = [
 
 # Make sure we put the "dev" imports at the end, not as a third-party module
 [tool.ruff.lint.isort.sections]
-testing = ["dev", "providers.tests"]
+testing = ["dev", "providers.tests", "task_sdk.tests"]
 
 [tool.ruff.lint.extend-per-file-ignores]
 "airflow/__init__.py" = ["F401", "TCH004"]
@@ -626,12 +626,14 @@ ignore_errors = true
 [tool.uv]
 dev-dependencies = [
   "local-providers",
+  "apache-airflow-task-sdk"
 ]
 
 [tool.uv.sources]
 # These names must match the names as defined in the pyproject.toml of the 
workspace items,
 # *not* the workspace folder paths
 local-providers = { workspace = true }
+apache-airflow-task-sdk = { workspace = true }
 
 [tool.uv.workspace]
-members = ["providers"]
+members = ["providers", "task_sdk"]
diff --git a/scripts/ci/docker-compose/local.yml 
b/scripts/ci/docker-compose/local.yml
index 66a4736c5fd..f0bce468941 100644
--- a/scripts/ci/docker-compose/local.yml
+++ b/scripts/ci/docker-compose/local.yml
@@ -88,6 +88,9 @@ services:
       - type: bind
         source: ../../../providers
         target: /opt/airflow/providers
+      - type: bind
+        source: ../../../task_sdk
+        target: /opt/airflow/task_sdk
       - type: bind
         source: ../../../pyproject.toml
         target: /opt/airflow/pyproject.toml
diff --git a/scripts/ci/kubernetes/k8s_requirements.txt 
b/scripts/ci/kubernetes/k8s_requirements.txt
index 1e587051f58..e04ef564127 100644
--- a/scripts/ci/kubernetes/k8s_requirements.txt
+++ b/scripts/ci/kubernetes/k8s_requirements.txt
@@ -1,3 +1,4 @@
 --constraint 
https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-3.9.txt
 -e .[devel-devscripts,devel-tests,cncf.kubernetes]
 -e ./providers
+-e ./task_sdk
diff --git a/scripts/docker/install_airflow.sh 
b/scripts/docker/install_airflow.sh
index 324bca7ccfe..769279c2cb0 100644
--- a/scripts/docker/install_airflow.sh
+++ b/scripts/docker/install_airflow.sh
@@ -48,13 +48,18 @@ function install_airflow() {
     # Determine the installation_command_flags based on 
AIRFLOW_INSTALLATION_METHOD method
     local installation_command_flags
     if [[ ${AIRFLOW_INSTALLATION_METHOD} == "." ]]; then
-        # We need _a _ file in there otherwise the editable install doesn't 
include anything in the .pth file
+        # We need _a_ file in there otherwise the editable install doesn't 
include anything in the .pth file
         mkdir -p ./providers/src/airflow/providers/
         touch ./providers/src/airflow/providers/__init__.py
-        trap 'rm -f ./providers/src/airflow/providers/__init__.py 2>/dev/null' 
EXIT
+
+        # Similarly we need _a_ file for task_sdk too
+        mkdir -p ./task_sdk/src/airflow/sdk/
+        touch ./task_sdk/src/airflow/__init__.py
+
+        trap 'rm -f ./providers/src/airflow/providers/__init__.py 
./task_sdk/src/airflow/__init__.py 2>/dev/null' EXIT
 
         # When installing from sources - we always use `--editable` mode
-        installation_command_flags="--editable 
.[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION} --editable ./providers"
+        installation_command_flags="--editable 
.[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION} --editable ./providers 
--editable ./task_sdk"
     elif [[ ${AIRFLOW_INSTALLATION_METHOD} == "apache-airflow" ]]; then
         
installation_command_flags="apache-airflow[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
     elif [[ ${AIRFLOW_INSTALLATION_METHOD} == apache-airflow\ @\ * ]]; then
diff --git a/task_sdk/README.md b/task_sdk/README.md
new file mode 100644
index 00000000000..ef14affc68c
--- /dev/null
+++ b/task_sdk/README.md
@@ -0,0 +1,18 @@
+<!--
+ 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.
+ -->
diff --git a/task_sdk/pyproject.toml b/task_sdk/pyproject.toml
new file mode 100644
index 00000000000..149a9731ce9
--- /dev/null
+++ b/task_sdk/pyproject.toml
@@ -0,0 +1,40 @@
+# 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.
+
+[project]
+name = "apache-airflow-task-sdk"
+version = "0.1.0.dev0"
+description = "Python Task SDK for Apache Airflow DAG Authors"
+#readme = "README.md"
+requires-python = ">=3.9, <3.13"
+dependencies = []
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/airflow"]
+
+[tool.ruff]
+extend = "../pyproject.toml"
+src = ["src"]
+
+[tool.ruff.lint.per-file-ignores]
+
+# Ignore Doc rules et al for anything outside of tests
+"!src/*" = ["D", "TID253", "S101", "TRY002"]
diff --git a/task_sdk/src/airflow/sdk/__init__.py 
b/task_sdk/src/airflow/sdk/__init__.py
new file mode 100644
index 00000000000..2a3e01b64bc
--- /dev/null
+++ b/task_sdk/src/airflow/sdk/__init__.py
@@ -0,0 +1,21 @@
+# 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
+
+
+def hello() -> str:
+    return "Hello from task-sdk!"
diff --git a/task_sdk/src/airflow/sdk/py.typed 
b/task_sdk/src/airflow/sdk/py.typed
new file mode 100644
index 00000000000..445548d8636
--- /dev/null
+++ b/task_sdk/src/airflow/sdk/py.typed
@@ -0,0 +1,18 @@
+# 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.
+
+# Marker file for PEP 561.  This package uses inline types.
diff --git a/task_sdk/tests/__init__.py b/task_sdk/tests/__init__.py
new file mode 100644
index 00000000000..13a83393a91
--- /dev/null
+++ b/task_sdk/tests/__init__.py
@@ -0,0 +1,16 @@
+# 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.
diff --git a/task_sdk/tests/conftest.py b/task_sdk/tests/conftest.py
new file mode 100644
index 00000000000..209fad46d7d
--- /dev/null
+++ b/task_sdk/tests/conftest.py
@@ -0,0 +1,26 @@
+# 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 pytest
+
+pytest_plugins = "dev.tests_common.pytest_plugin"
+
+
[email protected](tryfirst=True)
+def pytest_configure(config: pytest.Config) -> None:
+    config.inicfg["airflow_deprecations_ignore"] = ()
diff --git a/task_sdk/tests/test_hello.py b/task_sdk/tests/test_hello.py
new file mode 100644
index 00000000000..62cfdc069ca
--- /dev/null
+++ b/task_sdk/tests/test_hello.py
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from airflow.sdk import hello
+
+
+def test_hello():
+    assert hello() == "Hello from task-sdk!"

Reply via email to