From e49bb34e87bc4ef3cdcff2eb9469d198e451f3c6 Mon Sep 17 00:00:00 2001 From: Tom Chauveau Date: Fri, 11 Feb 2022 14:52:08 +0100 Subject: [PATCH 1/3] Port go package to universe to resolves #1553 Definition are now split in their own file. `#Image` is a simple base image to set up a go container `#Container` is a standalone environment to execute go command, any go command should use this definition. It shares `docker.#Run` fields to easily maintains this definition. `#Build` and `#Test` are high level definition that use `#Container` to execute common go operation in a CI. Those definitions are tested with a simple greeting package. Signed-off-by: Vasek - Tom C --- pkg/universe.dagger.io/go/build.cue | 51 ++++++++++++++++++ pkg/universe.dagger.io/go/container.cue | 53 +++++++++++++++++++ pkg/universe.dagger.io/go/image.cue | 34 ++++++++++++ pkg/universe.dagger.io/go/test.cue | 11 ++++ pkg/universe.dagger.io/go/test/build.cue | 45 ++++++++++++++++ pkg/universe.dagger.io/go/test/container.cue | 18 +++++++ .../go/test/data/hello/go.mod | 3 ++ .../go/test/data/hello/greeting/greeting.go | 7 +++ .../test/data/hello/greeting/greeting_test.go | 13 +++++ .../go/test/data/hello/main.go | 16 ++++++ pkg/universe.dagger.io/go/test/image.cue | 45 ++++++++++++++++ pkg/universe.dagger.io/go/test/test.bats | 10 ++++ pkg/universe.dagger.io/go/test/test.cue | 15 ++++++ 13 files changed, 321 insertions(+) create mode 100644 pkg/universe.dagger.io/go/build.cue create mode 100644 pkg/universe.dagger.io/go/container.cue create mode 100644 pkg/universe.dagger.io/go/image.cue create mode 100644 pkg/universe.dagger.io/go/test.cue create mode 100644 pkg/universe.dagger.io/go/test/build.cue create mode 100644 pkg/universe.dagger.io/go/test/container.cue create mode 100644 pkg/universe.dagger.io/go/test/data/hello/go.mod create mode 100644 pkg/universe.dagger.io/go/test/data/hello/greeting/greeting.go create mode 100644 pkg/universe.dagger.io/go/test/data/hello/greeting/greeting_test.go create mode 100644 pkg/universe.dagger.io/go/test/data/hello/main.go create mode 100644 pkg/universe.dagger.io/go/test/image.cue create mode 100644 pkg/universe.dagger.io/go/test/test.bats create mode 100644 pkg/universe.dagger.io/go/test/test.cue diff --git a/pkg/universe.dagger.io/go/build.cue b/pkg/universe.dagger.io/go/build.cue new file mode 100644 index 00000000..5684460c --- /dev/null +++ b/pkg/universe.dagger.io/go/build.cue @@ -0,0 +1,51 @@ +package go + +import ( + "dagger.io/dagger" + "dagger.io/dagger/engine" +) + +// Build a go binary +#Build: { + // Go version to use + version: *#Image.version | string + + // Source code + source: dagger.#FS + + // Target package to build + package: *"." | string + + // Target architecture + arch: *"amd64" | string + + // Target OS + os: *"linux" | string + + // Build tags to use for building + tags: *"" | string + + // LDFLAGS to use for linking + ldflags: *"" | string + + // Target binary output + output: string + + env: [string]: string + + _build: #Container & { + "version": version + "source": source + "env": env + args: ["build", "-v", "-tags", tags, "-ldflags", ldflags, "-o", output, package] + } + + _copy: engine.#Copy & { + input: engine.#Scratch + contents: _build.output.rootfs + source: output + dest: output + } + + binary: _copy.output +} diff --git a/pkg/universe.dagger.io/go/container.cue b/pkg/universe.dagger.io/go/container.cue new file mode 100644 index 00000000..617f3b70 --- /dev/null +++ b/pkg/universe.dagger.io/go/container.cue @@ -0,0 +1,53 @@ +// Go operation +package go + +import ( + "dagger.io/dagger" + "dagger.io/dagger/engine" + "universe.dagger.io/docker" +) + +// A standalone go environment to run go command +#Container: { + // Go version to use + version: *#Image.version | string + + // Source code + source: dagger.#FS + + // Arguments + args: [...string] + + // Use go image + _image: #Image & { + "version": version + } + + _sourcePath: "/src" + _cachePath: "/root/.cache/gocache" + + docker.#Run & { + input: _image.output + workdir: "/src" + command: { + name: "go" + "args": args + } + mounts: { + "source": { + dest: _sourcePath + contents: source + } + "go assets cache": { + contents: engine.#CacheDir & { + id: "\(_cachePath)_assets" + } + dest: _cachePath + } + } + env: { + CGO_ENABLED: "0" + GOMODCACHE: _cachePath + } + } +} diff --git a/pkg/universe.dagger.io/go/image.cue b/pkg/universe.dagger.io/go/image.cue new file mode 100644 index 00000000..ff46e0d5 --- /dev/null +++ b/pkg/universe.dagger.io/go/image.cue @@ -0,0 +1,34 @@ +package go + +import ( + "universe.dagger.io/docker" +) + +// Build a go base image +#Image: { + version: *"1.16" | string + + packages: [pkgName=string]: version: string | *"" + + // FIXME Basically a copy of alpine.#Build with a different image + // Should we create a special definition? + docker.#Build & { + steps: [ + docker.#Pull & { + source: "index.docker.io/golang:\(version)-alpine" + }, + for pkgName, pkg in packages { + docker.#Run & { + command: { + name: "apk" + args: ["add", "\(pkgName)\(pkg.version)"] + flags: { + "-U": true + "--no-cache": true + } + } + } + }, + ] + } +} diff --git a/pkg/universe.dagger.io/go/test.cue b/pkg/universe.dagger.io/go/test.cue new file mode 100644 index 00000000..6594bef8 --- /dev/null +++ b/pkg/universe.dagger.io/go/test.cue @@ -0,0 +1,11 @@ +package go + +// Test a go package +#Test: { + // Package to test + package: *"." | string + + #Container & { + args: ["test", "-v", package] + } +} diff --git a/pkg/universe.dagger.io/go/test/build.cue b/pkg/universe.dagger.io/go/test/build.cue new file mode 100644 index 00000000..34e653e1 --- /dev/null +++ b/pkg/universe.dagger.io/go/test/build.cue @@ -0,0 +1,45 @@ +package go + +import ( + "dagger.io/dagger" + "dagger.io/dagger/engine" + "universe.dagger.io/go" + "universe.dagger.io/docker" + "universe.dagger.io/alpine" +) + +dagger.#Plan & { + inputs: directories: testhello: path: "./data/hello" + + actions: tests: build: { + _baseImage: alpine.#Build + + simple: { + build: go.#Build & { + source: inputs.directories.testhello.contents + output: "/bin/hello" + } + + exec: docker.#Run & { + input: _baseImage.output + command: { + name: "/bin/sh" + args: ["-c", "hello >> /output.txt"] + } + env: NAME: "dagger" + mounts: binary: { + dest: build.output + contents: build.binary + source: "/bin/hello" + } + } + + verify: engine.#ReadFile & { + input: exec.output.rootfs + path: "/output.txt" + } & { + contents: "Hi dagger!" + } + } + } +} diff --git a/pkg/universe.dagger.io/go/test/container.cue b/pkg/universe.dagger.io/go/test/container.cue new file mode 100644 index 00000000..b845df9a --- /dev/null +++ b/pkg/universe.dagger.io/go/test/container.cue @@ -0,0 +1,18 @@ +package go + +import ( + "dagger.io/dagger" + "dagger.io/dagger/engine" + "universe.dagger.io/go" +) + +dagger.#Plan & { + actions: tests: container: { + _source: engine.#Scratch & {} + + simple: go.#Container & { + source: _source + args: ["version"] + } + } +} diff --git a/pkg/universe.dagger.io/go/test/data/hello/go.mod b/pkg/universe.dagger.io/go/test/data/hello/go.mod new file mode 100644 index 00000000..496135e4 --- /dev/null +++ b/pkg/universe.dagger.io/go/test/data/hello/go.mod @@ -0,0 +1,3 @@ +module dagger.io/test + +go 1.17 diff --git a/pkg/universe.dagger.io/go/test/data/hello/greeting/greeting.go b/pkg/universe.dagger.io/go/test/data/hello/greeting/greeting.go new file mode 100644 index 00000000..b830aabf --- /dev/null +++ b/pkg/universe.dagger.io/go/test/data/hello/greeting/greeting.go @@ -0,0 +1,7 @@ +package greeting + +import "fmt" + +func Greeting(name string) string { + return fmt.Sprintf("Hi %s!", name) +} diff --git a/pkg/universe.dagger.io/go/test/data/hello/greeting/greeting_test.go b/pkg/universe.dagger.io/go/test/data/hello/greeting/greeting_test.go new file mode 100644 index 00000000..f2f2d812 --- /dev/null +++ b/pkg/universe.dagger.io/go/test/data/hello/greeting/greeting_test.go @@ -0,0 +1,13 @@ +package greeting + +import "testing" + +func TestGreeting(t *testing.T) { + name := "Dagger Test" + expect := "Hi Dagger Test!" + value := Greeting(name) + + if expect != value { + t.Fatalf("Hello(%s) = '%s', expected '%s'", name, value, expect) + } +} diff --git a/pkg/universe.dagger.io/go/test/data/hello/main.go b/pkg/universe.dagger.io/go/test/data/hello/main.go new file mode 100644 index 00000000..262cf293 --- /dev/null +++ b/pkg/universe.dagger.io/go/test/data/hello/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "os" + + "dagger.io/test/greeting" +) + +func main() { + name := os.Getenv("NAME") + if name == "" { + name = "John Doe" + } + fmt.Printf(greeting.Greeting(name)) +} diff --git a/pkg/universe.dagger.io/go/test/image.cue b/pkg/universe.dagger.io/go/test/image.cue new file mode 100644 index 00000000..9d45725b --- /dev/null +++ b/pkg/universe.dagger.io/go/test/image.cue @@ -0,0 +1,45 @@ +package go + +import ( + "dagger.io/dagger" + "dagger.io/dagger/engine" + "universe.dagger.io/go" + "universe.dagger.io/docker" +) + +dagger.#Plan & { + actions: tests: image: { + _source: engine.#Scratch & {} + + simple: { + _image: go.#Image & {} + + verify: docker.#Run & { + input: _image.output + command: { + name: "/bin/sh" + args: ["-c", """ + go version | grep "1.16" + """] + } + } + } + + custom: { + _image: go.#Image & { + version: "1.17" + packages: bash: _ + } + + verify: docker.#Run & { + input: _image.output + command: { + name: "/bin/bash" + args: ["-c", """ + go version | grep "1.17" + """] + } + } + } + } +} diff --git a/pkg/universe.dagger.io/go/test/test.bats b/pkg/universe.dagger.io/go/test/test.bats new file mode 100644 index 00000000..52dc4dc7 --- /dev/null +++ b/pkg/universe.dagger.io/go/test/test.bats @@ -0,0 +1,10 @@ +setup() { + load '../../bats_helpers' + + common_setup +} + +@test "bash" { + dagger up +} + diff --git a/pkg/universe.dagger.io/go/test/test.cue b/pkg/universe.dagger.io/go/test/test.cue new file mode 100644 index 00000000..e37c32e4 --- /dev/null +++ b/pkg/universe.dagger.io/go/test/test.cue @@ -0,0 +1,15 @@ +package go + +import ( + "dagger.io/dagger" + "universe.dagger.io/go" +) + +dagger.#Plan & { + inputs: directories: testhello: path: "./data/hello" + + actions: tests: test: simple: go.#Test & { + source: inputs.directories.testhello.contents + package: "./greeting" + } +} From 2887139bf7c4f1d8b867c39b32cf7076c9808681 Mon Sep 17 00:00:00 2001 From: Tom Chauveau Date: Thu, 17 Feb 2022 15:56:19 +0100 Subject: [PATCH 2/3] Apply Solomon comments on universe.dagger.io/go - Improve #Container with a better docker.#Run integration - Supports concurrency caching in #Container - Simplify code maintainability and readability - Simplify binary export in #Build - Support multi binary building - External #Version management Signed-off-by: Vasek - Tom C --- pkg/universe.dagger.io/cue.mod/pkg/.gitignore | 3 +- pkg/universe.dagger.io/go/build.cue | 35 +++++++++---------- pkg/universe.dagger.io/go/container.cue | 18 +++++----- pkg/universe.dagger.io/go/image.cue | 5 ++- pkg/universe.dagger.io/go/test.cue | 8 ++++- pkg/universe.dagger.io/go/test/build.cue | 10 +++--- pkg/universe.dagger.io/go/test/container.cue | 5 ++- pkg/universe.dagger.io/go/test/image.cue | 3 +- 8 files changed, 45 insertions(+), 42 deletions(-) diff --git a/pkg/universe.dagger.io/cue.mod/pkg/.gitignore b/pkg/universe.dagger.io/cue.mod/pkg/.gitignore index 5089911a..331f139d 100644 --- a/pkg/universe.dagger.io/cue.mod/pkg/.gitignore +++ b/pkg/universe.dagger.io/cue.mod/pkg/.gitignore @@ -1,4 +1,5 @@ # generated by dagger dagger.lock alpha.dagger.io -universe.dagger.io +dagger.io +universe.dagger.io \ No newline at end of file diff --git a/pkg/universe.dagger.io/go/build.cue b/pkg/universe.dagger.io/go/build.cue index 5684460c..b8084c07 100644 --- a/pkg/universe.dagger.io/go/build.cue +++ b/pkg/universe.dagger.io/go/build.cue @@ -2,14 +2,10 @@ package go import ( "dagger.io/dagger" - "dagger.io/dagger/engine" ) // Build a go binary #Build: { - // Go version to use - version: *#Image.version | string - // Source code source: dagger.#FS @@ -28,24 +24,27 @@ import ( // LDFLAGS to use for linking ldflags: *"" | string - // Target binary output - output: string - env: [string]: string - _build: #Container & { - "version": version - "source": source - "env": env - args: ["build", "-v", "-tags", tags, "-ldflags", ldflags, "-o", output, package] + container: #Container & { + "source": source + "env": env + command: { + args: [package] + flags: { + build: true + "-v": true + "-tags": tags + "-ldflags": ldflags + "-o": "/output/" + } + } } - _copy: engine.#Copy & { - input: engine.#Scratch - contents: _build.output.rootfs - source: output - dest: output + _binary: dagger.#Subdir & { + input: container.output.rootfs + path: "/output" } - binary: _copy.output + binary: _binary.output } diff --git a/pkg/universe.dagger.io/go/container.cue b/pkg/universe.dagger.io/go/container.cue index 617f3b70..cc7da69c 100644 --- a/pkg/universe.dagger.io/go/container.cue +++ b/pkg/universe.dagger.io/go/container.cue @@ -3,20 +3,21 @@ package go import ( "dagger.io/dagger" - "dagger.io/dagger/engine" "universe.dagger.io/docker" ) // A standalone go environment to run go command #Container: { // Go version to use - version: *#Image.version | string + version: *#DefaultVersion | string // Source code source: dagger.#FS - // Arguments - args: [...string] + // Configure caching + cache: { + id: *"go_build" | string + } // Use go image _image: #Image & { @@ -29,18 +30,15 @@ import ( docker.#Run & { input: _image.output workdir: "/src" - command: { - name: "go" - "args": args - } + command: name: "go" mounts: { "source": { dest: _sourcePath contents: source } "go assets cache": { - contents: engine.#CacheDir & { - id: "\(_cachePath)_assets" + contents: dagger.#CacheDir & { + id: "\(cache.id)_assets" } dest: _cachePath } diff --git a/pkg/universe.dagger.io/go/image.cue b/pkg/universe.dagger.io/go/image.cue index ff46e0d5..9edbd2da 100644 --- a/pkg/universe.dagger.io/go/image.cue +++ b/pkg/universe.dagger.io/go/image.cue @@ -4,9 +4,12 @@ import ( "universe.dagger.io/docker" ) +// Go image default version +#DefaultVersion: "1.16" + // Build a go base image #Image: { - version: *"1.16" | string + version: *#DefaultVersion | string packages: [pkgName=string]: version: string | *"" diff --git a/pkg/universe.dagger.io/go/test.cue b/pkg/universe.dagger.io/go/test.cue index 6594bef8..5de2b94b 100644 --- a/pkg/universe.dagger.io/go/test.cue +++ b/pkg/universe.dagger.io/go/test.cue @@ -6,6 +6,12 @@ package go package: *"." | string #Container & { - args: ["test", "-v", package] + command: { + args: [package] + flags: { + test: true + "-v": true + } + } } } diff --git a/pkg/universe.dagger.io/go/test/build.cue b/pkg/universe.dagger.io/go/test/build.cue index 34e653e1..8f8dba2c 100644 --- a/pkg/universe.dagger.io/go/test/build.cue +++ b/pkg/universe.dagger.io/go/test/build.cue @@ -2,7 +2,6 @@ package go import ( "dagger.io/dagger" - "dagger.io/dagger/engine" "universe.dagger.io/go" "universe.dagger.io/docker" "universe.dagger.io/alpine" @@ -17,24 +16,23 @@ dagger.#Plan & { simple: { build: go.#Build & { source: inputs.directories.testhello.contents - output: "/bin/hello" } exec: docker.#Run & { input: _baseImage.output command: { name: "/bin/sh" - args: ["-c", "hello >> /output.txt"] + args: ["-c", "/bin/hello >> /output.txt"] } env: NAME: "dagger" mounts: binary: { - dest: build.output + dest: "/bin/hello" contents: build.binary - source: "/bin/hello" + source: "/test" } } - verify: engine.#ReadFile & { + verify: dagger.#ReadFile & { input: exec.output.rootfs path: "/output.txt" } & { diff --git a/pkg/universe.dagger.io/go/test/container.cue b/pkg/universe.dagger.io/go/test/container.cue index b845df9a..fd925cc3 100644 --- a/pkg/universe.dagger.io/go/test/container.cue +++ b/pkg/universe.dagger.io/go/test/container.cue @@ -2,17 +2,16 @@ package go import ( "dagger.io/dagger" - "dagger.io/dagger/engine" "universe.dagger.io/go" ) dagger.#Plan & { actions: tests: container: { - _source: engine.#Scratch & {} + _source: dagger.#Scratch & {} simple: go.#Container & { source: _source - args: ["version"] + command: args: ["version"] } } } diff --git a/pkg/universe.dagger.io/go/test/image.cue b/pkg/universe.dagger.io/go/test/image.cue index 9d45725b..5a7ecbbb 100644 --- a/pkg/universe.dagger.io/go/test/image.cue +++ b/pkg/universe.dagger.io/go/test/image.cue @@ -2,14 +2,13 @@ package go import ( "dagger.io/dagger" - "dagger.io/dagger/engine" "universe.dagger.io/go" "universe.dagger.io/docker" ) dagger.#Plan & { actions: tests: image: { - _source: engine.#Scratch & {} + _source: dagger.#Scratch & {} simple: { _image: go.#Image & {} From 1e384c4e9a0f8a29e165607b5782e7c51fd1656e Mon Sep 17 00:00:00 2001 From: Tom Chauveau Date: Fri, 18 Feb 2022 15:12:58 +0100 Subject: [PATCH 3/3] Apply Solomon comments - Simplify cache id parameter with a field `name` - Configure GOOS & GOARCH values - Container image can now be overridden - Simplify build export Signed-off-by: Vasek - Tom C --- pkg/universe.dagger.io/go/build.cue | 14 +++++++------- pkg/universe.dagger.io/go/container.cue | 17 +++++------------ pkg/universe.dagger.io/go/test/container.cue | 13 +++++++++++++ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/pkg/universe.dagger.io/go/build.cue b/pkg/universe.dagger.io/go/build.cue index b8084c07..5b4e6e03 100644 --- a/pkg/universe.dagger.io/go/build.cue +++ b/pkg/universe.dagger.io/go/build.cue @@ -28,7 +28,11 @@ import ( container: #Container & { "source": source - "env": env + "env": { + env + GOOS: os + GOARCH: arch + } command: { args: [package] flags: { @@ -39,12 +43,8 @@ import ( "-o": "/output/" } } + export: directories: "/output/": _ } - _binary: dagger.#Subdir & { - input: container.output.rootfs - path: "/output" - } - - binary: _binary.output + binary: container.export.directories."/output/".contents } diff --git a/pkg/universe.dagger.io/go/container.cue b/pkg/universe.dagger.io/go/container.cue index cc7da69c..81e00f28 100644 --- a/pkg/universe.dagger.io/go/container.cue +++ b/pkg/universe.dagger.io/go/container.cue @@ -8,27 +8,20 @@ import ( // A standalone go environment to run go command #Container: { - // Go version to use - version: *#DefaultVersion | string + // Container app name + name: *"go_builder" | string // Source code source: dagger.#FS - // Configure caching - cache: { - id: *"go_build" | string - } - // Use go image - _image: #Image & { - "version": version - } + _image: #Image _sourcePath: "/src" _cachePath: "/root/.cache/gocache" docker.#Run & { - input: _image.output + input: *_image.output | docker.#Image workdir: "/src" command: name: "go" mounts: { @@ -38,7 +31,7 @@ import ( } "go assets cache": { contents: dagger.#CacheDir & { - id: "\(cache.id)_assets" + id: "\(name)_assets" } dest: _cachePath } diff --git a/pkg/universe.dagger.io/go/test/container.cue b/pkg/universe.dagger.io/go/test/container.cue index fd925cc3..ac7056c7 100644 --- a/pkg/universe.dagger.io/go/test/container.cue +++ b/pkg/universe.dagger.io/go/test/container.cue @@ -3,6 +3,7 @@ package go import ( "dagger.io/dagger" "universe.dagger.io/go" + "universe.dagger.io/alpine" ) dagger.#Plan & { @@ -13,5 +14,17 @@ dagger.#Plan & { source: _source command: args: ["version"] } + + overide: { + base: alpine.#Build & { + packages: go: _ + } + + command: go.#Container & { + input: base.output + source: _source + command: args: ["version"] + } + } } }