This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-3-test by this push:
new 1df08159035 [v3-3-test] Fix breeze --include-mypy-volume not mounting
the mypy cache volume (#72569) (#72692)
1df08159035 is described below
commit 1df08159035ce0c9010d6307f5429be757a2aa49
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Sep 8 12:29:29 2026 +0200
[v3-3-test] Fix breeze --include-mypy-volume not mounting the mypy cache
volume (#72569) (#72692)
* Fix breeze --include-mypy-volume not mounting the mypy cache volume
The compose constant for the mypy volume pointed at local.yml instead of
mypy.yml since the path constants were extracted in #58732, so the
mypy-cache-volume was created but never mounted and the cache was lost
whenever the container was removed.
* Add --include-mypy-volume to breeze run so provider mypy hooks keep their
cache
The provider mypy prek hooks pass INCLUDE_MYPY_VOLUME=true to breeze run,
but only breeze shell had the option, so the env var was ignored and the
mypy cache was rebuilt on every hook run. The mypy cache volume is
external, so the per-run compose project teardown leaves it in place.
(cherry picked from commit a88aaff419)
Co-authored-by: Andrew Chang <[email protected]>
---
dev/breeze/doc/images/output_run.svg | 26 ++++++++++-------
dev/breeze/doc/images/output_run.txt | 2 +-
.../airflow_breeze/commands/developer_commands.py | 3 ++
.../commands/developer_commands_config.py | 1 +
dev/breeze/src/airflow_breeze/utils/path_utils.py | 2 +-
dev/breeze/tests/test_developer_commands.py | 34 +++++++++++++++++++++-
dev/breeze/tests/test_shell_params.py | 10 ++++++-
7 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/dev/breeze/doc/images/output_run.svg
b/dev/breeze/doc/images/output_run.svg
index e155248e08c..1f663a97be3 100644
--- a/dev/breeze/doc/images/output_run.svg
+++ b/dev/breeze/doc/images/output_run.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1270.0"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 1294.3999999999999"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-run-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="1219.0" />
+ <rect x="0" y="0" width="1463.0" height="1243.3999999999999" />
</clipPath>
<clipPath id="breeze-run-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -192,9 +192,12 @@
<clipPath id="breeze-run-line-48">
<rect x="0" y="1172.7" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-run-line-49">
+ <rect x="0" y="1197.1" width="1464" height="24.65"/>
+ </clipPath>
</defs>
- <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="1268" rx="8"/><text class="breeze-run-title"
fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: run</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="1292.4" 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"/>
@@ -246,14 +249,15 @@
</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="183"
clip-path="url(#breeze-run-line-40)"> Other options </text><text
class="breeze-run-r5" x="207.4" y="996" textLength="1232.2"
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="317.2"
clip-path="url(#breeze-run-line-41)">--forward-credentials     </text><text
class="breeze-run-r6" x="366" y="1020.4" textLength="24.4"
clip-path="url(#breeze-run-line-41)">-f</text><text class="breeze-run-r1"
x="414.8" y="1020.4" textLength="634.4" clip-path="url(#breeze-run-line-41)"
[...]
-</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="317.2"
clip-path="url(#breeze-run-line-42)">--skip-image-upgrade-check</text><text
class="breeze-run-r1" x="414.8" y="1044.8" textLength="536.8"
clip-path="url(#breeze-run-line-42)">Skip checking if the CI image is up to date.</text><text
class="breeze-run-r5" x="1451.8" [...]
-</text><text class="breeze-run-r5" x="0" y="1069.2" textLength="1464"
clip-path="url(#breeze-run-line-43)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1069.2" textLength="12.2"
clip-path="url(#breeze-run-line-43)">
-</text><text class="breeze-run-r5" x="0" y="1093.6" textLength="24.4"
clip-path="url(#breeze-run-line-44)">╭─</text><text class="breeze-run-r5"
x="24.4" y="1093.6" textLength="195.2"
clip-path="url(#breeze-run-line-44)"> Common options </text><text
class="breeze-run-r5" x="219.6" y="1093.6" textLength="1220"
clip-path="url(#breeze-run-line-44)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-run [...]
-</text><text class="breeze-run-r5" x="0" y="1118" textLength="12.2"
clip-path="url(#breeze-run-line-45)">│</text><text class="breeze-run-r4"
x="24.4" y="1118" textLength="109.8"
clip-path="url(#breeze-run-line-45)">--answer </text><text
class="breeze-run-r6" x="158.6" y="1118" textLength="24.4"
clip-path="url(#breeze-run-line-45)">-a</text><text class="breeze-run-r1"
x="207.4" y="1118" textLength="329.4"
clip-path="url(#breeze-run-line-45)">Force answer to questions.&
[...]
-</text><text class="breeze-run-r5" x="0" y="1142.4" textLength="12.2"
clip-path="url(#breeze-run-line-46)">│</text><text class="breeze-run-r4"
x="24.4" y="1142.4" textLength="109.8"
clip-path="url(#breeze-run-line-46)">--dry-run</text><text
class="breeze-run-r6" x="158.6" y="1142.4" textLength="24.4"
clip-path="url(#breeze-run-line-46)">-D</text><text class="breeze-run-r1"
x="207.4" y="1142.4" textLength="719.8"
clip-path="url(#breeze-run-line-46)">If dry-run is set, 
[...]
-</text><text class="breeze-run-r5" x="0" y="1166.8" textLength="12.2"
clip-path="url(#breeze-run-line-47)">│</text><text class="breeze-run-r4"
x="24.4" y="1166.8" textLength="109.8"
clip-path="url(#breeze-run-line-47)">--verbose</text><text
class="breeze-run-r6" x="158.6" y="1166.8" textLength="24.4"
clip-path="url(#breeze-run-line-47)">-v</text><text class="breeze-run-r1"
x="207.4" y="1166.8" textLength="585.6"
clip-path="url(#breeze-run-line-47)">Print verbose information
[...]
-</text><text class="breeze-run-r5" x="0" y="1191.2" textLength="12.2"
clip-path="url(#breeze-run-line-48)">│</text><text class="breeze-run-r4"
x="24.4" y="1191.2" textLength="109.8"
clip-path="url(#breeze-run-line-48)">--help   </text><text
class="breeze-run-r6" x="158.6" y="1191.2" textLength="24.4"
clip-path="url(#breeze-run-line-48)">-h</text><text class="breeze-run-r1"
x="207.4" y="1191.2" textLength="329.4"
clip-path="url(#breeze-run-line-48)">Show this mess [...]
-</text><text class="breeze-run-r5" x="0" y="1215.6" textLength="1464"
clip-path="url(#breeze-run-line-49)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1215.6" textLength="12.2"
clip-path="url(#breeze-run-line-49)">
+</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="317.2"
clip-path="url(#breeze-run-line-42)">--include-mypy-volume     </text><text
class="breeze-run-r1" x="414.8" y="1044.8" textLength="915"
clip-path="url(#breeze-run-line-42)">Whether to include mounting of the mypy volume (useful for deb
[...]
+</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="317.2"
clip-path="url(#breeze-run-line-43)">--skip-image-upgrade-check</text><text
class="breeze-run-r1" x="414.8" y="1069.2" textLength="536.8"
clip-path="url(#breeze-run-line-43)">Skip checking if the CI image is up to date.</text><text
class="breeze-run-r5" x="1451.8" [...]
+</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><text class="breeze-run-r5" x="0" y="1118" textLength="24.4"
clip-path="url(#breeze-run-line-45)">╭─</text><text class="breeze-run-r5"
x="24.4" y="1118" textLength="195.2"
clip-path="url(#breeze-run-line-45)"> Common options </text><text
class="breeze-run-r5" x="219.6" y="1118" textLength="1220"
clip-path="url(#breeze-run-line-45)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text
class="breeze-run-r5" x [...]
+</text><text class="breeze-run-r5" x="0" y="1142.4" textLength="12.2"
clip-path="url(#breeze-run-line-46)">│</text><text class="breeze-run-r4"
x="24.4" y="1142.4" textLength="109.8"
clip-path="url(#breeze-run-line-46)">--answer </text><text
class="breeze-run-r6" x="158.6" y="1142.4" textLength="24.4"
clip-path="url(#breeze-run-line-46)">-a</text><text class="breeze-run-r1"
x="207.4" y="1142.4" textLength="329.4"
clip-path="url(#breeze-run-line-46)">Force answer to que [...]
+</text><text class="breeze-run-r5" x="0" y="1166.8" textLength="12.2"
clip-path="url(#breeze-run-line-47)">│</text><text class="breeze-run-r4"
x="24.4" y="1166.8" textLength="109.8"
clip-path="url(#breeze-run-line-47)">--dry-run</text><text
class="breeze-run-r6" x="158.6" y="1166.8" textLength="24.4"
clip-path="url(#breeze-run-line-47)">-D</text><text class="breeze-run-r1"
x="207.4" y="1166.8" textLength="719.8"
clip-path="url(#breeze-run-line-47)">If dry-run is set, 
[...]
+</text><text class="breeze-run-r5" x="0" y="1191.2" textLength="12.2"
clip-path="url(#breeze-run-line-48)">│</text><text class="breeze-run-r4"
x="24.4" y="1191.2" textLength="109.8"
clip-path="url(#breeze-run-line-48)">--verbose</text><text
class="breeze-run-r6" x="158.6" y="1191.2" textLength="24.4"
clip-path="url(#breeze-run-line-48)">-v</text><text class="breeze-run-r1"
x="207.4" y="1191.2" textLength="585.6"
clip-path="url(#breeze-run-line-48)">Print verbose information
[...]
+</text><text class="breeze-run-r5" x="0" y="1215.6" textLength="12.2"
clip-path="url(#breeze-run-line-49)">│</text><text class="breeze-run-r4"
x="24.4" y="1215.6" textLength="109.8"
clip-path="url(#breeze-run-line-49)">--help   </text><text
class="breeze-run-r6" x="158.6" y="1215.6" textLength="24.4"
clip-path="url(#breeze-run-line-49)">-h</text><text class="breeze-run-r1"
x="207.4" y="1215.6" textLength="329.4"
clip-path="url(#breeze-run-line-49)">Show this mess [...]
+</text><text class="breeze-run-r5" x="0" y="1240" textLength="1464"
clip-path="url(#breeze-run-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-run-r1" x="1464" y="1240" textLength="12.2"
clip-path="url(#breeze-run-line-50)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_run.txt
b/dev/breeze/doc/images/output_run.txt
index 4a274308775..6d88ea6dd56 100644
--- a/dev/breeze/doc/images/output_run.txt
+++ b/dev/breeze/doc/images/output_run.txt
@@ -1 +1 @@
-e850a14ddf66f700b2595d65d7511869
+8f60079b567a52620babed8a0ed01b2a
diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
index 34b755851a5..2377e996799 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
@@ -1291,6 +1291,7 @@ def doctor(ctx):
@option_forward_credentials
@option_forward_ports
@option_github_repository
+@option_include_mypy_volume
@option_mysql_version
@option_platform_single
@option_postgres_version
@@ -1311,6 +1312,7 @@ def run(
forward_credentials: bool,
forward_ports: bool,
github_repository: str,
+ include_mypy_volume: bool,
mysql_version: str,
platform: str | None,
postgres_version: str,
@@ -1378,6 +1380,7 @@ def run(
force_build=force_build,
forward_credentials=forward_credentials,
github_repository=github_repository,
+ include_mypy_volume=include_mypy_volume,
mysql_version=mysql_version,
platform=platform,
postgres_version=postgres_version,
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 17d32146110..b79b9d0c4ae 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
@@ -334,6 +334,7 @@ DEVELOPER_PARAMETERS: dict[str, list[dict[str, str |
list[str]]]] = {
"name": "Other options",
"options": [
"--forward-credentials",
+ "--include-mypy-volume",
"--skip-image-upgrade-check",
],
},
diff --git a/dev/breeze/src/airflow_breeze/utils/path_utils.py
b/dev/breeze/src/airflow_breeze/utils/path_utils.py
index 716d7c2c7cc..611db564a5e 100644
--- a/dev/breeze/src/airflow_breeze/utils/path_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/path_utils.py
@@ -523,7 +523,7 @@ SCRIPTS_CI_DOCKER_COMPOSE_INTEGRATION_KERBEROS_PATH = (
SCRIPTS_CI_DOCKER_COMPOSE_LOCAL_ALL_SOURCES_PATH =
SCRIPTS_CI_DOCKER_COMPOSE_PATH / "local-all-sources.yml"
SCRIPTS_CI_DOCKER_COMPOSE_LOCAL_YAML_PATH = SCRIPTS_CI_DOCKER_COMPOSE_PATH /
"local.yml"
SCRIPTS_CI_DOCKER_COMPOSE_MOUNT_UI_DIST_PATH = SCRIPTS_CI_DOCKER_COMPOSE_PATH
/ "mount-ui-dist.yml"
-SCRIPTS_CI_DOCKER_COMPOSE_MYPY_PATH = SCRIPTS_CI_DOCKER_COMPOSE_PATH /
"local.yml"
+SCRIPTS_CI_DOCKER_COMPOSE_MYPY_PATH = SCRIPTS_CI_DOCKER_COMPOSE_PATH /
"mypy.yml"
SCRIPTS_CI_DOCKER_COMPOSE_PROVIDERS_AND_TESTS_SOURCES_PATH = (
SCRIPTS_CI_DOCKER_COMPOSE_PATH / "providers-and-tests-sources.yml"
)
diff --git a/dev/breeze/tests/test_developer_commands.py
b/dev/breeze/tests/test_developer_commands.py
index 9c4a3a8f2f4..a684ae196ad 100644
--- a/dev/breeze/tests/test_developer_commands.py
+++ b/dev/breeze/tests/test_developer_commands.py
@@ -22,7 +22,7 @@ from unittest.mock import patch
import pytest
from click.testing import CliRunner
-from airflow_breeze.commands.developer_commands import build_docs
+from airflow_breeze.commands.developer_commands import build_docs, run
from airflow_breeze.global_constants import DEFAULT_PYTHON_MAJOR_MINOR_VERSION
@@ -73,3 +73,35 @@ class TestBuildDocsPythonVersion:
assert result.exit_code != 0
assert "no such option" in result.output.lower()
+
+
+class TestRunIncludeMypyVolume:
+ @pytest.fixture(autouse=True)
+ def _no_docker(self, monkeypatch):
+ monkeypatch.setenv("SKIP_SAVING_CHOICES", "true")
+ monkeypatch.delenv("INCLUDE_MYPY_VOLUME", raising=False)
+ monkeypatch.setattr(
+
"airflow_breeze.commands.developer_commands.bring_compose_project_down", lambda
*a, **kw: None
+ )
+ for name in ("fix_ownership_using_docker", "remove_docker_networks"):
+
monkeypatch.setattr(f"airflow_breeze.utils.docker_command_utils.{name}", lambda
*a, **kw: None)
+
+ def _invoke(self, runner: CliRunner, args: list[str], env: dict[str, str]
| None = None):
+ with (
+
patch("airflow_breeze.commands.ci_image_commands.build_ci_image_if_needed"),
+
patch("airflow_breeze.utils.docker_command_utils.execute_command_in_shell") as
mock_shell,
+ ):
+ mock_shell.return_value.returncode = 0
+ runner.invoke(run, [*args, "true"], env=env,
catch_exceptions=False)
+ return mock_shell.call_args.kwargs["shell_params"]
+
+ @pytest.mark.parametrize(
+ ("args", "env", "expected"),
+ [
+ pytest.param([], None, False, id="default"),
+ pytest.param(["--include-mypy-volume"], None, True, id="flag"),
+ pytest.param([], {"INCLUDE_MYPY_VOLUME": "true"}, True, id="env"),
+ ],
+ )
+ def test_include_mypy_volume_is_passed_to_shell_params(self, runner, args,
env, expected):
+ assert self._invoke(runner, args, env=env).include_mypy_volume is
expected
diff --git a/dev/breeze/tests/test_shell_params.py
b/dev/breeze/tests/test_shell_params.py
index 0d67d51e017..41f3dfdaf4c 100644
--- a/dev/breeze/tests/test_shell_params.py
+++ b/dev/breeze/tests/test_shell_params.py
@@ -25,7 +25,10 @@ from rich.console import Console
from airflow_breeze.branch_defaults import AIRFLOW_BRANCH
from airflow_breeze.params.shell_params import ShellParams
-from airflow_breeze.utils.path_utils import SCRIPTS_CI_DOCKER_COMPOSE_BASE_PATH
+from airflow_breeze.utils.path_utils import (
+ SCRIPTS_CI_DOCKER_COMPOSE_BASE_PATH,
+ SCRIPTS_CI_DOCKER_COMPOSE_PATH,
+)
console = Console(width=400, color_system="standard")
@@ -218,3 +221,8 @@ def
test_generated_env_files_do_not_change_when_pythonwarnings_is_set(tmp_path,
def test_pythonwarnings_is_forwarded_by_the_compose_base_file():
base_compose_file =
yaml.safe_load(SCRIPTS_CI_DOCKER_COMPOSE_BASE_PATH.read_text())
assert "PYTHONWARNINGS" in
base_compose_file["services"]["airflow"]["environment"]
+
+
+def test_include_mypy_volume_adds_mypy_compose_file():
+ compose_files =
ShellParams(include_mypy_volume=True).compose_file.split(":")
+ assert str(SCRIPTS_CI_DOCKER_COMPOSE_PATH / "mypy.yml") in compose_files