Files
fips/.github/workflows/aur-publish.yml
T
Johnathan Corgan d399f8e07d Pin every GitHub Action to a commit SHA, and verify the nak download
Not one action reference in this repository was pinned. Every uses: line named
a mutable tag, and one named a branch. That includes the jobs holding the AUR
deploy key, the jobs with release write scope, and the packaging jobs that run
with a signing key in the environment, so whoever controls one of those action
repositories could repoint a tag into a job holding our credentials.

Sixty-two of the sixty-six references are now full commit SHAs with the
original tag kept as a trailing comment, so a reader can still tell which
release a pin is. Each SHA was resolved from the upstream peeled tag. Four
references are left unpinned and justified in one place rather than silently:
two actions select the tool they install from the ref name itself, so a bare
SHA hands them a hex string where a toolchain name belongs and the step fails.
Pinning those means moving the selection into with:, which changes what
resolves, and that is a separate decision from pinning.

A guard enforces the form on every sweep, wired into the parity job and the
local runner beside the existing checkers. It accepts only owner/repo@40-hex
with a mandatory trailing comment, treats an unreadable tree as exit 2 rather
than as a pass, and its header names what it does not cover: the actions that
pinned actions themselves invoke, the pip and cargo installs that are version
pinned at best, and anything fetched at run time.

The sharper hole was not the tags. The OpenWrt packaging workflow fetched a
helper binary straight from a release URL with no verification, in two jobs
that hold a signing key, which is code execution from a third-party host into a
credentialed job and needs nobody to retag anything. That download now goes
through a shared script with per-architecture pinned SHA-256 constants,
modelled on the zig block already in that workflow. Upstream publishes no
checksum document, so the provenance comment records the asset URL and the date
the hashes were taken by downloading rather than pretending they were verified
against a published sum.
2026-08-11 15:44:07 +00:00

204 lines
8.5 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
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- 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'
|| (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 }}
- 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 }}"