Add timetable-bin with automated AUR update workflow
This commit is contained in:
commit
6f7398075a
7 files changed
+345
No files matched your search
@@ -0,0 +1,55 @@
|
|||||||
|
name: Update AUR packages
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# every 6 hours (offset from the full hour to avoid GitHub's load spikes)
|
||||||
|
- cron: '37 */6 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- '*/PKGBUILD'
|
||||||
|
- '*/pkg.sh'
|
||||||
|
- 'scripts/**'
|
||||||
|
- '.github/workflows/update.yml'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
discover:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
packages: ${{ steps.list.outputs.packages }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- id: list
|
||||||
|
run: |
|
||||||
|
echo "packages=$(ls -d */PKGBUILD 2>/dev/null | xargs -r -n1 dirname | jq -R . | jq -cs .)" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
update:
|
||||||
|
needs: discover
|
||||||
|
if: needs.discover.outputs.packages != '[]'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: archlinux:base-devel
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
# serialize so parallel jobs don't race on pushing to this repository
|
||||||
|
max-parallel: 1
|
||||||
|
matrix:
|
||||||
|
package: ${{ fromJson(needs.discover.outputs.packages) }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
steps:
|
||||||
|
- name: Install base tooling
|
||||||
|
run: pacman -Syu --noconfirm --needed git openssh github-cli jq zstd
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Update ${{ matrix.package }}
|
||||||
|
env:
|
||||||
|
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||||
|
AUR_GIT_NAME: ${{ vars.AUR_GIT_NAME }}
|
||||||
|
AUR_GIT_EMAIL: ${{ vars.AUR_GIT_EMAIL }}
|
||||||
|
run: bash scripts/update-package.sh "${{ matrix.package }}"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# makepkg build leftovers and downloaded/built artifacts
|
||||||
|
*.tar.zst
|
||||||
|
*.pkg.tar.*
|
||||||
|
*/src/
|
||||||
|
*/pkg/
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# PKGBUILDS
|
||||||
|
|
||||||
|
Automated `-bin` packages for the [AUR](https://aur.archlinux.org), kept up to
|
||||||
|
date by GitHub Actions.
|
||||||
|
|
||||||
|
Every 6 hours the [update workflow](.github/workflows/update.yml) checks each
|
||||||
|
package's upstream for a new release. When one is found it:
|
||||||
|
|
||||||
|
1. builds the software in an Arch Linux container,
|
||||||
|
2. publishes the resulting install tree as a `.tar.zst` asset on a GitHub
|
||||||
|
release of **this** repository (tag `<pkgname>-<version>`),
|
||||||
|
3. updates the `PKGBUILD` (pkgver/pkgrel/sha256sums), test-builds it with
|
||||||
|
`makepkg` and regenerates `.SRCINFO`,
|
||||||
|
4. commits the changes back to this repository, and
|
||||||
|
5. pushes `PKGBUILD` + `.SRCINFO` to the AUR.
|
||||||
|
|
||||||
|
The AUR packages themselves only download the prebuilt asset from step 2, so
|
||||||
|
users don't need any build dependencies.
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
| Package | Upstream | AUR |
|
||||||
|
|---|---|---|
|
||||||
|
| `timetable-bin` | [ostfriese4/untis](https://codeberg.org/ostfriese4/untis) — "Timetable", a GTK4 + LibAdwaita client for WebUntis | [timetable-bin](https://aur.archlinux.org/packages/timetable-bin) |
|
||||||
|
|
||||||
|
## Setup (one-time)
|
||||||
|
|
||||||
|
1. Create an [AUR account](https://aur.archlinux.org/register) and add an SSH
|
||||||
|
public key to it (AUR account settings).
|
||||||
|
2. Add the matching **private** key as a repository secret named
|
||||||
|
`AUR_SSH_PRIVATE_KEY`
|
||||||
|
(Settings → Secrets and variables → Actions → New repository secret).
|
||||||
|
3. Optionally set the repository **variables** `AUR_GIT_NAME` and
|
||||||
|
`AUR_GIT_EMAIL` to control the commit identity used on the AUR
|
||||||
|
(defaults: `Felitendo` / `95575686+Felitendo@users.noreply.github.com`).
|
||||||
|
|
||||||
|
The first push to `ssh://aur@aur.archlinux.org/<pkgname>.git` creates the AUR
|
||||||
|
package automatically.
|
||||||
|
|
||||||
|
## Adding a package
|
||||||
|
|
||||||
|
Create a new directory named after the AUR package containing:
|
||||||
|
|
||||||
|
- **`PKGBUILD`** — sources the prebuilt asset from
|
||||||
|
`https://github.com/Felitendo/PKGBUILDS/releases/download/<pkgname>-<pkgver>/<pkgname>-<pkgver>.tar.zst`.
|
||||||
|
`pkgver`, `pkgrel` and `sha256sums` are maintained by CI.
|
||||||
|
- **`pkg.sh`** — bash sourced by [scripts/update-package.sh](scripts/update-package.sh),
|
||||||
|
providing:
|
||||||
|
- `BUILD_DEPS` — array of Arch packages installed before building,
|
||||||
|
- `latest_version` — prints the latest upstream version (no `v` prefix),
|
||||||
|
- `build_artifact <version> <output-file>` — downloads/builds upstream and
|
||||||
|
writes the install tree (a tarball containing `usr/`) to `<output-file>`.
|
||||||
|
|
||||||
|
The workflow discovers package directories automatically. Trigger a run
|
||||||
|
manually via *Actions → Update AUR packages → Run workflow* to publish it
|
||||||
|
immediately.
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Update one package directory:
|
||||||
|
# 1. determine the latest upstream version (pkg.sh: latest_version)
|
||||||
|
# 2. build the binary artifact if the matching GitHub release asset is
|
||||||
|
# missing (pkg.sh: build_artifact), otherwise reuse the published one
|
||||||
|
# 3. refresh PKGBUILD (pkgver/pkgrel/sha256sums), test-build it with
|
||||||
|
# makepkg and regenerate .SRCINFO
|
||||||
|
# 4. commit changes back to this repository
|
||||||
|
# 5. push PKGBUILD + .SRCINFO to the AUR
|
||||||
|
#
|
||||||
|
# Requires: GH_TOKEN (GitHub release + repo push), AUR_SSH_PRIVATE_KEY.
|
||||||
|
# Optional: AUR_GIT_NAME / AUR_GIT_EMAIL for the AUR commit identity.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
pkg="${1:?usage: update-package.sh <package-dir>}"
|
||||||
|
repo_root="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
cd "$repo_root"
|
||||||
|
pkg="${pkg%/}"
|
||||||
|
|
||||||
|
source "$pkg/pkg.sh"
|
||||||
|
|
||||||
|
ver="$(latest_version || true)"
|
||||||
|
if [[ -z "$ver" || "$ver" == "null" ]]; then
|
||||||
|
echo "::error::$pkg: could not determine the latest upstream version"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "$pkg: latest upstream version is $ver"
|
||||||
|
|
||||||
|
oldver="$(grep -Po '^pkgver=\K.*' "$pkg/PKGBUILD")"
|
||||||
|
oldrel="$(grep -Po '^pkgrel=\K.*' "$pkg/PKGBUILD")"
|
||||||
|
oldsha="$(grep -Po "^sha256sums=\('\K[0-9a-f]{64}" "$pkg/PKGBUILD" || true)"
|
||||||
|
|
||||||
|
tag="$pkg-$ver"
|
||||||
|
asset="$pkg-$ver.tar.zst"
|
||||||
|
|
||||||
|
### 1+2: make sure the release asset exists, get a local copy of it #########
|
||||||
|
|
||||||
|
if gh release view "$tag" --json assets -q '.assets[].name' 2>/dev/null | grep -qxF "$asset"; then
|
||||||
|
echo "$pkg: release $tag already contains $asset - reusing it"
|
||||||
|
gh release download "$tag" --pattern "$asset" --dir "$pkg" --clobber
|
||||||
|
else
|
||||||
|
echo "$pkg: building $asset"
|
||||||
|
if [[ "${CI:-}" == "true" && "${#BUILD_DEPS[@]}" -gt 0 ]]; then
|
||||||
|
pacman -S --noconfirm --needed "${BUILD_DEPS[@]}"
|
||||||
|
fi
|
||||||
|
build_artifact "$ver" "$repo_root/$pkg/$asset"
|
||||||
|
gh release view "$tag" >/dev/null 2>&1 || \
|
||||||
|
gh release create "$tag" --title "$tag" \
|
||||||
|
--notes "Automated build of $pkg $ver (upstream: ${UPSTREAM_REPO:-unknown})."
|
||||||
|
gh release upload "$tag" "$pkg/$asset" --clobber
|
||||||
|
fi
|
||||||
|
|
||||||
|
sha="$(sha256sum "$pkg/$asset" | cut -d' ' -f1)"
|
||||||
|
|
||||||
|
### 3: refresh PKGBUILD, test-build, regenerate .SRCINFO ####################
|
||||||
|
|
||||||
|
if [[ "$ver" != "$oldver" ]]; then
|
||||||
|
rel=1
|
||||||
|
elif [[ "$sha" != "$oldsha" ]]; then
|
||||||
|
rel=$((oldrel + 1))
|
||||||
|
else
|
||||||
|
rel="$oldrel"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i \
|
||||||
|
-e "s|^pkgver=.*|pkgver=$ver|" \
|
||||||
|
-e "s|^pkgrel=.*|pkgrel=$rel|" \
|
||||||
|
-e "s|^sha256sums=.*|sha256sums=('$sha')|" \
|
||||||
|
"$pkg/PKGBUILD"
|
||||||
|
|
||||||
|
# makepkg refuses to run as root (the CI container), so hand the build to an
|
||||||
|
# unprivileged user there. -d: the runner only needs to package, not run.
|
||||||
|
if [[ "$EUID" -eq 0 ]]; then
|
||||||
|
useradd -m builder 2>/dev/null || true
|
||||||
|
chown -R builder "$pkg"
|
||||||
|
(cd "$pkg" && runuser -u builder -- makepkg -fdc)
|
||||||
|
(cd "$pkg" && runuser -u builder -- makepkg --printsrcinfo > .SRCINFO)
|
||||||
|
chown -R 0:0 "$pkg"
|
||||||
|
else
|
||||||
|
(cd "$pkg" && makepkg -fdc)
|
||||||
|
(cd "$pkg" && makepkg --printsrcinfo > .SRCINFO)
|
||||||
|
fi
|
||||||
|
echo "$pkg: makepkg test build succeeded"
|
||||||
|
rm -f "$pkg/$asset" "$pkg"/*.pkg.tar.*
|
||||||
|
|
||||||
|
### 4: commit back to this repository ########################################
|
||||||
|
|
||||||
|
if [[ "${CI:-}" == "true" ]]; then
|
||||||
|
git config --global --add safe.directory "$repo_root"
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
git add "$pkg/PKGBUILD" "$pkg/.SRCINFO"
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "$pkg: no changes to commit"
|
||||||
|
else
|
||||||
|
git commit -m "$pkg: update to $ver-$rel [skip ci]"
|
||||||
|
git pull --rebase origin "${GITHUB_REF_NAME:-main}"
|
||||||
|
git push origin "HEAD:${GITHUB_REF_NAME:-main}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
### 5: push to the AUR #######################################################
|
||||||
|
|
||||||
|
if [[ -z "${AUR_SSH_PRIVATE_KEY:-}" ]]; then
|
||||||
|
echo "::error::$pkg: AUR_SSH_PRIVATE_KEY is not set - cannot push to the AUR." \
|
||||||
|
"Add your AUR SSH private key as a repository secret named AUR_SSH_PRIVATE_KEY."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||||
|
printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur_key
|
||||||
|
chmod 600 ~/.ssh/aur_key
|
||||||
|
cat >> ~/.ssh/config <<'EOF'
|
||||||
|
Host aur.archlinux.org
|
||||||
|
User aur
|
||||||
|
IdentityFile ~/.ssh/aur_key
|
||||||
|
IdentitiesOnly yes
|
||||||
|
EOF
|
||||||
|
# Pinned host key, see https://aur.archlinux.org
|
||||||
|
echo 'aur.archlinux.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEuBKrPzbawxA/k2g6NcyV5jmqwJ2s+zpgZGZ7tpLIcN' \
|
||||||
|
>> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
aurdir="$(mktemp -d)"
|
||||||
|
git clone "ssh://aur@aur.archlinux.org/$pkg.git" "$aurdir"
|
||||||
|
cp "$pkg/PKGBUILD" "$pkg/.SRCINFO" "$aurdir/"
|
||||||
|
|
||||||
|
cd "$aurdir"
|
||||||
|
git config user.name "${AUR_GIT_NAME:-Felitendo}"
|
||||||
|
git config user.email "${AUR_GIT_EMAIL:-95575686+Felitendo@users.noreply.github.com}"
|
||||||
|
git add PKGBUILD .SRCINFO
|
||||||
|
if git diff --cached --quiet && [[ -n "$(git ls-remote origin)" ]]; then
|
||||||
|
echo "$pkg: AUR package is already up to date"
|
||||||
|
else
|
||||||
|
git commit -m "Update to $ver-$rel"
|
||||||
|
git push origin HEAD:master
|
||||||
|
echo "$pkg: pushed $ver-$rel to the AUR"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
pkgbase = timetable-bin
|
||||||
|
pkgdesc = GTK4 + LibAdwaita client for WebUntis (prebuilt, bundles python-webuntis)
|
||||||
|
pkgver = 3.1
|
||||||
|
pkgrel = 1
|
||||||
|
url = https://codeberg.org/ostfriese4/untis
|
||||||
|
arch = any
|
||||||
|
license = GPL-3.0-or-later
|
||||||
|
depends = gtk4
|
||||||
|
depends = libadwaita
|
||||||
|
depends = python
|
||||||
|
depends = python-gobject
|
||||||
|
depends = python-requests
|
||||||
|
depends = glib2
|
||||||
|
depends = hicolor-icon-theme
|
||||||
|
provides = untis
|
||||||
|
provides = timetable
|
||||||
|
conflicts = untis
|
||||||
|
conflicts = timetable
|
||||||
|
source = https://github.com/Felitendo/PKGBUILDS/releases/download/timetable-bin-3.1/timetable-bin-3.1.tar.zst
|
||||||
|
sha256sums = ffd735d1a08204fe18e563815813b3a62f7625bce5bd5d4c086f1456422e0590
|
||||||
|
|
||||||
|
pkgname = timetable-bin
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Maintainer: Felitendo
|
||||||
|
# This PKGBUILD is updated automatically:
|
||||||
|
# https://github.com/Felitendo/PKGBUILDS
|
||||||
|
|
||||||
|
pkgname=timetable-bin
|
||||||
|
pkgver=3.1
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc="GTK4 + LibAdwaita client for WebUntis (prebuilt, bundles python-webuntis)"
|
||||||
|
arch=('any')
|
||||||
|
url="https://codeberg.org/ostfriese4/untis"
|
||||||
|
license=('GPL-3.0-or-later')
|
||||||
|
depends=('gtk4' 'libadwaita' 'python' 'python-gobject' 'python-requests' 'glib2' 'hicolor-icon-theme')
|
||||||
|
provides=('untis' 'timetable')
|
||||||
|
conflicts=('untis' 'timetable')
|
||||||
|
source=("https://github.com/Felitendo/PKGBUILDS/releases/download/${pkgname}-${pkgver}/${pkgname}-${pkgver}.tar.zst")
|
||||||
|
sha256sums=('ffd735d1a08204fe18e563815813b3a62f7625bce5bd5d4c086f1456422e0590')
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cp -a "$srcdir/usr" "$pkgdir/"
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# timetable-bin - prebuilt package of https://codeberg.org/ostfriese4/untis
|
||||||
|
# ("Timetable", a GTK4 + LibAdwaita WebUntis client written in Python).
|
||||||
|
#
|
||||||
|
# Upstream publishes no binary release assets, so build_artifact() builds the
|
||||||
|
# app from the release tarball and the resulting install tree is published as
|
||||||
|
# a GitHub release asset of this repository, which the PKGBUILD then uses.
|
||||||
|
|
||||||
|
UPSTREAM_REPO="ostfriese4/untis"
|
||||||
|
|
||||||
|
# Installed in CI (pacman) before build_artifact runs.
|
||||||
|
BUILD_DEPS=(meson ninja glib2 glib2-devel gtk4 libadwaita python python-gobject python-pip gettext)
|
||||||
|
|
||||||
|
latest_version() {
|
||||||
|
curl -sf "https://codeberg.org/api/v1/repos/$UPSTREAM_REPO/releases/latest" \
|
||||||
|
| jq -r '.tag_name' | sed 's/^v//'
|
||||||
|
}
|
||||||
|
|
||||||
|
# build_artifact <version> <output-file>
|
||||||
|
build_artifact() {
|
||||||
|
local ver="$1" outfile="$2"
|
||||||
|
local workdir destdir
|
||||||
|
workdir="$(mktemp -d)"
|
||||||
|
destdir="$(mktemp -d)"
|
||||||
|
|
||||||
|
curl -sfL "https://codeberg.org/$UPSTREAM_REPO/archive/v$ver.tar.gz" | tar -xz -C "$workdir"
|
||||||
|
|
||||||
|
# Upstream does not maintain the version in meson.build; use the release tag
|
||||||
|
# so the About dialog shows the right version.
|
||||||
|
sed -i "0,/version:/s/version: *'[^']*'/version: '$ver'/" "$workdir/untis/meson.build"
|
||||||
|
|
||||||
|
meson setup "$workdir/build" "$workdir/untis" --prefix=/usr --buildtype=release
|
||||||
|
meson install -C "$workdir/build" --destdir "$destdir"
|
||||||
|
|
||||||
|
# Bundle the pure-python webuntis library: it is packaged neither in the
|
||||||
|
# Arch repos nor on the AUR. /usr/share/untis is on the launcher's sys.path.
|
||||||
|
pip download --no-deps --only-binary :all: --dest "$workdir/wheels" webuntis
|
||||||
|
python -m zipfile -e "$workdir"/wheels/webuntis-*.whl "$destdir/usr/share/untis/"
|
||||||
|
|
||||||
|
# These caches are generated by pacman hooks; shipping them would cause
|
||||||
|
# file conflicts on install.
|
||||||
|
rm -f "$destdir/usr/share/glib-2.0/schemas/gschemas.compiled" \
|
||||||
|
"$destdir/usr/share/applications/mimeinfo.cache" \
|
||||||
|
"$destdir/usr/share/icons/hicolor/icon-theme.cache"
|
||||||
|
|
||||||
|
tar --zstd --sort=name --owner=0 --group=0 --numeric-owner --mtime='@0' \
|
||||||
|
-cf "$outfile" -C "$destdir" usr
|
||||||
|
|
||||||
|
rm -rf "$workdir" "$destdir"
|
||||||
|
}
|
||||||
Reference in new issue
Block a user