Skip to content

Commit 03e2e59

Browse files
authored
Merge pull request #391 from sapcc/docker-test-target
Add docker test target which can be easily run in concourse
2 parents 4253fc3 + 510798f commit 03e2e59

File tree

7 files changed

+106
-37
lines changed

7 files changed

+106
-37
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ Since only entire packages (not single source files) can be selected for coverag
170170
```yaml
171171
dockerfile:
172172
enabled: true
173+
checkEnv:
174+
- CHECK_SKIPS_FUNCTIONAL_TEST=true
173175
entrypoint: [ "/bin/bash", "--", "--arg" ]
174176
extraBuildStages:
175177
- |
@@ -204,6 +206,7 @@ To ensure that the resulting Docker Image is functional, tests should be run bef
204206
As an additional smoke test, the compiled binaries are invoked with the `--version` argument after being copied to the final image.
205207
With [go-api-declarations](https://github.com/sapcc/go-api-declarations)'s [`bininfo.HandleVersionArgument` function](https://pkg.go.dev/github.com/sapcc/go-api-declarations/bininfo#HandleVersionArgument), this can be implemented in one line. If you are using Cobra or any other library to handle arguments, the [`bininfo.Version` function](https://pkg.go.dev/github.com/sapcc/go-api-declarations/bininfo#Version) is recommended instead.
206208

209+
* `checkEnv` sets environment variables for `make check` inside the docker check build.
207210
* `entrypoint` allows overwriting the final entrypoint.
208211
* `extraBuildStages` prepends additional build stages at the top of the Dockerfile. This is useful for bringing in precompiled assets from other images, or if a non-Go compilation step is required.
209212
* `extraBuildPackages` installs extra Alpine packages in the Docker layer where `make install` is executed. We always install `ca-certificates`, `gcc`, `git`, `make` and `musl-dev`.

internal/core/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ type RenovateConfig struct {
240240
// DockerfileConfig appears in type Configuration.
241241
type DockerfileConfig struct {
242242
Enabled bool `yaml:"enabled"`
243+
CheckEnv []string `yaml:"checkEnv"`
243244
Entrypoint []string `yaml:"entrypoint"`
244245
ExtraBuildDirectives []string `yaml:"extraBuildDirectives"`
245246
ExtraBuildPackages []string `yaml:"extraBuildPackages"`

internal/dockerfile/Dockerfile.tmpl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,41 @@ RUN {{ if .UseBuildKit }}--mount=type=cache,target=/go/pkg/mod \
2626
{{ end -}}
2727
################################################################################
2828

29+
# To only build the tests run: docker build . --target test
30+
# We can't do `FROM builder AS test` here, as then make prepare-static-check would not be cached during interactive use when developing
31+
# and caching all the tools, especially golangci-lint, takes a few minutes.
32+
FROM {{ .DockerHubMirror }}golang:{{ .Constants.DefaultGoVersion }}-alpine{{ .Constants.DefaultAlpineImage }} AS test
33+
34+
COPY Makefile /src/Makefile
35+
36+
# used below by USER
37+
RUN addgroup -g 4200 appgroup \
38+
&& adduser -h /home/appuser -s /sbin/nologin -G appgroup -D -u 4200 appuser
39+
40+
RUN apk add --no-cache --no-progress git make {{- range .ExtraTestPackages }} {{.}}{{ end }} \
41+
{{- if .ReuseEnabled }}
42+
&& pip3 install --break-system-packages reuse \
43+
{{- end }}
44+
&& make -C /src prepare-static-check
45+
46+
47+
# We only copy here because we want the "prepare-static-check" to be cacheable.
48+
# It is not a problem that we are overwriting the go cache from the earlier steps because we do not need to rebuild those tools.
49+
COPY --from=builder /go /go
50+
COPY --from=builder /src /src
51+
52+
RUN {{ range $dcfg.CheckEnv }}{{ . }} {{ end }}make -C /src static-check
53+
54+
# Some things like postgres do not like to run as root. For simplicity, just always run as an unprivileged user,
55+
# but for it to be able to read the go cache, we need to allow it.
56+
RUN chmod 777 -R /src/
57+
USER 4200:4200
58+
RUN cd /src \
59+
&& git config --global --add safe.directory /src \
60+
&& {{ range $dcfg.CheckEnv }}{{ . }} {{ end }}make build/cover.out
61+
62+
################################################################################
63+
2964
FROM {{ .DockerHubMirror }}alpine:{{ .Constants.DefaultAlpineImage }}
3065

3166
{{ if not $dcfg.RunAsRoot -}}

internal/dockerfile/docker.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/sapcc/go-bits/must"
1313

1414
"github.com/sapcc/go-makefile-maker/internal/core"
15+
"github.com/sapcc/go-makefile-maker/internal/golang"
1516
"github.com/sapcc/go-makefile-maker/internal/util"
1617
)
1718

@@ -22,7 +23,7 @@ var (
2223
dockerignoreTemplate string
2324
)
2425

25-
func RenderConfig(cfg core.Configuration) {
26+
func RenderConfig(cfg core.Configuration, sr golang.ScanResult) {
2627
// if there is an entrypoint configured use that otherwise fallback to the first binary name
2728
var entrypoint string
2829
if len(cfg.Dockerfile.Entrypoint) > 0 {
@@ -70,19 +71,36 @@ func RenderConfig(cfg core.Configuration) {
7071
dockerHubMirror = "keppel.eu-de-1.cloud.sap/ccloud-dockerhub-mirror/library/"
7172
}
7273

74+
var extraTestPackages []string
75+
reuseEnabled := cfg.Reuse.Enabled.UnwrapOr(true)
76+
if reuseEnabled {
77+
extraTestPackages = append(extraTestPackages, "py3-pip")
78+
}
79+
if sr.UsesPostgres {
80+
extraTestPackages = append(extraTestPackages, "postgresql")
81+
}
82+
7383
must.Succeed(util.WriteFileFromTemplate("Dockerfile", dockerfileTemplate, map[string]any{
7484
"Config": cfg,
7585
"Constants": map[string]any{
7686
"DefaultGoVersion": core.DefaultGoVersion,
7787
"DefaultAlpineImage": core.DefaultAlpineImage,
7888
},
7989
"DockerHubMirror": dockerHubMirror,
90+
"CheckEnv": cfg.Dockerfile.CheckEnv,
91+
"ExtraTestPackages": extraTestPackages,
8092
"Entrypoint": entrypoint,
93+
"ReuseEnabled": reuseEnabled,
8194
"RunCommands": strings.Join(commands, " \\\n && "),
8295
"RunVersionCommands": strings.Join(runVersionCommands, " \\\n && "),
8396
"UseBuildKit": cfg.Dockerfile.UseBuildKit,
8497
}))
98+
99+
ignores := cfg.Dockerfile.ExtraIgnores
100+
if sr.UsesPostgres {
101+
ignores = append(ignores, "/.testdb/")
102+
}
85103
must.Succeed(util.WriteFileFromTemplate(".dockerignore", dockerignoreTemplate, map[string]any{
86-
"ExtraIgnores": cfg.Dockerfile.ExtraIgnores,
104+
"ExtraIgnores": ignores,
87105
}))
88106
}

internal/dockerfile/dockerignore.tmpl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@
77
# TODO: uncomment when applications no longer use git to get version information
88
#.git/
99
/.github/
10-
/.gitignore
11-
/.golangci.yaml
1210
/.goreleaser.yml
1311
/.vscode/
1412
/CONTRIBUTING.md
1513
/Dockerfile
16-
/LICENSE*
1714
/Makefile.maker.yaml
1815
/README.md
1916
/build/

internal/makefile/makefile.go

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func newMakefile(cfg core.Configuration, sr golang.ScanResult) *makefile {
4242
}
4343

4444
isSAPCC := cfg.Metadata.IsSAPProject()
45+
reuseEnabled := cfg.Reuse.Enabled.UnwrapOr(true)
4546

4647
///////////////////////////////////////////////////////////////////////////
4748
// General
@@ -153,24 +154,26 @@ endif
153154
})
154155
prepareStaticRecipe = append(prepareStaticRecipe, "install-addlicense")
155156

156-
prepare.addRule(rule{
157-
description: "Install reuse required by license-headers/check-reuse",
158-
phony: true,
159-
target: "install-reuse",
160-
recipe: []string{
161-
`@if ! hash reuse 2>/dev/null; then` +
162-
` if ! hash pipx 2>/dev/null; then` +
163-
` printf "\e[1;31m>> You are required to manually intervene to install reuse as go-makefile-maker cannot automatically resolve installing reuse on all setups.\e[0m\n";` +
164-
` printf "\e[1;31m>> The preferred way for go-makefile-maker to install python tools after nix-shell is pipx which could not be found. Either install pipx using your package manager or install reuse using your package manager if at least version 6 is available.\e[0m\n";` +
165-
` printf "\e[1;31m>> As your Python was likely installed by your package manager, just doing pip install --user sadly does no longer work as pip issues a warning about breaking your system. Generally running --break-system-packages with --user is safe to do but you should only run this command if you can resolve issues with it yourself: pip3 install --user --break-system-packages reuse\e[0m\n";` +
166-
` else` +
167-
` printf "\e[1;36m>> Installing reuse...\e[0m\n";` +
168-
` pipx install reuse;` +
169-
` fi;` +
170-
` fi`,
171-
},
172-
})
173-
prepareStaticRecipe = append(prepareStaticRecipe, "install-reuse")
157+
if reuseEnabled {
158+
prepare.addRule(rule{
159+
description: "Install reuse required by license-headers/check-reuse",
160+
phony: true,
161+
target: "install-reuse",
162+
recipe: []string{
163+
`@if ! hash reuse 2>/dev/null; then` +
164+
` if ! hash pipx 2>/dev/null; then` +
165+
` printf "\e[1;31m>> You are required to manually intervene to install reuse as go-makefile-maker cannot automatically resolve installing reuse on all setups.\e[0m\n";` +
166+
` printf "\e[1;31m>> The preferred way for go-makefile-maker to install python tools after nix-shell is pipx which could not be found. Either install pipx using your package manager or install reuse using your package manager if at least version 6 is available.\e[0m\n";` +
167+
` printf "\e[1;31m>> As your Python was likely installed by your package manager, just doing pip install --user sadly does no longer work as pip issues a warning about breaking your system. Generally running --break-system-packages with --user is safe to do but you should only run this command if you can resolve issues with it yourself: pip3 install --user --break-system-packages reuse\e[0m\n";` +
168+
` else` +
169+
` printf "\e[1;36m>> Installing reuse...\e[0m\n";` +
170+
` pipx install reuse;` +
171+
` fi;` +
172+
` fi`,
173+
},
174+
})
175+
prepareStaticRecipe = append(prepareStaticRecipe, "install-reuse")
176+
}
174177
}
175178
// add target for installing dependencies for `make static-check`
176179
prepare.addRule(rule{
@@ -501,11 +504,16 @@ endif
501504
`))
502505
copyright := cfg.License.Copyright.UnwrapOr("SAP SE or an SAP affiliate company")
503506

