Pārlūkot izejas kodu

Try using ko to build images

Signed-off-by: Xe Iaso <me@xeiaso.net>
Xe Iaso 3 mēneši atpakaļ
vecāks
revīzija
1efcb88261
6 mainītis faili ar 166 papildinājumiem un 11 dzēšanām
  1. 14 10
      .github/workflows/docker.yml
  2. 13 0
      .ko.yaml
  3. 2 1
      Brewfile
  4. 3 0
      CHANGELOG.md
  5. 1 0
      cmd/containerbuild/.gitignore
  6. 133 0
      cmd/containerbuild/main.go

+ 14 - 10
.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

+ 13 - 0
.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}}

+ 2 - 1
Brewfile

@@ -1,3 +1,4 @@
 # programming languages
 brew "go@1.24"
-brew "node"
+brew "node"
+brew "ko"

+ 3 - 0
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

+ 1 - 0
cmd/containerbuild/.gitignore

@@ -0,0 +1 @@
+images

+ 133 - 0
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)
+}