Skip to content
Open
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
63 changes: 62 additions & 1 deletion .dagger/modules/e2e/main.dang
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ End-to-end checks for the Go module.
type E2e {
let generatedFixturePath: String! = "testdata/go-module-generate"
let generatedFilePath: String! = generatedFixturePath + "/generated.go"
let baseFixturePath: String! = "testdata/go-module-custom-base"
let baseGeneratedFilePath: String! = baseFixturePath + "/generated.go"
let emptyFixturePath: String! = "testdata/go-module-empty"

let base: Container! {
container
.from("golang:1.25-alpine")
.withEnvVariable("DAGGER_GO_CUSTOM_BASE", "yes")
.withNewFile("/custom-go-base", "yes\n")
}

let assert(condition: Boolean!, message: String!): Void {
if (condition == false) {
raise message
Expand Down Expand Up @@ -58,19 +67,71 @@ type E2e {
go(version: "1.25").module(ws, "fixtures/go-module-with-replace").test(ws)
}

"""
A custom base container must be used for Go helpers, tests, and generate.
"""
pub baseCheck(ws: Workspace!): Void @check {
let tool = go(
base: base,
skipLintFilename: ".dagger-skip-lint-disabled",
skipTestFilename: ".dagger-skip-test-disabled",
skipGenerateFilename: ".dagger-skip-generate-disabled",
)
let mod = tool.module(ws, baseFixturePath)

assert(
tool.version == null,
"base-only constructor exposed a Go version for a black-box base image",
)

let conflict = try {
go(version: "1.25", base: base).version ?? "missing conflict"
} catch {
err => err.message
}
assert(
conflict.contains("version and base are mutually exclusive"),
"constructor did not reject version and base together: " + conflict,
)

let testDirs = mod.testDirectories(ws)
assert(
containsModulePath(testDirs.{path}, baseFixturePath),
"custom base test directory discovery did not include expected path",
)

mod.test(ws)

let changes = mod.generate(ws)
assert(
containsPath(changes.addedPaths, baseGeneratedFilePath),
"custom base generate did not add expected path: " + baseGeneratedFilePath,
)
assert(
changes.layer.file(baseGeneratedFilePath).contents.contains("GeneratedFromBase"),
"custom base generate did not produce expected contents",
)

null
}

"""
Per-module introspection fields must expose the source selection intermediates.
"""
pub moduleIntrospectionCheck(ws: Workspace!): Void @check {
let mod = go(version: "1.25").module(ws, "testdata/go-module-with-testdata/testdata")

assert(
go().version == "1.26",
"default constructor did not expose default Go version",
)
assert(
mod.path == "testdata/go-module-with-testdata",
"module lookup did not snap to containing module: " + mod.path,
)
assert(
mod.version == "1.25",
"module did not expose inherited Go version: " + mod.version,
"module did not expose inherited Go version: " + (mod.version ?? "<null>"),
)

let direct = go(version: "1.25").module(ws, "testdata/go-module-with-testdata/testdata", findUp: false)
Expand Down
86 changes: 68 additions & 18 deletions go.dang
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,56 @@ https://golang.org
"""
type Go {
"""
Go version used for test and generate commands.
"""
pub version: String! = "1.26"
Go version used for the default Go base image. Null when a custom base is set.
"""
pub version: String

"""
Base image used for Go test, generate, and helper containers.
"""
pub base: Container!

new(
"""
Go version used for the default Go base image.
"""
version: String = null,
"""
Base image used for Go test, generate, and helper containers.
Mutually exclusive with version.
"""
base: Container = null,
"""
Extra workspace-root include patterns mounted for each module's Go commands.
Use this for fixtures, generator inputs, or other files not covered by the
built-in Go patterns.
"""
includeExtraFiles: [String!]! = [],
"""
Marker filename that skips lint checks when found at or above a Go module root.
"""
skipLintFilename: String! = ".dagger-skip-go-lint",
"""
Marker filename that skips tests when found at or above a Go module root.
"""
skipTestFilename: String! = ".dagger-skip-go-test",
"""
Marker filename that skips go generate when found at or above a Go module root.
"""
skipGenerateFilename: String! = ".dagger-skip-go-generate",
) {
if (version != null and base != null) {
raise "version and base are mutually exclusive"
} else {
self.version = if (base == null) { version ?? "1.26" } else { null }
self.base = base ?? container.from("golang:" + (version ?? "1.26") + "-alpine")
self.includeExtraFiles = includeExtraFiles
self.skipLintFilename = skipLintFilename
self.skipTestFilename = skipTestFilename
self.skipGenerateFilename = skipGenerateFilename
self
}
}

"""
Extra workspace-root include patterns mounted for each module's Go commands.
Expand Down Expand Up @@ -67,6 +114,7 @@ type Go {
GoModule(
path: modPath,
version: version,
baseImage: base,
includeExtraFiles: includeExtraFiles,
skipLintFilename: skipLintFilename,
skipTestFilename: skipTestFilename,
Expand Down Expand Up @@ -133,6 +181,7 @@ type Go {
path.trimPrefix("/")
},
version: version,
baseImage: base,
includeExtraFiles: includeExtraFiles,
skipLintFilename: skipLintFilename,
skipTestFilename: skipTestFilename,
Expand Down Expand Up @@ -218,9 +267,14 @@ type GoModule {
pub path: String!

"""
Go version used by this module's test and generate containers.
Go version configured on the root Go module. Null when a custom base is set.
"""
pub version: String

"""
Base image used by this module's Go containers.
"""
pub version: String!
let baseImage: Container!

"""
Extra workspace-root include patterns mounted for this module's Go commands.
Expand Down Expand Up @@ -268,8 +322,7 @@ type GoModule {
Base container for the Go include helper.
"""
let goIncludesHelper(ws: Workspace!): Container! {
container
.from("golang:" + version + "-alpine")
baseImage
.withoutEntrypoint
.withWorkdir("/helpers/go-includes")
.withMountedCache("/go/pkg/mod", cacheVolume("go-mod"))
Expand Down Expand Up @@ -380,7 +433,7 @@ type GoModule {
path: testPath,
ws: ws,
modulePath: path,
version: version,
baseImage: baseImage,
includeExtraFiles: includeExtraFiles,
skipTestFilename: skipTestFilename,
testSkipMarkers: testSkipMarkers,
Expand Down Expand Up @@ -472,8 +525,7 @@ type GoModule {
Base Go container before source files and commands are added.
"""
pub base: Container! {
container
.from("golang:" + version + "-alpine")
baseImage
.withoutEntrypoint
.withWorkdir("/ws")
.withMountedCache("/go/pkg/mod", cacheVolume("go-mod"))
Expand Down Expand Up @@ -599,14 +651,14 @@ type GoDirectory {
let modulePath: String!

"""
Go version used by this directory's test container.
Extra workspace-root include patterns mounted for this directory's Go tests.
"""
let version: String!
let includeExtraFiles: [String!]!

"""
Extra workspace-root include patterns mounted for this directory's Go tests.
Base image used by this directory's Go containers.
"""
let includeExtraFiles: [String!]!
let baseImage: Container!

"""
Marker filename that skips tests when found at or above this directory's Go module root.
Expand Down Expand Up @@ -637,8 +689,7 @@ type GoDirectory {
Base container for the Go include helper.
"""
let goIncludesHelper: Container! {
container
.from("golang:" + version + "-alpine")
baseImage
.withoutEntrypoint
.withWorkdir("/helpers/go-includes")
.withMountedCache("/go/pkg/mod", cacheVolume("go-mod"))
Expand Down Expand Up @@ -709,8 +760,7 @@ type GoDirectory {
Base Go container before source files and commands are added.
"""
let base: Container! {
container
.from("golang:" + version + "-alpine")
baseImage
.withoutEntrypoint
.withWorkdir("/ws")
.withMountedCache("/go/pkg/mod", cacheVolume("go-mod"))
Expand Down
1 change: 1 addition & 0 deletions testdata/go-module-custom-base/.dagger-skip-go-generate
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skip
1 change: 1 addition & 0 deletions testdata/go-module-custom-base/.dagger-skip-go-lint
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skip
1 change: 1 addition & 0 deletions testdata/go-module-custom-base/.dagger-skip-go-test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
skip
23 changes: 23 additions & 0 deletions testdata/go-module-custom-base/cmd/writegenerated/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import (
"fmt"
"os"
)

func main() {
if got := os.Getenv("DAGGER_GO_CUSTOM_BASE"); got != "yes" {
panic(fmt.Sprintf("DAGGER_GO_CUSTOM_BASE = %q, want yes", got))
}
if _, err := os.Stat("/custom-go-base"); err != nil {
panic(err)
}

const contents = `package custombase

const GeneratedFromBase = true
`
if err := os.WriteFile("generated.go", []byte(contents), 0o644); err != nil {
panic(err)
}
}
15 changes: 15 additions & 0 deletions testdata/go-module-custom-base/custom_base_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package custombase

import (
"os"
"testing"
)

func TestBase(t *testing.T) {
if got := os.Getenv("DAGGER_GO_CUSTOM_BASE"); got != "yes" {
t.Fatalf("DAGGER_GO_CUSTOM_BASE = %q, want yes", got)
}
if _, err := os.Stat("/custom-go-base"); err != nil {
t.Fatalf("custom base marker file is missing: %v", err)
}
}
3 changes: 3 additions & 0 deletions testdata/go-module-custom-base/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package custombase

//go:generate go run ./cmd/writegenerated
3 changes: 3 additions & 0 deletions testdata/go-module-custom-base/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module example.com/custombase

go 1.25