Merge pull request 'Skip AUR for now, attach Arch package as a GitHub release asset' (#42) from fix/aur-render-expression-collision into main
Secret Scan / scan (push) Successful in 6s

Reviewed-on: #42
This commit was merged in pull request #42.
This commit is contained in:
2026-08-27 21:50:54 +00:00
4 changed files with 95 additions and 85 deletions
@@ -1,37 +1,36 @@
name: Publish AUR Package name: Publish Arch Package
# Builds and pushes the `triple-c-bin` AUR package (packaging/arch/PKGBUILD) # Builds the `triple-c-bin` Arch package (packaging/arch/PKGBUILD) for a
# for a given release, or the latest one if none is given. Manual dispatch # given release, or the latest one if none is given, and attaches the built
# only — deliberately not triggered by `release` or `push`, for the same # .pkg.tar.zst to that release on GitHub as a downloadable asset. Manual
# reason sync-release.yml (removed in triple-c#32) never worked safely as an # dispatch only — deliberately not triggered by `release` or `push`, for the
# automatic trigger: this repo's releases are assembled by build-app.yml # same reason sync-release.yml (removed in triple-c#32) never worked safely
# across three separate platform jobs, and there is no single automatic event # as an automatic trigger: this repo's releases are assembled by
# that fires only once everything (including the Linux .deb this workflow # build-app.yml across three separate platform jobs, and there is no single
# needs) is actually uploaded. A human deciding "this release is ready, go # automatic event that fires only once everything (including the Linux .deb
# package it" is the correct trigger, the same reasoning # this workflow needs) is actually uploaded. A human deciding "this release
# is ready, go package it" is the correct trigger, the same reasoning
# backfill-releases.yml already uses for its own manual-only GitHub sync. # backfill-releases.yml already uses for its own manual-only GitHub sync.
# #
# ## What this does and does not do # ## What this does and does not do
# #
# It renders `packaging/arch/PKGBUILD` for one specific version (real # It renders `packaging/arch/PKGBUILD` for one specific version (real
# download URL, real sha256sums — never guessed; see the resolve-asset step) # download URL, real sha256sums — never guessed; see the resolve-asset step),
# and pushes the rendered PKGBUILD plus a regenerated `.SRCINFO` to AUR. It # validates it with `makepkg`/`namcap` in a real Arch container, and uploads
# does NOT commit anything back to this repo — `packaging/arch/PKGBUILD` stays # the resulting `.pkg.tar.zst` to the GitHub release it was built from —
# a hand-maintained template with a placeholder version, and every real, # installable by hand with `pacman -U`. It does NOT commit anything back to
# published version lives only in AUR's own git history, which is where a # this repo — `packaging/arch/PKGBUILD` stays a hand-maintained template with
# PKGBUILD's revision history is expected to live. A corollary worth knowing: # a placeholder version, and the workflow never starts from or writes to it.
# a hand-edit made directly in the AUR repo (outside this workflow) is
# silently overwritten the next time this runs, since every run renders fresh
# from this repo's template rather than starting from AUR's current state.
# #
# ## Required secret # ## Not published to the AUR (yet)
# #
# `AUR_SSH_PRIVATE_KEY` — an SSH private key registered against an AUR # This originally also pushed the rendered PKGBUILD to an AUR git repo, which
# account that has already created (or been given co-maintainer access to) # needs a maintainer AUR account and its SSH key registered as a secret here
# the `triple-c-bin` package. This workflow cannot create that AUR account or # — both manual, one-time steps neither this workflow nor anyone but a
# register the key for you — both are manual, one-time steps on # maintainer can do. Until that setup happens, a downloadable release asset
# https://aur.archlinux.org. Until this secret exists, every run fails at the # gets the same package to users without it. The AUR push step is still in
# "Push to AUR" step with a clear error rather than silently doing nothing. # this file's git history (see the commit that added this comment) if that
# setup is ever done and it's worth reinstating.
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@@ -43,7 +42,6 @@ on:
env: env:
GITHUB_REPO: shadowdao/triple-c GITHUB_REPO: shadowdao/triple-c
AUR_REPO: ssh://aur@aur.archlinux.org/triple-c-bin.git
jobs: jobs:
publish: publish:
@@ -97,10 +95,20 @@ jobs:
fi fi
echo "Found asset: ${DEB_NAME}" echo "Found asset: ${DEB_NAME}"
# For attaching the built package to this same release later —
# every release object carries its own `upload_url` regardless of
# whether it was just created or (as here) already existed, and
# the `{?name,label}` URI-template suffix has to come off before
# this is usable as a plain URL to POST to.
RELEASE_ID=$(echo "$RELEASE_JSON" | jq -r '.id')
UPLOAD_URL=$(echo "$RELEASE_JSON" | jq -r '.upload_url' | sed 's/{?name,label}//')
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT" echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "deb_url=${DEB_URL}" >> "$GITHUB_OUTPUT" echo "deb_url=${DEB_URL}" >> "$GITHUB_OUTPUT"
echo "deb_name=${DEB_NAME}" >> "$GITHUB_OUTPUT" echo "deb_name=${DEB_NAME}" >> "$GITHUB_OUTPUT"
echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT"
echo "upload_url=${UPLOAD_URL}" >> "$GITHUB_OUTPUT"
- name: Download the release asset and compute real checksums - name: Download the release asset and compute real checksums
id: checksums id: checksums
@@ -197,6 +205,7 @@ jobs:
! grep -q "SKIP" PKGBUILD ! grep -q "SKIP" PKGBUILD
- name: Validate with makepkg and namcap - name: Validate with makepkg and namcap
id: build
run: | run: |
set -euo pipefail set -euo pipefail
@@ -218,6 +227,13 @@ jobs:
echo "builder ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/builder echo "builder ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/builder
sudo -u builder bash -c "cd /work && makepkg --printsrcinfo > .SRCINFO" sudo -u builder bash -c "cd /work && makepkg --printsrcinfo > .SRCINFO"
sudo -u builder bash -c "cd /work && makepkg -s --noconfirm" sudo -u builder bash -c "cd /work && makepkg -s --noconfirm"
# Named once here, inside the container, rather than guessed
# from options=(!strip !debug) plus pkgver/pkgrel/arch on the
# host after the fact — makepkg is the one place that actually
# knows its own output name, and `!debug` already guarantees
# this glob can only ever match the one real package (no
# -debug split package gets produced).
basename /work/*.pkg.tar.* > /work/.pkgfile
echo "--- namcap ---" echo "--- namcap ---"
NAMCAP_OUT=$(sudo -u builder bash -c "cd /work && namcap PKGBUILD *.pkg.tar.*" || true) NAMCAP_OUT=$(sudo -u builder bash -c "cd /work && namcap PKGBUILD *.pkg.tar.*" || true)
echo "$NAMCAP_OUT" echo "$NAMCAP_OUT"
@@ -238,50 +254,45 @@ jobs:
# bind mount still fails the job the same way. # bind mount still fails the job the same way.
docker start -a "${CID}" docker start -a "${CID}"
docker cp "${CID}:/work/.SRCINFO" rendered/.SRCINFO docker cp "${CID}:/work/.SRCINFO" rendered/.SRCINFO
docker cp "${CID}:/work/.pkgfile" rendered/.pkgfile
PKG_FILE=$(cat rendered/.pkgfile)
docker cp "${CID}:/work/${PKG_FILE}" "rendered/${PKG_FILE}"
docker rm -f "${CID}" >/dev/null docker rm -f "${CID}" >/dev/null
- name: Push to AUR echo "pkg_file=${PKG_FILE}" >> "$GITHUB_OUTPUT"
- name: Attach the package to the GitHub release
env: env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }} GH_PAT: ${{ secrets.GH_PAT }}
VERSION: ${{ steps.resolve.outputs.version }} TAG: ${{ steps.resolve.outputs.tag }}
RELEASE_ID: ${{ steps.resolve.outputs.release_id }}
UPLOAD_URL: ${{ steps.resolve.outputs.upload_url }}
PKG_FILE: ${{ steps.build.outputs.pkg_file }}
run: | run: |
set -euo pipefail set -euo pipefail
if [ -z "${AUR_SSH_PRIVATE_KEY}" ]; then if [ -z "${GH_PAT}" ]; then
echo "AUR_SSH_PRIVATE_KEY is not set — see this workflow file's header comment for" >&2 echo "GH_PAT is not set — this step needs it to attach a release asset." >&2
echo "the one-time AUR account setup this needs before it can publish anything." >&2
exit 1 exit 1
fi fi
mkdir -p ~/.ssh # A manual re-dispatch for a version that's already been packaged
# Created with the final mode before any bytes land in it, rather # would otherwise hit GitHub's 422 "already_exists" here instead
# than a plain redirect followed by chmod, which leaves the key # of just replacing the stale build with this one.
# world-readable for whatever window falls between the two calls. EXISTING_ID=$(curl -fsS -H "Authorization: Bearer ${GH_PAT}" -H "Accept: application/vnd.github+json" \
install -m 600 /dev/null ~/.ssh/aur "https://api.github.com/repos/${GITHUB_REPO}/releases/${RELEASE_ID}/assets" \
echo "${AUR_SSH_PRIVATE_KEY}" > ~/.ssh/aur | jq -r --arg name "$PKG_FILE" '.[] | select(.name == $name) | .id')
# TOFU, not verification — accepted here because pinning AUR's if [ -n "$EXISTING_ID" ]; then
# actual host key needs a value fetched from somewhere trusted echo "Replacing the existing ${PKG_FILE} (asset id ${EXISTING_ID}) already on ${TAG}"
# ahead of time, which this workflow doesn't have, and getting a curl -fsS -X DELETE -H "Authorization: Bearer ${GH_PAT}" -H "Accept: application/vnd.github+json" \
# pinned value wrong fails every future run rather than just this "https://api.github.com/repos/${GITHUB_REPO}/releases/assets/${EXISTING_ID}"
# one. A keyscan failure below surfaces later as an opaque
# "Host key verification failed" rather than a clear one here.
ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null
export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o IdentitiesOnly=yes -o UserKnownHostsFile=~/.ssh/known_hosts"
git clone "${AUR_REPO}" aur-repo
cp rendered/PKGBUILD rendered/.SRCINFO aur-repo/
cd aur-repo
git config user.name "Triple-C CI"
git config user.email "noreply@triple-c.invalid"
git add PKGBUILD .SRCINFO
if git diff --cached --quiet; then
echo "No change from what's already published on AUR for ${VERSION}"
exit 0
fi fi
git commit -m "triple-c-bin: update to ${VERSION}"
# AUR itself uses `master`, which is what a fresh, not-yet-created curl -fsS -X POST \
# AUR package's empty repo advertises on clone — but the *local* -H "Authorization: Bearer ${GH_PAT}" \
# branch name after cloning an empty repo falls back to whatever -H "Accept: application/vnd.github+json" \
# this runner's `init.defaultBranch` is if the server sends no -H "Content-Type: application/octet-stream" \
# symref, so naming the destination explicitly is what keeps this --data-binary "@rendered/${PKG_FILE}" \
# working if that default is ever `main` instead of `master`. "${UPLOAD_URL}?name=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1]))" "${PKG_FILE}")" \
git push origin HEAD:master > /dev/null
echo "Attached ${PKG_FILE} to ${TAG}"
+2 -2
View File
@@ -418,10 +418,10 @@ triple-c/
│ ├── build-stt.yml # Build the STT image │ ├── build-stt.yml # Build the STT image
│ ├── backfill-releases.yml # Bulk copy releases to GitHub │ ├── backfill-releases.yml # Bulk copy releases to GitHub
│ ├── cleanup-releases.yml # Prune old releases │ ├── cleanup-releases.yml # Prune old releases
│ └── publish-aur-package.yml # Publish triple-c-bin to the AUR (packaging/arch/) │ └── publish-arch-package.yml # Build triple-c-bin, attach it to the GitHub release (packaging/arch/)
├── packaging/ ├── packaging/
│ └── arch/ # AUR triple-c-bin package — see packaging/arch/README.md │ └── arch/ # triple-c-bin Arch package — see packaging/arch/README.md
│ ├── PKGBUILD │ ├── PKGBUILD
│ └── README.md │ └── README.md
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Triple-C Contributors # Maintainer: Triple-C Contributors
# #
# This file is regenerated by .gitea/workflows/publish-aur-package.yml on every # This file is regenerated by .gitea/workflows/publish-arch-package.yml on every
# publish — pkgver, the source URL and sha256sums are rewritten from the real, # publish — pkgver, the source URL and sha256sums are rewritten from the real,
# already-uploaded release asset, never guessed. Editing pkgver/source/ # already-uploaded release asset, never guessed. Editing pkgver/source/
# sha256sums by hand here only matters until the next automated run overwrites # sha256sums by hand here only matters until the next automated run overwrites
+16 -17
View File
@@ -1,7 +1,9 @@
# Arch / CachyOS package # Arch / CachyOS package
`PKGBUILD` here is the AUR `triple-c-bin` package's template — see triple-c#34 `PKGBUILD` here is the `triple-c-bin` package's template — see triple-c#34
(the "I would like to also have an Arch/CachyOS native version" part of it). (the "I would like to also have an Arch/CachyOS native version" part of it).
It's written to AUR conventions (and may go there eventually — see
"Publishing" below) but isn't published to the AUR yet.
## Why "-bin" ## Why "-bin"
@@ -18,24 +20,23 @@ to be real dependencies of *this* binary and were dropped), and ran a real
## Publishing ## Publishing
`.gitea/workflows/publish-aur-package.yml` does the actual work: given a `.gitea/workflows/publish-arch-package.yml` does the actual work: given a
version (or "latest" if none is given), it finds that release's real Linux version (or "latest" if none is given), it finds that release's real Linux
asset on GitHub, downloads it, computes real checksums, renders this asset on GitHub, downloads it, computes real checksums, renders this
template into a version-specific PKGBUILD, validates it with `makepkg` and template into a version-specific PKGBUILD, validates it with `makepkg` and
`namcap` inside a real Arch container, and pushes the result to AUR. `namcap` inside a real Arch container, and attaches the resulting
`.pkg.tar.zst` to that same GitHub release as a downloadable asset —
installable by hand with `sudo pacman -U`.
It is `workflow_dispatch`-only, deliberately — see the workflow file's own It is `workflow_dispatch`-only, deliberately — see the workflow file's own
header comment for why an automatic trigger isn't safe here (the same reason header comment for why an automatic trigger isn't safe here (the same reason
`sync-release.yml` didn't work and was removed in triple-c#32). `sync-release.yml` didn't work and was removed in triple-c#32).
**Before it can push anything**, an AUR account has to exist and the **Not on the AUR yet.** Publishing there would need a maintainer AUR account
`triple-c-bin` package has to have been created (or you added as a and its SSH key added as a secret on this repo — both manual, one-time steps
co-maintainer) under it — both are one-time, manual steps on on https://aur.archlinux.org that only a maintainer can do. The workflow's
https://aur.archlinux.org, since there's no API to automate creating an git history still has the AUR-push step from before this was descoped, if
account or a new package. Once that's done, add the account's SSH private that setup happens later and it's worth reinstating.
key as the `AUR_SSH_PRIVATE_KEY` secret on this repo. Until that secret
exists, the workflow fails at the "Push to AUR" step with a message saying
so, rather than silently doing nothing.
## What's hand-maintained vs. generated ## What's hand-maintained vs. generated
@@ -45,9 +46,7 @@ result back here, so don't read this file's `pkgver` as "the last published
version." Everything else (`depends`, `pkgdesc`, `package()`) is meant to be version." Everything else (`depends`, `pkgdesc`, `package()`) is meant to be
edited by hand normally, the same as any other PKGBUILD. edited by hand normally, the same as any other PKGBUILD.
**A hand-edit made directly in the AUR repo is silently overwritten the **A hand-edit made to the rendered PKGBUILD attached to a GitHub release is
next time this workflow runs.** Every run renders fresh from *this* not this file.** Every run renders fresh from *this* repo's template, so a
repo's template rather than starting from whatever AUR's copy currently packaging fix belongs here, not in a downloaded copy — the next dispatch for
looks like, so a quick fix pushed straight to AUR (bumping `pkgrel` for a that version would just overwrite it anyway.
packaging-only issue, say) survives only until the next dispatch. Make
the fix here instead.