Files
felhom-controller/controller/cmd/controller/r208_dockerfile_args_test.go
T

57 lines
2.1 KiB
Go

package main
import (
"os"
"regexp"
"strings"
"testing"
)
// R-208: `ARG VERSION` / `ARG GIT_COMMIT` declared ABOVE `RUN go mod download` put a per-build value
// into that RUN's cache key, so every release re-downloaded the modules (measured: 208 cache records,
// every one with usage count 1). The consequence pinned here, in the builder stage: no ARG whose value
// changes per build is declared before the module-download step, and both are still declared before
// the `go build` that reads them (or the binary would report "dev"/"unknown").
func TestR208_DockerfileVersionArgsSitBelowModuleDownload(t *testing.T) {
src, err := os.ReadFile("../../Dockerfile")
if err != nil {
t.Fatal(err)
}
lines := strings.Split(string(src), "\n")
argRe := regexp.MustCompile(`^\s*ARG\s+(VERSION|GIT_COMMIT|BUILD_TIME)\b`)
download, build := -1, -1
args := map[string]int{}
for i, l := range lines {
if strings.HasPrefix(strings.TrimSpace(l), "FROM ") && i > 0 && download >= 0 && build >= 0 {
break // the runtime stage: only the builder matters
}
if m := argRe.FindStringSubmatch(l); m != nil {
if _, seen := args[m[1]]; !seen {
args[m[1]] = i // the FIRST declaration: any one above the download is the defect
}
}
if strings.Contains(l, "go mod download") && download < 0 {
download = i
}
if strings.Contains(l, "go build") && build < 0 {
build = i
}
}
if download < 0 || build < 0 {
t.Fatalf("the builder stage no longer has a `go mod download` (%d) or a `go build` (%d) — this test reads the wrong file", download, build)
}
for _, name := range []string{"VERSION", "GIT_COMMIT"} {
at, ok := args[name]
if !ok {
t.Errorf("ARG %s is not declared in the builder stage — the binary would be built without it", name)
continue
}
if at < download {
t.Errorf("R-208: ARG %s (line %d) is declared above `go mod download` (line %d), so every build with a new value re-downloads the modules", name, at+1, download+1)
}
if at > build {
t.Errorf("ARG %s (line %d) is declared after the `go build` that reads it (line %d)", name, at+1, build+1)
}
}
}