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:
1 parent
04770492d5
commit
79a4e649d1
3 files changed
+139
-19
No files matched your search
@@ -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"
|
||||||
@@ -45,29 +45,28 @@ docker build -t domogeek . # or: buildah bud -t domogeek .
|
|||||||
|
|
||||||
## Continuous builds
|
## Continuous builds
|
||||||
|
|
||||||
Pushing a Git tag matching `v[0-9]*` (existing convention: `vX.Y.Z`, e.g. `v0.4.0`) to
|
Pushing a Git tag matching `v[0-9]*` (convention: `vX.Y.Z`, e.g. `v0.4.0`) to the Gitea remote
|
||||||
the Gitea remote triggers the homelab Tekton pipeline `gitea-docker-build-multiarch`,
|
triggers the **Gitea Actions** workflow `.gitea/workflows/build.yaml` (homelab runner, no Docker,
|
||||||
which builds and pushes a multi-arch (amd64 + arm64) image plus a signed CycloneDX SBOM:
|
no privileges): the binary is cross-compiled for amd64/arm64 (CGO off, `netgo`, vendored, Go 1.27 =
|
||||||
|
`GO_VERSION` in the workflow), appended onto the pinned `gcr.io/distroless/static-debian12` base
|
||||||
|
with `crane` (entrypoint `/go/bin/domogeek`, user 1234, port 8080), and published as a multi-arch
|
||||||
|
image plus a CycloneDX SBOM uploaded to DependencyTrack (no cosign signature anymore):
|
||||||
|
|
||||||
```
|
```
|
||||||
git.cyrilix.bzh/cyrilix/domogeek:<tag>
|
git.cyrilix.bzh/cyrilix/domogeek:<tag>
|
||||||
```
|
```
|
||||||
|
|
||||||
The pipeline uses its defaults — `Dockerfile` at the repo root, build context `.` — so
|
A manual `workflow_dispatch` run publishes `test-<sha>`. The `Dockerfile` remains for local builds
|
||||||
the Dockerfile must stay at the root. It builds each target platform natively (no
|
(`docker build -t domogeek .`) but is not used by CI — keep its base/user/entrypoint in sync with the
|
||||||
`GOOS`/`GOARCH` overrides in the `go build` step), so the Dockerfile must not hardcode a
|
workflow. Migrated from the Tekton pipeline (and its Gitea webhook) on 2026-10-13.
|
||||||
single-arch `GOOS`/`GOARCH` — that was a real bug fixed alongside this: the builder image
|
|
||||||
is now pinned to `golang:1.27-alpine` (matching the `go 1.25` module requirement) and the
|
|
||||||
`go build` step targets the whole package (`./cmd/domogeek`), not a single file.
|
|
||||||
|
|
||||||
There is no Tekton YAML in this repo: the pipeline and its Gitea webhook trigger are
|
|
||||||
defined cluster-side. Watch a run: <https://tekton.banquise.cyrilix.bzh>
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git tag v0.4.0
|
git tag v0.4.1
|
||||||
git push --tags
|
git push --tags
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Watch the run: Gitea → `cyrilix/domogeek` → Actions.
|
||||||
|
|
||||||
Note: this replaces the previous `docker.io/cyrilix/domogeek:<git describe>` releases
|
Note: this replaces the previous `docker.io/cyrilix/domogeek:<git describe>` releases
|
||||||
built locally via the now-removed `build-docker.sh`/`buildah` script.
|
built locally via the now-removed `build-docker.sh`/`buildah` script.
|
||||||
|
|
||||||
|
|||||||
@@ -18,18 +18,17 @@ and date/time information as MCP tools (`get_current_datetime`, `get_calendar_to
|
|||||||
|
|
||||||
## Continuous builds
|
## Continuous builds
|
||||||
|
|
||||||
Pushing a Git tag matching `v[0-9]*` (e.g. `v0.4.0`) to the Gitea remote triggers the
|
Pushing a Git tag matching `v[0-9]*` (e.g. `v0.4.1`) to the Gitea remote triggers the Gitea Actions
|
||||||
homelab Tekton pipeline `gitea-docker-build-multiarch`, which builds and pushes a
|
workflow `.gitea/workflows/build.yaml` (no Docker, no privileges), which builds and pushes a
|
||||||
multi-arch (amd64 + arm64) image plus a signed SBOM:
|
multi-arch (amd64 + arm64) image plus a CycloneDX SBOM to DependencyTrack:
|
||||||
|
|
||||||
```
|
```
|
||||||
git.cyrilix.bzh/cyrilix/domogeek:<tag>
|
git.cyrilix.bzh/cyrilix/domogeek:<tag>
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git tag v0.4.0
|
git tag v0.4.1
|
||||||
git push --tags
|
git push --tags
|
||||||
```
|
```
|
||||||
|
|
||||||
Watch the run: <https://tekton.banquise.cyrilix.bzh>
|
Watch the run: Gitea → `cyrilix/domogeek` → Actions.
|
||||||
|
|
||||||
Reference in new issue
Block a user