The forge VM's runner is told http://localhost:3000, which a job container can't reach, so cloning petersweb-infra and the PR API would fail there. New input server, default https://forge.quinefoundation.com. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
129 lines
4.8 KiB
YAML
129 lines
4.8 KiB
YAML
# Builds and pushes a site's container image, then opens a petersweb-infra
|
|
# PR that pins it by digest (README.md). Runs on runner-x86-linux (host
|
|
# mode: podman, git, curl, jq on the host).
|
|
name: site-image
|
|
description: >-
|
|
Build and push a site's image, then open a petersweb-infra PR that bumps
|
|
the image's pinned digest.
|
|
|
|
inputs:
|
|
image:
|
|
description: The image, without a tag, as petersweb-infra pins it (forge.quinefoundation.com/<owner>/<name>)
|
|
required: true
|
|
infra-file:
|
|
description: The petersweb-infra file that pins it as <image>@sha256:<digest>
|
|
required: true
|
|
name:
|
|
description: Short name for the branch and PR title (default the image's last path part)
|
|
default: ''
|
|
context:
|
|
description: Build context
|
|
default: .
|
|
containerfile:
|
|
description: Containerfile or Dockerfile (default podman's choice in the context)
|
|
default: ''
|
|
platform:
|
|
description: Platform to build for
|
|
default: linux/amd64
|
|
registry-username:
|
|
description: Account that pushes the image
|
|
required: true
|
|
registry-password:
|
|
description: Its token (package write)
|
|
required: true
|
|
infra-token:
|
|
description: Token that can push a branch to petersweb-infra and open a PR there
|
|
required: true
|
|
infra-repo:
|
|
description: The infra repo
|
|
default: Cold-Air-Networks/petersweb-infra
|
|
server:
|
|
description: >-
|
|
The forge's address, for cloning, the API and links. Not
|
|
github.server_url: a runner next to Forgejo (the forge VM's) is told
|
|
http://localhost:3000, which a job container can't reach.
|
|
default: https://forge.quinefoundation.com
|
|
|
|
outputs:
|
|
digest:
|
|
description: The pushed image's digest (sha256:...)
|
|
value: ${{ steps.push.outputs.digest }}
|
|
pr:
|
|
description: The PR's URL, or empty if petersweb-infra already pins this digest
|
|
value: ${{ steps.pr.outputs.url }}
|
|
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Build and push the image
|
|
id: push
|
|
shell: bash
|
|
env:
|
|
IMAGE: ${{ inputs.image }}
|
|
CONTEXT: ${{ inputs.context }}
|
|
CONTAINERFILE: ${{ inputs.containerfile }}
|
|
PLATFORM: ${{ inputs.platform }}
|
|
REGISTRY_USERNAME: ${{ inputs.registry-username }}
|
|
REGISTRY_PASSWORD: ${{ inputs.registry-password }}
|
|
SHA: ${{ github.sha }}
|
|
run: |
|
|
set -euo pipefail
|
|
printf %s "$REGISTRY_PASSWORD" | podman login "${IMAGE%%/*}" -u "$REGISTRY_USERNAME" --password-stdin
|
|
args=(--platform "$PLATFORM" -t "$IMAGE:$SHA")
|
|
[ -z "$CONTAINERFILE" ] || args+=(-f "$CONTAINERFILE")
|
|
podman build "${args[@]}" "$CONTEXT"
|
|
digestfile=$(mktemp)
|
|
podman push --retry 5 --digestfile "$digestfile" "$IMAGE:$SHA"
|
|
digest=$(cat "$digestfile")
|
|
rm -f "$digestfile"
|
|
echo "pushed $IMAGE:$SHA as $digest"
|
|
echo "digest=$digest" >>"$GITHUB_OUTPUT"
|
|
|
|
- name: Open a petersweb-infra PR
|
|
id: pr
|
|
shell: bash
|
|
env:
|
|
IMAGE: ${{ inputs.image }}
|
|
INFRA_FILE: ${{ inputs.infra-file }}
|
|
INFRA_REPO: ${{ inputs.infra-repo }}
|
|
INFRA_TOKEN: ${{ inputs.infra-token }}
|
|
NAME: ${{ inputs.name }}
|
|
SERVER: ${{ inputs.server }}
|
|
DIGEST: ${{ steps.push.outputs.digest }}
|
|
SHA: ${{ github.sha }}
|
|
run: |
|
|
set -euo pipefail
|
|
server=$SERVER
|
|
name=${NAME:-${IMAGE##*/}}
|
|
short=${SHA:0:7}
|
|
branch="bump-$name-$short"
|
|
commit_url="$server/$GITHUB_REPOSITORY/commit/$SHA"
|
|
run_url="$server/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_NUMBER"
|
|
|
|
work=$(mktemp -d)
|
|
git clone -q --depth 1 "https://ci:$INFRA_TOKEN@${server#https://}/$INFRA_REPO.git" "$work"
|
|
cd "$work"
|
|
if ! grep -qF "$IMAGE@sha256:" "$INFRA_FILE"; then
|
|
echo "::error::$INFRA_REPO's $INFRA_FILE doesn't pin $IMAGE@sha256:<digest>"
|
|
exit 1
|
|
fi
|
|
sed -i -E "s|(${IMAGE//./\\.}@)sha256:[0-9a-f]{64}|\1$DIGEST|" "$INFRA_FILE"
|
|
if git diff --quiet; then
|
|
echo "$INFRA_REPO already pins $IMAGE@$DIGEST"
|
|
echo "url=" >>"$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
|
|
git switch -q -c "$branch"
|
|
git -c user.name="Site image CI" -c user.email="ci@quinefoundation.com" \
|
|
commit -q -a -m "$name: bump to $short" \
|
|
-m "$IMAGE@$DIGEST, built from $commit_url ($run_url)."
|
|
git push -q origin "$branch"
|
|
|
|
body=$(jq -n --arg t "$name: bump to $short" --arg h "$branch" \
|
|
--arg b "Pins \`$IMAGE@$DIGEST\` in \`$INFRA_FILE\`, built from $commit_url by $run_url." \
|
|
'{title: $t, head: $h, base: "main", body: $b}')
|
|
url=$(curl -fsS -X POST -H "Authorization: token $INFRA_TOKEN" -H "Content-Type: application/json" \
|
|
"$server/api/v1/repos/$INFRA_REPO/pulls" -d "$body" | jq -r .html_url)
|
|
echo "opened $url"
|
|
echo "url=$url" >>"$GITHUB_OUTPUT"
|