Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/gomod-patch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ EOF
# Note: 'go work vendor' requires Go 1.22+
if [ -f "$gowork_path" ]; then
# Check if 'go work vendor' is available (Go 1.22+)
if go work vendor -h >/dev/null 2>&1; then
if go help work vendor >/dev/null 2>&1; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some tests to cover this code path?

echo " Running go work vendor to sync workspace vendor directory"
go work vendor
else
Expand Down
94 changes: 94 additions & 0 deletions test/linux_target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2578,6 +2578,100 @@ func True(t interface{}, value bool, msgAndArgs ...interface{}) bool {
})
})

t.Run("gomod replace with go work and vendor syncs workspace transitive deps", func(t *testing.T) {
t.Parallel()
ctx := startTestSpan(baseCtx, t)

// 'go work vendor' requires Go 1.22+. On older distros the script falls back
// to 'GOWORK=off go mod vendor', which does not walk workspace sub-modules.
// Skip rather than fail on those targets.
skip.If(t, !testConfig.SupportsGomodVersionUpdate,
"Test requires Go 1.22+ for 'go work vendor' support")

// This test specifically covers the case where a replace directive introduces
// a transitive dependency that is only reachable through a workspace sub-module,
// not the root module. With the correct 'go work vendor' behaviour, the dep
// must appear in vendor/. With the broken 'GOWORK=off go mod vendor' fallback
// it will be missing, causing a GOPROXY=off build failure.
pg := dalec.ProgressGroup("Setup test context")
contextSt := llb.Scratch().
// Root module — no dependencies at all. This is critical: with GOWORK=off
// go mod vendor, the root has nothing to vendor so testify would be absent.
// Only 'go work vendor' walks the full workspace and vendors sub-module deps.
File(llb.Mkfile("/go.mod", 0644, []byte("module example.com/root\n\ngo 1.18\n")), pg).
File(llb.Mkfile("/go.work", 0644, []byte("go 1.18\n\nuse .\nuse ./sub\n")), pg).
File(llb.Mkfile("/main.go", 0644, []byte(`package main
func main() {}
`)), pg).
// Sub-module — requires testify. Only reachable via go.work, not via root go.mod.
File(llb.Mkdir("/sub", 0755), pg).
File(llb.Mkfile("/sub/go.mod", 0644, []byte(
"module example.com/sub\n\ngo 1.18\n\nrequire github.com/stretchr/testify v1.9.0\n",
)), pg).
File(llb.Mkfile("/sub/sub.go", 0644, []byte(`package sub
import _ "github.com/stretchr/testify/assert"
`)), pg).
// Minimal vendor dir — just a marker file so gomod-patch.sh knows to run
// 'go work vendor'. Contains NO pre-existing testify files, so if testify
// appears in vendor after patching it proves 'go work vendor' ran (not
// 'GOWORK=off go mod vendor', which would produce an empty vendor for a
// root module with no dependencies). Adding files via patch is safe from
// the dpkg-source --include-removal issue; only deletions are skipped.
File(llb.Mkdir("/vendor", 0755), pg).
File(llb.Mkfile("/vendor/modules.txt", 0644, []byte("## workspace\n")), pg)

const contextName = "gowork-vendor-transitive-test"
spec := &dalec.Spec{
Name: "test-gomod-gowork-vendor-transitive",
Version: "0.0.1",
Revision: "1",
License: "MIT",
Website: "https://github.com/project-dalec/dalec",
Vendor: "Dalec",
Packager: "Dalec",
Description: "Testing that go work vendor syncs workspace sub-module transitive deps",
Sources: map[string]dalec.Source{
"src": {
Context: &dalec.SourceContext{Name: contextName},
Generate: []*dalec.SourceGenerator{
{
Gomod: &dalec.GeneratorGomod{
Edits: &dalec.GomodEdits{
Replace: []dalec.GomodReplace{
// Bump testify — this is only a dep of the sub-module,
// not the root. GOWORK=off go mod vendor would miss it.
{Original: "github.com/stretchr/testify", Update: "github.com/stretchr/testify@v1.8.0"},
},
},
},
},
},
},
},
Dependencies: &dalec.PackageDependencies{
Build: map[string]dalec.PackageConstraints{
testConfig.GetPackage("golang"): {},
},
},
Build: dalec.ArtifactBuild{
Steps: []dalec.BuildStep{
// testify/assert must be present in the vendor directory.
// This is only possible if 'go work vendor' walked the full workspace
// graph and included the sub-module's dependencies. If the broken
// 'GOWORK=off go mod vendor' fallback ran instead, only the root module's
// dependencies would be vendored — and the root module doesn't require
// testify, so it would be absent.
{Command: "test -d ./src/vendor/github.com/stretchr/testify/assert"},
},
},
}

testEnv.RunTest(ctx, t, func(ctx context.Context, client gwclient.Client) {
req := newSolveRequest(withBuildTarget(testConfig.Target.Container), withSpec(ctx, t, spec), withBuildContext(ctx, t, contextName, contextSt))
solveT(ctx, t, client, req)
})
})

t.Run("gomod go work version sync", func(t *testing.T) {
t.Parallel()
ctx := startTestSpan(baseCtx, t)
Expand Down
Loading