Skip to content

ci(release): publish AUR packages on release (#6334)#6341

Merged
houko merged 4 commits into
mainfrom
ci/aur-publish
Jun 29, 2026
Merged

ci(release): publish AUR packages on release (#6334)#6341
houko merged 4 commits into
mainfrom
ci/aur-publish

Conversation

@houko

@houko houko commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Implements Option 2 of #6334: automated AUR publishing on release.

PR #6314 added the AUR package sources under packaging/aur/ but nothing pushes them to the Arch User Repository.
This adds the automation so yay -S librefang-bin / librefang-desktop-bin / librefang-docker track each LibreFang release, pinned to the exact version (never latest).

How

Three new release.yml jobs — sync_aur_bin, sync_aur_desktop, sync_aur_docker — modeled directly on the existing sync_homebrew / sync_homebrew_cask jobs.
They share the same tag/dispatch if: guard and each waits (needs:) on the build job that produced its asset (cli_linux / desktop / docker-manifest).
Split into three independent jobs (not a matrix) so a desktop build failure cannot block the librefang-bin publish, and vice versa.

A shared composite action (.github/actions/publish-aur) runs packaging/aur/publish-to-aur.sh inside archlinux:base-devel (via docker run on the ubuntu host, so actions/checkout keeps using the host's Node/git).
The script self-bootstraps: as root it installs the Arch tooling and drops to an unprivileged builder (makepkg refuses to run as root), then per package it:

  • bumps pkgver (encoding the tag's first - as _, e.g. v2026.6.26-beta.242026.6.26_beta.24) and resets pkgrel to 1;
  • for librefang-desktop-bin, reads the Tauri bundle version off the actual LibreFang_<ver>_amd64.deb asset name (it differs from the tag, exactly like the cask sync);
  • for librefang-docker, re-pins the ghcr.io/librefang/librefang:<version> tag inside the helper script and env file;
  • regenerates sha256sums (updpkgsums) and .SRCINFO (makepkg --printsrcinfo);
  • clones ssh://[email protected]/<package>.git, copies only the committed source files (never downloaded artifacts), and pushes if anything changed.

The committed packaging/aur/ files remain a working baseline for local makepkg; the release-correct pkgver / sha256sums / .SRCINFO are generated into the AUR repositories on each tag.

Maintainer setup required (the issue's Option-2 prerequisites)

The jobs degrade to a no-op with a notice until AUR_SSH_PRIVATE_KEY is configured, so this PR is safe to merge first.
To activate:

  1. Create the three AUR repositories under the owning AUR account.
  2. Add AUR_SSH_PRIVATE_KEY (and optionally AUR_KNOWN_HOSTS, AUR_GIT_NAME, AUR_GIT_EMAIL) as repo secrets — full commands in .github/SECRETS.md.
  3. Validate via workflow_dispatch on release.yml (channel=current, tag=<existing release>).

Notes

  • Publishes for every v* tag including betas, matching the Homebrew sync and the project's current beta-only cadence; the version is always pinned (no floating latest), per the issue's requirement.
  • known_hosts is fetched with ssh-keyscan at runtime (TOFU) unless AUR_KNOWN_HOSTS is set; the SSH key file is wiped on step exit via a trap.
  • archlinux-keyring is refreshed in the same pacman transaction to avoid the stale-keyring signature-verification flake.

Verification

  • python3 -c "yaml.safe_load(...)" parses release.yml and action.yml.
  • bash -n passes on publish-to-aur.sh and the composite action's run block; the run block contains no ${{ }} interpolation (no shell-injection surface).
  • All three needs: targets (cli_linux, desktop, docker-manifest) exist; the three new job IDs are unique across the file.
  • Simulated the version round-trip (beta/stable/rc/lts), the pkgver/pkgrel edits, the desktop .deb version parse, and the Docker image-tag sed against the real PKGBUILDs — the image-tag regex replaces only the version and preserves the surrounding ${...:-...} brace.

Live AUR push is exercised the first time the maintainer dispatches a release with the secret configured (it cannot run in CI without the key).

Refs #6334

Add three release.yml jobs (sync_aur_bin / sync_aur_desktop / sync_aur_docker) that push the release-pinned packages under packaging/aur/ to the Arch User Repository on every tag, mirroring the existing Homebrew sync jobs.

A shared composite action (.github/actions/publish-aur) runs packaging/aur/publish-to-aur.sh inside archlinux:base-devel.
The script bumps pkgver (encoding the tag's first '-' as '_'), resets pkgrel, derives the desktop bundle version from the actual LibreFang_<ver>_amd64.deb asset name, re-pins the ghcr.io/librefang/librefang image tag for the Docker package, then regenerates sha256sums (updpkgsums) and .SRCINFO (makepkg --printsrcinfo) before pushing to ssh://[email protected].

The jobs degrade to a no-op when AUR_SSH_PRIVATE_KEY is unset, so forks and unconfigured repos are unaffected.
The committed packaging/aur/ files stay a working baseline; the release-correct values are regenerated into the AUR repositories on each tag.

Document the new secrets in .github/SECRETS.md and the automation plus one-time maintainer bootstrap in packaging/aur/README.md.

Refs #6334
@github-actions github-actions Bot added size/L 250-999 lines changed area/ci CI/CD and build tooling labels Jun 26, 2026
houko added a commit that referenced this pull request Jun 29, 2026
)

* ci(release): publish project-maintained pacman repo to R2 (#6334)

AUR account registration is closed with no reopening date, which blocks the AUR automation in #6341. Ship the same release-pinned binary packages directly through a project-maintained pacman repository so Arch users can install with `pacman -Syu`.

A new `publish_arch_repo` release job builds, GPG-signs, and folds librefang-bin / librefang-desktop-bin / librefang-docker into one shared pacman database, then syncs it to Cloudflare R2 (packages.librefang.ai). It reuses the committed PKGBUILDs under packaging/aur/ as the single source of truth, deriving only the per-release values (pkgver, sha256sums, desktop bundle version, pinned Docker tag). Single job, not three, because all packages share one db; a fixed concurrency group serialises the read-modify-write across releases.

Degrades to a no-op when the GPG key or R2 secrets are absent, so it is safe to merge before the secrets are configured. pacman verifies GPG/PGP only and cannot use the cosign keyless signatures the rest of the release uses, so this introduces the project's first long-lived signing key — documented as an offline primary key with a passphrase-less CI subkey.

* fix(arch-repo): materialise .db.sig/.files.sig symlinks for R2 upload

repo-add --sign writes the short-name librefang.db.sig / librefang.files.sig as symlinks to their .tar.gz.sig targets, alongside the .db / .files symlinks. The publish script only materialised the latter two, so rclone (which skips symlinks) silently dropped the two .sig files. The repo would then serve librefang.db with no fetchable librefang.db.sig, breaking pacman's signed-db verification under the default SigLevel.

Materialise all four symlinks as real objects before upload.

Verified by a local dry-run against R2 (amd64 container): the prior `Can't follow symlink` rclone notices for the two .sig files are gone, the incremental repo-add replaces the same-version entries pulled from R2, and the upload completes clean.

---------

Co-authored-by: Evan <[email protected]>
@houko
houko merged commit f3c2420 into main Jun 29, 2026
31 checks passed
@houko
houko deleted the ci/aur-publish branch June 29, 2026 06:31
@houko houko mentioned this pull request Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci CI/CD and build tooling size/L 250-999 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants