From e49bb34e87bc4ef3cdcff2eb9469d198e451f3c6 Mon Sep 17 00:00:00 2001 From: Tom Chauveau Date: Fri, 11 Feb 2022 14:52:08 +0100 Subject: [PATCH] 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" + } +}