Skip to content

Commit

Permalink
Explicitly forbid workspace vendoring
Browse files Browse the repository at this point in the history
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.

For more info, see:
- https://go.dev/doc/go1.22#tools
- golang/go#60056

Signed-off-by: Bruno Pimentel <[email protected]>
  • Loading branch information
brunoapimentel committed Jul 15, 2024
1 parent 95bdbdf commit b867ab2
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
13 changes: 13 additions & 0 deletions cachito/workers/pkg_managers/gomod.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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,
Expand Down
39 changes: 39 additions & 0 deletions tests/test_workers/test_pkg_managers/test_gomod.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -881,6 +883,43 @@ def test_vet_local_file_dep_paths_outside_repo():
gomod._vet_local_file_dep_paths(dependencies, app_dir, git_dir)


def test_vet_workspace_vendoring(tmp_path: Path):
go = mock.Mock()
go.return_value = str(tmp_path / "go.work")
(tmp_path / "vendor").mkdir()

expect_error = "Workspace vendoring introduced in Go 1.22 is not supported"
with pytest.raises(UnsupportedFeature, match=expect_error):
gomod._vet_workspace_vendoring(go, {})


def test_workspaces_are_allowed_if_no_vendoring(tmp_path: Path):
go = mock.Mock()
go.return_value = str(tmp_path / "go.work")

gomod._vet_workspace_vendoring(go, {})
go.assert_called_once_with(["env", "GOWORK"], {})


@pytest.mark.parametrize(
"go_work_env",
[
pytest.param("off", id="go_work_off"),
pytest.param("", id="go_work_empty"),
],
)
def test_vendoring_is_allowed_if_no_workspaces(
go_work_env: str,
tmp_path: Path,
):
go = mock.Mock()
go.return_value = go_work_env
(tmp_path / "vendor").mkdir()

gomod._vet_workspace_vendoring(go, {})
go.assert_called_once_with(["env", "GOWORK"], {})


@pytest.mark.parametrize(
"main_module_deps, pkg_deps_pre, pkg_deps_post",
[
Expand Down

0 comments on commit b867ab2

Please sign in to comment.