ProofedMesh/.forgejo/workflows/build-images.yml
CTO (Paperclip) 20ba29d3ac
All checks were successful
build-images / signing-service image (push) Successful in 26s
build-images / verification-service image (push) Successful in 27s
build-images / approval-service image (push) Successful in 31s
build-images / dummy-sink image (push) Successful in 29s
validate / JSON Schema (ajv) (push) Successful in 23s
validate / Rego (opa fmt + opa test) (push) Successful in 16s
phase1-smoke / Phase 1 end-to-end smoke (push) Successful in 1m0s
validate / DB (migrate up/down dry-run) (push) Successful in 26s
validate / Go (vet + test) (push) Successful in 1m20s
approval-service: K8s deployment manifests + Pocket-ID OIDC client (DEV-614)
Phase-1 Subtask 8/10 (parent DEV-606):
- deploy/approval-service/: SA (no auto-mount), Deployment (replicas=2,
  distroless-nonroot, read-only rootfs), ClusterIP :8080, NetworkPolicy
  (ingress from pangolin namespace only; egress to signing-service,
  transparency-log, trust-pg in agent-trust + pocket-id + DNS), README.
- 10-secret-dev.example.yaml template + the real 10-secret-dev.sealed.yaml
  carrying the Pocket-ID client id/secret, WebAuthn RP config, and the
  dev signing-service bearer; unsealed in-cluster to Secret
  approval-service-dev.
- services/approval-service/Dockerfile: BuildKit multi-stage, context-at-
  repo-root, matches the signing/verification/dummy-sink pattern.
- .forgejo/workflows/build-images.yml: new approval-service job pushing
  harbor.basicstack.de/basicstack/approval-service:{sha,main} on main.
- Pocket-ID: created proofedmesh-admin group + OIDC client
  "ProofedMesh Approval" with PKCE enforced, callback
  https://approval.proofedmesh.basicstack.de/oidc/callback, group
  restriction to proofedmesh-admin. Client secret stored as Paperclip
  secret proposal and in the SealedSecret above — never pasted inline.

Deployment applied cluster-side pending the first CI image build:
`kubectl apply -f deploy/approval-service/` is green; pods ErrImagePull
until the Forgejo workflow completes and pushes the :main tag.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 21:12:01 +00:00

307 lines
11 KiB
YAML

