ci: build the image on Gitea Actions instead of Tekton

Go cross-compilation (CGO off, netgo, vendored, Go 1.27) for amd64/arm64,
crane append onto the pinned distroless/static base (entrypoint, user 1234,
port 8080 set with crane mutate), multi-arch index, CycloneDX SBOM to
DependencyTrack. Tags v[0-9]* or manual runs (test-<sha>).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cyrilixandClaude Opus 5.5 committed 2026-10-13 21:30:54 +02:00
1 parent 04770492d5
commit 79a4e649d1
3 files changed
+139 -19

No files matched your search

+122
View File
@@ -0,0 +1,122 @@
# domogeek image without Docker nor privileges (restricted job pod):
# Go cross-compilation (CGO off, netgo, vendored) for amd64/arm64 in the job, then
# `crane append` of the binary onto the pinned distroless/static base per arch, entrypoint and
# user set with `crane mutate`, `crane index append`, CycloneDX SBOM -> DependencyTrack.
# Tag convention unchanged (vX.Y.Z): image git.cyrilix.bzh/cyrilix/domogeek:<tag> (+ -amd64/-arm64).
name: build
on:
push:
tags: ["v[0-9]*"]
workflow_dispatch: # publishes test-<sha>
permissions:
contents: read
env:
REGISTRY: git.cyrilix.bzh
IMAGE: git.cyrilix.bzh/cyrilix/domogeek
# Same base as the Dockerfile (distroless/static), pinned multi-arch index.
BASE: gcr.io/distroless/static-debian12@sha256:d75cdd72874d4790092fcb1b058493ecf6bb5bf2b2b897045b00ff01d91843f2
# Toolchain of the Dockerfile builder (golang:1.27); go.mod only requires go 1.25.
GO_VERSION: "1.27"
CRANE_VERSION: v0.22.1
CRANE_SHA256: 0ab7a1d6932a213aed964ce97666c3077fe691c8606413674a8b3e0b9ec4cda0
SYFT_VERSION: 1.54.1
SYFT_SHA256: c069905b391cc4c20a5ba65ad5c10be2a7ba074f8ea6ad203e24d14e303dad47
DT_BASE_URL: http://dependency-track-dt-api-server.dependency-track.svc.cluster.local:8080
jobs:
build:
runs-on: banquise-amd64
# 512Mi job pods: bound the Go runtime (compiler, crane, syft).
env:
GOMEMLIMIT: 350MiB
GOGC: "25"
steps:
- uses: builtin:checkout
- name: tag
id: meta
run: |
set -eu
case "$GITHUB_REF" in
refs/tags/*) tag="${GITHUB_REF#refs/tags/}" ;;
*) tag="test-$(echo "$GITHUB_SHA" | cut -c1-8)" ;;
esac
echo "tag=$tag" | tee -a "$GITHUB_OUTPUT"
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
cache: false # vendor/ is committed
- name: build binaries (cross-compiled, no qemu)
run: |
set -eu
for arch in amd64 arm64; do
mkdir -p "layer-$arch/go/bin"
CGO_ENABLED=0 GOOS=linux GOARCH=$arch go build -p 2 -mod=vendor -tags netgo -trimpath -ldflags="-s -w" \
-o "layer-$arch/go/bin/domogeek" ./cmd/domogeek
done
go version -m layer-amd64/go/bin/domogeek | head -2
- name: install crane and syft (pinned, checksum-verified)
run: |
set -eu
mkdir -p "$HOME/bin" && cd "$(mktemp -d)"
curl -fsSLo crane.tgz "https://github.com/google/go-containerregistry/releases/download/${CRANE_VERSION}/go-containerregistry_Linux_x86_64.tar.gz"
echo "${CRANE_SHA256} crane.tgz" | sha256sum -c -
tar -xzf crane.tgz crane && mv crane "$HOME/bin/"
curl -fsSLo syft.tgz "https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/syft_${SYFT_VERSION}_linux_amd64.tar.gz"
echo "${SYFT_SHA256} syft.tgz" | sha256sum -c -
tar -xzf syft.tgz syft && mv syft "$HOME/bin/"
echo "$HOME/bin" >> "$GITHUB_PATH"
# Gitea 28.1 rejects the job token on the container registry (empty access scope for
# Actions task tokens) -> dedicated PAT of the package owner, scope write:package only.
- name: registry login
run: echo "${{ secrets.REGISTRY_TOKEN }}" | crane auth login "$REGISTRY" -u cyrilix --password-stdin
- name: image per arch, then the multi-arch index
run: |
set -eu
tag="${{ steps.meta.outputs.tag }}"
epoch=$(git log -1 --format=%ct)
for arch in amd64 arm64; do
tar --sort=name --owner=0 --group=0 --numeric-owner --mtime="@$epoch" -C "layer-$arch" -cf "app-$arch.tar" .
crane append --platform "linux/$arch" -b "$BASE" -f "app-$arch.tar" -t "$IMAGE:$tag-$arch"
crane mutate "$IMAGE:$tag-$arch" --entrypoint /go/bin/domogeek --user 1234 --exposed-ports 8080/tcp \
--label org.opencontainers.image.source=https://git.cyrilix.bzh/cyrilix/domogeek \
--label org.opencontainers.image.version="$tag"
done
crane index append -t "$IMAGE:$tag" -m "$IMAGE:$tag-amd64" -m "$IMAGE:$tag-arm64"
echo "index digest: $(crane digest "$IMAGE:$tag")"
- name: SBOM (syft, CycloneDX)
env:
SYFT_CHECK_FOR_APP_UPDATE: "false"
run: |
set -eu
syft "registry:$IMAGE:${{ steps.meta.outputs.tag }}" --platform linux/amd64 -o cyclonedx-json=sbom.cdx.json
echo "components: $(grep -o '"bom-ref"' sbom.cdx.json | wc -l)"
- name: upload SBOM to DependencyTrack
env:
DT_API_KEY: ${{ secrets.DT_API_KEY }}
run: |
set -eu
name="${IMAGE#*/}"
version="${{ steps.meta.outputs.tag }}"
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 30 -X PUT \
-H "X-Api-Key: $DT_API_KEY" -H 'Content-Type: application/json' \
-d '{"name":"oci","active":true,"collectionLogic":"AGGREGATE_DIRECT_CHILDREN"}' \
"$DT_BASE_URL/api/v1/project")
case "$code" in 201|409) ;; *) echo "parent project 'oci': HTTP $code"; exit 1 ;; esac
{ printf '{"parentName":"oci","projectName":"%s","projectVersion":"%s","autoCreate":true,"bom":"' "$name" "$version"
base64 -w0 sbom.cdx.json; printf '"}'; } > dt-payload.json
code=$(curl -s -o dt-response.json -w '%{http_code}' --max-time 120 -X PUT \
-H "X-Api-Key: $DT_API_KEY" -H 'Content-Type: application/json' \
-d @dt-payload.json "$DT_BASE_URL/api/v1/bom")
[ "$code" = 200 ] || { echo "BOM upload: HTTP $code"; cat dt-response.json; exit 1; }
echo "DependencyTrack: $name $version accepted"