From 1934b86c13d8543d01739e0c8febccb057538ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asger=20Geel=20Weirs=C3=B8e?= Date: Wed, 30 Sep 2026 21:41:11 +0200 Subject: [PATCH] Publish ahfail-bin, hosted on the tarballz index A second AUR package with the same release prebuilt. The workflow builds the tag into a staged meson install tree (--prefix=/usr, no update check), names the tarball after its sha256 so a published name never changes bytes, uploads it to asger.weirsoe.dk/tarballz with a key that may only write ahfail-* tarballs, checks that the public URL serves the same bytes, and only then pushes ahfail-bin to the AUR. A manual run can now publish source, bin or both. Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG --- .gitea/workflows/aur-publish.yml | 133 +++++++++++++++++++++++++++++++ packaging/aur-bin/PKGBUILD | 58 ++++++++++++++ packaging/aur-bin/ahfail.install | 29 +++++++ 3 files changed, 220 insertions(+) create mode 100644 packaging/aur-bin/PKGBUILD create mode 100644 packaging/aur-bin/ahfail.install diff --git a/.gitea/workflows/aur-publish.yml b/.gitea/workflows/aur-publish.yml index 82305af..02b9471 100644 --- a/.gitea/workflows/aur-publish.yml +++ b/.gitea/workflows/aur-publish.yml @@ -15,9 +15,14 @@ on: description: 'Package release number' required: true default: '1' + packages: + description: 'Which AUR packages: both, source (ahfail) or bin (ahfail-bin)' + required: true + default: 'both' jobs: aur: + if: github.event_name != 'workflow_dispatch' || inputs.packages != 'bin' runs-on: ubuntu-latest container: image: archlinux:base-devel @@ -112,3 +117,131 @@ jobs: chmod 600 ~/.ssh/tarballz ssh -i ~/.ssh/tarballz -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new \ root@192.168.10.148 < aur-pkg/PKGBUILD + + # ahfail-bin: the same release, prebuilt. The binary is built from the TAG + # (also when this runs by hand from master), staged as a `meson install` tree, + # hosted on https://asger.weirsøe.dk/tarballz/ next to the other packages, and + # the AUR package only unpacks it. + aur-bin: + if: github.event_name != 'workflow_dispatch' || inputs.packages != 'source' + runs-on: ubuntu-latest + container: + image: archlinux:base-devel + steps: + - name: Install build and packaging tools + run: > + pacman -Syu --noconfirm --needed git openssh nodejs sudo pacman-contrib curl + rust meson ninja gtk3 gtk-session-lock gstreamer gst-plugins-base + gst-plugins-good gst-plugins-bad-libs pam + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Resolve version + id: version + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + VERSION="${{ inputs.version }}" + PKGREL="${{ inputs.pkgrel }}" + else + VERSION="${GITHUB_REF#refs/tags/v}" + PKGREL=1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "pkgrel=$PKGREL" >> "$GITHUB_OUTPUT" + + - name: Build the tagged source into a staged tree + run: | + # The packaging files come from this checkout; the binary from the tag. + cp -r packaging/aur-bin /tmp/aur-bin + git -c advice.detachedHead=false checkout "v${{ steps.version.outputs.version }}" + meson setup build --prefix=/usr --buildtype=release -Dupdate_check=false + meson compile -C build + DESTDIR="$PWD/stage" meson install -C build + find stage -type f | sort + + - name: Pack the tarball + id: tarball + run: | + # Reproducible-ish: fixed owner, sorted entries, mtime of the tagged commit. + EPOCH="$(git log -1 --format=%ct)" + tar --sort=name --owner=0 --group=0 --numeric-owner --mtime="@$EPOCH" \ + --zstd -cf ahfail.tar.zst -C stage usr etc + SHA="$(sha256sum ahfail.tar.zst | cut -d' ' -f1)" + # The hash is part of the name, so a published name never changes bytes. + NAME="ahfail-${{ steps.version.outputs.version }}-${SHA:0:12}-x86_64.tar.zst" + mv ahfail.tar.zst "$NAME" + echo "name=$NAME" >> "$GITHUB_OUTPUT" + echo "sha=$SHA" >> "$GITHUB_OUTPUT" + ls -l "$NAME" + + - name: Upload the tarball to tarballz + env: + TARBALLZ_BIN_SSH_KEY: ${{ secrets.TARBALLZ_BIN_SSH_KEY }} + run: | + mkdir -p ~/.ssh + printf '%s\n' "$TARBALLZ_BIN_SSH_KEY" > ~/.ssh/tarballz-bin + chmod 600 ~/.ssh/tarballz-bin + # Forced command on the web host: this key may only write ahfail-*.tar.* + # and ahfail-bin.PKGBUILD, and keeps the newest three tarballs. + ssh -i ~/.ssh/tarballz-bin -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new \ + root@192.168.10.148 "tarball ${{ steps.tarball.outputs.name }}" < "${{ steps.tarball.outputs.name }}" + + - name: Verify the public URL serves the same bytes + run: | + URL="https://asger.weirsoe.dk/tarballz/${{ steps.tarball.outputs.name }}" + GOT="$(curl -fsSL --retry 3 "$URL" | sha256sum | cut -d' ' -f1)" + if [ "$GOT" != "${{ steps.tarball.outputs.sha }}" ]; then + echo "error: $URL does not serve the uploaded tarball" >&2 + exit 1 + fi + + - name: Configure SSH for AUR + run: | + echo "${{ secrets.AUR_SSH_PRIVATE_KEY }}" > ~/.ssh/aur + chmod 600 ~/.ssh/aur + ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null + cat > ~/.ssh/config <<'EOF' + Host aur.archlinux.org + User aur + IdentityFile ~/.ssh/aur + StrictHostKeyChecking accept-new + EOF + useradd -m builder + + - name: Render PKGBUILD and .SRCINFO + run: | + git clone ssh://aur@aur.archlinux.org/ahfail-bin.git aur-bin-pkg 2>&1 || true + if [ ! -d aur-bin-pkg/.git ]; then + mkdir -p aur-bin-pkg && cd aur-bin-pkg + git init -b master + git remote add origin ssh://aur@aur.archlinux.org/ahfail-bin.git + cd .. + fi + cp /tmp/aur-bin/PKGBUILD /tmp/aur-bin/ahfail.install aur-bin-pkg/ + cd aur-bin-pkg + sed -i "s/@TARBALL@/${{ steps.tarball.outputs.name }}/g; s/@SHA256@/${{ steps.tarball.outputs.sha }}/" PKGBUILD + sed -i "s/^pkgver=.*/pkgver=${{ steps.version.outputs.version }}/; s/^pkgrel=.*/pkgrel=${{ steps.version.outputs.pkgrel }}/" PKGBUILD + chown -R builder: . + sudo -u builder makepkg --printsrcinfo > .SRCINFO + cat PKGBUILD | tail -20 + + - name: Commit and push to AUR + run: | + cd aur-bin-pkg + git config user.name "Asger Geel Weirsoe" + git config user.email "asger@weircon.dk" + git add PKGBUILD .SRCINFO ahfail.install + if git diff --staged --quiet; then + echo "No changes, nothing to push." + exit 0 + fi + git commit -m "Update to ${{ steps.version.outputs.version }}-${{ steps.version.outputs.pkgrel }}" + git push -u origin master + + - name: Publish PKGBUILD to the tarballz index + continue-on-error: true + run: | + ssh -i ~/.ssh/tarballz-bin -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new \ + root@192.168.10.148 < aur-bin-pkg/PKGBUILD diff --git a/packaging/aur-bin/PKGBUILD b/packaging/aur-bin/PKGBUILD new file mode 100644 index 0000000..8f7583c --- /dev/null +++ b/packaging/aur-bin/PKGBUILD @@ -0,0 +1,58 @@ +# Maintainer: Asger Geel Weirsoe +# +# DISCLAIMER +# +# ahfail is a joke with a real screen locker underneath. Two things to know +# before installing it: +# +# 1. Security. It sits in the authentication path of your session. It is +# provided as is, without any warranty (see the AGPL-3.0 license). On +# Wayland a crash leaves the session locked; on X11, as with i3lock, a +# killed locker leaves it open. /etc/pam.d/ahfail includes `login`, so +# the system's pam_faillock policy applies to wrong guesses. +# +# 2. Media. The sprite frames and the audio clip are a parody of the +# "ah ah ah, you didn't say the magic word" scene from Jurassic Park +# (1993). The film and its characters belong to their respective rights +# holders; they are used here non-commercially for parody, and the +# AGPL-3.0 license covers the code, not those assets. Rights holders who +# object can reach the maintainer at the address above and the assets +# will be replaced. +# +# PROVENANCE OF THE BINARY +# +# Built by the gtk-ahfail release workflow from the tagged source, in an +# archlinux:base-devel container, with --prefix=/usr and without the Gitea +# update check. The same recipe builds the source package `ahfail`. +# +# build recipe: https://gitea.weircon.dk/agw/gtk-ahfail +# download: https://asger.weirsoe.dk/tarballz/@TARBALL@ + +pkgname=ahfail-bin +pkgver=0.0.0 +pkgrel=1 +pkgdesc="Screen locker that says 'ah ah ah, you didn't say the magic word' on a wrong password (prebuilt binary)" +arch=('x86_64') +url="https://gitea.weircon.dk/agw/gtk-ahfail" +license=('AGPL-3.0-only') +# gst-plugins-bad-libs: libgstplayer. gst-plugins-base/-good are runtime plugins +# (audio conversion, the mpg123 mp3 decoder) that namcap cannot see being used. +depends=('gtk3' 'gtk-session-lock' 'gstreamer' 'gst-plugins-bad-libs' 'gst-plugins-base' + 'gst-plugins-good' 'pam' 'glib2' 'gdk-pixbuf2' 'cairo' 'pango' 'at-spi2-core' 'gst-plugins-base-libs' 'glibc' 'libgcc' 'libx11') +optdepends=('pipewire-pulse: raise the volume to 100% on a failed attempt (or libpulse)' + 'libpulse: raise the volume to 100% on a failed attempt' + 'swayidle: lock automatically on Wayland' + 'xss-lock: lock automatically on X11' + 'gtklock: legacy gtklock module (/usr/lib/gtklock/ahfail-module.so)') +provides=("ahfail=$pkgver") +conflicts=('ahfail') +backup=('etc/pam.d/ahfail') +install=ahfail.install +options=('!strip' '!debug') +source=("https://asger.weirsoe.dk/tarballz/@TARBALL@") +sha256sums=('@SHA256@') + +package() { + # The tarball is a staged `meson install` tree: usr/ and etc/ at its root. + cp -a "$srcdir/usr" "$srcdir/etc" "$pkgdir/" +} diff --git a/packaging/aur-bin/ahfail.install b/packaging/aur-bin/ahfail.install new file mode 100644 index 0000000..7f4a365 --- /dev/null +++ b/packaging/aur-bin/ahfail.install @@ -0,0 +1,29 @@ +_ahfail_msg() { + cat <<'MSG' +==> ahfail is its own screen locker and uses its own PAM service (/etc/pam.d/ahfail). + Nothing in your other PAM files has been changed. + + Check your setup: ahfail doctor + See the effect safely: ahfail test + Lock the screen: ahfail + + Lock automatically: + Wayland: swayidle -w timeout 300 'ahfail' before-sleep 'ahfail' + X11: xss-lock -- ahfail + + The old PAM hook (auth optional .../libahfail_pam.so in e.g. /etc/pam.d/i3lock) + is no longer needed with `ahfail`. Remove that line yourself if you added it. +MSG +} + +post_install() { + _ahfail_msg +} + +post_upgrade() { + # Only when coming from before 0.10.0, when ahfail became its own locker; + # repeating the message on every update would just teach people to skip it. + if (( $(vercmp "$2" 0.10.0) < 0 )); then + _ahfail_msg + fi +}