This is an automated email from the ASF dual-hosted git repository. vatsrahul1001 pushed a commit to branch backport-322-66311 in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 14a5e3d719b849b117c18d6ed4bda869aa05f5ea Author: Jarek Potiuk <[email protected]> AuthorDate: Sun May 3 19:04:09 2026 +0200 Breeze: make `breeze down` discover and stop every compose project (#66311) Discovers running docker compose projects via the `com.docker.compose.project` label and brings down every one matching a known breeze prefix (`breeze`, `prek`, `docker-compose`, `docs`, `db`, `providers`, plus `breeze-`, `airflow-test`, `constraints-`, `providers-`). One `breeze down` now leaves the host clean regardless of which breeze commands, prek hooks, or CI steps were running. Two new flags: `--all-projects` also catches compose projects that don't match any known breeze prefix (off by default to avoid wiping unrelated host projects); `--project-name <name>` restricts cleanup to a single project (useful in CI). Single-use cleanup gaps fixed: - `run_command_via_breeze_shell` (used by every breeze-shell-based prek hook) now wraps the subprocess in try/finally and passes `--volumes` to the down call, so prek runs no longer leak DB volumes between hooks and KeyboardInterrupt no longer skips cleanup. - `breeze registry extract-data` and `breeze registry backfill-data` added try/finally cleanup of their unique compose projects (previously leaked `breeze-registry-*` and `breeze-backfill-*` on every invocation). - `breeze doctor` now uses the same label-based cleanup. (cherry picked from commit 263549590ecbb0c489fb0166caefa456dfe9b8d4) --- dev/breeze/doc/03_developer_tasks.rst | 13 +++ dev/breeze/doc/images/output-commands.svg | 84 ++++++++++--------- dev/breeze/doc/images/output_down.svg | 67 +++++++++++---- dev/breeze/doc/images/output_down.txt | 2 +- .../airflow_breeze/commands/developer_commands.py | 59 +++++++++++-- .../commands/developer_commands_config.py | 7 ++ .../airflow_breeze/commands/registry_commands.py | 30 ++++--- dev/breeze/src/airflow_breeze/global_constants.py | 22 +++++ .../airflow_breeze/utils/docker_command_utils.py | 79 ++++++++++++++++++ dev/breeze/tests/test_docker_command_utils.py | 97 ++++++++++++++++++++++ scripts/ci/prek/common_prek_utils.py | 31 ++++--- 11 files changed, 405 insertions(+), 86 deletions(-) diff --git a/dev/breeze/doc/03_developer_tasks.rst b/dev/breeze/doc/03_developer_tasks.rst index 37dff9045ad..cc951edb1f2 100644 --- a/dev/breeze/doc/03_developer_tasks.rst +++ b/dev/breeze/doc/03_developer_tasks.rst @@ -694,6 +694,19 @@ You can always stop it via: breeze down +``breeze down`` discovers every running docker compose project that breeze knows +about — ``breeze shell``, ``breeze testing``, ``breeze build-docs``, ``breeze db``, +release-management, registry, ``breeze run``, and prek-hook compose projects — by +reading the ``com.docker.compose.project`` label that compose sets on every container +it creates. Each matching project is brought down with ``--remove-orphans`` and +``--volumes`` (unless ``--preserve-volumes`` is passed). One ``breeze down`` is +enough to leave the host clean. + +If you have an unrelated docker compose project running on the host that does not +match any breeze prefix, it is left alone by default. Pass ``--all-projects`` to +also bring those down. To restrict the cleanup to a single named project (useful +in CI steps), pass ``--project-name <name>``. + These are all available flags of ``down`` command: .. image:: ./images/output_down.svg diff --git a/dev/breeze/doc/images/output-commands.svg b/dev/breeze/doc/images/output-commands.svg index d6cd7ad2284..e5762bf56c8 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 2538.7999999999997" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 1482 2563.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="2487.7999999999997" /> + <rect x="0" y="0" width="1463.0" height="2512.2" /> </clipPath> <clipPath id="breeze-help-line-0"> <rect x="0" y="1.5" width="1464" height="24.65"/> @@ -348,9 +348,12 @@ <clipPath id="breeze-help-line-100"> <rect x="0" y="2441.5" width="1464" height="24.65"/> </clipPath> +<clipPath id="breeze-help-line-101"> + <rect x="0" y="2465.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="2536.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="2561.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"/> @@ -423,45 +426,46 @@ </text><text class="breeze-help-r5" x="0" y="1484" textLength="12.2" clip-path="url(#breeze-help-line-60)">│</text><text class="breeze-help-r4" x="24.4" y="1484" textLength="280.6" clip-path="url(#breeze-help-line-60)">start-airflow          </text><text class="breeze-help-r1" x="329.4" y="1484" textLength="1110.2" clip-path="url(#breeze-help-line-60)">Enter breeze environment and starts all Airflow comp [...] </text><text class="breeze-help-r5" x="0" y="1508.4" textLength="12.2" clip-path="url(#breeze-help-line-61)">│</text><text class="breeze-help-r1" x="329.4" y="1508.4" textLength="1110.2" clip-path="url(#breeze-help-line-61)">Compile assets if contents of www directory changed.                               [...] </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)">build-docs             </text><text class="breeze-help-r1" x="329.4" y="1532.8" textLength="1110.2" clip-path="url(#breeze-help-line-62)">Build documents.        [...] -</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)">down                   </text><text class="breeze-help-r1" x="329.4" y="1557.2" textLength="1110.2" clip-path="url(#breeze-help-line-63)">Stop running breeze e [...] -</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)">shell                  </text><text class="breeze-help-r1" x="329.4" y="1581.6" textLength="1110.2" clip-path="url(#breeze-help-line-64)">Enter breeze environment.  [...] -</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)">exec                   </text><text class="breeze-help-r1" x="329.4" y="1606" textLength="1110.2" clip-path="url(#breeze-help-line-65)">Joins the interactive shell [...] -</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)">run                    </text><text class="breeze-help-r1" x="329.4" y="1630.4" textLength="1110.2" clip-path="url(#breeze-help-line-66)">Run a command in [...] -</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="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)">down                   </text><text class="breeze-help-r1" x="329.4" y="1557.2" textLength="1110.2" clip-path="url(#breeze-help-line-63)">Stop every docker com [...] +</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-r1" x="329.4" y="1581.6" textLength="805.2" clip-path="url(#breeze-help-line-64)">`com.docker.compose.project` label and brings each one down with `</text><text class="breeze-help-r4" x="1134.6" y="1581.6" textLength="195.2" clip-path="url(#breeze-help-line-64)">--remove-orphans</text><text class="breeze-help [...] +</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-r1" x="329.4" y="1606" textLength="12.2" clip-path="url(#breeze-help-line-65)">`</text><text class="breeze-help-r4" x="341.6" y="1606" textLength="109.8" clip-path="url(#breeze-help-line-65)">--volumes</text><text class="breeze-help-r1" x="451.4" y="1606" textLength="122" clip-path="url(#breeze-help-line-65)">` unless `</text><text class="b [...] +</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-r1" x="329.4" y="1630.4" textLength="1110.2" clip-path="url(#breeze-help-line-66)">testing`, `breeze build-docs`, `breeze db`, release-management, registry, and prek-hook    </text><text class="breeze-help-r5" x="1451.8" y="1630.4" textLength="12.2" clip-path="url(#breeze-help-line-66)">│< [...] +</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-r1" x="329.4" y="1654.8" textLength="1110.2" clip-path="url(#breeze-help-line-67)">compose projects in a single command.                                  & [...] +</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)">shell                  </text><text class="breeze-help-r1" x="329.4" y="1679.2" textLength="1110.2" clip-path="url(#breeze-help-line-68)">Enter breeze environment.  [...] +</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)">exec                   </text><text class="breeze-help-r1" x="329.4" y="1703.6" textLength="1110.2" clip-path="url(#breeze-help-line-69)">Joins the interactive  [...] +</text><text class="breeze-help-r5" x="0" y="1728" textLength="12.2" clip-path="url(#breeze-help-line-70)">│</text><text class="breeze-help-r4" x="24.4" y="1728" textLength="280.6" clip-path="url(#breeze-help-line-70)">run                    </text><text class="breeze-help-r1" x="329.4" y="1728" textLength="1110.2" clip-path="url(#breeze-help-line-70)">Run a command in  [...] +</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="280.6" clip-path="url(#breeze-help-line-71)">cleanup                </text><text class="breeze-help-r1" x="329.4" y="1752.4" textLength="1110.2" clip-path="url(#breeze-help-line-71)">Cleans the cache of parameters, [...] +</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="280.6" clip-path="url(#breeze-help-line-72)">generate-migration-file</text><text class="breeze-help-r1" x="329.4" y="1776.8" textLength="1110.2" clip-path="url(#breeze-help-line-72)">Autogenerate the alembic migration file for the ORM changes.     & [...] +</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="280.6" clip-path="url(#breeze-help-line-73)">doctor                 </text><text class="breeze-help-r1" x="329.4" y="1801.2" textLength="1110.2" clip-path="url(#breeze-help-line-73)">Auto-healing of breeze  &# [...] </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="1850" textLength="24.4" clip-path="url(#breeze-help-line-75)">╭─</text><text class="breeze-help-r5" x="24.4" y="1850" textLength="219.6" clip-path="url(#breeze-help-line-75)"> Testing commands </text><text class="breeze-help-r5" x="244" y="1850" textLength="1195.6" 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="183" clip-path="url(#breeze-help-line-76)">testing        </text><text class="breeze-help-r1" x="231.8" y="1874.4" textLength="1207.8" clip-path="url(#breeze-help-line-76)">Tools that developers can use to run tests     [...] +</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="183" clip-path="url(#breeze-help-line-77)">k8s            </text><text class="breeze-help-r1" x="231.8" y="1898.8" textLength="1207.8" clip-path="url(#breeze-help-line-77)">Tools that developers use to run Kubernetes te [...] </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="158.6" clip-path="url(#breeze-help-line-84)"> CI commands </text><text class="breeze-help-r5" x="183" y="2069.6" textLength="1256.6" 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="61" clip-path="url(#breeze-help-line-85)">ci   </text><text class="breeze-help-r1" x="109.8" y="2094" textLength="1329.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="2142.8" textLength="24.4" clip-path="url(#breeze-help-line-87)">╭─</text><text class="breeze-help-r5" x="24.4" y="2142.8" textLength="231.8" clip-path="url(#breeze-help-line-87)"> Registry commands </text><text class="breeze-help-r5" x="256.2" y="2142.8" textLength="1183.4" clip-path="url(#breeze-help-line-87)">─────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="br [...] -</text><text class="breeze-help-r5" x="0" y="2167.2" textLength="12.2" clip-path="url(#breeze-help-line-88)">│</text><text class="breeze-help-r4" x="24.4" y="2167.2" textLength="256.2" clip-path="url(#breeze-help-line-88)">registry             </text><text class="breeze-help-r1" x="305" y="2167.2" textLength="1134.6" clip-path="url(#breeze-help-line-88)">Tools for the Airflow Provider Registry  [...] -</text><text class="breeze-help-r5" x="0" y="2191.6" textLength="1464" clip-path="url(#breeze-help-line-89)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2191.6" textLength="12.2" clip-path="url(#breeze-help-line-89)"> -</text><text class="breeze-help-r5" x="0" y="2216" textLength="24.4" clip-path="url(#breeze-help-line-90)">╭─</text><text class="breeze-help-r5" x="24.4" y="2216" textLength="158.6" clip-path="url(#breeze-help-line-90)"> UI commands </text><text class="breeze-help-r5" x="183" y="2216" textLength="1256.6" clip-path="url(#breeze-help-line-90)">───────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-hel [...] -</text><text class="breeze-help-r5" x="0" y="2240.4" textLength="12.2" clip-path="url(#breeze-help-line-91)">│</text><text class="breeze-help-r4" x="24.4" y="2240.4" textLength="85.4" clip-path="url(#breeze-help-line-91)">ui     </text><text class="breeze-help-r1" x="134.2" y="2240.4" textLength="1305.4" clip-path="url(#breeze-help-line-91)">Tools for UI development and maintenance          [...] -</text><text class="breeze-help-r5" x="0" y="2264.8" textLength="1464" clip-path="url(#breeze-help-line-92)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2264.8" textLength="12.2" clip-path="url(#breeze-help-line-92)"> -</text><text class="breeze-help-r5" x="0" y="2289.2" textLength="24.4" clip-path="url(#breeze-help-line-93)">╭─</text><text class="breeze-help-r5" x="24.4" y="2289.2" textLength="207.4" clip-path="url(#breeze-help-line-93)"> Issues commands </text><text class="breeze-help-r5" x="231.8" y="2289.2" textLength="1207.8" clip-path="url(#breeze-help-line-93)">───────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="br [...] -</text><text class="breeze-help-r5" x="0" y="2313.6" textLength="12.2" clip-path="url(#breeze-help-line-94)">│</text><text class="breeze-help-r4" x="24.4" y="2313.6" textLength="231.8" clip-path="url(#breeze-help-line-94)">issues             </text><text class="breeze-help-r1" x="280.6" y="2313.6" textLength="1159" clip-path="url(#breeze-help-line-94)">Tools for managing GitHub issues.   & [...] -</text><text class="breeze-help-r5" x="0" y="2338" textLength="1464" clip-path="url(#breeze-help-line-95)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2338" textLength="12.2" clip-path="url(#breeze-help-line-95)"> -</text><text class="breeze-help-r5" x="0" y="2362.4" textLength="24.4" clip-path="url(#breeze-help-line-96)">╭─</text><text class="breeze-help-r5" x="24.4" y="2362.4" textLength="158.6" clip-path="url(#breeze-help-line-96)"> PR commands </text><text class="breeze-help-r5" x="183" y="2362.4" textLength="1256.6" clip-path="url(#breeze-help-line-96)">───────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="bree [...] -</text><text class="breeze-help-r5" x="0" y="2386.8" textLength="12.2" clip-path="url(#breeze-help-line-97)">│</text><text class="breeze-help-r4" x="24.4" y="2386.8" textLength="85.4" clip-path="url(#breeze-help-line-97)">pr     </text><text class="breeze-help-r1" x="134.2" y="2386.8" textLength="1305.4" clip-path="url(#breeze-help-line-97)">Tools for managing GitHub pull requests.          [...] -</text><text class="breeze-help-r5" x="0" y="2411.2" textLength="1464" clip-path="url(#breeze-help-line-98)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2411.2" textLength="12.2" clip-path="url(#breeze-help-line-98)"> -</text><text class="breeze-help-r5" x="0" y="2435.6" textLength="24.4" clip-path="url(#breeze-help-line-99)">╭─</text><text class="breeze-help-r5" x="24.4" y="2435.6" textLength="195.2" clip-path="url(#breeze-help-line-99)"> Setup commands </text><text class="breeze-help-r5" x="219.6" y="2435.6" textLength="1220" clip-path="url(#breeze-help-line-99)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="bree [...] -</text><text class="breeze-help-r5" x="0" y="2460" textLength="12.2" clip-path="url(#breeze-help-line-100)">│</text><text class="breeze-help-r4" x="24.4" y="2460" textLength="146.4" clip-path="url(#breeze-help-line-100)">setup       </text><text class="breeze-help-r1" x="195.2" y="2460" textLength="1244.4" clip-path="url(#breeze-help-line-100)">Tools that developers can use to configure Breeze    &# [...] -</text><text class="breeze-help-r5" x="0" y="2484.4" textLength="1464" clip-path="url(#breeze-help-line-101)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2484.4" textLength="12.2" clip-path="url(#breeze-help-line-101)"> +</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="195.2" clip-path="url(#breeze-help-line-79)"> Image commands </text><text class="breeze-help-r5" x="219.6" y="1947.6" textLength="1220" clip-path="url(#breeze-help-line-79)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="bree [...] +</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="207.4" clip-path="url(#breeze-help-line-80)">ci-image         </text><text class="breeze-help-r1" x="256.2" y="1972" textLength="1183.4" clip-path="url(#breeze-help-line-80)">Tools that developers can use to manually manage CI i [...] +</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="207.4" clip-path="url(#breeze-help-line-81)">prod-image       </text><text class="breeze-help-r1" x="256.2" y="1996.4" textLength="1183.4" clip-path="url(#breeze-help-line-81)">Tools that developers can use to manually manage PROD ima [...] +</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="353.8" clip-path="url(#breeze-help-line-83)"> Release management commands </text><text class="breeze-help-r5" x="378.2" y="2045.2" textLength="1061.4" clip-path="url(#breeze-help-line-83)">───────────────────────────────────────────────────────────────────────────────────────</text><text clas [...] +</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="280.6" clip-path="url(#breeze-help-line-84)">release-management     </text><text class="breeze-help-r1" x="329.4" y="2069.6" textLength="1110.2" clip-path="url(#breeze-help-line-84)">Tools that release managers can use to prepare and manage [...] +</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="280.6" clip-path="url(#breeze-help-line-85)">sbom                   </text><text class="breeze-help-r1" x="329.4" y="2094" textLength="1110.2" clip-path="url(#breeze-help-line-85)">Tools that release managers [...] +</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="280.6" clip-path="url(#breeze-help-line-86)">workflow-run           </text><text class="breeze-help-r1" x="329.4" y="2118.4" textLength="1110.2" clip-path="url(#breeze-help-line-86)">Tools to manage Airflow repository workflows & [...] +</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><text class="breeze-help-r5" x="0" y="2167.2" textLength="24.4" clip-path="url(#breeze-help-line-88)">╭─</text><text class="breeze-help-r5" x="24.4" y="2167.2" textLength="158.6" clip-path="url(#breeze-help-line-88)"> CI commands </text><text class="breeze-help-r5" x="183" y="2167.2" textLength="1256.6" clip-path="url(#breeze-help-line-88)">───────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="bree [...] +</text><text class="breeze-help-r5" x="0" y="2191.6" textLength="12.2" clip-path="url(#breeze-help-line-89)">│</text><text class="breeze-help-r4" x="24.4" y="2191.6" textLength="61" clip-path="url(#breeze-help-line-89)">ci   </text><text class="breeze-help-r1" x="109.8" y="2191.6" textLength="1329.8" clip-path="url(#breeze-help-line-89)">Tools that CI workflows use to cleanup/manage CI environment      & [...] +</text><text class="breeze-help-r5" x="0" y="2216" textLength="1464" clip-path="url(#breeze-help-line-90)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2216" textLength="12.2" clip-path="url(#breeze-help-line-90)"> +</text><text class="breeze-help-r5" x="0" y="2240.4" textLength="24.4" clip-path="url(#breeze-help-line-91)">╭─</text><text class="breeze-help-r5" x="24.4" y="2240.4" textLength="231.8" clip-path="url(#breeze-help-line-91)"> Registry commands </text><text class="breeze-help-r5" x="256.2" y="2240.4" textLength="1183.4" clip-path="url(#breeze-help-line-91)">─────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="br [...] +</text><text class="breeze-help-r5" x="0" y="2264.8" textLength="12.2" clip-path="url(#breeze-help-line-92)">│</text><text class="breeze-help-r4" x="24.4" y="2264.8" textLength="256.2" clip-path="url(#breeze-help-line-92)">registry             </text><text class="breeze-help-r1" x="305" y="2264.8" textLength="1134.6" clip-path="url(#breeze-help-line-92)">Tools for the Airflow Provider Registry  [...] +</text><text class="breeze-help-r5" x="0" y="2289.2" textLength="1464" clip-path="url(#breeze-help-line-93)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2289.2" textLength="12.2" clip-path="url(#breeze-help-line-93)"> +</text><text class="breeze-help-r5" x="0" y="2313.6" textLength="24.4" clip-path="url(#breeze-help-line-94)">╭─</text><text class="breeze-help-r5" x="24.4" y="2313.6" textLength="158.6" clip-path="url(#breeze-help-line-94)"> UI commands </text><text class="breeze-help-r5" x="183" y="2313.6" textLength="1256.6" clip-path="url(#breeze-help-line-94)">───────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="bree [...] +</text><text class="breeze-help-r5" x="0" y="2338" textLength="12.2" clip-path="url(#breeze-help-line-95)">│</text><text class="breeze-help-r4" x="24.4" y="2338" textLength="85.4" clip-path="url(#breeze-help-line-95)">ui     </text><text class="breeze-help-r1" x="134.2" y="2338" textLength="1305.4" clip-path="url(#breeze-help-line-95)">Tools for UI development and maintenance           [...] +</text><text class="breeze-help-r5" x="0" y="2362.4" textLength="1464" clip-path="url(#breeze-help-line-96)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2362.4" textLength="12.2" clip-path="url(#breeze-help-line-96)"> +</text><text class="breeze-help-r5" x="0" y="2386.8" textLength="24.4" clip-path="url(#breeze-help-line-97)">╭─</text><text class="breeze-help-r5" x="24.4" y="2386.8" textLength="207.4" clip-path="url(#breeze-help-line-97)"> Issues commands </text><text class="breeze-help-r5" x="231.8" y="2386.8" textLength="1207.8" clip-path="url(#breeze-help-line-97)">───────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="br [...] +</text><text class="breeze-help-r5" x="0" y="2411.2" textLength="12.2" clip-path="url(#breeze-help-line-98)">│</text><text class="breeze-help-r4" x="24.4" y="2411.2" textLength="231.8" clip-path="url(#breeze-help-line-98)">issues             </text><text class="breeze-help-r1" x="280.6" y="2411.2" textLength="1159" clip-path="url(#breeze-help-line-98)">Tools for managing GitHub issues.   & [...] +</text><text class="breeze-help-r5" x="0" y="2435.6" textLength="1464" clip-path="url(#breeze-help-line-99)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2435.6" textLength="12.2" clip-path="url(#breeze-help-line-99)"> +</text><text class="breeze-help-r5" x="0" y="2460" textLength="24.4" clip-path="url(#breeze-help-line-100)">╭─</text><text class="breeze-help-r5" x="24.4" y="2460" textLength="195.2" clip-path="url(#breeze-help-line-100)"> Setup commands </text><text class="breeze-help-r5" x="219.6" y="2460" textLength="1220" clip-path="url(#breeze-help-line-100)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze- [...] +</text><text class="breeze-help-r5" x="0" y="2484.4" textLength="12.2" clip-path="url(#breeze-help-line-101)">│</text><text class="breeze-help-r4" x="24.4" y="2484.4" textLength="146.4" clip-path="url(#breeze-help-line-101)">setup       </text><text class="breeze-help-r1" x="195.2" y="2484.4" textLength="1244.4" clip-path="url(#breeze-help-line-101)">Tools that developers can use to configure Breeze   &# [...] +</text><text class="breeze-help-r5" x="0" y="2508.8" textLength="1464" clip-path="url(#breeze-help-line-102)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-help-r1" x="1464" y="2508.8" textLength="12.2" clip-path="url(#breeze-help-line-102)"> </text> </g> </g> diff --git a/dev/breeze/doc/images/output_down.svg b/dev/breeze/doc/images/output_down.svg index 4375f66f8db..84dd611651f 100644 --- a/dev/breeze/doc/images/output_down.svg +++ b/dev/breeze/doc/images/output_down.svg @@ -1,4 +1,4 @@ -<svg class="rich-terminal" viewBox="0 0 1482 416.0" xmlns="http://www.w3.org/2000/svg"> +<svg class="rich-terminal" viewBox="0 0 1482 635.5999999999999" xmlns="http://www.w3.org/2000/svg"> <!-- Generated with Rich https://www.textualize.io --> <style> @@ -38,11 +38,12 @@ .breeze-down-r4 { fill: #68a0b3;font-weight: bold } .breeze-down-r5 { fill: #868887 } .breeze-down-r6 { fill: #98a84b;font-weight: bold } +.breeze-down-r7 { fill: #8d7b39 } </style> <defs> <clipPath id="breeze-down-clip-terminal"> - <rect x="0" y="0" width="1463.0" height="365.0" /> + <rect x="0" y="0" width="1463.0" height="584.5999999999999" /> </clipPath> <clipPath id="breeze-down-line-0"> <rect x="0" y="1.5" width="1464" height="24.65"/> @@ -86,9 +87,36 @@ <clipPath id="breeze-down-line-13"> <rect x="0" y="318.7" width="1464" height="24.65"/> </clipPath> +<clipPath id="breeze-down-line-14"> + <rect x="0" y="343.1" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-15"> + <rect x="0" y="367.5" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-16"> + <rect x="0" y="391.9" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-17"> + <rect x="0" y="416.3" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-18"> + <rect x="0" y="440.7" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-19"> + <rect x="0" y="465.1" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-20"> + <rect x="0" y="489.5" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-21"> + <rect x="0" y="513.9" width="1464" height="24.65"/> + </clipPath> +<clipPath id="breeze-down-line-22"> + <rect x="0" y="538.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="414" rx="8"/><text class="breeze-down-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: down</text> + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="633.6" rx="8"/><text class="breeze-down-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: down</text> <g transform="translate(26,22)"> <circle cx="0" cy="0" r="7" fill="#ff5f57"/> <circle cx="22" cy="0" r="7" fill="#febc2e"/> @@ -101,18 +129,27 @@ <text class="breeze-down-r1" x="1464" y="20" textLength="12.2" clip-path="url(#breeze-down-line-0)"> </text><text class="breeze-down-r2" x="12.2" y="44.4" textLength="73.2" clip-path="url(#breeze-down-line-1)">Usage:</text><text class="breeze-down-r3" x="97.6" y="44.4" textLength="134.2" clip-path="url(#breeze-down-line-1)">breeze down</text><text class="breeze-down-r1" x="244" y="44.4" textLength="12.2" clip-path="url(#breeze-down-line-1)">[</text><text class="breeze-down-r4" x="256.2" y="44.4" textLength="85.4" clip-path="url(#breeze-down-line-1)">OPTIONS</text><text class="breez [...] </text><text class="breeze-down-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#breeze-down-line-2)"> -</text><text class="breeze-down-r1" x="12.2" y="93.2" textLength="390.4" clip-path="url(#breeze-down-line-3)">Stop running breeze environment.</text><text class="breeze-down-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#breeze-down-line-3)"> -</text><text class="breeze-down-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#breeze-down-line-4)"> -</text><text class="breeze-down-r5" x="0" y="142" textLength="24.4" clip-path="url(#breeze-down-line-5)">╭─</text><text class="breeze-down-r5" x="24.4" y="142" textLength="146.4" clip-path="url(#breeze-down-line-5)"> Down flags </text><text class="breeze-down-r5" x="170.8" y="142" textLength="1268.8" clip-path="url(#breeze-down-line-5)">────────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-down-r5 [...] -</text><text class="breeze-down-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-down-line-6)">│</text><text class="breeze-down-r4" x="24.4" y="166.4" textLength="256.2" clip-path="url(#breeze-down-line-6)">--preserve-volumes   </text><text class="breeze-down-r6" x="305" y="166.4" textLength="24.4" clip-path="url(#breeze-down-line-6)">-p</text><text class="breeze-down-r1" x="353.8" y="166.4" textLength="634.4" clip-path="url(#breeze-down-line-6)">Skip remo [...] -</text><text class="breeze-down-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-down-line-7)">│</text><text class="breeze-down-r4" x="24.4" y="190.8" textLength="256.2" clip-path="url(#breeze-down-line-7)">--cleanup-mypy-cache </text><text class="breeze-down-r6" x="305" y="190.8" textLength="24.4" clip-path="url(#breeze-down-line-7)">-c</text><text class="breeze-down-r1" x="353.8" y="190.8" textLength="390.4" clip-path="url(#breeze-down-line-7)">Additionally cleanu [...] -</text><text class="breeze-down-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-down-line-8)">│</text><text class="breeze-down-r4" x="24.4" y="215.2" textLength="256.2" clip-path="url(#breeze-down-line-8)">--cleanup-build-cache</text><text class="breeze-down-r6" x="305" y="215.2" textLength="24.4" clip-path="url(#breeze-down-line-8)">-b</text><text class="breeze-down-r1" x="353.8" y="215.2" textLength="512.4" clip-path="url(#breeze-down-line-8)">Additionally cleanup [...] -</text><text class="breeze-down-r5" x="0" y="239.6" textLength="1464" clip-path="url(#breeze-down-line-9)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-down-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-down-line-9)"> -</text><text class="breeze-down-r5" x="0" y="264" textLength="24.4" clip-path="url(#breeze-down-line-10)">╭─</text><text class="breeze-down-r5" x="24.4" y="264" textLength="195.2" clip-path="url(#breeze-down-line-10)"> Common options </text><text class="breeze-down-r5" x="219.6" y="264" textLength="1220" clip-path="url(#breeze-down-line-10)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-down-r [...] -</text><text class="breeze-down-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-down-line-11)">│</text><text class="breeze-down-r4" x="24.4" y="288.4" textLength="109.8" clip-path="url(#breeze-down-line-11)">--verbose</text><text class="breeze-down-r6" x="158.6" y="288.4" textLength="24.4" clip-path="url(#breeze-down-line-11)">-v</text><text class="breeze-down-r1" x="207.4" y="288.4" textLength="585.6" clip-path="url(#breeze-down-line-11)">Print verbose information [...] -</text><text class="breeze-down-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-down-line-12)">│</text><text class="breeze-down-r4" x="24.4" y="312.8" textLength="109.8" clip-path="url(#breeze-down-line-12)">--dry-run</text><text class="breeze-down-r6" x="158.6" y="312.8" textLength="24.4" clip-path="url(#breeze-down-line-12)">-D</text><text class="breeze-down-r1" x="207.4" y="312.8" textLength="719.8" clip-path="url(#breeze-down-line-12)">If dry-run is set,&# [...] -</text><text class="breeze-down-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-down-line-13)">│</text><text class="breeze-down-r4" x="24.4" y="337.2" textLength="109.8" clip-path="url(#breeze-down-line-13)">--help   </text><text class="breeze-down-r6" x="158.6" y="337.2" textLength="24.4" clip-path="url(#breeze-down-line-13)">-h</text><text class="breeze-down-r1" x="207.4" y="337.2" textLength="329.4" clip-path="url(#breeze-down-line-13)">Show this  [...] -</text><text class="breeze-down-r5" x="0" y="361.6" textLength="1464" clip-path="url(#breeze-down-line-14)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-down-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-down-line-14)"> +</text><text class="breeze-down-r1" x="12.2" y="93.2" textLength="1439.6" clip-path="url(#breeze-down-line-3)">Stop every docker compose project breeze knows about. Discovers running projects via the `com.docker.compose.project` </text><text class="breeze-down-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#breeze-down-line-3)"> +</text><text class="breeze-down-r1" x="12.2" y="117.6" textLength="451.4" clip-path="url(#breeze-down-line-4)">label and brings each one down with `</text><text class="breeze-down-r4" x="463.6" y="117.6" textLength="195.2" clip-path="url(#breeze-down-line-4)">--remove-orphans</text><text class="breeze-down-r1" x="658.8" y="117.6" textLength="97.6" clip-path="url(#breeze-down-line-4)">` (and `</text><text class="breeze-down-r4" x="756.4" y="117 [...] +</text><text class="breeze-down-r1" x="12.2" y="142" textLength="1366.4" clip-path="url(#breeze-down-line-5)">`breeze shell`, `breeze testing`, `breeze build-docs`, `breeze db`, release-management, registry, and prek-hook </text><text class="breeze-down-r1" x="1464" y="142" textLength="12.2" clip-path="url(#breeze-down-line-5)"> +</text><text class="breeze-down-r1" x="12.2" y="166.4" textLength="451.4" clip-path="url(#breeze-down-line-6)">compose projects in a single command.</text><text class="breeze-down-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-down-line-6)"> +</text><text class="breeze-down-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-down-line-7)"> +</text><text class="breeze-down-r5" x="0" y="215.2" textLength="24.4" clip-path="url(#breeze-down-line-8)">╭─</text><text class="breeze-down-r5" x="24.4" y="215.2" textLength="146.4" clip-path="url(#breeze-down-line-8)"> Down flags </text><text class="breeze-down-r5" x="170.8" y="215.2" textLength="1268.8" clip-path="url(#breeze-down-line-8)">────────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-d [...] +</text><text class="breeze-down-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-down-line-9)">│</text><text class="breeze-down-r4" x="24.4" y="239.6" textLength="256.2" clip-path="url(#breeze-down-line-9)">--preserve-volumes   </text><text class="breeze-down-r6" x="305" y="239.6" textLength="24.4" clip-path="url(#breeze-down-line-9)">-p</text><text class="breeze-down-r1" x="353.8" y="239.6" textLength="634.4" clip-path="url(#breeze-down-line-9)">Skip remo [...] +</text><text class="breeze-down-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-down-line-10)">│</text><text class="breeze-down-r4" x="24.4" y="264" textLength="256.2" clip-path="url(#breeze-down-line-10)">--cleanup-mypy-cache </text><text class="breeze-down-r6" x="305" y="264" textLength="24.4" clip-path="url(#breeze-down-line-10)">-c</text><text class="breeze-down-r1" x="353.8" y="264" textLength="390.4" clip-path="url(#breeze-down-line-10)">Additionally cleanup [...] +</text><text class="breeze-down-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-down-line-11)">│</text><text class="breeze-down-r4" x="24.4" y="288.4" textLength="256.2" clip-path="url(#breeze-down-line-11)">--cleanup-build-cache</text><text class="breeze-down-r6" x="305" y="288.4" textLength="24.4" clip-path="url(#breeze-down-line-11)">-b</text><text class="breeze-down-r1" x="353.8" y="288.4" textLength="512.4" clip-path="url(#breeze-down-line-11)">Additionally cleanup [...] +</text><text class="breeze-down-r5" x="0" y="312.8" textLength="1464" clip-path="url(#breeze-down-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-down-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-down-line-12)"> +</text><text class="breeze-down-r5" x="0" y="337.2" textLength="24.4" clip-path="url(#breeze-down-line-13)">╭─</text><text class="breeze-down-r5" x="24.4" y="337.2" textLength="231.8" clip-path="url(#breeze-down-line-13)"> Project selection </text><text class="breeze-down-r5" x="256.2" y="337.2" textLength="1183.4" clip-path="url(#breeze-down-line-13)">─────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breez [...] +</text><text class="breeze-down-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-down-line-14)">│</text><text class="breeze-down-r4" x="24.4" y="361.6" textLength="170.8" clip-path="url(#breeze-down-line-14)">--all-projects</text><text class="breeze-down-r1" x="219.6" y="361.6" textLength="1220" clip-path="url(#breeze-down-line-14)">Also bring down docker compose projects whose names do not match any known breez [...] +</text><text class="breeze-down-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-down-line-15)">│</text><text class="breeze-down-r1" x="219.6" y="386" textLength="1220" clip-path="url(#breeze-down-line-15)">default to avoid touching unrelated projects on the host.                              [...] +</text><text class="breeze-down-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-down-line-16)">│</text><text class="breeze-down-r4" x="24.4" y="410.4" textLength="170.8" clip-path="url(#breeze-down-line-16)">--project-name</text><text class="breeze-down-r1" x="219.6" y="410.4" textLength="1220" clip-path="url(#breeze-down-line-16)">Restrict the cleanup to a single docker compose project name and skip discovery.  [...] +</text><text class="breeze-down-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-down-line-17)">│</text><text class="breeze-down-r1" x="219.6" y="434.8" textLength="549" clip-path="url(#breeze-down-line-17)">that want to bring exactly one project down. </text><text class="breeze-down-r7" x="768.6" y="434.8" textLength="73.2" clip-path="url(#breeze-down-line-17)">(TEXT)</text><text class="breeze-down-r5" x="1451.8" y="434.8" textLength=" [...] +</text><text class="breeze-down-r5" x="0" y="459.2" textLength="1464" clip-path="url(#breeze-down-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-down-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-down-line-18)"> +</text><text class="breeze-down-r5" x="0" y="483.6" textLength="24.4" clip-path="url(#breeze-down-line-19)">╭─</text><text class="breeze-down-r5" x="24.4" y="483.6" textLength="195.2" clip-path="url(#breeze-down-line-19)"> Common options </text><text class="breeze-down-r5" x="219.6" y="483.6" textLength="1220" clip-path="url(#breeze-down-line-19)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze- [...] +</text><text class="breeze-down-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-down-line-20)">│</text><text class="breeze-down-r4" x="24.4" y="508" textLength="109.8" clip-path="url(#breeze-down-line-20)">--verbose</text><text class="breeze-down-r6" x="158.6" y="508" textLength="24.4" clip-path="url(#breeze-down-line-20)">-v</text><text class="breeze-down-r1" x="207.4" y="508" textLength="585.6" clip-path="url(#breeze-down-line-20)">Print verbose information ab [...] +</text><text class="breeze-down-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-down-line-21)">│</text><text class="breeze-down-r4" x="24.4" y="532.4" textLength="109.8" clip-path="url(#breeze-down-line-21)">--dry-run</text><text class="breeze-down-r6" x="158.6" y="532.4" textLength="24.4" clip-path="url(#breeze-down-line-21)">-D</text><text class="breeze-down-r1" x="207.4" y="532.4" textLength="719.8" clip-path="url(#breeze-down-line-21)">If dry-run is set,&# [...] +</text><text class="breeze-down-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-down-line-22)">│</text><text class="breeze-down-r4" x="24.4" y="556.8" textLength="109.8" clip-path="url(#breeze-down-line-22)">--help   </text><text class="breeze-down-r6" x="158.6" y="556.8" textLength="24.4" clip-path="url(#breeze-down-line-22)">-h</text><text class="breeze-down-r1" x="207.4" y="556.8" textLength="329.4" clip-path="url(#breeze-down-line-22)">Show this  [...] +</text><text class="breeze-down-r5" x="0" y="581.2" textLength="1464" clip-path="url(#breeze-down-line-23)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-down-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-down-line-23)"> </text> </g> </g> diff --git a/dev/breeze/doc/images/output_down.txt b/dev/breeze/doc/images/output_down.txt index c0200cc3228..9c1280841b6 100644 --- a/dev/breeze/doc/images/output_down.txt +++ b/dev/breeze/doc/images/output_down.txt @@ -1 +1 @@ -5c5712f40f3397d077afce24bc6b5d4d +cde032283bb58d1cf97ee92f145f1ea8 diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py b/dev/breeze/src/airflow_breeze/commands/developer_commands.py index afb22da6355..d1d9b30d269 100644 --- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py +++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py @@ -113,6 +113,7 @@ from airflow_breeze.params.shell_params import ShellParams from airflow_breeze.utils.confirm import Answer, user_confirm from airflow_breeze.utils.console import console_print from airflow_breeze.utils.docker_command_utils import ( + bring_all_compose_projects_down, bring_compose_project_down, check_docker_resources, enter_shell, @@ -904,7 +905,17 @@ def build_docs( sys.exit(result.returncode) [email protected](name="down", help="Stop running breeze environment.") [email protected]( + name="down", + help=( + "Stop every docker compose project breeze knows about. Discovers running " + "projects via the `com.docker.compose.project` label and brings each one " + "down with `--remove-orphans` (and `--volumes` unless `--preserve-volumes` " + "is passed). Covers `breeze shell`, `breeze testing`, `breeze build-docs`, " + "`breeze db`, release-management, registry, and prek-hook compose projects " + "in a single command." + ), +) @click.option( "-p", "--preserve-volumes", @@ -923,12 +934,46 @@ def build_docs( help="Additionally cleanup Build (pip/uv) cache.", is_flag=True, ) [email protected]( + "--all-projects", + help=( + "Also bring down docker compose projects whose names do not match any known " + "breeze prefix. Off by default to avoid touching unrelated projects on the host." + ), + is_flag=True, +) [email protected]( + "--project-name", + help=( + "Restrict the cleanup to a single docker compose project name and skip " + "discovery. Useful in CI steps that want to bring exactly one project down." + ), + default=None, +) @option_verbose @option_dry_run -def down(preserve_volumes: bool, cleanup_mypy_cache: bool, cleanup_build_cache: bool): +def down( + preserve_volumes: bool, + cleanup_mypy_cache: bool, + cleanup_build_cache: bool, + all_projects: bool, + project_name: str | None, +): perform_environment_checks() - shell_params = ShellParams(backend="all", include_mypy_volume=cleanup_mypy_cache) - bring_compose_project_down(preserve_volumes=preserve_volumes, shell_params=shell_params) + brought_down, skipped = bring_all_compose_projects_down( + preserve_volumes=preserve_volumes, + include_unknown=all_projects, + only_project=project_name, + ) + if not brought_down and not project_name: + console_print("[info]No running breeze-managed docker compose projects found.[/]") + elif brought_down: + console_print(f"[success]Brought down {len(brought_down)} compose project(s): {brought_down}[/]") + if skipped: + console_print( + f"[warning]Left {len(skipped)} unrelated compose project(s) running: {skipped}\n" + f"Use `breeze down --all-projects` to also bring those down.[/]" + ) if cleanup_mypy_cache: command_to_execute = ["docker", "volume", "rm", "--force", "mypy-cache-volume"] run_command(command_to_execute) @@ -1071,8 +1116,9 @@ def doctor(ctx): if not get_dry_run() and given_answer == Answer.YES: cleanup_python_generated_files() - shell_params = ShellParams(backend="all", include_mypy_volume=True) - bring_compose_project_down(preserve_volumes=False, shell_params=shell_params) + # Doctor is the heal-everything command, so it sweeps EVERY compose project + # on the host (not only the known-prefix ones that `breeze down` defaults to). + bring_all_compose_projects_down(preserve_volumes=False, include_unknown=True) given_answer = user_confirm("Are you sure with the removal of mypy cache and build cache dir?") if given_answer == Answer.YES: @@ -1178,7 +1224,6 @@ def run( 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 ( - bring_compose_project_down, execute_command_in_shell, fix_ownership_using_docker, remove_docker_networks, 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 73059f22a06..74ca92841a1 100644 --- a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py +++ b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py @@ -347,6 +347,13 @@ DEVELOPER_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = { "--cleanup-build-cache", ], }, + { + "name": "Project selection", + "options": [ + "--all-projects", + "--project-name", + ], + }, ], "breeze build-docs": [ { diff --git a/dev/breeze/src/airflow_breeze/commands/registry_commands.py b/dev/breeze/src/airflow_breeze/commands/registry_commands.py index 900ce65f2de..70cb6949734 100644 --- a/dev/breeze/src/airflow_breeze/commands/registry_commands.py +++ b/dev/breeze/src/airflow_breeze/commands/registry_commands.py @@ -31,7 +31,12 @@ from airflow_breeze.commands.common_options import option_dry_run, option_python from airflow_breeze.params.shell_params import ShellParams from airflow_breeze.utils.ci_group import ci_group from airflow_breeze.utils.click_utils import BreezeGroup -from airflow_breeze.utils.docker_command_utils import execute_command_in_shell, fix_ownership_using_docker +from airflow_breeze.utils.docker_command_utils import ( + bring_compose_project_down, + execute_command_in_shell, + fix_ownership_using_docker, + remove_docker_networks, +) from airflow_breeze.utils.path_utils import AIRFLOW_ROOT_PATH from airflow_breeze.utils.run_utils import run_command @@ -111,15 +116,18 @@ def extract_data(python: str, provider: str | None, allow_unreleased: bool): f"python dev/registry/extract_connections.py{provider_flag}" ) - with ci_group("Extracting registry data"): - result = execute_command_in_shell( - shell_params=shell_params, - project_name=unique_project_name, - command=command, - preserve_backend=True, - ) - - fix_ownership_using_docker() + try: + with ci_group("Extracting registry data"): + result = execute_command_in_shell( + shell_params=shell_params, + project_name=unique_project_name, + command=command, + preserve_backend=True, + ) + finally: + bring_compose_project_down(preserve_volumes=False, shell_params=shell_params) + remove_docker_networks([f"{unique_project_name}_default"]) + fix_ownership_using_docker() sys.exit(result.returncode) @@ -336,6 +344,8 @@ def _backfill_docker( failed.append(f"{version}/docker-extraction") finally: shutil.rmtree(backfill_tmp_dir, ignore_errors=True) + bring_compose_project_down(preserve_volumes=False, shell_params=shell_params) + remove_docker_networks([f"{unique_project_name}_default"]) fix_ownership_using_docker() return failed diff --git a/dev/breeze/src/airflow_breeze/global_constants.py b/dev/breeze/src/airflow_breeze/global_constants.py index d64ca7464ff..8f0ae4dbd16 100644 --- a/dev/breeze/src/airflow_breeze/global_constants.py +++ b/dev/breeze/src/airflow_breeze/global_constants.py @@ -146,6 +146,28 @@ AUTOCOMPLETE_ALL_INTEGRATIONS = sorted( ALLOWED_TTY = ["auto", "enabled", "disabled"] ALLOWED_TERMINAL_MULTIPLEXERS = ["mprocs", "tmux"] ALLOWED_DOCKER_COMPOSE_PROJECTS = ["breeze", "prek", "docker-compose"] + +# Every docker compose project name that any breeze command, prek hook, or +# CI workflow uses. `breeze down` discovers running compose projects via the +# `com.docker.compose.project` label and only touches the ones that match +# either an exact entry in `KNOWN_DOCKER_COMPOSE_PROJECT_NAMES` or one of the +# prefixes in `KNOWN_DOCKER_COMPOSE_PROJECT_PREFIXES`. When you add a new +# project_name pattern anywhere (new breeze command, new prek hook, new CI +# step), update this list so `breeze down` stays a one-shot cleanup. +KNOWN_DOCKER_COMPOSE_PROJECT_NAMES = [ + "breeze", # default `breeze shell` / `breeze start-airflow` + "prek", # prek hooks (see scripts/ci/prek/common_prek_utils.py) + "docker-compose", # legacy name kept for migration_tests CI + "docs", # `breeze build-docs` + "db", # `breeze db ...` + "providers", # release-management providers builds +] +KNOWN_DOCKER_COMPOSE_PROJECT_PREFIXES = [ + "breeze-", # breeze-registry-*, breeze-backfill-*, *-run-* + "airflow-test", # airflow-test, airflow-test-<test-type> + "constraints-", # constraints-<python-version> + "providers-", # providers-<index> (parallel provider builds) +] ALLOWED_LOG_LEVELS = ["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"] DEFAULT_LOG_LEVEL = ALLOWED_LOG_LEVELS[0] 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 4cb8356169b..d95ae33fc1f 100644 --- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py +++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py @@ -54,6 +54,8 @@ from airflow_breeze.global_constants import ( ALLOWED_DEBIAN_VERSIONS, DEFAULT_PYTHON_MAJOR_MINOR_VERSION, DOCKER_DEFAULT_PLATFORM, + KNOWN_DOCKER_COMPOSE_PROJECT_NAMES, + KNOWN_DOCKER_COMPOSE_PROJECT_PREFIXES, MIN_DOCKER_COMPOSE_VERSION, MIN_DOCKER_VERSION, ) @@ -833,6 +835,83 @@ def bring_compose_project_down(preserve_volumes: bool, shell_params: ShellParams ) +def discover_running_compose_projects() -> set[str]: + """ + Return the set of compose project names of every container on the host. + + Reads the ``com.docker.compose.project`` label that ``docker compose`` + sets on every container/network/volume it creates. Returns an empty set + if docker is unreachable or no compose-managed containers exist. + """ + result = run_command( + [ + "docker", + "ps", + "--all", + "--filter", + "label=com.docker.compose.project", + "--format", + '{{ index .Labels "com.docker.compose.project" }}', + ], + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0 or not result.stdout: + return set() + return {line.strip() for line in result.stdout.splitlines() if line.strip()} + + +def is_known_breeze_compose_project(name: str) -> bool: + """Return True if ``name`` matches a project breeze knows it owns.""" + if name in KNOWN_DOCKER_COMPOSE_PROJECT_NAMES: + return True + return any(name.startswith(prefix) for prefix in KNOWN_DOCKER_COMPOSE_PROJECT_PREFIXES) + + +def bring_all_compose_projects_down( + *, + preserve_volumes: bool = False, + include_unknown: bool = False, + only_project: str | None = None, +) -> tuple[list[str], list[str]]: + """ + Discover and bring down every docker compose project breeze manages. + + :param preserve_volumes: if True, pass ``--volumes`` is omitted so DB + volumes survive (matches the existing ``--preserve-volumes`` flag + on ``breeze down``). + :param include_unknown: if True, also bring down projects whose names + do not match any known breeze prefix. Useful as an emergency + cleanup; can wipe out unrelated docker compose projects on the + host, so off by default. + :param only_project: if set, restrict to exactly this project name and + skip discovery entirely (for the ``--project-name`` flag). + :returns: ``(brought_down, skipped)`` lists of project names, both + sorted, suitable for printing in a session summary. + """ + if only_project: + targets = {only_project} + skipped: set[str] = set() + else: + running = discover_running_compose_projects() + if include_unknown: + targets = running + skipped = set() + else: + targets = {name for name in running if is_known_breeze_compose_project(name)} + skipped = running - targets + brought_down: list[str] = [] + for name in sorted(targets): + console_print(f"[info]Bringing down docker compose project: {name}[/]") + cmd = ["docker", "compose", "--project-name", name, "down", "--remove-orphans"] + if not preserve_volumes: + cmd.append("--volumes") + run_command(cmd, text=True, check=False) + brought_down.append(name) + return brought_down, sorted(skipped) + + def execute_command_in_shell( shell_params: ShellParams, project_name: str, diff --git a/dev/breeze/tests/test_docker_command_utils.py b/dev/breeze/tests/test_docker_command_utils.py index 7c832813186..f08862e047d 100644 --- a/dev/breeze/tests/test_docker_command_utils.py +++ b/dev/breeze/tests/test_docker_command_utils.py @@ -24,8 +24,11 @@ import pytest from airflow_breeze.utils.docker_command_utils import ( autodetect_docker_context, + bring_all_compose_projects_down, check_docker_compose_version, check_docker_version, + discover_running_compose_projects, + is_known_breeze_compose_project, ) @@ -292,3 +295,97 @@ SOCKET_INFO_DESKTOP_LINUX = json.dumps( } ] ) + + [email protected]( + ("name", "expected"), + [ + ("breeze", True), + ("prek", True), + ("docker-compose", True), + ("docs", True), + ("db", True), + ("providers", True), + ("breeze-registry-abcd1234", True), + ("breeze-backfill-deadbeef", True), + ("breeze-run-12345678", True), + ("airflow-test", True), + ("airflow-test-providers-google", True), + ("constraints-3-12", True), + ("providers-7", True), + ("my-other-project", False), + ("airflow", False), + ("doc", False), + ("", False), + ], +) +def test_is_known_breeze_compose_project(name, expected): + assert is_known_breeze_compose_project(name) is expected + + [email protected]("airflow_breeze.utils.docker_command_utils.run_command") +def test_discover_running_compose_projects_parses_label_output(mock_run_command): + mock_run_command.return_value = mock.Mock( + returncode=0, + stdout="breeze\nbreeze\nairflow-test-providers-amazon\n \n", + ) + assert discover_running_compose_projects() == {"breeze", "airflow-test-providers-amazon"} + cmd = mock_run_command.call_args.args[0] + assert cmd[:2] == ["docker", "ps"] + assert "label=com.docker.compose.project" in cmd + + [email protected]("airflow_breeze.utils.docker_command_utils.run_command") +def test_discover_running_compose_projects_returns_empty_on_failure(mock_run_command): + mock_run_command.return_value = mock.Mock(returncode=1, stdout="") + assert discover_running_compose_projects() == set() + + [email protected]("airflow_breeze.utils.docker_command_utils.console_print") [email protected]("airflow_breeze.utils.docker_command_utils.run_command") [email protected]("airflow_breeze.utils.docker_command_utils.discover_running_compose_projects") +def test_bring_all_compose_projects_down_filters_unknown_by_default( + mock_discover, mock_run_command, _mock_console +): + mock_discover.return_value = {"breeze", "providers-3", "my-app"} + brought_down, skipped = bring_all_compose_projects_down() + assert brought_down == ["breeze", "providers-3"] + assert skipped == ["my-app"] + down_calls = [c for c in mock_run_command.call_args_list if c.args[0][:2] == ["docker", "compose"]] + assert len(down_calls) == 2 + for c in down_calls: + assert "--volumes" in c.args[0] + assert "--remove-orphans" in c.args[0] + + [email protected]("airflow_breeze.utils.docker_command_utils.console_print") [email protected]("airflow_breeze.utils.docker_command_utils.run_command") [email protected]("airflow_breeze.utils.docker_command_utils.discover_running_compose_projects") +def test_bring_all_compose_projects_down_include_unknown(mock_discover, mock_run_command, _mock_console): + mock_discover.return_value = {"breeze", "my-app"} + brought_down, skipped = bring_all_compose_projects_down(include_unknown=True) + assert brought_down == ["breeze", "my-app"] + assert skipped == [] + + [email protected]("airflow_breeze.utils.docker_command_utils.console_print") [email protected]("airflow_breeze.utils.docker_command_utils.run_command") [email protected]("airflow_breeze.utils.docker_command_utils.discover_running_compose_projects") +def test_bring_all_compose_projects_down_only_project_skips_discovery( + mock_discover, mock_run_command, _mock_console +): + brought_down, skipped = bring_all_compose_projects_down(only_project="my-app") + assert brought_down == ["my-app"] + assert skipped == [] + mock_discover.assert_not_called() + + [email protected]("airflow_breeze.utils.docker_command_utils.console_print") [email protected]("airflow_breeze.utils.docker_command_utils.run_command") [email protected]("airflow_breeze.utils.docker_command_utils.discover_running_compose_projects") +def test_bring_all_compose_projects_down_preserve_volumes(mock_discover, mock_run_command, _mock_console): + mock_discover.return_value = {"breeze"} + bring_all_compose_projects_down(preserve_volumes=True) + down_call = next(c for c in mock_run_command.call_args_list if c.args[0][:2] == ["docker", "compose"]) + assert "--volumes" not in down_call.args[0] + assert "--remove-orphans" in down_call.args[0] diff --git a/scripts/ci/prek/common_prek_utils.py b/scripts/ci/prek/common_prek_utils.py index f28923b78bc..45f38b5d3c6 100644 --- a/scripts/ci/prek/common_prek_utils.py +++ b/scripts/ci/prek/common_prek_utils.py @@ -374,19 +374,24 @@ def run_command_via_breeze_shell( print(f"Running command: {' '.join([shlex.quote(item) for item in subprocess_cmd])}") print("With environment:") print(new_env) - result = subprocess.run( - subprocess_cmd, - check=False, - text=True, - **other_popen_kwargs, - env=new_env, - ) - # Stop remaining containers - down_command = ["docker", "compose", "--progress", "quiet"] - if project_name: - down_command.extend(["--project-name", project_name]) - down_command.extend(["down", "--remove-orphans"]) - subprocess.run(down_command, check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + try: + result = subprocess.run( + subprocess_cmd, + check=False, + text=True, + **other_popen_kwargs, + env=new_env, + ) + finally: + # Always clean up containers, networks, and volumes the breeze shell + # invocation created — even if the subprocess raised (KeyboardInterrupt, + # OSError, etc.). Without --volumes the next prek run inherits state + # from the previous run, which is the bug this finally clause prevents. + down_command = ["docker", "compose", "--progress", "quiet"] + if project_name: + down_command.extend(["--project-name", project_name]) + down_command.extend(["down", "--remove-orphans", "--volumes"]) + subprocess.run(down_command, check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) return result
