aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/docker.yml24
-rw-r--r--.ko.yaml13
-rw-r--r--Brewfile3
-rw-r--r--CHANGELOG.md3
-rw-r--r--cmd/containerbuild/.gitignore1
-rw-r--r--cmd/containerbuild/main.go133
6 files changed, 166 insertions, 11 deletions
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 958f9eb..5aa85db 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -8,6 +8,9 @@ on:
pull_request:
branches: [ "main" ]
+env:
+ DOCKER_METADATA_SET_OUTPUT_ENV: "true"
+
permissions:
contents: read
packages: write
@@ -20,6 +23,9 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
+ with:
+ fetch-tags: true
+ fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -27,6 +33,12 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
+ - uses: actions/setup-go@v5
+ with:
+ go-version: '1.24.x'
+
+ - uses: ko-build/setup-ko@v0.8
+
- name: Log into registry
uses: docker/login-action@v3
with:
@@ -42,16 +54,8 @@ jobs:
- name: Build and push
id: build
- uses: docker/build-push-action@v6
- with:
- context: .
- cache-to: type=gha
- cache-from: type=gha
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- platforms: linux/arm64/v8,linux/amd64
- sbom: true
- push: true
+ run: |
+ go run ./cmd/containerbuild --docker-repo ghcr.io/techarohq/anubis --slog-level debug
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
diff --git a/.ko.yaml b/.ko.yaml
new file mode 100644
index 0000000..35c1fa0
--- /dev/null
+++ b/.ko.yaml
@@ -0,0 +1,13 @@
+defaultBaseImage: cgr.dev/chainguard/static
+defaultPlatforms:
+- linux/arm64
+- linux/amd64
+- linux/arm/v7
+
+builds:
+- id: anubis
+ main: ./cmd/anubis
+ ldflags:
+ - -s -w
+ - -extldflags "-static"
+ - -X github.com/TecharoHQ/anubis.Version={{.Env.VERSION}}
diff --git a/Brewfile b/Brewfile
index 883ba6b..2b6b486 100644
--- a/Brewfile
+++ b/Brewfile
@@ -1,3 +1,4 @@
# programming languages
brew "go@1.24"
-brew "node" \ No newline at end of file
+brew "node"
+brew "ko" \ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d6a37f..c530507 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+- Images are built using ko instead of `docker buildx build`
+ [#13](https://github.com/TecharoHQ/anubis/pull/13)
+
## 1.12.1
- Phrasing in the `<noscript>` warning was replaced from its original placeholder text to
diff --git a/cmd/containerbuild/.gitignore b/cmd/containerbuild/.gitignore
new file mode 100644
index 0000000..5e798fa
--- /dev/null
+++ b/cmd/containerbuild/.gitignore
@@ -0,0 +1 @@
+images \ No newline at end of file
diff --git a/cmd/containerbuild/main.go b/cmd/containerbuild/main.go
new file mode 100644
index 0000000..4eeae4c
--- /dev/null
+++ b/cmd/containerbuild/main.go
@@ -0,0 +1,133 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "log/slog"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "github.com/TecharoHQ/anubis/internal"
+ "github.com/facebookgo/flagenv"
+)
+
+var (
+ dockerAnnotations = flag.String("docker-annotations", os.Getenv("DOCKER_METADATA_OUTPUT_ANNOTATIONS"), "Docker image annotations")
+ dockerLabels = flag.String("docker-labels", os.Getenv("DOCKER_METADATA_OUTPUT_LABELS"), "Docker image labels")
+ dockerRepo = flag.String("docker-repo", "registry.int.xeserv.us/techaro/anubis", "Docker image repository for Anubis")
+ dockerTags = flag.String("docker-tags", os.Getenv("DOCKER_METADATA_OUTPUT_TAGS"), "newline separated docker tags including the registry name")
+ slogLevel = flag.String("slog-level", "INFO", "logging level (see https://pkg.go.dev/log/slog#hdr-Levels)")
+)
+
+func main() {
+ flagenv.Parse()
+ flag.Parse()
+
+ internal.InitSlog(*slogLevel)
+
+ koDockerRepo := strings.TrimRight(*dockerRepo, "/"+filepath.Base(*dockerRepo))
+ version, err := run("git describe --tags --always --dirty")
+
+ slog.Debug(
+ "ko env",
+ "KO_DOCKER_REPO", koDockerRepo,
+ "VERSION", version,
+ )
+
+ os.Setenv("KO_DOCKER_REPO", koDockerRepo)
+ os.Setenv("VERSION", version)
+
+ setOutput("version", version)
+
+ if *dockerTags == "" {
+ log.Fatal("Must set --docker-tags or DOCKER_METADATA_OUTPUT_TAGS")
+ }
+
+ images, err := parseImageList(*dockerTags)
+ if err != nil {
+ log.Fatalf("can't parse images: %v", err)
+ }
+
+ for _, img := range images {
+ if img.repository != *dockerRepo {
+ slog.Error(
+ "Something weird is going on. Wanted docker repo differs from contents of --docker-tags. Did a flag get set incorrectly?",
+ "wanted", *dockerRepo,
+ "got", img.repository,
+ "docker-tags", *dockerTags,
+ )
+ os.Exit(2)
+ }
+ }
+
+ var tags []string
+ for _, img := range images {
+ tags = append(tags, img.tag)
+ }
+
+ 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))
+ if err != nil {
+ log.Fatalf("can't run ko build, check stderr: %v", err)
+ }
+
+ sp := strings.SplitN(output, "@", 2)
+
+ setOutput("digest", sp[1])
+}
+
+type image struct {
+ repository string
+ tag string
+}
+
+func newlineSep2Comma(inp string) string {
+ lines := strings.Split(inp, "\n")
+ return strings.Join(lines, ",")
+}
+
+func parseImageList(imageList string) ([]image, error) {
+ images := strings.Split(imageList, "\n")
+ var result []image
+ for _, img := range images {
+ if img == "" {
+ continue
+ }
+
+ // reg.xeiaso.net/techaro/anubis:latest
+ // repository: reg.xeiaso.net/techaro/anubis
+ // tag: latest
+ parts := strings.SplitN(img, ":", 2)
+ result = append(result, image{
+ repository: parts[0],
+ tag: parts[1],
+ })
+ }
+
+ if len(result) == 0 {
+ return nil, fmt.Errorf("no images provided, bad flags??")
+ }
+
+ return result, nil
+}
+
+// run executes a command and returns the trimmed output.
+func run(command string) (string, error) {
+ bin, err := exec.LookPath("sh")
+ if err != nil {
+ return "", err
+ }
+ cmd := exec.Command(bin, "-c", command)
+ cmd.Stderr = os.Stderr
+ out, err := cmd.Output()
+ if err != nil {
+ return "", err
+ }
+ return strings.TrimSpace(string(out)), nil
+}
+
+func setOutput(key, val string) {
+ fmt.Printf("::set-output name=%s::%s\n", key, val)
+}