diff --git a/pre_commit/languages/docker.py b/pre_commit/languages/docker.py index 26328515..f0cc5346 100644 --- a/pre_commit/languages/docker.py +++ b/pre_commit/languages/docker.py @@ -10,6 +10,7 @@ from pre_commit.prefix import Prefix from pre_commit.util import CalledProcessError from pre_commit.util import cmd_output_b +ENV_VAR_OVERRIDE_HOST_PATH = 'PRE_COMMIT_OVERRIDE_DOCKER_HOST_PATH' ENVIRONMENT_DIR = 'docker' PRE_COMMIT_LABEL = 'PRE_COMMIT' get_default_version = lang_base.basic_get_default_version @@ -37,6 +38,8 @@ def _get_container_id() -> str: def _get_docker_path(path: str) -> str: + if ENV_VAR_OVERRIDE_HOST_PATH in os.environ: + return os.environ[ENV_VAR_OVERRIDE_HOST_PATH] if not _is_in_docker(): return path diff --git a/tests/languages/docker_test.py b/tests/languages/docker_test.py index 836382a8..45d8aa3c 100644 --- a/tests/languages/docker_test.py +++ b/tests/languages/docker_test.py @@ -33,6 +33,8 @@ DOCKER_CGROUP_EXAMPLE = b'''\ # The ID should match the above cgroup example. CONTAINER_ID = 'c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7' # noqa: E501 +HOST_PATH_ENV_VAR_OVERRIDE_EXAMPLE = '/host/path/override' + NON_DOCKER_CGROUP_EXAMPLE = b'''\ 12:perf_event:/ 11:hugetlb:/ @@ -96,18 +98,52 @@ def test_get_container_id_failure(): docker._get_container_id() -def test_get_docker_path_not_in_docker_returns_same(): - with mock.patch.object(docker, '_is_in_docker', return_value=False): +def test_get_docker_path_not_in_docker_returns_same_no_env_var(): + with mock.patch.object( + docker, + '_is_in_docker', + return_value=False, + ), mock.patch.dict( + docker.os.environ, + {}, + clear=True, + ): assert docker._get_docker_path('abc') == 'abc' +def test_get_docker_path_not_in_docker_returns_override_env_var(): + with mock.patch.object( + docker, + '_is_in_docker', + return_value=False, + ), mock.patch.dict( + docker.os.environ, + { + docker.ENV_VAR_OVERRIDE_HOST_PATH: + HOST_PATH_ENV_VAR_OVERRIDE_EXAMPLE, + }, + clear=True, + ): + assert docker._get_docker_path('abc') == \ + HOST_PATH_ENV_VAR_OVERRIDE_EXAMPLE + + @pytest.fixture def in_docker(): - with mock.patch.object(docker, '_is_in_docker', return_value=True): - with mock.patch.object( - docker, '_get_container_id', return_value=CONTAINER_ID, - ): - yield + with mock.patch.dict( + docker.os.environ, + {}, + clear=True, + ), mock.patch.object( + docker, + '_is_in_docker', + return_value=True, + ), mock.patch.object( + docker, + '_get_container_id', + return_value=CONTAINER_ID, + ): + yield def _linux_commonpath(): @@ -130,6 +166,19 @@ def test_get_docker_path_in_docker_no_binds_same_path(in_docker): assert docker._get_docker_path('abc') == 'abc' +def test_get_docker_path_in_docker_env_var_override(): + with mock.patch.dict( + docker.os.environ, + { + docker.ENV_VAR_OVERRIDE_HOST_PATH: + HOST_PATH_ENV_VAR_OVERRIDE_EXAMPLE, + }, + clear=True, + ): + assert docker._get_docker_path('/project') == \ + HOST_PATH_ENV_VAR_OVERRIDE_EXAMPLE + + def test_get_docker_path_in_docker_binds_path_equal(in_docker): binds_list = [{'Source': '/opt/my_code', 'Destination': '/project'}] docker_out = json.dumps([{'Mounts': binds_list}]).encode()