Publish an Arch package to the AUR from the release

The AppImage runs on Arch but not as a Wayland client. It carries Ubuntu's
GTK stack including libwayland-client, which cannot talk to a current
compositor, so on Hyprland it fails to initialise GTK and only starts once it
falls back to Xwayland. Verified both ways on a real session: the AppImage
comes up with xwayland 1, the packaged build with xwayland 0.

margin-calendar-bin repackages the published .deb rather than building from
source, which is forced rather than lazy. The Google OAuth client is embedded
at compile time from a file that is not in the repo, so a source package
would build cleanly on a stranger's machine and then tell them Google
Calendar is not set up.

The job runs after the manifest check, so the AUR can only ever point at a
release that survived it, and it checksums the artifact it just downloaded
rather than one it assumed was there. Without AUR_SSH_PRIVATE_KEY it renders
the package, warns, and leaves the release alone.

license=('custom') is honest rather than chosen: this repo has no licence
file. That is worth fixing before anyone else packages it.
This commit is contained in:
pj committed 2026-08-12 20:59:21 +05:30
1 parent b3ba71c556
commit fef1ad7ff5
3 files changed
+115

No files matched your search

+61
View File
@@ -179,3 +179,64 @@ jobs:
fi fi
done done
gh release edit "$TAG" --repo "$REPO" --draft=false --latest gh release edit "$TAG" --repo "$REPO" --draft=false --latest
# Arch gets its own package rather than the AppImage. The AppImage carries Ubuntu's GTK stack,
# which cannot talk to a modern Wayland compositor and silently falls back to Xwayland; a package
# linked against the system webkit2gtk runs as a native Wayland client. Runs after publish so it
# can only ever point at a release that survived the manifest check.
aur:
needs: [prepare, publish]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Render the PKGBUILD for this release
env:
VERSION: ${{ needs.prepare.outputs.version }}
REPO: ${{ github.repository }}
run: |
URL="https://github.com/$REPO/releases/download/v$VERSION/Margin.Calendar_${VERSION}_amd64.deb"
# From the published asset, so the checksum is of the artifact users will actually fetch.
curl -fsSL --retry 3 -o package.deb "$URL"
SHA=$(sha256sum package.deb | cut -d' ' -f1)
sed -e "s/@VERSION@/$VERSION/g" -e "s/@SHA256@/$SHA/g" packaging/aur/PKGBUILD.in > PKGBUILD
echo "pkgver $VERSION, sha256 $SHA"
- name: Generate .SRCINFO
# makepkg is Arch-only and refuses to run as root, hence the container and the throwaway
# user. --printsrcinfo parses the PKGBUILD, it does not build anything.
run: |
docker run --rm -v "$PWD:/w" -w /w archlinux:base-devel bash -c '
useradd -m builder && chown -R builder /w
su builder -c "makepkg --printsrcinfo" > .SRCINFO'
cat .SRCINFO
- name: Push to the AUR
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
VERSION: ${{ needs.prepare.outputs.version }}
run: |
if [ -z "$AUR_SSH_PRIVATE_KEY" ]; then
echo "::warning::AUR_SSH_PRIVATE_KEY is not set, so the AUR package was built but not published. The release itself is unaffected."
exit 0
fi
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan -t ed25519,rsa aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null
export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o IdentitiesOnly=yes"
git clone ssh://[email protected]/margin-calendar-bin.git aur
cp PKGBUILD .SRCINFO aur/
cd aur
# A package that does not exist yet clones as an empty repo, where the local branch name
# is whatever git defaults to. The AUR only accepts master.
git checkout -B master
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add PKGBUILD .SRCINFO
if git diff --cached --quiet; then
echo "AUR is already at this version, nothing to push."
exit 0
fi
git commit -m "margin-calendar-bin $VERSION"
git push origin master
+22
View File
@@ -36,6 +36,28 @@ targets, at which point the publish gate wants `windows-x86_64` too.
Phones do not come from this pipeline at all. The store is their update channel, and what building Phones do not come from this pipeline at all. The store is their update channel, and what building
for one takes is in [mobile.md](mobile.md). for one takes is in [mobile.md](mobile.md).
## Arch
Arch gets its own package, `margin-calendar-bin` on the AUR, pushed by the release workflow after
the manifest check passes. It is worth the extra moving part: the AppImage bundles Ubuntu's GTK
stack, and a bundled `libwayland-client` cannot talk to a current compositor, so on Hyprland the
AppImage silently falls back to Xwayland. The packaged build links against the system
`webkit2gtk-4.1` and runs as a native Wayland client.
It is a binary package by necessity rather than laziness. The Google OAuth client is embedded at
compile time from a file that is deliberately not in the repo, so anything built from source on
someone else's machine would run and then tell them Google Calendar is not set up. The PKGBUILD
therefore repackages the published `.deb`, whose payload is already a normal `/usr` tree.
`packaging/aur/PKGBUILD.in` is the template. The workflow fills in the version and the sha256 of
the artifact that was actually published, generates `.SRCINFO` with `makepkg` in an Arch container,
and pushes to `ssh://[email protected]/margin-calendar-bin.git` using `AUR_SSH_PRIVATE_KEY`.
Without that secret the job renders the package, says so, and does not fail the release.
The `license=('custom')` line is a placeholder for the fact that this repo has no licence file at
all. Nothing stops the package publishing, but a package on the AUR that nobody has licensed is
worth fixing before anyone else builds on it.
## What the build needs ## What the build needs
Three repository secrets, all already set: Three repository secrets, all already set:
+32
View File
@@ -0,0 +1,32 @@
# Maintainer: PJ <[email protected]>
# The template the release workflow renders. @VERSION@ and @SHA256@ are filled in from the release
# that has just published, so the PKGBUILD on the AUR always points at an artifact that exists.
#
# A binary package rather than one built from source, and that is forced rather than lazy: the
# Google OAuth client is embedded at compile time from a file that is not in the repo, so anything
# built from source on a stranger's machine runs and then says Google Calendar is not set up.
pkgname=margin-calendar-bin
pkgver=@VERSION@
pkgrel=1
pkgdesc="A calendar for Google Calendar, where the grid owns the window and the day fits without scrolling"
arch=('x86_64')
url="https://github.com/priyanshujain/margin-calendar"
license=('custom')
depends=('webkit2gtk-4.1' 'gtk3')
provides=('margin-calendar')
conflicts=('margin-calendar')
# Prebuilt and already linked: stripping it again buys nothing and risks the binary.
options=('!strip' '!debug')
source=("${pkgname}-${pkgver}.deb::${url}/releases/download/v${pkgver}/Margin.Calendar_${pkgver}_amd64.deb")
noextract=("${pkgname}-${pkgver}.deb")
sha256sums=('@SHA256@')
package() {
bsdtar -xOf "${pkgname}-${pkgver}.deb" data.tar.gz | bsdtar -xf - -C "${pkgdir}"
# The bundler names it after the product, spaces and all. Everything that reads this directory
# copes with that, and nothing that reads it enjoys it.
mv "${pkgdir}/usr/share/applications/Margin Calendar.desktop" \
"${pkgdir}/usr/share/applications/margin-calendar.desktop"
}