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 2ae713862c3 [v3-3-test] Fix Breeze ownership fix-up chowning all 
sources under rootless Docker (#73606) (#73641)
2ae713862c3 is described below

commit 2ae713862c39e10840cb3e0335d30ff9e17133ec
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Sep 23 23:41:59 2026 +0200

    [v3-3-test] Fix Breeze ownership fix-up chowning all sources under rootless 
Docker (#73606) (#73641)
    
    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.
    (cherry picked from commit ababf5cea5b49c3bba97318edba0d64ba39d5b91)
    
    Co-authored-by: David Blain <[email protected]>
---
 .../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 a1f00c574e9..2e1bbc66202 100644
--- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
@@ -709,7 +709,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 555cf897b3c..b9f6fe6cea4 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,
@@ -639,3 +640,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:

Reply via email to