site-image/action.yml
Philip Peterson 9cc94f92b7 Use the forge's public address, not github.server_url
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>
2026-11-02 05:35:49 -09:00

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"