mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 11:36:15 +00:00
ci: build and lint the AUR package on every CI trigger
Run the AUR package through makepkg + namcap on the same triggers as the other package workflows (pushes to master/maint/next, pull requests, tags, and manual dispatch), so a broken PKGBUILD is caught continuously rather than only at release time. The build runs in an Arch container (makepkg/namcap are not on ubuntu-latest) and packages the checked-out tree from a local git-archive tarball, so it works for branch/PR builds and unreleased rc tags that have no published GitHub source archive yet. makepkg runs with --nocheck since the test suite is already covered by ci.yml; this job validates packaging. Publishing to the AUR is unchanged in intent but now gated to a real (non-prerelease) release tag push, plus the existing manual-dispatch republish path for packaging-only pkgrel bumps; it depends on the build job so a package that fails to build or lint is never published. Branch pushes and pull requests build and lint but never publish. The PKGBUILD-patching logic is factored into a shared packaging/aur/patch-pkgbuild.sh used by both jobs; the build path sanitizes the version for makepkg (which forbids '-' in pkgver).
This commit is contained in:
@@ -1,25 +1,151 @@
|
||||
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.3.0). Defaults to the tag the workflow was dispatched from.'
|
||||
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'
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
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
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- 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.
|
||||
# ───────────────────────────────────────────────────────────────────────────
|
||||
aur-publish-fips:
|
||||
name: Publish fips to AUR
|
||||
needs: aur-build
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'workflow_dispatch' || !contains(github.ref_name, '-')
|
||||
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
|
||||
@@ -59,36 +185,7 @@ jobs:
|
||||
TAG: ${{ steps.tag.outputs.tag }}
|
||||
VERSION: ${{ steps.tag.outputs.version }}
|
||||
PKGREL: ${{ steps.tag.outputs.pkgrel }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
URL="https://github.com/${GITHUB_REPOSITORY}/archive/${TAG}.tar.gz"
|
||||
echo "Fetching $URL"
|
||||
SOURCE_SUM=$(curl -fsSL --retry 3 "$URL" | b2sum | awk '{print $1}')
|
||||
SYSUSERS_SUM=$(b2sum packaging/aur/fips.sysusers | awk '{print $1}')
|
||||
TMPFILES_SUM=$(b2sum packaging/aur/fips.tmpfiles | awk '{print $1}')
|
||||
for v in SOURCE_SUM SYSUSERS_SUM TMPFILES_SUM; do
|
||||
eval val=\$$v
|
||||
if [ -z "$val" ]; then echo "$v is empty"; exit 1; fi
|
||||
done
|
||||
sed -i "s/^pkgver=.*/pkgver=${VERSION}/" packaging/aur/PKGBUILD
|
||||
sed -i "s/^pkgrel=.*/pkgrel=${PKGREL}/" packaging/aur/PKGBUILD
|
||||
sed -i "s/^conflicts=.*/conflicts=('fips-git' 'fips-git-debug')/" packaging/aur/PKGBUILD
|
||||
sed -i "s/^options=.*/options=('!lto' '!debug')/" packaging/aur/PKGBUILD
|
||||
sed -i "s|^b2sums=('SKIP'.*|b2sums=('${SOURCE_SUM}'|" packaging/aur/PKGBUILD
|
||||
awk -v s1="$SYSUSERS_SUM" -v s2="$TMPFILES_SUM" '
|
||||
/^b2sums=\(/ { in_block=1; count=0 }
|
||||
in_block {
|
||||
count++
|
||||
if (count == 2) sub(/[a-f0-9]{128}/, s1)
|
||||
if (count == 3) sub(/[a-f0-9]{128}/, s2)
|
||||
if ($0 ~ /\)/) in_block=0
|
||||
}
|
||||
{ print }
|
||||
' packaging/aur/PKGBUILD > packaging/aur/PKGBUILD.new
|
||||
mv packaging/aur/PKGBUILD.new packaging/aur/PKGBUILD
|
||||
echo "Patched PKGBUILD:"
|
||||
grep -E "^(pkgver|pkgrel|conflicts|options)=" packaging/aur/PKGBUILD
|
||||
awk '/^b2sums=\(/,/\)$/' packaging/aur/PKGBUILD
|
||||
run: bash packaging/aur/patch-pkgbuild.sh
|
||||
|
||||
- name: Publish to AUR
|
||||
uses: KSXGitHub/github-actions-deploy-aur@v4.1.2
|
||||
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# Patch packaging/aur/PKGBUILD in place with the release pkgver, pkgrel,
|
||||
# conflicts, options, and b2sums.
|
||||
#
|
||||
# Shared by the AUR publish workflow's real-publish job and its dry-run job
|
||||
# so the patching logic lives in exactly one place.
|
||||
#
|
||||
# Required environment variables:
|
||||
# TAG - release tag (e.g. v0.4.0 or v0.4.0-rc1)
|
||||
# VERSION - tag without the leading 'v' (e.g. 0.4.0)
|
||||
# PKGREL - AUR pkgrel (positive integer)
|
||||
#
|
||||
# Source of the tarball b2sum:
|
||||
# Default: fetch the GitHub source archive for $TAG and hash it.
|
||||
# Dry-run: set LOCAL_TARBALL to a path; its b2sum is used instead and the
|
||||
# PKGBUILD source= line is rewritten to point at that local file.
|
||||
# This lets a dry-run validate an rc tag that has no published
|
||||
# GitHub release archive yet (the archive URL would 404).
|
||||
#
|
||||
# Uses $GITHUB_REPOSITORY for the source URL (owner/repo).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: "${TAG:?TAG must be set}"
|
||||
: "${VERSION:?VERSION must be set}"
|
||||
: "${PKGREL:?PKGREL must be set}"
|
||||
|
||||
PKGBUILD="packaging/aur/PKGBUILD"
|
||||
|
||||
SYSUSERS_SUM=$(b2sum packaging/aur/fips.sysusers | awk '{print $1}')
|
||||
TMPFILES_SUM=$(b2sum packaging/aur/fips.tmpfiles | awk '{print $1}')
|
||||
|
||||
if [ -n "${LOCAL_TARBALL:-}" ]; then
|
||||
# Dry-run path: hash the locally-created tarball of the checkout.
|
||||
echo "Using local tarball $LOCAL_TARBALL for b2sum (dry-run)"
|
||||
SOURCE_SUM=$(b2sum "$LOCAL_TARBALL" | awk '{print $1}')
|
||||
else
|
||||
URL="https://github.com/${GITHUB_REPOSITORY:?GITHUB_REPOSITORY must be set}/archive/${TAG}.tar.gz"
|
||||
echo "Fetching $URL"
|
||||
SOURCE_SUM=$(curl -fsSL --retry 3 "$URL" | b2sum | awk '{print $1}')
|
||||
fi
|
||||
|
||||
for v in SOURCE_SUM SYSUSERS_SUM TMPFILES_SUM; do
|
||||
eval val=\$$v
|
||||
if [ -z "$val" ]; then echo "$v is empty"; exit 1; fi
|
||||
done
|
||||
|
||||
sed -i "s/^pkgver=.*/pkgver=${VERSION}/" "$PKGBUILD"
|
||||
sed -i "s/^pkgrel=.*/pkgrel=${PKGREL}/" "$PKGBUILD"
|
||||
sed -i "s/^conflicts=.*/conflicts=('fips-git' 'fips-git-debug')/" "$PKGBUILD"
|
||||
sed -i "s/^options=.*/options=('!lto' '!debug')/" "$PKGBUILD"
|
||||
|
||||
if [ -n "${LOCAL_TARBALL:-}" ]; then
|
||||
# Repoint the first source entry at the local tarball so makepkg builds the
|
||||
# checked-out tree instead of fetching the (possibly unpublished) GitHub
|
||||
# archive. makepkg resolves a bare filename source against $startdir.
|
||||
LOCAL_BASE=$(basename "$LOCAL_TARBALL")
|
||||
sed -i "s|^source=(\"\$pkgname-\$pkgver.tar.gz::[^\"]*\"|source=(\"\$pkgname-\$pkgver.tar.gz::${LOCAL_BASE}\"|" "$PKGBUILD"
|
||||
fi
|
||||
|
||||
sed -i "s|^b2sums=('SKIP'.*|b2sums=('${SOURCE_SUM}'|" "$PKGBUILD"
|
||||
awk -v s1="$SYSUSERS_SUM" -v s2="$TMPFILES_SUM" '
|
||||
/^b2sums=\(/ { in_block=1; count=0 }
|
||||
in_block {
|
||||
count++
|
||||
if (count == 2) sub(/[a-f0-9]{128}/, s1)
|
||||
if (count == 3) sub(/[a-f0-9]{128}/, s2)
|
||||
if ($0 ~ /\)/) in_block=0
|
||||
}
|
||||
{ print }
|
||||
' "$PKGBUILD" > "$PKGBUILD.new"
|
||||
mv "$PKGBUILD.new" "$PKGBUILD"
|
||||
|
||||
echo "Patched PKGBUILD:"
|
||||
grep -E "^(pkgver|pkgrel|conflicts|options|source)=" "$PKGBUILD"
|
||||
awk '/^b2sums=\(/,/\)$/' "$PKGBUILD"
|
||||
Reference in New Issue
Block a user