This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new ababf5cea5b Fix Breeze ownership fix-up chowning all sources under
rootless Docker (#73606)
ababf5cea5b is described below
commit ababf5cea5b49c3bba97318edba0d64ba39d5b91
Author: David Blain <[email protected]>
AuthorDate: Wed Sep 23 23:25:57 2026 +0200
Fix Breeze ownership fix-up chowning all sources under rootless Docker
(#73606)
Breeze skips the ownership fix-up when Docker runs in rootless mode, because
container root already maps to the host user. The flag however reached the
in-container script as the Python literal "True" while the script only skips
on lowercase "true", so the skip never applied: every file that looked
root-owned inside the container (all of the host user's files) was chowned
to the mapped user id and ended up owned by a subordinate uid on the host,
leaving the checkout unusable after each `breeze run` or hook that uses it.
---
.../airflow_breeze/utils/docker_command_utils.py | 2 +-
dev/breeze/tests/test_docker_command_utils.py | 28 ++++++++++++++++++++++
scripts/in_container/run_fix_ownership.py | 2 +-
3 files changed, 30 insertions(+), 2 deletions(-)
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 21604a24145..68b7182f528 100644
--- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
@@ -714,7 +714,7 @@ def fix_ownership_using_docker(quiet: bool = True):
"-e",
f"VERBOSE={str(get_verbose()).lower()}",
"-e",
- f"DOCKER_IS_ROOTLESS={is_docker_rootless()}",
+ f"DOCKER_IS_ROOTLESS={str(is_docker_rootless()).lower()}",
"--rm",
"-t",
OWNERSHIP_CLEANUP_DOCKER_TAG,
diff --git a/dev/breeze/tests/test_docker_command_utils.py
b/dev/breeze/tests/test_docker_command_utils.py
index a0ef5bffd73..81a03867c87 100644
--- a/dev/breeze/tests/test_docker_command_utils.py
+++ b/dev/breeze/tests/test_docker_command_utils.py
@@ -39,6 +39,7 @@ from airflow_breeze.utils.docker_command_utils import (
check_docker_version,
discover_running_compose_projects,
enter_shell,
+ fix_ownership_using_docker,
get_images_to_pull,
is_known_breeze_compose_project,
prepare_docker_build_command,
@@ -640,3 +641,30 @@ def
test_prepare_docker_build_command_does_not_add_sources_hash_label_to_prod_im
mock_check_if_buildx_plugin_installed.return_value = False
command = prepare_docker_build_command(BuildProdParams())
assert not any(flag.startswith(CI_IMAGE_SOURCES_HASH_LABEL) for flag in
command)
+
+
[email protected]("airflow_breeze.utils.docker_command_utils.run_command")
[email protected]("airflow_breeze.utils.docker_command_utils.get_main_git_dir_for_worktree",
return_value=None)
[email protected]("airflow_breeze.utils.docker_command_utils.get_host_group_id",
return_value=1000)
[email protected]("airflow_breeze.utils.docker_command_utils.get_host_user_id",
return_value=1000)
[email protected]("airflow_breeze.utils.docker_command_utils.get_host_os",
return_value="linux")
[email protected]("airflow_breeze.utils.docker_command_utils.is_docker_rootless")
[email protected](
+ ("rootless", "expected"),
+ [(True, "DOCKER_IS_ROOTLESS=true"), (False, "DOCKER_IS_ROOTLESS=false")],
+)
+def test_fix_ownership_using_docker_passes_lowercase_rootless_flag(
+ mock_is_docker_rootless,
+ _mock_get_host_os,
+ _mock_get_host_user_id,
+ _mock_get_host_group_id,
+ _mock_get_main_git_dir,
+ mock_run_command,
+ rootless,
+ expected,
+):
+ """The in-container script compares the flag with lowercase ``true``, so
``True`` would never skip."""
+ mock_is_docker_rootless.return_value = rootless
+ fix_ownership_using_docker()
+ docker_command = mock_run_command.call_args[0][0]
+ assert expected in docker_command
diff --git a/scripts/in_container/run_fix_ownership.py
b/scripts/in_container/run_fix_ownership.py
index 184c6da0bb9..581b3365cbf 100755
--- a/scripts/in_container/run_fix_ownership.py
+++ b/scripts/in_container/run_fix_ownership.py
@@ -24,7 +24,7 @@ import sys
from pathlib import Path
HOST_OS = os.environ.get("HOST_OS", "")
-DOCKER_IS_ROOTLESS = os.environ.get("DOCKER_IS_ROOTLESS", "false") == "true"
+DOCKER_IS_ROOTLESS = os.environ.get("DOCKER_IS_ROOTLESS", "false").lower() ==
"true"
def change_ownership_of_files(path: Path) -> None: