This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch v3-0-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-0-test by this push:
new 6a95e10823b [v3-0-test] Add new `breeze run` command for
non-interactive command execution (#52370) (#52373)
6a95e10823b is described below
commit 6a95e10823be64e9cf1bebdcb17ed8469c8edc79
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Jun 28 13:00:48 2025 +0200
[v3-0-test] Add new `breeze run` command for non-interactive command
execution (#52370) (#52373)
Add a new `breeze run` command that allows running commands in the Breeze
environment without entering an interactive shell. This is useful for
automated testing, and one-off command execution which is useful for AI too.
(cherry picked from commit bb041b3e1ac4afe962faf273c7798d819b5d5351)
Co-authored-by: Kaxil Naik <[email protected]>
---
dev/breeze/doc/03_developer_tasks.rst | 50 +++++
dev/breeze/doc/images/output-commands.svg | 54 ++---
dev/breeze/doc/images/output_run.svg | 240 +++++++++++++++++++++
dev/breeze/doc/images/output_run.txt | 1 +
.../output_setup_check-all-params-in-groups.svg | 2 +-
.../output_setup_check-all-params-in-groups.txt | 2 +-
.../output_setup_regenerate-command-images.svg | 2 +-
.../output_setup_regenerate-command-images.txt | 2 +-
.../airflow_breeze/commands/developer_commands.py | 137 ++++++++++++
.../commands/developer_commands_config.py | 37 ++++
.../src/airflow_breeze/commands/setup_commands.py | 1 +
11 files changed, 499 insertions(+), 29 deletions(-)
diff --git a/dev/breeze/doc/03_developer_tasks.rst
b/dev/breeze/doc/03_developer_tasks.rst
index 9bc70819903..3a425469283 100644
--- a/dev/breeze/doc/03_developer_tasks.rst
+++ b/dev/breeze/doc/03_developer_tasks.rst
@@ -494,6 +494,56 @@ Those are all available flags of ``shell`` command:
:width: 100%
:alt: Breeze shell
+Running commands without interactive shell
+------------------------------------------
+
+For automated testing, and one-off command execution, you can use the ``breeze
run`` command
+to execute commands in the Breeze environment without entering the interactive
shell. This command is
+particularly useful when you want to run a specific command and exit
immediately, without the overhead
+of an interactive session.
+
+The ``breeze run`` command creates a fresh container that is automatically
cleaned up after the command
+completes, and each run uses a unique project name to avoid conflicts with
other instances.
+
+Here are some common examples:
+
+Running a specific test:
+
+.. code-block:: bash
+
+ breeze run pytest
providers/google/tests/unit/google/cloud/operators/test_dataflow.py -v
+
+Running Python commands:
+
+.. code-block:: bash
+
+ breeze run python -c "from airflow.providers.google.version_compat import
AIRFLOW_V_3_0_PLUS; print(AIRFLOW_V_3_0_PLUS)"
+
+Running bash commands:
+
+.. code-block:: bash
+
+ breeze run bash -c "cd /opt/airflow && python -m pytest
providers/google/tests/"
+
+Running with different Python version:
+
+.. code-block:: bash
+
+ breeze run --python 3.11 pytest
providers/standard/tests/unit/operators/test_bash.py
+
+Running with PostgreSQL backend:
+
+.. code-block:: bash
+
+ breeze run --backend postgres pytest providers/postgres/tests/
+
+Those are all available flags of ``run`` command:
+
+.. image:: ./images/output_run.svg
+ :target:
https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/images/output_run.svg
+ :width: 100%
+ :alt: Breeze run
+
Running Breeze with Metrics
---------------------------
diff --git a/dev/breeze/doc/images/output-commands.svg
b/dev/breeze/doc/images/output-commands.svg
index 234bfa5ee81..3589844031e 100644
--- a/dev/breeze/doc/images/output-commands.svg
+++ b/dev/breeze/doc/images/output-commands.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 2172.7999999999997"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 2197.2"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-help-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="2121.7999999999997" />
+ <rect x="0" y="0" width="1463.0" height="2146.2" />
</clipPath>
<clipPath id="breeze-help-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -303,9 +303,12 @@
<clipPath id="breeze-help-line-85">
<rect x="0" y="2075.5" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-help-line-86">
+ <rect x="0" y="2099.9" width="1464" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="2170.8" rx="8"/><text
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Breeze commands</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="2195.2" rx="8"/><text
class="breeze-help-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Breeze commands</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -380,28 +383,29 @@
</text><text class="breeze-help-r5" x="0" y="1532.8" textLength="12.2"
clip-path="url(#breeze-help-line-62)">│</text><text class="breeze-help-r4"
x="24.4" y="1532.8" textLength="280.6"
clip-path="url(#breeze-help-line-62)">down                   </text><text
class="breeze-help-r1" x="329.4" y="1532.8" textLength="1110.2"
clip-path="url(#breeze-help-line-62)">Stop running breeze e [...]
</text><text class="breeze-help-r5" x="0" y="1557.2" textLength="12.2"
clip-path="url(#breeze-help-line-63)">│</text><text class="breeze-help-r4"
x="24.4" y="1557.2" textLength="280.6"
clip-path="url(#breeze-help-line-63)">shell                  </text><text
class="breeze-help-r1" x="329.4" y="1557.2" textLength="1110.2"
clip-path="url(#breeze-help-line-63)">Enter breeze environment. 
[...]
</text><text class="breeze-help-r5" x="0" y="1581.6" textLength="12.2"
clip-path="url(#breeze-help-line-64)">│</text><text class="breeze-help-r4"
x="24.4" y="1581.6" textLength="280.6"
clip-path="url(#breeze-help-line-64)">exec                   </text><text
class="breeze-help-r1" x="329.4" y="1581.6" textLength="1110.2"
clip-path="url(#breeze-help-line-64)">Joins the interactive  [...]
-</text><text class="breeze-help-r5" x="0" y="1606" textLength="12.2"
clip-path="url(#breeze-help-line-65)">│</text><text class="breeze-help-r4"
x="24.4" y="1606" textLength="280.6"
clip-path="url(#breeze-help-line-65)">compile-ui-assets      </text><text
class="breeze-help-r1" x="329.4" y="1606" textLength="1110.2"
clip-path="url(#breeze-help-line-65)">Compiles ui assets.             
[...]
-</text><text class="breeze-help-r5" x="0" y="1630.4" textLength="12.2"
clip-path="url(#breeze-help-line-66)">│</text><text class="breeze-help-r4"
x="24.4" y="1630.4" textLength="280.6"
clip-path="url(#breeze-help-line-66)">cleanup                </text><text
class="breeze-help-r1" x="329.4" y="1630.4" textLength="1110.2"
clip-path="url(#breeze-help-line-66)">Cleans the cache of parameters,
[...]
-</text><text class="breeze-help-r5" x="0" y="1654.8" textLength="12.2"
clip-path="url(#breeze-help-line-67)">│</text><text class="breeze-help-r4"
x="24.4" y="1654.8" textLength="280.6"
clip-path="url(#breeze-help-line-67)">generate-migration-file</text><text
class="breeze-help-r1" x="329.4" y="1654.8" textLength="1110.2"
clip-path="url(#breeze-help-line-67)">Autogenerate the alembic migration file for the ORM changes.     &
[...]
-</text><text class="breeze-help-r5" x="0" y="1679.2" textLength="12.2"
clip-path="url(#breeze-help-line-68)">│</text><text class="breeze-help-r4"
x="24.4" y="1679.2" textLength="280.6"
clip-path="url(#breeze-help-line-68)">doctor                 </text><text
class="breeze-help-r1" x="329.4" y="1679.2" textLength="1110.2"
clip-path="url(#breeze-help-line-68)">Auto-healing of breeze  &#
[...]
-</text><text class="breeze-help-r5" x="0" y="1703.6" textLength="1464"
clip-path="url(#breeze-help-line-69)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="1703.6" textLength="12.2"
clip-path="url(#breeze-help-line-69)">
-</text><text class="breeze-help-r5" x="0" y="1728" textLength="24.4"
clip-path="url(#breeze-help-line-70)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1728" textLength="219.6"
clip-path="url(#breeze-help-line-70)"> Testing commands </text><text
class="breeze-help-r5" x="244" y="1728" textLength="1195.6"
clip-path="url(#breeze-help-line-70)">──────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-hel [...]
-</text><text class="breeze-help-r5" x="0" y="1752.4" textLength="12.2"
clip-path="url(#breeze-help-line-71)">│</text><text class="breeze-help-r4"
x="24.4" y="1752.4" textLength="183"
clip-path="url(#breeze-help-line-71)">testing        </text><text
class="breeze-help-r1" x="231.8" y="1752.4" textLength="1207.8"
clip-path="url(#breeze-help-line-71)">Tools that developers can use to run tests    
[...]
-</text><text class="breeze-help-r5" x="0" y="1776.8" textLength="12.2"
clip-path="url(#breeze-help-line-72)">│</text><text class="breeze-help-r4"
x="24.4" y="1776.8" textLength="183"
clip-path="url(#breeze-help-line-72)">k8s            </text><text
class="breeze-help-r1" x="231.8" y="1776.8" textLength="1207.8"
clip-path="url(#breeze-help-line-72)">Tools that developers use to run Kubernetes te
[...]
-</text><text class="breeze-help-r5" x="0" y="1801.2" textLength="1464"
clip-path="url(#breeze-help-line-73)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="1801.2" textLength="12.2"
clip-path="url(#breeze-help-line-73)">
-</text><text class="breeze-help-r5" x="0" y="1825.6" textLength="24.4"
clip-path="url(#breeze-help-line-74)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1825.6" textLength="195.2"
clip-path="url(#breeze-help-line-74)"> Image commands </text><text
class="breeze-help-r5" x="219.6" y="1825.6" textLength="1220"
clip-path="url(#breeze-help-line-74)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
-</text><text class="breeze-help-r5" x="0" y="1850" textLength="12.2"
clip-path="url(#breeze-help-line-75)">│</text><text class="breeze-help-r4"
x="24.4" y="1850" textLength="207.4"
clip-path="url(#breeze-help-line-75)">ci-image         </text><text
class="breeze-help-r1" x="256.2" y="1850" textLength="1183.4"
clip-path="url(#breeze-help-line-75)">Tools that developers can use to manually manage CI i
[...]
-</text><text class="breeze-help-r5" x="0" y="1874.4" textLength="12.2"
clip-path="url(#breeze-help-line-76)">│</text><text class="breeze-help-r4"
x="24.4" y="1874.4" textLength="207.4"
clip-path="url(#breeze-help-line-76)">prod-image       </text><text
class="breeze-help-r1" x="256.2" y="1874.4" textLength="1183.4"
clip-path="url(#breeze-help-line-76)">Tools that developers can use to manually manage PROD ima
[...]
-</text><text class="breeze-help-r5" x="0" y="1898.8" textLength="1464"
clip-path="url(#breeze-help-line-77)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="1898.8" textLength="12.2"
clip-path="url(#breeze-help-line-77)">
-</text><text class="breeze-help-r5" x="0" y="1923.2" textLength="24.4"
clip-path="url(#breeze-help-line-78)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1923.2" textLength="353.8"
clip-path="url(#breeze-help-line-78)"> Release management commands </text><text
class="breeze-help-r5" x="378.2" y="1923.2" textLength="1061.4"
clip-path="url(#breeze-help-line-78)">───────────────────────────────────────────────────────────────────────────────────────</text><text
clas [...]
-</text><text class="breeze-help-r5" x="0" y="1947.6" textLength="12.2"
clip-path="url(#breeze-help-line-79)">│</text><text class="breeze-help-r4"
x="24.4" y="1947.6" textLength="280.6"
clip-path="url(#breeze-help-line-79)">release-management     </text><text
class="breeze-help-r1" x="329.4" y="1947.6" textLength="1110.2"
clip-path="url(#breeze-help-line-79)">Tools that release managers can use to prepare and manage
[...]
-</text><text class="breeze-help-r5" x="0" y="1972" textLength="12.2"
clip-path="url(#breeze-help-line-80)">│</text><text class="breeze-help-r4"
x="24.4" y="1972" textLength="280.6"
clip-path="url(#breeze-help-line-80)">sbom                   </text><text
class="breeze-help-r1" x="329.4" y="1972" textLength="1110.2"
clip-path="url(#breeze-help-line-80)">Tools that release managers
[...]
-</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="12.2"
clip-path="url(#breeze-help-line-81)">│</text><text class="breeze-help-r4"
x="24.4" y="1996.4" textLength="280.6"
clip-path="url(#breeze-help-line-81)">workflow-run           </text><text
class="breeze-help-r1" x="329.4" y="1996.4" textLength="1110.2"
clip-path="url(#breeze-help-line-81)">Tools to manage Airflow repository workflows &
[...]
-</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="1464"
clip-path="url(#breeze-help-line-82)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2020.8" textLength="12.2"
clip-path="url(#breeze-help-line-82)">
-</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="24.4"
clip-path="url(#breeze-help-line-83)">╭─</text><text class="breeze-help-r5"
x="24.4" y="2045.2" textLength="195.2"
clip-path="url(#breeze-help-line-83)"> Other commands </text><text
class="breeze-help-r5" x="219.6" y="2045.2" textLength="1220"
clip-path="url(#breeze-help-line-83)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
-</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="12.2"
clip-path="url(#breeze-help-line-84)">│</text><text class="breeze-help-r4"
x="24.4" y="2069.6" textLength="122"
clip-path="url(#breeze-help-line-84)">setup     </text><text
class="breeze-help-r1" x="170.8" y="2069.6" textLength="1268.8"
clip-path="url(#breeze-help-line-84)">Tools that developers can use to configure Breeze      &
[...]
-</text><text class="breeze-help-r5" x="0" y="2094" textLength="12.2"
clip-path="url(#breeze-help-line-85)">│</text><text class="breeze-help-r4"
x="24.4" y="2094" textLength="122"
clip-path="url(#breeze-help-line-85)">ci        </text><text
class="breeze-help-r1" x="170.8" y="2094" textLength="1268.8"
clip-path="url(#breeze-help-line-85)">Tools that CI workflows use to cleanup/manage CI environment  
[...]
-</text><text class="breeze-help-r5" x="0" y="2118.4" textLength="1464"
clip-path="url(#breeze-help-line-86)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2118.4" textLength="12.2"
clip-path="url(#breeze-help-line-86)">
+</text><text class="breeze-help-r5" x="0" y="1606" textLength="12.2"
clip-path="url(#breeze-help-line-65)">│</text><text class="breeze-help-r4"
x="24.4" y="1606" textLength="280.6"
clip-path="url(#breeze-help-line-65)">run                    </text><text
class="breeze-help-r1" x="329.4" y="1606" textLength="1110.2"
clip-path="url(#breeze-help-line-65)">Run a command in 
[...]
+</text><text class="breeze-help-r5" x="0" y="1630.4" textLength="12.2"
clip-path="url(#breeze-help-line-66)">│</text><text class="breeze-help-r4"
x="24.4" y="1630.4" textLength="280.6"
clip-path="url(#breeze-help-line-66)">compile-ui-assets      </text><text
class="breeze-help-r1" x="329.4" y="1630.4" textLength="1110.2"
clip-path="url(#breeze-help-line-66)">Compiles ui assets.            
[...]
+</text><text class="breeze-help-r5" x="0" y="1654.8" textLength="12.2"
clip-path="url(#breeze-help-line-67)">│</text><text class="breeze-help-r4"
x="24.4" y="1654.8" textLength="280.6"
clip-path="url(#breeze-help-line-67)">cleanup                </text><text
class="breeze-help-r1" x="329.4" y="1654.8" textLength="1110.2"
clip-path="url(#breeze-help-line-67)">Cleans the cache of parameters,
[...]
+</text><text class="breeze-help-r5" x="0" y="1679.2" textLength="12.2"
clip-path="url(#breeze-help-line-68)">│</text><text class="breeze-help-r4"
x="24.4" y="1679.2" textLength="280.6"
clip-path="url(#breeze-help-line-68)">generate-migration-file</text><text
class="breeze-help-r1" x="329.4" y="1679.2" textLength="1110.2"
clip-path="url(#breeze-help-line-68)">Autogenerate the alembic migration file for the ORM changes.     &
[...]
+</text><text class="breeze-help-r5" x="0" y="1703.6" textLength="12.2"
clip-path="url(#breeze-help-line-69)">│</text><text class="breeze-help-r4"
x="24.4" y="1703.6" textLength="280.6"
clip-path="url(#breeze-help-line-69)">doctor                 </text><text
class="breeze-help-r1" x="329.4" y="1703.6" textLength="1110.2"
clip-path="url(#breeze-help-line-69)">Auto-healing of breeze  &#
[...]
+</text><text class="breeze-help-r5" x="0" y="1728" textLength="1464"
clip-path="url(#breeze-help-line-70)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="1728" textLength="12.2"
clip-path="url(#breeze-help-line-70)">
+</text><text class="breeze-help-r5" x="0" y="1752.4" textLength="24.4"
clip-path="url(#breeze-help-line-71)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1752.4" textLength="219.6"
clip-path="url(#breeze-help-line-71)"> Testing commands </text><text
class="breeze-help-r5" x="244" y="1752.4" textLength="1195.6"
clip-path="url(#breeze-help-line-71)">──────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
+</text><text class="breeze-help-r5" x="0" y="1776.8" textLength="12.2"
clip-path="url(#breeze-help-line-72)">│</text><text class="breeze-help-r4"
x="24.4" y="1776.8" textLength="183"
clip-path="url(#breeze-help-line-72)">testing        </text><text
class="breeze-help-r1" x="231.8" y="1776.8" textLength="1207.8"
clip-path="url(#breeze-help-line-72)">Tools that developers can use to run tests    
[...]
+</text><text class="breeze-help-r5" x="0" y="1801.2" textLength="12.2"
clip-path="url(#breeze-help-line-73)">│</text><text class="breeze-help-r4"
x="24.4" y="1801.2" textLength="183"
clip-path="url(#breeze-help-line-73)">k8s            </text><text
class="breeze-help-r1" x="231.8" y="1801.2" textLength="1207.8"
clip-path="url(#breeze-help-line-73)">Tools that developers use to run Kubernetes te
[...]
+</text><text class="breeze-help-r5" x="0" y="1825.6" textLength="1464"
clip-path="url(#breeze-help-line-74)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="1825.6" textLength="12.2"
clip-path="url(#breeze-help-line-74)">
+</text><text class="breeze-help-r5" x="0" y="1850" textLength="24.4"
clip-path="url(#breeze-help-line-75)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1850" textLength="195.2"
clip-path="url(#breeze-help-line-75)"> Image commands </text><text
class="breeze-help-r5" x="219.6" y="1850" textLength="1220"
clip-path="url(#breeze-help-line-75)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-hel [...]
+</text><text class="breeze-help-r5" x="0" y="1874.4" textLength="12.2"
clip-path="url(#breeze-help-line-76)">│</text><text class="breeze-help-r4"
x="24.4" y="1874.4" textLength="207.4"
clip-path="url(#breeze-help-line-76)">ci-image         </text><text
class="breeze-help-r1" x="256.2" y="1874.4" textLength="1183.4"
clip-path="url(#breeze-help-line-76)">Tools that developers can use to manually manage CI&
[...]
+</text><text class="breeze-help-r5" x="0" y="1898.8" textLength="12.2"
clip-path="url(#breeze-help-line-77)">│</text><text class="breeze-help-r4"
x="24.4" y="1898.8" textLength="207.4"
clip-path="url(#breeze-help-line-77)">prod-image       </text><text
class="breeze-help-r1" x="256.2" y="1898.8" textLength="1183.4"
clip-path="url(#breeze-help-line-77)">Tools that developers can use to manually manage PROD ima
[...]
+</text><text class="breeze-help-r5" x="0" y="1923.2" textLength="1464"
clip-path="url(#breeze-help-line-78)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="1923.2" textLength="12.2"
clip-path="url(#breeze-help-line-78)">
+</text><text class="breeze-help-r5" x="0" y="1947.6" textLength="24.4"
clip-path="url(#breeze-help-line-79)">╭─</text><text class="breeze-help-r5"
x="24.4" y="1947.6" textLength="353.8"
clip-path="url(#breeze-help-line-79)"> Release management commands </text><text
class="breeze-help-r5" x="378.2" y="1947.6" textLength="1061.4"
clip-path="url(#breeze-help-line-79)">───────────────────────────────────────────────────────────────────────────────────────</text><text
clas [...]
+</text><text class="breeze-help-r5" x="0" y="1972" textLength="12.2"
clip-path="url(#breeze-help-line-80)">│</text><text class="breeze-help-r4"
x="24.4" y="1972" textLength="280.6"
clip-path="url(#breeze-help-line-80)">release-management     </text><text
class="breeze-help-r1" x="329.4" y="1972" textLength="1110.2"
clip-path="url(#breeze-help-line-80)">Tools that release managers can use to prepare and manage Airf
[...]
+</text><text class="breeze-help-r5" x="0" y="1996.4" textLength="12.2"
clip-path="url(#breeze-help-line-81)">│</text><text class="breeze-help-r4"
x="24.4" y="1996.4" textLength="280.6"
clip-path="url(#breeze-help-line-81)">sbom                   </text><text
class="breeze-help-r1" x="329.4" y="1996.4" textLength="1110.2"
clip-path="url(#breeze-help-line-81)">Tools that release ma [...]
+</text><text class="breeze-help-r5" x="0" y="2020.8" textLength="12.2"
clip-path="url(#breeze-help-line-82)">│</text><text class="breeze-help-r4"
x="24.4" y="2020.8" textLength="280.6"
clip-path="url(#breeze-help-line-82)">workflow-run           </text><text
class="breeze-help-r1" x="329.4" y="2020.8" textLength="1110.2"
clip-path="url(#breeze-help-line-82)">Tools to manage Airflow repository workflows &
[...]
+</text><text class="breeze-help-r5" x="0" y="2045.2" textLength="1464"
clip-path="url(#breeze-help-line-83)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2045.2" textLength="12.2"
clip-path="url(#breeze-help-line-83)">
+</text><text class="breeze-help-r5" x="0" y="2069.6" textLength="24.4"
clip-path="url(#breeze-help-line-84)">╭─</text><text class="breeze-help-r5"
x="24.4" y="2069.6" textLength="195.2"
clip-path="url(#breeze-help-line-84)"> Other commands </text><text
class="breeze-help-r5" x="219.6" y="2069.6" textLength="1220"
clip-path="url(#breeze-help-line-84)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
+</text><text class="breeze-help-r5" x="0" y="2094" textLength="12.2"
clip-path="url(#breeze-help-line-85)">│</text><text class="breeze-help-r4"
x="24.4" y="2094" textLength="122"
clip-path="url(#breeze-help-line-85)">setup     </text><text
class="breeze-help-r1" x="170.8" y="2094" textLength="1268.8"
clip-path="url(#breeze-help-line-85)">Tools that developers can use to configure Breeze       &
[...]
+</text><text class="breeze-help-r5" x="0" y="2118.4" textLength="12.2"
clip-path="url(#breeze-help-line-86)">│</text><text class="breeze-help-r4"
x="24.4" y="2118.4" textLength="122"
clip-path="url(#breeze-help-line-86)">ci        </text><text
class="breeze-help-r1" x="170.8" y="2118.4" textLength="1268.8"
clip-path="url(#breeze-help-line-86)">Tools that CI workflows use to cleanup/manage CI environment 
[...]
+</text><text class="breeze-help-r5" x="0" y="2142.8" textLength="1464"
clip-path="url(#breeze-help-line-87)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-help-r1" x="1464" y="2142.8" textLength="12.2"
clip-path="url(#breeze-help-line-87)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_run.svg
b/dev/breeze/doc/images/output_run.svg
new file mode 100644
index 00000000000..b672a174b29
--- /dev/null
+++ b/dev/breeze/doc/images/output_run.svg
@@ -0,0 +1,240 @@
+<svg class="rich-terminal" viewBox="0 0 1482 1148.0"
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-run-matrix {
+ font-family: Fira Code, monospace;
+ font-size: 20px;
+ line-height: 24.4px;
+ font-variant-east-asian: full-width;
+ }
+
+ .breeze-run-title {
+ font-size: 18px;
+ font-weight: bold;
+ font-family: arial;
+ }
+
+ .breeze-run-r1 { fill: #c5c8c6 }
+.breeze-run-r2 { fill: #d0b344 }
+.breeze-run-r3 { fill: #c5c8c6;font-weight: bold }
+.breeze-run-r4 { fill: #68a0b3;font-weight: bold }
+.breeze-run-r5 { fill: #868887 }
+.breeze-run-r6 { fill: #98a84b;font-weight: bold }
+.breeze-run-r7 { fill: #8d7b39 }
+ </style>
+
+ <defs>
+ <clipPath id="breeze-run-clip-terminal">
+ <rect x="0" y="0" width="1463.0" height="1097.0" />
+ </clipPath>
+ <clipPath id="breeze-run-line-0">
+ <rect x="0" y="1.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-1">
+ <rect x="0" y="25.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-2">
+ <rect x="0" y="50.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-3">
+ <rect x="0" y="74.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-4">
+ <rect x="0" y="99.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-5">
+ <rect x="0" y="123.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-6">
+ <rect x="0" y="147.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-7">
+ <rect x="0" y="172.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-8">
+ <rect x="0" y="196.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-9">
+ <rect x="0" y="221.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-10">
+ <rect x="0" y="245.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-11">
+ <rect x="0" y="269.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-12">
+ <rect x="0" y="294.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-13">
+ <rect x="0" y="318.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-14">
+ <rect x="0" y="343.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-15">
+ <rect x="0" y="367.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-16">
+ <rect x="0" y="391.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-17">
+ <rect x="0" y="416.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-18">
+ <rect x="0" y="440.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-19">
+ <rect x="0" y="465.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-20">
+ <rect x="0" y="489.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-21">
+ <rect x="0" y="513.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-22">
+ <rect x="0" y="538.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-23">
+ <rect x="0" y="562.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-24">
+ <rect x="0" y="587.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-25">
+ <rect x="0" y="611.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-26">
+ <rect x="0" y="635.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-27">
+ <rect x="0" y="660.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-28">
+ <rect x="0" y="684.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-29">
+ <rect x="0" y="709.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-30">
+ <rect x="0" y="733.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-31">
+ <rect x="0" y="757.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-32">
+ <rect x="0" y="782.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-33">
+ <rect x="0" y="806.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-34">
+ <rect x="0" y="831.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-35">
+ <rect x="0" y="855.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-36">
+ <rect x="0" y="879.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-37">
+ <rect x="0" y="904.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-38">
+ <rect x="0" y="928.7" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-39">
+ <rect x="0" y="953.1" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-40">
+ <rect x="0" y="977.5" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-41">
+ <rect x="0" y="1001.9" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-42">
+ <rect x="0" y="1026.3" width="1464" height="24.65"/>
+ </clipPath>
+<clipPath id="breeze-run-line-43">
+ <rect x="0" y="1050.7" width="1464" height="24.65"/>
+ </clipPath>
+ </defs>
+
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="1146" rx="8"/><text class="breeze-run-title"
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: run</text>
+ <g transform="translate(26,22)">
+ <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+ <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+ <circle cx="44" cy="0" r="7" fill="#28c840"/>
+ </g>
+
+ <g transform="translate(9, 41)" clip-path="url(#breeze-run-clip-terminal)">
+
+ <g class="breeze-run-matrix">
+ <text class="breeze-run-r1" x="1464" y="20" textLength="12.2"
clip-path="url(#breeze-run-line-0)">
+</text><text class="breeze-run-r2" x="12.2" y="44.4" textLength="73.2"
clip-path="url(#breeze-run-line-1)">Usage:</text><text class="breeze-run-r3"
x="97.6" y="44.4" textLength="122"
clip-path="url(#breeze-run-line-1)">breeze run</text><text
class="breeze-run-r1" x="231.8" y="44.4" textLength="12.2"
clip-path="url(#breeze-run-line-1)">[</text><text class="breeze-run-r4" x="244"
y="44.4" textLength="85.4"
clip-path="url(#breeze-run-line-1)">OPTIONS</text><text class="breeze-run-r1" x
[...]
+</text><text class="breeze-run-r1" x="1464" y="68.8" textLength="12.2"
clip-path="url(#breeze-run-line-2)">
+</text><text class="breeze-run-r1" x="12.2" y="93.2" textLength="963.8"
clip-path="url(#breeze-run-line-3)">Run a command in the Breeze environment without entering the interactive shell.</text><text
class="breeze-run-r1" x="1464" y="93.2" textLength="12.2"
clip-path="url(#breeze-run-line-3)">
+</text><text class="breeze-run-r1" x="1464" y="117.6" textLength="12.2"
clip-path="url(#breeze-run-line-4)">
+</text><text class="breeze-run-r5" x="0" y="142" textLength="24.4"
clip-path="url(#breeze-run-line-5)">╭─</text><text class="breeze-run-r5"
x="24.4" y="142" textLength="231.8"
clip-path="url(#breeze-run-line-5)"> Command execution </text><text
class="breeze-run-r5" x="256.2" y="142" textLength="1183.4"
clip-path="url(#breeze-run-line-5)">─────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-run-r5" x="14 [...]
+</text><text class="breeze-run-r5" x="0" y="166.4" textLength="12.2"
clip-path="url(#breeze-run-line-6)">│</text><text class="breeze-run-r4"
x="24.4" y="166.4" textLength="97.6"
clip-path="url(#breeze-run-line-6)">--python</text><text class="breeze-run-r6"
x="268.4" y="166.4" textLength="24.4"
clip-path="url(#breeze-run-line-6)">-p</text><text class="breeze-run-r1"
x="317.2" y="166.4" textLength="732"
clip-path="url(#breeze-run-line-6)">Python major/minor version used 
[...]
+</text><text class="breeze-run-r5" x="0" y="190.8" textLength="12.2"
clip-path="url(#breeze-run-line-7)">│</text><text class="breeze-run-r5"
x="317.2" y="190.8" textLength="732"
clip-path="url(#breeze-run-line-7)">[default: 3.10]                                           
[...]
+</text><text class="breeze-run-r5" x="0" y="215.2" textLength="12.2"
clip-path="url(#breeze-run-line-8)">│</text><text class="breeze-run-r4"
x="24.4" y="215.2" textLength="109.8"
clip-path="url(#breeze-run-line-8)">--backend</text><text class="breeze-run-r6"
x="268.4" y="215.2" textLength="24.4"
clip-path="url(#breeze-run-line-8)">-b</text><text class="breeze-run-r1"
x="317.2" y="215.2" textLength="1122.4"
clip-path="url(#breeze-run-line-8)">Database backend to use. I
[...]
+</text><text class="breeze-run-r5" x="0" y="239.6" textLength="12.2"
clip-path="url(#breeze-run-line-9)">│</text><text class="breeze-run-r1"
x="317.2" y="239.6" textLength="1122.4"
clip-path="url(#breeze-run-line-9)">configuration, meaning there will be no database available, and any attempts to connect to  </text><text
class="breeze-run-r5" x="1451.8" y="239.6" textLength="12.2"
clip-path="url(#breeze-run-line-9) [...]
+</text><text class="breeze-run-r5" x="0" y="264" textLength="12.2"
clip-path="url(#breeze-run-line-10)">│</text><text class="breeze-run-r1"
x="317.2" y="264" textLength="1122.4"
clip-path="url(#breeze-run-line-10)">the Airflow database will fail.                                     
[...]
+</text><text class="breeze-run-r5" x="0" y="288.4" textLength="12.2"
clip-path="url(#breeze-run-line-11)">│</text><text class="breeze-run-r7"
x="317.2" y="288.4" textLength="1122.4"
clip-path="url(#breeze-run-line-11)">(>sqlite< | mysql | postgres | none)                                 
[...]
+</text><text class="breeze-run-r5" x="0" y="312.8" textLength="12.2"
clip-path="url(#breeze-run-line-12)">│</text><text class="breeze-run-r5"
x="317.2" y="312.8" textLength="1122.4"
clip-path="url(#breeze-run-line-12)">[default: sqlite]                                          
[...]
+</text><text class="breeze-run-r5" x="0" y="337.2" textLength="12.2"
clip-path="url(#breeze-run-line-13)">│</text><text class="breeze-run-r4"
x="24.4" y="337.2" textLength="219.6"
clip-path="url(#breeze-run-line-13)">--postgres-version</text><text
class="breeze-run-r6" x="268.4" y="337.2" textLength="24.4"
clip-path="url(#breeze-run-line-13)">-P</text><text class="breeze-run-r1"
x="317.2" y="337.2" textLength="305"
clip-path="url(#breeze-run-line-13)">Version of Postgres u [...]
+</text><text class="breeze-run-r5" x="0" y="361.6" textLength="12.2"
clip-path="url(#breeze-run-line-14)">│</text><text class="breeze-run-r4"
x="24.4" y="361.6" textLength="183"
clip-path="url(#breeze-run-line-14)">--mysql-version</text><text
class="breeze-run-r6" x="268.4" y="361.6" textLength="24.4"
clip-path="url(#breeze-run-line-14)">-M</text><text class="breeze-run-r1"
x="317.2" y="361.6" textLength="268.4"
clip-path="url(#breeze-run-line-14)">Version of MySQL used.</
[...]
+</text><text class="breeze-run-r5" x="0" y="386" textLength="1464"
clip-path="url(#breeze-run-line-15)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="386" textLength="12.2"
clip-path="url(#breeze-run-line-15)">
+</text><text class="breeze-run-r5" x="0" y="410.4" textLength="24.4"
clip-path="url(#breeze-run-line-16)">╭─</text><text class="breeze-run-r5"
x="24.4" y="410.4" textLength="500.2"
clip-path="url(#breeze-run-line-16)"> Build CI image (before running command) </text><text
class="breeze-run-r5" x="524.6" y="410.4" textLength="915"
clip-path="url(#breeze-run-line-16)">───────────────────────────────────────────────────────────────────────────</text><text
c [...]
+</text><text class="breeze-run-r5" x="0" y="434.8" textLength="12.2"
clip-path="url(#breeze-run-line-17)">│</text><text class="breeze-run-r4"
x="24.4" y="434.8" textLength="158.6"
clip-path="url(#breeze-run-line-17)">--force-build</text><text
class="breeze-run-r1" x="341.6" y="434.8" textLength="707.6"
clip-path="url(#breeze-run-line-17)">Force image build no matter if it is determined as needed.</text><text
class="breeze-run-r5" x="1451. [...]
+</text><text class="breeze-run-r5" x="0" y="459.2" textLength="12.2"
clip-path="url(#breeze-run-line-18)">│</text><text class="breeze-run-r4"
x="24.4" y="459.2" textLength="122"
clip-path="url(#breeze-run-line-18)">--platform</text><text
class="breeze-run-r1" x="341.6" y="459.2" textLength="329.4"
clip-path="url(#breeze-run-line-18)">Platform for Airflow image.</text><text
class="breeze-run-r7" x="683.2" y="459.2" textLength="707.6"
clip-path="url(#breeze-run-line-18)">(li [...]
+</text><text class="breeze-run-r5" x="0" y="483.6" textLength="12.2"
clip-path="url(#breeze-run-line-19)">│</text><text class="breeze-run-r4"
x="24.4" y="483.6" textLength="231.8"
clip-path="url(#breeze-run-line-19)">--github-repository</text><text
class="breeze-run-r6" x="292.8" y="483.6" textLength="24.4"
clip-path="url(#breeze-run-line-19)">-g</text><text class="breeze-run-r1"
x="341.6" y="483.6" textLength="585.6"
clip-path="url(#breeze-run-line-19)">GitHub repository used& [...]
+</text><text class="breeze-run-r5" x="0" y="508" textLength="12.2"
clip-path="url(#breeze-run-line-20)">│</text><text class="breeze-run-r4"
x="24.4" y="508" textLength="109.8"
clip-path="url(#breeze-run-line-20)">--builder</text><text
class="breeze-run-r1" x="341.6" y="508" textLength="756.4"
clip-path="url(#breeze-run-line-20)">Buildx builder used to perform `docker buildx build` commands.</text><text
class="breeze-run-r7" x="1110.2" y="508" textL [...]
+</text><text class="breeze-run-r5" x="0" y="532.4" textLength="12.2"
clip-path="url(#breeze-run-line-21)">│</text><text class="breeze-run-r5"
x="341.6" y="532.4" textLength="756.4"
clip-path="url(#breeze-run-line-21)">[default: autodetect]                                         </
[...]
+</text><text class="breeze-run-r5" x="0" y="556.8" textLength="12.2"
clip-path="url(#breeze-run-line-22)">│</text><text class="breeze-run-r4"
x="24.4" y="556.8" textLength="97.6"
clip-path="url(#breeze-run-line-22)">--use-uv</text><text class="breeze-run-r1"
x="122" y="556.8" textLength="12.2"
clip-path="url(#breeze-run-line-22)">/</text><text class="breeze-run-r4"
x="134.2" y="556.8" textLength="134.2"
clip-path="url(#breeze-run-line-22)">--no-use-uv</text><text
class="breeze-run-r1" x= [...]
+</text><text class="breeze-run-r5" x="0" y="581.2" textLength="12.2"
clip-path="url(#breeze-run-line-23)">│</text><text class="breeze-run-r4"
x="24.4" y="581.2" textLength="207.4"
clip-path="url(#breeze-run-line-23)">--uv-http-timeout</text><text
class="breeze-run-r1" x="341.6" y="581.2" textLength="829.6"
clip-path="url(#breeze-run-line-23)">Timeout for requests that UV makes (only used in case of UV builds).</text><text
class= [...]
+</text><text class="breeze-run-r5" x="0" y="605.6" textLength="12.2"
clip-path="url(#breeze-run-line-24)">│</text><text class="breeze-run-r5"
x="341.6" y="605.6" textLength="829.6"
clip-path="url(#breeze-run-line-24)">[default: 300; x>=1]                                        &
[...]
+</text><text class="breeze-run-r5" x="0" y="630" textLength="1464"
clip-path="url(#breeze-run-line-25)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="630" textLength="12.2"
clip-path="url(#breeze-run-line-25)">
+</text><text class="breeze-run-r5" x="0" y="654.4" textLength="24.4"
clip-path="url(#breeze-run-line-26)">╭─</text><text class="breeze-run-r5"
x="24.4" y="654.4" textLength="427"
clip-path="url(#breeze-run-line-26)"> Docker Compose project management </text><text
class="breeze-run-r5" x="451.4" y="654.4" textLength="988.2"
clip-path="url(#breeze-run-line-26)">─────────────────────────────────────────────────────────────────────────────────</text><text
class="bree [...]
+</text><text class="breeze-run-r5" x="0" y="678.8" textLength="12.2"
clip-path="url(#breeze-run-line-27)">│</text><text class="breeze-run-r4"
x="24.4" y="678.8" textLength="170.8"
clip-path="url(#breeze-run-line-27)">--project-name</text><text
class="breeze-run-r1" x="244" y="678.8" textLength="1195.6"
clip-path="url(#breeze-run-line-27)">Name of the docker-compose project to bring down. The `docker-compose` is for legacy b
[...]
+</text><text class="breeze-run-r5" x="0" y="703.2" textLength="12.2"
clip-path="url(#breeze-run-line-28)">│</text><text class="breeze-run-r1"
x="244" y="703.2" textLength="512.4"
clip-path="url(#breeze-run-line-28)">project name and you can use `breeze down </text><text
class="breeze-run-r4" x="756.4" y="703.2" textLength="170.8"
clip-path="url(#breeze-run-line-28)">--project-name</text><text
class="breeze-run-r1" x="927.2" y="703.2" textLength="51 [...]
+</text><text class="breeze-run-r5" x="0" y="727.6" textLength="12.2"
clip-path="url(#breeze-run-line-29)">│</text><text class="breeze-run-r1"
x="244" y="727.6" textLength="1195.6"
clip-path="url(#breeze-run-line-29)">belonging to it.                                         
[...]
+</text><text class="breeze-run-r5" x="0" y="752" textLength="12.2"
clip-path="url(#breeze-run-line-30)">│</text><text class="breeze-run-r7"
x="244" y="752" textLength="1195.6"
clip-path="url(#breeze-run-line-30)">(breeze | pre-commit | docker-compose)                                     
[...]
+</text><text class="breeze-run-r5" x="0" y="776.4" textLength="12.2"
clip-path="url(#breeze-run-line-31)">│</text><text class="breeze-run-r5"
x="244" y="776.4" textLength="1195.6"
clip-path="url(#breeze-run-line-31)">[default: breeze]                                          &
[...]
+</text><text class="breeze-run-r5" x="0" y="800.8" textLength="12.2"
clip-path="url(#breeze-run-line-32)">│</text><text class="breeze-run-r4"
x="24.4" y="800.8" textLength="158.6"
clip-path="url(#breeze-run-line-32)">--docker-host</text><text
class="breeze-run-r1" x="244" y="800.8" textLength="915"
clip-path="url(#breeze-run-line-32)">Optional - docker host to use when running docker commands. When set, the `</text><text
cl [...]
+</text><text class="breeze-run-r5" x="0" y="825.2" textLength="12.2"
clip-path="url(#breeze-run-line-33)">│</text><text class="breeze-run-r1"
x="244" y="825.2" textLength="1195.6"
clip-path="url(#breeze-run-line-33)">ignored when building images.                                      
[...]
+</text><text class="breeze-run-r5" x="0" y="849.6" textLength="12.2"
clip-path="url(#breeze-run-line-34)">│</text><text class="breeze-run-r7"
x="244" y="849.6" textLength="1195.6"
clip-path="url(#breeze-run-line-34)">(TEXT)                                             
[...]
+</text><text class="breeze-run-r5" x="0" y="874" textLength="1464"
clip-path="url(#breeze-run-line-35)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="874" textLength="12.2"
clip-path="url(#breeze-run-line-35)">
+</text><text class="breeze-run-r5" x="0" y="898.4" textLength="24.4"
clip-path="url(#breeze-run-line-36)">╭─</text><text class="breeze-run-r5"
x="24.4" y="898.4" textLength="183"
clip-path="url(#breeze-run-line-36)"> Other options </text><text
class="breeze-run-r5" x="207.4" y="898.4" textLength="1232.2"
clip-path="url(#breeze-run-line-36)">─────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-run-r5 [...]
+</text><text class="breeze-run-r5" x="0" y="922.8" textLength="12.2"
clip-path="url(#breeze-run-line-37)">│</text><text class="breeze-run-r4"
x="24.4" y="922.8" textLength="256.2"
clip-path="url(#breeze-run-line-37)">--forward-credentials</text><text
class="breeze-run-r6" x="366" y="922.8" textLength="24.4"
clip-path="url(#breeze-run-line-37)">-f</text><text class="breeze-run-r1"
x="414.8" y="922.8" textLength="634.4"
clip-path="url(#breeze-run-line-37)">Forward local credentia [...]
+</text><text class="breeze-run-r5" x="0" y="947.2" textLength="12.2"
clip-path="url(#breeze-run-line-38)">│</text><text class="breeze-run-r4"
x="24.4" y="947.2" textLength="317.2"
clip-path="url(#breeze-run-line-38)">--skip-image-upgrade-check</text><text
class="breeze-run-r1" x="414.8" y="947.2" textLength="536.8"
clip-path="url(#breeze-run-line-38)">Skip checking if the CI image is up to date.</text><text
class="breeze-run-r5" x="1451.8" y=" [...]
+</text><text class="breeze-run-r5" x="0" y="971.6" textLength="1464"
clip-path="url(#breeze-run-line-39)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="971.6" textLength="12.2"
clip-path="url(#breeze-run-line-39)">
+</text><text class="breeze-run-r5" x="0" y="996" textLength="24.4"
clip-path="url(#breeze-run-line-40)">╭─</text><text class="breeze-run-r5"
x="24.4" y="996" textLength="195.2"
clip-path="url(#breeze-run-line-40)"> Common options </text><text
class="breeze-run-r5" x="219.6" y="996" textLength="1220"
clip-path="url(#breeze-run-line-40)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-run-r5" x="1 [...]
+</text><text class="breeze-run-r5" x="0" y="1020.4" textLength="12.2"
clip-path="url(#breeze-run-line-41)">│</text><text class="breeze-run-r4"
x="24.4" y="1020.4" textLength="109.8"
clip-path="url(#breeze-run-line-41)">--dry-run</text><text
class="breeze-run-r6" x="158.6" y="1020.4" textLength="24.4"
clip-path="url(#breeze-run-line-41)">-D</text><text class="breeze-run-r1"
x="207.4" y="1020.4" textLength="719.8"
clip-path="url(#breeze-run-line-41)">If dry-run is set, 
[...]
+</text><text class="breeze-run-r5" x="0" y="1044.8" textLength="12.2"
clip-path="url(#breeze-run-line-42)">│</text><text class="breeze-run-r4"
x="24.4" y="1044.8" textLength="109.8"
clip-path="url(#breeze-run-line-42)">--verbose</text><text
class="breeze-run-r6" x="158.6" y="1044.8" textLength="24.4"
clip-path="url(#breeze-run-line-42)">-v</text><text class="breeze-run-r1"
x="207.4" y="1044.8" textLength="585.6"
clip-path="url(#breeze-run-line-42)">Print verbose information
[...]
+</text><text class="breeze-run-r5" x="0" y="1069.2" textLength="12.2"
clip-path="url(#breeze-run-line-43)">│</text><text class="breeze-run-r4"
x="24.4" y="1069.2" textLength="73.2"
clip-path="url(#breeze-run-line-43)">--help</text><text class="breeze-run-r6"
x="158.6" y="1069.2" textLength="24.4"
clip-path="url(#breeze-run-line-43)">-h</text><text class="breeze-run-r1"
x="207.4" y="1069.2" textLength="329.4"
clip-path="url(#breeze-run-line-43)">Show this message and e
[...]
+</text><text class="breeze-run-r5" x="0" y="1093.6" textLength="1464"
clip-path="url(#breeze-run-line-44)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1093.6" textLength="12.2"
clip-path="url(#breeze-run-line-44)">
+</text>
+ </g>
+ </g>
+</svg>
diff --git a/dev/breeze/doc/images/output_run.txt
b/dev/breeze/doc/images/output_run.txt
new file mode 100644
index 00000000000..53c445f3e15
--- /dev/null
+++ b/dev/breeze/doc/images/output_run.txt
@@ -0,0 +1 @@
+820a829e6ae777a8625862d010f8e693
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 dd7f6cd19f2..0603451c7d5 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
@@ -208,7 +208,7 @@
</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:publish-docs-to-s3 | release-management:release-prod-images |           &#
[...]
</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)">release-management:start-rc-process | release-management:start-release |            
[...]
</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)">release-management:tag-providers | release-management:update-constraints |           
[...]
-</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)">release-management:verify-provider-distributions | sbom | sbom:build-all-airflow-images |       
[...]
+</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)">release-management:verify-provider-distributions | run | sbom | sbom:build-all-airflow-images |     
[...]
</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)">sbom:export-dependency-information | sbom:generate-providers-requirements |           
[...]
</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)">sbom:update-sbom-information | setup | setup:autocomplete | setup:check-all-params-in-groups |     
[...]
</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)">setup:config | setup:regenerate-command-images | setup:self-upgrade | setup:synchronize-local-mounts | </text><text
cla [...]
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 c712a698cd5..6afbc1c4b9a 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 @@
-990975cc123e19cc0e094e129dcac59b
+b1c66655acd75f4f7c65b2d35552f54e
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 9304f343dbc..91345750033 100644
--- a/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
+++ b/dev/breeze/doc/images/output_setup_regenerate-command-images.svg
@@ -229,7 +229,7 @@
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="703.2"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:publish-docs-to-s3 | release-management:release-prod-images |           &#
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="727.6"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-29)">release-management:start-rc-process | release-management:start-release |            
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="752"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-30)">release-management:tag-providers | release-management:update-constraints |             
[...]
-</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:verify-provider-distributions | sbom | sbom:build-all-airflow-images |        &
[...]
+</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="776.4"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:verify-provider-distributions | run | sbom | sbom:build-all-airflow-images |     </t
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="800.8"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-32)">sbom:export-dependency-information | sbom:generate-providers-requirements |            &
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="825.2"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-33)">sbom:update-sbom-information | setup | setup:autocomplete | setup:check-all-params-in-groups |     
[...]
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6"
textLength="12.2"
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text
class="breeze-setup-regenerate-command-images-r6" x="219.6" y="849.6"
textLength="1220"
clip-path="url(#breeze-setup-regenerate-command-images-line-34)">setup:config | setup:regenerate-command-images | setup:self-upgrade | setup:synchronize-local-mounts</text><text
class="breeze-setup- [...]
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 4fd763c19df..e1261a22897 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 @@
-dd551b481de86089ffc562db65a88f2c
+d112f32bf3ac63a45cafb3cd1248d728
diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
index e4f032108fd..0a6ad967909 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
@@ -1075,6 +1075,9 @@ def exec(exec_args: tuple):
if not process:
sys.exit(1)
sys.exit(process.returncode)
+ else:
+ get_console().print("[error]No airflow containers are running[/]")
+ sys.exit(1)
def stop_exec_on_error(returncode: int):
@@ -1197,3 +1200,137 @@ def doctor(ctx):
ctx.forward(cleanup)
elif given_answer == Answer.QUIT:
sys.exit(0)
+
+
[email protected](
+ name="run",
+ help="Run a command in the Breeze environment without entering the
interactive shell.",
+ context_settings={"ignore_unknown_options": True, "allow_extra_args":
True},
+)
[email protected]("command", required=True)
[email protected]("command_args", nargs=-1, type=click.UNPROCESSED)
+@option_backend
+@option_builder
+@option_docker_host
+@option_dry_run
+@option_force_build
+@option_forward_credentials
+@option_github_repository
+@option_mysql_version
+@option_platform_single
+@option_postgres_version
+@option_project_name
+@option_python
+@option_skip_image_upgrade_check
+@option_use_uv
+@option_uv_http_timeout
+@option_verbose
+def run(
+ command: str,
+ command_args: tuple,
+ backend: str,
+ builder: str,
+ docker_host: str | None,
+ force_build: bool,
+ forward_credentials: bool,
+ github_repository: str,
+ mysql_version: str,
+ platform: str | None,
+ postgres_version: str,
+ project_name: str,
+ python: str,
+ skip_image_upgrade_check: bool,
+ use_uv: bool,
+ uv_http_timeout: int,
+):
+ """
+ Run a command in the Breeze environment without entering the interactive
shell.
+
+ This is useful for automated testing, CI workflows, and one-off command
execution.
+ The command will be executed in a fresh container that is automatically
cleaned up.
+ Each run uses a unique project name to avoid conflicts with other
instances.
+
+ Examples:
+ # Run a specific test
+ breeze run pytest
providers/google/tests/unit/google/cloud/operators/test_dataflow.py -v
+
+ # Check version compatibility
+ breeze run python -c "from airflow.providers.google.version_compat
import AIRFLOW_V_3_0_PLUS; print(AIRFLOW_V_3_0_PLUS)"
+
+ # Run bash commands
+ breeze run bash -c "cd /opt/airflow && python -m pytest
providers/google/tests/"
+
+ # Run with different Python version
+ breeze run --python 3.11 pytest
providers/standard/tests/unit/operators/test_bash.py
+
+ # Run with PostgreSQL backend
+ breeze run --backend postgres pytest providers/postgres/tests/
+ """
+ import uuid
+
+ from airflow_breeze.commands.ci_image_commands import
rebuild_or_pull_ci_image_if_needed
+ from airflow_breeze.params.shell_params import ShellParams
+ from airflow_breeze.utils.ci_group import ci_group
+ from airflow_breeze.utils.docker_command_utils import
execute_command_in_shell
+ from airflow_breeze.utils.platforms import get_normalized_platform
+
+ # Generate a unique project name to avoid conflicts with other running
instances
+ unique_project_name = f"{project_name}-run-{uuid.uuid4().hex[:8]}"
+
+ # Build the full command string with proper escaping
+ import shlex
+
+ if command_args:
+ # Use shlex.join to properly escape arguments
+ full_command = f"{command} {shlex.join(command_args)}"
+ else:
+ full_command = command
+
+ platform = get_normalized_platform(platform)
+
+ # Create shell parameters optimized for non-interactive command execution
+ shell_params = ShellParams(
+ backend=backend,
+ builder=builder,
+ docker_host=docker_host,
+ force_build=force_build,
+ forward_credentials=forward_credentials,
+ github_repository=github_repository,
+ mysql_version=mysql_version,
+ platform=platform,
+ postgres_version=postgres_version,
+ project_name=unique_project_name,
+ python=python,
+ skip_image_upgrade_check=skip_image_upgrade_check,
+ use_uv=use_uv,
+ uv_http_timeout=uv_http_timeout,
+ # Optimizations for non-interactive execution
+ quiet=True,
+ skip_environment_initialization=True,
+ tty="disabled",
+ # Set extra_args to empty tuple since we'll pass the command directly
+ extra_args=(),
+ )
+
+ if get_verbose():
+ get_console().print(f"[info]Running command in Breeze:
{full_command}[/]")
+ get_console().print(f"[info]Using project name:
{unique_project_name}[/]")
+
+ # Build or pull the CI image if needed
+ rebuild_or_pull_ci_image_if_needed(command_params=shell_params)
+
+ # Execute the command in the shell
+ with ci_group(f"Running command: {command}"):
+ result = execute_command_in_shell(
+ shell_params=shell_params,
+ project_name=unique_project_name,
+ command=full_command,
+ )
+
+ # Clean up ownership
+ from airflow_breeze.utils.docker_command_utils import
fix_ownership_using_docker
+
+ fix_ownership_using_docker()
+
+ # Exit with the same code as the command
+ sys.exit(result.returncode)
diff --git
a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
index bb5e449d038..eae6e0cb862 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
@@ -25,6 +25,7 @@ DEVELOPER_COMMANDS: dict[str, str | list[str]] = {
"down",
"shell",
"exec",
+ "run",
"compile-ui-assets",
"cleanup",
"generate-migration-file",
@@ -295,6 +296,42 @@ DEVELOPER_PARAMETERS: dict[str, list[dict[str, str |
list[str]]]] = {
"breeze exec": [
{"name": "Drops in the interactive shell of active airflow container"},
],
+ "breeze run": [
+ {
+ "name": "Command execution",
+ "options": [
+ "--python",
+ "--backend",
+ "--postgres-version",
+ "--mysql-version",
+ ],
+ },
+ {
+ "name": "Build CI image (before running command)",
+ "options": [
+ "--force-build",
+ "--platform",
+ "--github-repository",
+ "--builder",
+ "--use-uv",
+ "--uv-http-timeout",
+ ],
+ },
+ {
+ "name": "Docker Compose project management",
+ "options": [
+ "--project-name",
+ "--docker-host",
+ ],
+ },
+ {
+ "name": "Other options",
+ "options": [
+ "--forward-credentials",
+ "--skip-image-upgrade-check",
+ ],
+ },
+ ],
"breeze down": [
{
"name": "Down flags",
diff --git a/dev/breeze/src/airflow_breeze/commands/setup_commands.py
b/dev/breeze/src/airflow_breeze/commands/setup_commands.py
index 1429a6b13f4..68954529007 100644
--- a/dev/breeze/src/airflow_breeze/commands/setup_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/setup_commands.py
@@ -562,6 +562,7 @@ DEVELOPER_COMMANDS = [
"down",
"exec",
"shell",
+ "run",
"compile-ui-assets",
"cleanup",
"generate-migration-file",