507+
licenseHeaderPrereqs := []string{"install-addlicense"}
508+
if reuseEnabled {
509+
licenseHeaderPrereqs = append(licenseHeaderPrereqs, "install-reuse")
510+
}
511+
504512
dev.addRule(rule{
505513
description: "Add (or overwrite) license headers on all non-vendored source code files.",
506514
target: "license-headers",
507515
phony: true,
508-
prerequisites: []string{"install-addlicense", "install-reuse"},
516+
prerequisites: licenseHeaderPrereqs,
509517
recipe: []string{
510518
`@printf "\e[1;36m>> addlicense (for license headers on source code files)\e[0m\n"`,
511519
// We must use gawk to use gnu awk on Darwin
@@ -539,22 +547,29 @@ endif
539547
fmt.Sprintf(`@addlicense --check %s %s`, ignoreOptionsStr, allSourceFilesExpr),
540548
},
541549
})
542-
test.addRule(rule{
543-
description: "Check reuse compliance",
544-
target: "check-reuse",
545-
phony: true,
546-
prerequisites: []string{"install-reuse"},
547-
recipe: []string{
548-
`@printf "\e[1;36m>> reuse lint\e[0m\n"`,
549-
// reuse is very verbose, so we only show the output if there are problems
550-
`@if ! reuse lint -q; then reuse lint; fi`,
551-
},
552-
})
550+
if reuseEnabled {
551+
test.addRule(rule{
552+
description: "Check reuse compliance",
553+
target: "check-reuse",
554+
phony: true,
555+
prerequisites: []string{"install-reuse"},
556+
recipe: []string{
557+
`@printf "\e[1;36m>> reuse lint\e[0m\n"`,
558+
// reuse is very verbose, so we only show the output if there are problems
559+
`@if ! reuse lint -q; then reuse lint; fi`,
560+
},
561+
})
562+
}
563+
// add target for static code checks
564+
staticCodeChecksPrerequisites := []string{"check-addlicense"}
565+
if reuseEnabled {
566+
staticCodeChecksPrerequisites = append(staticCodeChecksPrerequisites, "check-reuse")
567+
}
553568
test.addRule(rule{
554569
description: "Run static code checks",
555570
phony: true,
556571
target: "check-license-headers",
557-
prerequisites: []string{"check-addlicense", "check-reuse"},
572+
prerequisites: staticCodeChecksPrerequisites,
558573
})
559574

560575
if isGolang {

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func main() {
9595
// Render Dockerfile
9696
if cfg.Dockerfile.Enabled {
9797
logg.Debug("rendering Dockerfile")
98-
dockerfile.RenderConfig(cfg)
98+
dockerfile.RenderConfig(cfg, sr)
9999
}
100100

101101
// Render golangci-lint config file

0 commit comments

Comments
 (0)