The forge answered 504 to dnf-package-store's x86_64 RPM, uploaded just after its aarch64 one; the build was fine and the RPM never landed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
4.2 KiB
YAML
108 lines
4.2 KiB
YAML
# Builds an app as an RPM for each architecture and uploads it to the forge's
|
|
# RPM group (README.md). Runs on a host-mode runner (podman, curl):
|
|
# runner-x86-linux and runner-arm64-linux, one per architecture from the
|
|
# app's matrix; an architecture not the runner's own builds under QEMU
|
|
# emulation.
|
|
name: app-build
|
|
description: >-
|
|
Build an app (Flutter or Go) as RPMs for x86_64 and aarch64, packaged by
|
|
the repo's own spec, and upload them to the forge's RPM group.
|
|
|
|
inputs:
|
|
name:
|
|
description: The package's name; its spec is packaging/<name>.spec
|
|
required: true
|
|
kind:
|
|
description: flutter or go
|
|
required: true
|
|
go-packages:
|
|
description: For go, the packages to build into bin/ (space-separated, e.g. ./cmd/foo ./cmd/bar)
|
|
default: ''
|
|
dnf-packages:
|
|
description: Extra Fedora packages the build needs (space-separated)
|
|
default: ''
|
|
archs:
|
|
description: Architectures to build (space-separated podman names)
|
|
default: amd64 arm64
|
|
fedora:
|
|
description: Fedora release to build in
|
|
default: '44'
|
|
group:
|
|
description: The RPM group to upload to
|
|
default: quine
|
|
owner:
|
|
description: The forge account that holds the RPM group
|
|
default: quine-global-labs
|
|
registry-username:
|
|
description: Account that uploads the RPMs
|
|
required: true
|
|
registry-password:
|
|
description: Its token (package write)
|
|
required: true
|
|
server:
|
|
description: The forge's address (not github.server_url, as site-image explains)
|
|
default: https://forge.quinefoundation.com
|
|
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Build
|
|
shell: bash
|
|
env:
|
|
NAME: ${{ inputs.name }}
|
|
KIND: ${{ inputs.kind }}
|
|
GO_PACKAGES: ${{ inputs.go-packages }}
|
|
DNF_PACKAGES: ${{ inputs.dnf-packages }}
|
|
ARCHS: ${{ inputs.archs }}
|
|
FEDORA: ${{ inputs.fedora }}
|
|
ACTION_DIR: ${{ github.action_path }}
|
|
# /var/cache/quine-rpm-build outlives the job (host-mode runner): the
|
|
# Flutter SDKs, Go's toolchain, and package caches.
|
|
run: |
|
|
set -euo pipefail
|
|
case $KIND in flutter|go) ;; *) echo "::error::kind must be flutter or go, not '$KIND'"; exit 1 ;; esac
|
|
[ -f "packaging/$NAME.spec" ] || { echo "::error::no packaging/$NAME.spec"; exit 1; }
|
|
mkdir -p out /var/cache/quine-rpm-build
|
|
for arch in $ARCHS; do
|
|
echo "::group::$NAME for $arch"
|
|
podman run --rm --platform "linux/$arch" \
|
|
-v "$PWD":/src -v "$ACTION_DIR/scripts":/scripts:ro \
|
|
-v /var/cache/quine-rpm-build:/cache -v "$PWD/out":/out \
|
|
-e NAME -e GO_PACKAGES -e DNF_PACKAGES \
|
|
"registry.fedoraproject.org/fedora:$FEDORA" bash "/scripts/build-$KIND.sh"
|
|
echo "::endgroup::"
|
|
done
|
|
ls -l out
|
|
|
|
- name: Upload
|
|
shell: bash
|
|
env:
|
|
REGISTRY_USERNAME: ${{ inputs.registry-username }}
|
|
REGISTRY_PASSWORD: ${{ inputs.registry-password }}
|
|
URL: ${{ inputs.server }}/api/packages/${{ inputs.owner }}/rpm/${{ inputs.group }}/upload
|
|
run: |
|
|
set -euo pipefail
|
|
[ -n "$REGISTRY_PASSWORD" ] || { echo "::error::no registry-password (a token with package write)"; exit 1; }
|
|
netrc=$(mktemp); trap 'rm -f "$netrc"' EXIT; chmod 600 "$netrc"
|
|
host=${URL#https://}; host=${host%%/*}
|
|
printf 'machine %s login %s password %s\n' "$host" "$REGISTRY_USERNAME" "$REGISTRY_PASSWORD" >"$netrc"
|
|
# The forge rebuilds and signs the group's metadata on each upload, and
|
|
# answered 504 to one landing right after another (dnf-package-store,
|
|
# 2026-11-04): retry server errors, with a growing wait.
|
|
for f in out/*.rpm; do
|
|
for try in 1 2 3 4 5 6; do
|
|
code=$(curl -sS -o /dev/null -w '%{http_code}' --netrc-file "$netrc" --upload-file "$f" "$URL" || true)
|
|
echo "$code ${f#out/}"
|
|
# 409: this exact version is there already (also when a retried
|
|
# upload had landed after all).
|
|
[ "$code" = 201 ] || [ "$code" = 409 ] && continue 2
|
|
case $code in 5??|000) [ "$try" = 6 ] || { sleep $((try * 20)); continue; } ;; esac
|
|
exit 1
|
|
done
|
|
exit 1
|
|
done
|
|
|
|
- name: Clean up
|
|
if: always()
|
|
shell: bash
|
|
run: rm -rf out build bin
|