From 8f50224b1e30abd32372560c604b1b63ece45459 Mon Sep 17 00:00:00 2001 From: Bruno Pimentel Date: Fri, 12 Jul 2024 14:34:22 -0300 Subject: [PATCH] Explicitly forbid workspace vendoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ability to vendor dependencies in projects that make use of workspaces was introduced in Go 1.22¹. Cachito currently does not support the use of "go work vendor", so this commit introduces an explicit check for that scenario and a clearer error message. Note that by design, Go does not allow the use of "go mod vendor" if workspaces are present, so the check assumes that the existence of a vendor folder in a project with workspaces means that workspace vendoring is being used. ¹ https://github.com/golang/go/issues/60056 Signed-off-by: Bruno Pimentel --- cachito/workers/pkg_managers/gomod.py | 13 +++++++ .../test_pkg_managers/test_gomod.py | 38 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/cachito/workers/pkg_managers/gomod.py b/cachito/workers/pkg_managers/gomod.py index 8a2d0b633..5c0c62c9c 100644 --- a/cachito/workers/pkg_managers/gomod.py +++ b/cachito/workers/pkg_managers/gomod.py @@ -382,6 +382,7 @@ def resolve_gomod( flags, app_source_path, worker_config.cachito_gomod_strict_vendor ) if should_vendor: + _vet_workspace_vendoring(go, run_params) downloaded_modules = _vendor_deps(go, run_params, can_make_changes, git_dir_path) else: log.info("Downloading the gomod dependencies") @@ -506,6 +507,18 @@ def go_list_deps(pattern: Literal["./...", "all"]) -> Iterator[GoPackage]: } +def _vet_workspace_vendoring(go: Go, run_params: dict[str, Any]) -> None: + go_work_file = go(["env", "GOWORK"], run_params).rstrip() + + if not go_work_file or go_work_file == "off": + return + + vendor_dir = Path(go_work_file).parent / "vendor" + + if vendor_dir.is_dir(): + raise UnsupportedFeature("Workspace vendoring introduced in Go 1.22 is not supported") + + def _set_local_modules_versions( local_modules: LocalModules, git_dir_path: Path, diff --git a/tests/test_workers/test_pkg_managers/test_gomod.py b/tests/test_workers/test_pkg_managers/test_gomod.py index a6c43fbb1..32de9d8e7 100644 --- a/tests/test_workers/test_pkg_managers/test_gomod.py +++ b/tests/test_workers/test_pkg_managers/test_gomod.py @@ -211,7 +211,9 @@ def test_resolve_gomod( @mock.patch("cachito.workers.pkg_managers.gomod.GoCacheTemporaryDirectory") @mock.patch("subprocess.run") @mock.patch("cachito.workers.pkg_managers.gomod.RequestBundleDir") +@mock.patch("cachito.workers.pkg_managers.gomod._vet_workspace_vendoring") def test_resolve_gomod_vendor_dependencies( + mock_vet_workspace_vendoring: mock.Mock, mock_bundle_dir: mock.Mock, mock_run: mock.Mock, mock_temp_dir: mock.Mock, @@ -881,6 +883,42 @@ def test_vet_local_file_dep_paths_outside_repo(): gomod._vet_local_file_dep_paths(dependencies, app_dir, git_dir) +@pytest.mark.parametrize( + "go_work_env, vendor_folder_exists, raise_error", + [ + pytest.param("go.work", True, True, id="workspace_vendoring"), + pytest.param("go.work", False, False, id="workspaces_no_vendoring"), + pytest.param("off", True, False, id="go_work_off"), + pytest.param("", True, False, id="go_work_empty"), + ], +) +def test_vet_workspace_vendoring( + go_work_env: str, + vendor_folder_exists: bool, + raise_error: bool, + tmp_path: Path, +): + go = mock.Mock() + + if go_work_env == "go.work": + go.return_value = str(tmp_path / "go.work") + else: + go.return_value = go_work_env + + if vendor_folder_exists: + (tmp_path / "vendor").mkdir() + + expect_error = "Workspace vendoring introduced in Go 1.22 is not supported" + + if raise_error: + with pytest.raises(UnsupportedFeature, match=expect_error): + gomod._vet_workspace_vendoring(go, {}) + else: + gomod._vet_workspace_vendoring(go, {}) + + go.assert_called_once_with(["env", "GOWORK"], {}) + + @pytest.mark.parametrize( "main_module_deps, pkg_deps_pre, pkg_deps_post", [