mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-05 11:08:25 +00:00
The AUR publish job depended only on the AUR build job, so on a release tag it pushed the new pkgver while the Linux, macOS, Windows, OpenWrt and FreeBSD package workflows were still building and uploading. At v0.5.1 the AUR was updated while the release had 15 of its 17 assets. Once the AUR points at a tag, deleting that tag to withdraw a bad release leaves the AUR package unbuildable, because its b2sum pins the tag's source archive. The publish job now waits, before it touches the AUR, for every package-*.yml workflow in the tag's tree to have a successful run of the tag push. Runs are matched on the tag name as well as the commit, because the branch push of the same commit starts runs that are not the release's. A failed or cancelled run stops the publish at once; a missing, unfinished or unreadable run is polled for up to an hour and then fails the job. The gate script is taken from the workflow's own revision, so a dispatched republish of a tag cut before this change still runs it. The gate lives in packaging/aur/await-package-runs.sh so it can be exercised against a stubbed gh; its fixture tests run in the AUR build job on every trigger.
240 lines
10 KiB
YAML
240 lines
10 KiB
YAML
name: AUR Publish
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
- maint
|
|
- next
|
|
tags:
|
|
- 'v*'
|
|
pull_request:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: 'Release tag to publish (e.g. v0.4.0). Defaults to the tag the workflow was dispatched from.'
|
|
required: false
|
|
default: ''
|
|
pkgrel:
|
|
description: 'AUR pkgrel to publish. Use 2+ for packaging-only republishes of an existing tag.'
|
|
required: false
|
|
default: '1'
|
|
|
|
jobs:
|
|
# ───────────────────────────────────────────────────────────────────────────
|
|
# Build + lint the AUR package on every trigger, matching the coverage the
|
|
# other package workflows (linux/macos/windows/openwrt) give their artifacts:
|
|
# branch pushes, pull requests, tags, and manual dispatch. Uses makepkg +
|
|
# namcap in an Arch container (neither tool exists on ubuntu-latest) and builds
|
|
# the *checked-out tree* from a local git-archive tarball, so it works for
|
|
# branch/PR builds and unreleased rc tags whose GitHub source archive does not
|
|
# exist yet. This job never publishes.
|
|
# ───────────────────────────────────────────────────────────────────────────
|
|
aur-build:
|
|
name: Build and lint fips AUR package
|
|
runs-on: ubuntu-latest
|
|
container: archlinux:base-devel
|
|
|
|
steps:
|
|
- name: Install build and lint tooling
|
|
run: |
|
|
set -euo pipefail
|
|
pacman -Sy --noconfirm --needed base-devel namcap git curl jq
|
|
|
|
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
|
|
- name: Test the publish gate
|
|
# Fixture tests for the script the publish job below waits with. They
|
|
# run here, on every trigger, so a change to the gate is exercised
|
|
# before a release tag depends on it.
|
|
run: bash packaging/aur/test-await-package-runs.sh
|
|
|
|
- name: Resolve package version
|
|
id: ver
|
|
env:
|
|
INPUT_TAG: ${{ inputs.tag }}
|
|
INPUT_PKGREL: ${{ inputs.pkgrel }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [ -n "${INPUT_TAG:-}" ]; then
|
|
RAW="${INPUT_TAG#v}"
|
|
elif [ "${GITHUB_REF_TYPE:-}" = "tag" ]; then
|
|
RAW="${GITHUB_REF_NAME#v}"
|
|
else
|
|
# Branch push / PR: derive the version from the crate manifest.
|
|
RAW=$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/')
|
|
fi
|
|
# makepkg forbids '-' in pkgver; map e.g. 0.4.0-rc1 -> 0.4.0rc1,
|
|
# 0.4.0-dev -> 0.4.0dev. The build only needs an internally consistent
|
|
# pkgver (it matches the git-archive prefix below); this is not the
|
|
# value the real publish uses.
|
|
VERSION="${RAW//-/}"
|
|
PKGREL="${INPUT_PKGREL:-1}"
|
|
case "$PKGREL" in
|
|
''|*[!0-9]*|0) echo "pkgrel '$PKGREL' must be a positive integer"; exit 1 ;;
|
|
esac
|
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
echo "pkgrel=${PKGREL}" >> "$GITHUB_OUTPUT"
|
|
echo "Resolved AUR pkgver=${VERSION} pkgrel=${PKGREL}"
|
|
|
|
- name: Create non-root build user and fix ownership
|
|
run: |
|
|
set -euo pipefail
|
|
# makepkg refuses to run as root; create an unprivileged build user
|
|
# with passwordless sudo (needed for pacman dep installs during -s).
|
|
useradd -m -s /bin/bash builder
|
|
echo 'builder ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/builder
|
|
chmod 0440 /etc/sudoers.d/builder
|
|
# The checkout is owned by root; hand it to the build user.
|
|
chown -R builder:builder "$GITHUB_WORKSPACE"
|
|
|
|
- name: Build a local source tarball of the checkout
|
|
env:
|
|
VERSION: ${{ steps.ver.outputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
# The PKGBUILD source= points at GitHub archive/<tag>.tar.gz, which does
|
|
# not exist for a branch push, a PR, or an unreleased rc tag and would
|
|
# 404. Instead build the checked-out tree by packing it into a local
|
|
# tarball whose top-level directory matches what the PKGBUILD expects
|
|
# ("fips-<pkgver>/"); patch-pkgbuild.sh repoints source= at it.
|
|
TARBALL="packaging/aur/fips-${VERSION}.tar.gz"
|
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
git -C "$GITHUB_WORKSPACE" archive --format=tar.gz \
|
|
--prefix="fips-${VERSION}/" -o "$TARBALL" HEAD
|
|
chown builder:builder "$TARBALL"
|
|
ls -l "$TARBALL"
|
|
|
|
- name: Patch PKGBUILD
|
|
env:
|
|
TAG: v${{ steps.ver.outputs.version }}
|
|
VERSION: ${{ steps.ver.outputs.version }}
|
|
PKGREL: ${{ steps.ver.outputs.pkgrel }}
|
|
run: |
|
|
set -euo pipefail
|
|
LOCAL_TARBALL="packaging/aur/fips-${VERSION}.tar.gz" \
|
|
bash packaging/aur/patch-pkgbuild.sh
|
|
chown builder:builder packaging/aur/PKGBUILD
|
|
|
|
- name: makepkg build and namcap lint (as build user)
|
|
run: |
|
|
set -euo pipefail
|
|
sudo -u builder bash -euo pipefail -c '
|
|
cd packaging/aur
|
|
echo "::group::namcap PKGBUILD"
|
|
namcap PKGBUILD
|
|
echo "::endgroup::"
|
|
echo "::group::makepkg build"
|
|
# --nocheck: skip the PKGBUILD check() (cargo test --lib); the test
|
|
# suite is already covered by ci.yml. This job validates packaging.
|
|
makepkg -s --noconfirm --nocheck
|
|
echo "::endgroup::"
|
|
echo "::group::namcap built package"
|
|
for pkg in *.pkg.tar.*; do
|
|
echo "namcap $pkg"
|
|
namcap "$pkg"
|
|
done
|
|
echo "::endgroup::"
|
|
'
|
|
|
|
# ───────────────────────────────────────────────────────────────────────────
|
|
# Publish to the AUR. Runs only on a real (non-prerelease) release tag push,
|
|
# or a manual dispatch (packaging-only republish with explicit tag + pkgrel).
|
|
# Branch pushes and pull requests build+lint above but never reach this job.
|
|
# Gated on aur-build so a package that fails to build/lint is never published.
|
|
# It also waits for every package-*.yml run on the tag to succeed before it
|
|
# pushes: the AUR must not point at a tag whose release assets are still
|
|
# uploading or failed, and once it does, withdrawing the tag breaks the AUR
|
|
# package (its b2sum pins the tag's source archive).
|
|
# ───────────────────────────────────────────────────────────────────────────
|
|
aur-publish-fips:
|
|
name: Publish fips to AUR
|
|
needs: aur-build
|
|
runs-on: ubuntu-latest
|
|
# Above the gate's own 60-minute budget, so the gate reports a timeout
|
|
# rather than the runner killing it.
|
|
timeout-minutes: 90
|
|
permissions:
|
|
contents: read
|
|
actions: read
|
|
if: >-
|
|
github.event_name == 'workflow_dispatch'
|
|
|| (github.event_name == 'push'
|
|
&& startsWith(github.ref, 'refs/tags/v')
|
|
&& !contains(github.ref_name, '-'))
|
|
|
|
steps:
|
|
- name: Resolve release tag
|
|
id: tag
|
|
env:
|
|
INPUT_TAG: ${{ inputs.tag }}
|
|
INPUT_PKGREL: ${{ inputs.pkgrel }}
|
|
run: |
|
|
set -euo pipefail
|
|
TAG="${INPUT_TAG:-$GITHUB_REF_NAME}"
|
|
PKGREL="${INPUT_PKGREL:-1}"
|
|
case "$TAG" in
|
|
v*) ;;
|
|
*) echo "Tag '$TAG' does not look like a release tag (vX.Y.Z)"; exit 1 ;;
|
|
esac
|
|
case "$PKGREL" in
|
|
''|*[!0-9]*|0) echo "pkgrel '$PKGREL' must be a positive integer"; exit 1 ;;
|
|
esac
|
|
case "$TAG" in
|
|
*-*)
|
|
if [ "$GITHUB_EVENT_NAME" != "workflow_dispatch" ]; then
|
|
echo "Pre-release tag '$TAG' — skipping AUR publish"
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
|
echo "pkgrel=${PKGREL}" >> "$GITHUB_OUTPUT"
|
|
|
|
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
with:
|
|
ref: ${{ steps.tag.outputs.tag }}
|
|
|
|
# The gate script comes from this workflow's own revision, not the tag:
|
|
# a dispatch republishing a tag cut before the gate existed would not
|
|
# find it in the tag's tree. The workflows it waits on still come from
|
|
# the tag's tree, which is what the tag push triggered.
|
|
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
with:
|
|
path: gate-src
|
|
sparse-checkout: packaging/aur
|
|
|
|
- name: Wait for the tag's package workflows
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
TAG: ${{ steps.tag.outputs.tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
SHA=$(git rev-parse 'HEAD^{commit}')
|
|
echo "Tag $TAG is at $SHA"
|
|
SHA="$SHA" WORKFLOW_DIR=.github/workflows \
|
|
bash gate-src/packaging/aur/await-package-runs.sh
|
|
|
|
- name: Patch PKGBUILD with pkgver, pkgrel, conflicts, and b2sums
|
|
env:
|
|
TAG: ${{ steps.tag.outputs.tag }}
|
|
VERSION: ${{ steps.tag.outputs.version }}
|
|
PKGREL: ${{ steps.tag.outputs.pkgrel }}
|
|
run: bash packaging/aur/patch-pkgbuild.sh
|
|
|
|
- name: Publish to AUR
|
|
uses: KSXGitHub/github-actions-deploy-aur@abe8ac26b51011c88be58c8809fd2ac674068ea5 # v4.1.2
|
|
with:
|
|
pkgname: fips
|
|
pkgbuild: packaging/aur/PKGBUILD
|
|
updpkgsums: false
|
|
assets: |
|
|
packaging/aur/fips.sysusers
|
|
packaging/aur/fips.tmpfiles
|
|
packaging/aur/fips.install
|
|
commit_username: ${{ github.repository_owner }}
|
|
commit_email: ${{ secrets.AUR_EMAIL }}
|
|
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
|
commit_message: "Update to ${{ steps.tag.outputs.tag }}"
|