Try using ko to build images

Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso 2025-03-19 08:51:09 -04:00
parent 1a13292c2d
commit 1efcb88261
No known key found for this signature in database
6 changed files with 166 additions and 11 deletions

View file

@ -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
.ko.yaml Normal file
View file

@ -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}}

View file

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

View file

@ -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
cmd/containerbuild/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
images

133
cmd/containerbuild/main.go Normal file
View file

@ -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)
}