name: build-images
# Build + push container images for ProofedMesh services on every push to
# main. PRs run the build to catch Dockerfile breakage but do not push.
#
# The repository is sha256 — same gotchas as validate.yml apply: no
# actions/checkout, clone manually from a trixie/alpine container with
# git ≥ 2.42.
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
signing-service:
name: signing-service image
runs-on: ubuntu-latest
container:
image: debian:trixie-slim
options: --user 0:0
env:
REGISTRY: harbor.basicstack.de
IMAGE_REPO: harbor.basicstack.de/basicstack/signing-service
# The signing-service Dockerfile uses `RUN --mount=type=cache` which
# the legacy Docker builder rejects; the Debian `docker-buildx`
# package registers the buildx CLI plugin at
# `/usr/libexec/docker/cli-plugins/docker-buildx`, and setting
# `DOCKER_BUILDKIT=1` routes `docker build` through BuildKit so the
# `# syntax=docker/dockerfile:1.7` frontend handles `--mount`.
DOCKER_BUILDKIT: "1"
steps:
- name: Install git + buildx client + ca-certs
run: |
set -euo pipefail
apt-get update
# Debian trixie: `docker.io` only installs the daemon; the CLI
# (`/usr/bin/docker`) ships in `docker-cli`, which is a Recommends
# and therefore excluded by `--no-install-recommends`. The
# buildx plugin ships separately in `docker-buildx` and is
# required because the signing-service Dockerfile uses
# `RUN --mount=type=cache` (BuildKit-only syntax).
apt-get install -y --no-install-recommends \
git curl ca-certificates docker.io docker-cli docker-buildx
git --version
docker --version
docker buildx version
- name: Clone repository (sha256-aware)
run: |
set -euo pipefail
git clone --depth=1 --branch="${GITHUB_REF_NAME}" \
"https://x-access-token:${GITHUB_TOKEN}@forgejo.basicstack.de/${GITHUB_REPOSITORY}.git" \
"${GITHUB_WORKSPACE}"
cd "${GITHUB_WORKSPACE}"
git log -1 --oneline
- name: Resolve tags
id: tags
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
SHA="$(git rev-parse --short HEAD)"
echo "sha=${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_sha=${IMAGE_REPO}:${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_main=${IMAGE_REPO}:main" >> "${GITHUB_OUTPUT}"
- name: Build image
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
# Explicit `docker buildx build` so BuildKit frontend features
# (`# syntax=`, `--mount=type=cache`) work on any docker-cli
# version regardless of whether `docker build` is aliased to
# buildx. The default `docker` driver loads the result into the
# local daemon, so the subsequent `docker push` finds the tags.
docker buildx build \
--load \
-f services/signing-service/Dockerfile \
-t "${{ steps.tags.outputs.image_sha }}" \
-t "${{ steps.tags.outputs.image_main }}" \
.
- name: Login to Harbor (push jobs only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
# Harbor robot usernames contain `$` (e.g. `robot$basicstack+ci`),
# so inlining `${{ secrets.HARBOR_USERNAME }}` directly in the
# `run:` script makes bash expand `$basicstack` (and die under
# `set -u`). Pass the secrets as env vars so the shell only sees
# them as plain strings.
env:
HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }}
HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }}
run: |
set -eu
echo "${HARBOR_PASSWORD}" | \
docker login "${REGISTRY}" --username "${HARBOR_USERNAME}" --password-stdin
- name: Push image (main only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
set -eu
docker push "${{ steps.tags.outputs.image_sha }}"
docker push "${{ steps.tags.outputs.image_main }}"
verification-service:
name: verification-service image
runs-on: ubuntu-latest
container:
image: debian:trixie-slim
options: --user 0:0
env:
REGISTRY: harbor.basicstack.de
IMAGE_REPO: harbor.basicstack.de/basicstack/verification-service
DOCKER_BUILDKIT: "1"
steps:
- name: Install git + buildx client + ca-certs
run: |
set -euo pipefail
apt-get update
apt-get install -y --no-install-recommends \
git curl ca-certificates docker.io docker-cli docker-buildx
git --version
docker --version
docker buildx version
- name: Clone repository (sha256-aware)
run: |
set -euo pipefail
git clone --depth=1 --branch="${GITHUB_REF_NAME}" \
"https://x-access-token:${GITHUB_TOKEN}@forgejo.basicstack.de/${GITHUB_REPOSITORY}.git" \
"${GITHUB_WORKSPACE}"
cd "${GITHUB_WORKSPACE}"
git log -1 --oneline
- name: Resolve tags
id: tags
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
SHA="$(git rev-parse --short HEAD)"
echo "sha=${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_sha=${IMAGE_REPO}:${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_main=${IMAGE_REPO}:main" >> "${GITHUB_OUTPUT}"
- name: Build image
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
docker buildx build \
--load \
-f services/verification-service/Dockerfile \
-t "${{ steps.tags.outputs.image_sha }}" \
-t "${{ steps.tags.outputs.image_main }}" \
.
- name: Login to Harbor (push jobs only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }}
HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }}
run: |
set -eu
echo "${HARBOR_PASSWORD}" | \
docker login "${REGISTRY}" --username "${HARBOR_USERNAME}" --password-stdin
- name: Push image (main only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
set -eu
docker push "${{ steps.tags.outputs.image_sha }}"
docker push "${{ steps.tags.outputs.image_main }}"
approval-service:
name: approval-service image
runs-on: ubuntu-latest
container:
image: debian:trixie-slim
options: --user 0:0
env:
REGISTRY: harbor.basicstack.de
IMAGE_REPO: harbor.basicstack.de/basicstack/approval-service
DOCKER_BUILDKIT: "1"
steps:
- name: Install git + buildx client + ca-certs
run: |
set -euo pipefail
apt-get update
apt-get install -y --no-install-recommends \
git curl ca-certificates docker.io docker-cli docker-buildx
git --version
docker --version
docker buildx version
- name: Clone repository (sha256-aware)
run: |
set -euo pipefail
git clone --depth=1 --branch="${GITHUB_REF_NAME}" \
"https://x-access-token:${GITHUB_TOKEN}@forgejo.basicstack.de/${GITHUB_REPOSITORY}.git" \
"${GITHUB_WORKSPACE}"
cd "${GITHUB_WORKSPACE}"
git log -1 --oneline
- name: Resolve tags
id: tags
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
SHA="$(git rev-parse --short HEAD)"
echo "sha=${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_sha=${IMAGE_REPO}:${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_main=${IMAGE_REPO}:main" >> "${GITHUB_OUTPUT}"
- name: Build image
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
docker buildx build \
--load \
-f services/approval-service/Dockerfile \
-t "${{ steps.tags.outputs.image_sha }}" \
-t "${{ steps.tags.outputs.image_main }}" \
.
- name: Login to Harbor (push jobs only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }}
HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }}
run: |
set -eu
echo "${HARBOR_PASSWORD}" | \
docker login "${REGISTRY}" --username "${HARBOR_USERNAME}" --password-stdin
- name: Push image (main only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
set -eu
docker push "${{ steps.tags.outputs.image_sha }}"
docker push "${{ steps.tags.outputs.image_main }}"
dummy-sink:
name: dummy-sink image
runs-on: ubuntu-latest
container:
image: debian:trixie-slim
options: --user 0:0
env:
REGISTRY: harbor.basicstack.de
IMAGE_REPO: harbor.basicstack.de/basicstack/dummy-sink
DOCKER_BUILDKIT: "1"
steps:
- name: Install git + buildx client + ca-certs
run: |
set -euo pipefail
apt-get update
apt-get install -y --no-install-recommends \
git curl ca-certificates docker.io docker-cli docker-buildx
git --version
docker --version
docker buildx version
- name: Clone repository (sha256-aware)
run: |
set -euo pipefail
git clone --depth=1 --branch="${GITHUB_REF_NAME}" \
"https://x-access-token:${GITHUB_TOKEN}@forgejo.basicstack.de/${GITHUB_REPOSITORY}.git" \
"${GITHUB_WORKSPACE}"
cd "${GITHUB_WORKSPACE}"
git log -1 --oneline
- name: Resolve tags
id: tags
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
SHA="$(git rev-parse --short HEAD)"
echo "sha=${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_sha=${IMAGE_REPO}:${SHA}" >> "${GITHUB_OUTPUT}"
echo "image_main=${IMAGE_REPO}:main" >> "${GITHUB_OUTPUT}"
- name: Build image
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
docker buildx build \
--load \
-f services/dummy-sink/Dockerfile \
-t "${{ steps.tags.outputs.image_sha }}" \
-t "${{ steps.tags.outputs.image_main }}" \
.
- name: Login to Harbor (push jobs only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
HARBOR_USERNAME: ${{ secrets.HARBOR_USERNAME }}
HARBOR_PASSWORD: ${{ secrets.HARBOR_PASSWORD }}
run: |
set -eu
echo "${HARBOR_PASSWORD}" | \
docker login "${REGISTRY}" --username "${HARBOR_USERNAME}" --password-stdin
- name: Push image (main only)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
set -eu
docker push "${{ steps.tags.outputs.image_sha }}"
docker push "${{ steps.tags.outputs.image_main }}"