diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ded78f9..2f785eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -179,3 +179,64 @@ jobs: fi done 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://aur@aur.archlinux.org/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 diff --git a/docs/release.md b/docs/release.md index bdcf6f3..1b432e6 100644 --- a/docs/release.md +++ b/docs/release.md @@ -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 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://aur@aur.archlinux.org/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 Three repository secrets, all already set: diff --git a/packaging/aur/PKGBUILD.in b/packaging/aur/PKGBUILD.in new file mode 100644 index 0000000..12de25a --- /dev/null +++ b/packaging/aur/PKGBUILD.in @@ -0,0 +1,32 @@ +# Maintainer: PJ + +# 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" +}