+14
-10
.github/workflows/docker.yml
+14
-10
.github/workflows/docker.yml
···
8
8
pull_request:
9
9
branches: [ "main" ]
10
10
11
+
env:
12
+
DOCKER_METADATA_SET_OUTPUT_ENV: "true"
13
+
11
14
permissions:
12
15
contents: read
13
16
packages: write
···
20
23
steps:
21
24
- name: Checkout code
22
25
uses: actions/checkout@v4
26
+
with:
27
+
fetch-tags: true
28
+
fetch-depth: 0
23
29
24
30
- name: Set up QEMU
25
31
uses: docker/setup-qemu-action@v3
26
32
27
33
- name: Set up Docker Buildx
28
34
uses: docker/setup-buildx-action@v3
35
+
36
+
- uses: actions/setup-go@v5
37
+
with:
38
+
go-version: '1.24.x'
39
+
40
+
- uses: ko-build/setup-ko@v0.8
29
41
30
42
- name: Log into registry
31
43
uses: docker/login-action@v3
···
42
54
43
55
- name: Build and push
44
56
id: build
45
-
uses: docker/build-push-action@v6
46
-
with:
47
-
context: .
48
-
cache-to: type=gha
49
-
cache-from: type=gha
50
-
tags: ${{ steps.meta.outputs.tags }}
51
-
labels: ${{ steps.meta.outputs.labels }}
52
-
platforms: linux/arm64/v8,linux/amd64
53
-
sbom: true
54
-
push: true
57
+
run: |
58
+
go run ./cmd/containerbuild --docker-repo ghcr.io/techarohq/anubis --slog-level debug
55
59
56
60
- name: Generate artifact attestation
57
61
uses: actions/attest-build-provenance@v2
+13
.ko.yaml
+13
.ko.yaml
···
1
+
defaultBaseImage: cgr.dev/chainguard/static
2
+
defaultPlatforms:
3
+
- linux/arm64
4
+
- linux/amd64
5
+
- linux/arm/v7
6
+
7
+
builds:
8
+
- id: anubis
9
+
main: ./cmd/anubis
10
+
ldflags:
11
+
- -s -w
12
+
- -extldflags "-static"
13
+
- -X github.com/TecharoHQ/anubis.Version={{.Env.VERSION}}
+2
-1
Brewfile
+2
-1
Brewfile
+3
CHANGELOG.md
+3
CHANGELOG.md
+1
cmd/containerbuild/.gitignore
+1
cmd/containerbuild/.gitignore
···
1
+
images
+133
cmd/containerbuild/main.go
+133
cmd/containerbuild/main.go
···
1
+
package main
2
+
3
+
import (
4
+
"flag"
5
+
"fmt"
6
+
"log"
7
+
"log/slog"
8
+
"os"
9
+
"os/exec"
10
+
"path/filepath"
11
+
"strings"
12
+
13
+
"github.com/TecharoHQ/anubis/internal"
14
+
"github.com/facebookgo/flagenv"
15
+
)
16
+
17
+
var (
18
+
dockerAnnotations = flag.String("docker-annotations", os.Getenv("DOCKER_METADATA_OUTPUT_ANNOTATIONS"), "Docker image annotations")
19
+
dockerLabels = flag.String("docker-labels", os.Getenv("DOCKER_METADATA_OUTPUT_LABELS"), "Docker image labels")
20
+
dockerRepo = flag.String("docker-repo", "registry.int.xeserv.us/techaro/anubis", "Docker image repository for Anubis")
21
+
dockerTags = flag.String("docker-tags", os.Getenv("DOCKER_METADATA_OUTPUT_TAGS"), "newline separated docker tags including the registry name")
22
+
slogLevel = flag.String("slog-level", "INFO", "logging level (see https://pkg.go.dev/log/slog#hdr-Levels)")
23
+
)
24
+
25
+
func main() {
26
+
flagenv.Parse()
27
+
flag.Parse()
28
+
29
+
internal.InitSlog(*slogLevel)
30
+
31
+
koDockerRepo := strings.TrimRight(*dockerRepo, "/"+filepath.Base(*dockerRepo))
32
+
version, err := run("git describe --tags --always --dirty")
33
+
34
+
slog.Debug(
35
+
"ko env",
36
+
"KO_DOCKER_REPO", koDockerRepo,
37
+
"VERSION", version,
38
+
)
39
+
40
+
os.Setenv("KO_DOCKER_REPO", koDockerRepo)
41
+
os.Setenv("VERSION", version)
42
+
43
+
setOutput("version", version)
44
+
45
+
if *dockerTags == "" {
46
+
log.Fatal("Must set --docker-tags or DOCKER_METADATA_OUTPUT_TAGS")
47
+
}
48
+
49
+
images, err := parseImageList(*dockerTags)
50
+
if err != nil {
51
+
log.Fatalf("can't parse images: %v", err)
52
+
}
53
+
54
+
for _, img := range images {
55
+
if img.repository != *dockerRepo {
56
+
slog.Error(
57
+
"Something weird is going on. Wanted docker repo differs from contents of --docker-tags. Did a flag get set incorrectly?",
58
+
"wanted", *dockerRepo,
59
+
"got", img.repository,
60
+
"docker-tags", *dockerTags,
61
+
)
62
+
os.Exit(2)
63
+
}
64
+
}
65
+
66
+
var tags []string
67
+
for _, img := range images {
68
+
tags = append(tags, img.tag)
69
+
}
70
+
71
+
output, err := run(fmt.Sprintf("ko build --platform=all --base-import-paths --tags=%q --image-user=1000 --image-annotation=%q --image-label=%q ./cmd/anubis | tail -n1", strings.Join(tags, ","), *dockerAnnotations, *dockerLabels))
72
+
if err != nil {
73
+
log.Fatalf("can't run ko build, check stderr: %v", err)
74
+
}
75
+
76
+
sp := strings.SplitN(output, "@", 2)
77
+
78
+
setOutput("digest", sp[1])
79
+
}
80
+
81
+
type image struct {
82
+
repository string
83
+
tag string
84
+
}
85
+
86
+
func newlineSep2Comma(inp string) string {
87
+
lines := strings.Split(inp, "\n")
88
+
return strings.Join(lines, ",")
89
+
}
90
+
91
+
func parseImageList(imageList string) ([]image, error) {
92
+
images := strings.Split(imageList, "\n")
93
+
var result []image
94
+
for _, img := range images {
95
+
if img == "" {
96
+
continue
97
+
}
98
+
99
+
// reg.xeiaso.net/techaro/anubis:latest
100
+
// repository: reg.xeiaso.net/techaro/anubis
101
+
// tag: latest
102
+
parts := strings.SplitN(img, ":", 2)
103
+
result = append(result, image{
104
+
repository: parts[0],
105
+
tag: parts[1],
106
+
})
107
+
}
108
+
109
+
if len(result) == 0 {
110
+
return nil, fmt.Errorf("no images provided, bad flags??")
111
+
}
112
+
113
+
return result, nil
114
+
}
115
+
116
+
// run executes a command and returns the trimmed output.
117
+
func run(command string) (string, error) {
118
+
bin, err := exec.LookPath("sh")
119
+
if err != nil {
120
+
return "", err
121
+
}
122
+
cmd := exec.Command(bin, "-c", command)
123
+
cmd.Stderr = os.Stderr
124
+
out, err := cmd.Output()
125
+
if err != nil {
126
+
return "", err
127
+
}
128
+
return strings.TrimSpace(string(out)), nil
129
+
}
130
+
131
+
func setOutput(key, val string) {
132
+
fmt.Printf("::set-output name=%s::%s\n", key, val)
133
+
}