diff --git a/.gitea/workflows/arch.yml b/.gitea/workflows/arch.yml new file mode 100644 index 0000000..74bfe0c --- /dev/null +++ b/.gitea/workflows/arch.yml @@ -0,0 +1,131 @@ +# Build the punktfunk-host / punktfunk-client / punktfunk-web pacman packages from +# packaging/arch/PKGBUILD and publish them to Gitea's Arch package registry, so Arch boxes +# get new builds via `pacman -Syu`. Counterpart to deb.yml (apt) and rpm.yml (dnf/rpm-ostree). +# Arch is rolling, so the packages build against whatever the archlinux:base-devel container +# resolves today — the same sonames an up-to-date Arch box runs. +# +# Registry (public, unom org) — box setup (once), see packaging/arch/README.md: +# [punktfunk] # or [punktfunk-canary] for main-push builds +# SigLevel = Optional TrustAll +# Server = https://git.unom.io/api/packages/unom/arch/$repo/$arch +# +# REGISTRY_TOKEN: repo Actions secret, a PAT with write:package scope (shared with docker.yml). +name: arch + +on: + push: + branches: [main] + # Single project version: a `vX.Y.Z` tag is THE release. main publishes to the + # `punktfunk-canary` pacman repo as X.Y.Z-0. (sorts below the eventual X.Y.Z-1), + # tags to `punktfunk` — separate repos, so neither channel can shadow the other. + tags: ['v*'] + workflow_dispatch: + +env: + REGISTRY: git.unom.io + OWNER: unom + +jobs: + build-publish: + runs-on: ubuntu-24.04 + container: + image: docker.io/library/archlinux:base-devel + timeout-minutes: 90 + env: + CARGO_HOME: /usr/local/cargo + steps: + # git must exist before actions/checkout (base-devel ships without it). + - name: Install build + runtime-dev deps + run: | + pacman -Syu --noconfirm --needed \ + git rust clang cmake nasm pkgconf python \ + gtk4 libadwaita sdl3 ffmpeg pipewire wayland libxkbcommon opus libei \ + mesa libglvnd unzip libarchive + # bun builds the punktfunk-web console AND is vendored as its runtime (PF_WITH_WEB=1); + # it's AUR-only on Arch, so bootstrap the official binary. + command -v bun >/dev/null || { + curl -fsSL https://bun.sh/install | bash + install -m0755 "$HOME/.bun/bin/bun" /usr/local/bin/bun + } + bun --version + + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: /usr/local/cargo/registry + key: cargo-home-arch-${{ hashFiles('Cargo.lock') }} + restore-keys: cargo-home-arch- + + - name: Version + channel + # vX.Y.Z tag -> X.Y.Z-1 in the `punktfunk` repo; main push -> -0. in + # `punktfunk-canary` (pkgrel accepts only digits+dots — the run number carries the + # monotonic ordering; the commit sha is stamped into the binary via the workflow log). + run: | + eval "$(bash scripts/ci/pf-version.sh)" # -> PF_BASE (one minor ahead of latest stable) + case "$GITHUB_REF" in + refs/tags/v*) V="${GITHUB_REF_NAME#v}"; R="1"; REPO=punktfunk ;; + *) V="$PF_BASE"; R="0.${GITHUB_RUN_NUMBER}"; REPO=punktfunk-canary ;; + esac + echo "PF_PKGVER=$V" >> "$GITHUB_ENV" + echo "PF_PKGREL=$R" >> "$GITHUB_ENV" + echo "REPO=$REPO" >> "$GITHUB_ENV" + echo "pacman $V-$R -> repo '$REPO'" + + - name: Build packages (makepkg) + run: | + git config --global --add safe.directory "$PWD" + # libcuda link stub — same trick as packaging/rpm/build-rpm.sh: the zerocopy FFI + # links -lcuda but the builder has no GPU; synthesize every cu* symbol the source + # references so a newly-added call can't silently break the link. + CU_SYMS="$(grep -rhoE '\bcu[A-Z][A-Za-z0-9_]*' crates/punktfunk-host/src/ | sort -u || true)" + if [ -n "$CU_SYMS" ] && [ ! -e /usr/lib/libcuda.so ]; then + STUB_C="$(mktemp --suffix=.c)" + for s in $CU_SYMS; do printf 'int %s(void){return 0;}\n' "$s" >> "$STUB_C"; done + gcc -shared -fPIC -Wl,-soname,libcuda.so.1 -o /usr/lib/libcuda.so.1 "$STUB_C" + ln -sf libcuda.so.1 /usr/lib/libcuda.so + rm -f "$STUB_C"; ldconfig + echo "== libcuda stub: $(printf '%s\n' "$CU_SYMS" | wc -l) symbols ==" + fi + # makepkg refuses to run as root; deps are already installed above (-d skips the + # RPM-level check that can't see the script-installed bun anyway). + useradd -m builder + chown -R builder: "$PWD" "$CARGO_HOME" + sudo -u builder git config --global --add safe.directory "$PWD" + mkdir -p dist && chown builder: dist + cd packaging/arch + sudo -u builder env PF_SRCDIR="$GITHUB_WORKSPACE" PF_WITH_WEB=1 \ + PF_PKGVER="$PF_PKGVER" PF_PKGREL="$PF_PKGREL" \ + CARGO_HOME="$CARGO_HOME" PKGDEST="$GITHUB_WORKSPACE/dist" \ + makepkg -f -d --holdver + ls -lh "$GITHUB_WORKSPACE/dist" + + - name: Publish to the Gitea Arch registry + env: + TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + for pkg in dist/*.pkg.tar.zst; do + echo "uploading $pkg" + NAME=$(bsdtar -xOf "$pkg" .PKGINFO | sed -n 's/^pkgname = //p') + VER=$(bsdtar -xOf "$pkg" .PKGINFO | sed -n 's/^pkgver = //p') + ARCH=$(bsdtar -xOf "$pkg" .PKGINFO | sed -n 's/^arch = //p') + # A re-tagged release re-fires this workflow and the registry 409s on duplicate + # package versions — delete any prior copy first (404 on the first publish is fine). + curl -fsS -o /dev/null --user "enricobuehler:$TOKEN" -X DELETE \ + "https://$REGISTRY/api/packages/$OWNER/arch/$REPO/$NAME/$VER/$ARCH" || true + curl -fsS --user "enricobuehler:$TOKEN" --upload-file "$pkg" \ + "https://$REGISTRY/api/packages/$OWNER/arch/$REPO" + done + echo "published to $OWNER/arch/$REPO" + + # On a real release, also attach the packages to the unified Gitea Release. + - name: Attach packages to the Gitea release (stable tags only) + if: startsWith(gitea.ref, 'refs/tags/v') + env: + GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + . scripts/ci/gitea-release.sh + RID=$(ensure_release "$GITHUB_REF_NAME" "$GITHUB_REF_NAME" auto) + for pkg in dist/*.pkg.tar.zst; do + upsert_asset "$RID" "$pkg" + done diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 22950c6..da10c55 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -10,20 +10,28 @@ # - In-tree / CI: PF_SRCDIR=$(git rev-parse --show-toplevel) makepkg --holdver # (builds the working tree instead of the tagged source — see build()). # -# IMPORTANT: host encode is NVENC-only (crates/punktfunk-host/src/encode/linux.rs) — functional on -# NVIDIA hosts; an AMD Deck-as-HOST needs a VAAPI backend first. The CLIENT decodes via VAAPI -# (AMD/Intel, incl. the Deck) with a software fallback, so it works everywhere. See README.md. +# Host encode: NVENC on NVIDIA (nvidia-utils), VAAPI on AMD/Intel (mesa) — PUNKTFUNK_ENCODER=auto +# picks per GPU. The CLIENT decodes via VAAPI (AMD/Intel, incl. the Deck) with a software +# fallback, so it works everywhere. See README.md. pkgbase=punktfunk # punktfunk-web (the browser console) is OPT-IN: building it needs `bun` (AUR-only as bun-bin on # stock Arch/SteamOS), so a default makepkg builds only host+client with no JS tooling — mirroring # the RPM spec's `%bcond_with web` (off by default). Set PF_WITH_WEB=1 to also build punktfunk-web # (appended to pkgname + bun to makedepends below). pkgname=('punktfunk-host' 'punktfunk-client') -pkgver=0.2.0 -pkgrel=1 +# CI (.gitea/workflows/arch.yml) drives the version: stable tags -> X.Y.Z-1, main pushes -> +# X.Y.Z-0. in the separate punktfunk-canary repo (mirrors the RPM's 0.ciN release; pkgrel +# allows only digits+dots, so the run number carries the monotonic ordering). +pkgver="${PF_PKGVER:-0.7.0}" +pkgrel="${PF_PKGREL:-1}" arch=('x86_64') url="https://git.unom.io/unom/punktfunk" license=('MIT OR Apache-2.0') +# !lto: makepkg's `lto` option injects -flto=auto into CFLAGS; aws-lc-sys (rustls' crypto) +# compiles its C with those flags and GCC LTO bitcode objects are unreadable by rust's lld +# linker -> "undefined symbol: aws_lc_*" at link (reproduced 2026-07-04, Arch + rust 1.90). +# !debug: skip the -debug split package (debuginfo bloat, not shipped). +options=('!lto' '!debug') # All build deps for both crates (Arch runtime packages ship their own headers, so these cover # build + link). aws-lc/ring need clang+cmake; nasm is for asm. @@ -36,10 +44,16 @@ if [ "${PF_WITH_WEB:-0}" = 1 ]; then makedepends+=('bun') # `bun-bin` from the AUR if bun isn't in your configured repos fi -# AUR source (a tagged release). For an in-tree CI build, set PF_SRCDIR to the repo root and -# build() uses it instead; see the README. -source=("git+https://git.unom.io/unom/punktfunk.git#tag=v${pkgver}") -sha256sums=('SKIP') +# AUR source (a tagged release). For an in-tree CI build, set PF_SRCDIR to the repo root — +# build() uses it instead AND the fetch is skipped entirely (a canary pkgver has no tag to +# clone, and CI already has the checkout). +if [ -z "${PF_SRCDIR:-}" ]; then + source=("git+https://git.unom.io/unom/punktfunk.git#tag=v${pkgver}") + sha256sums=('SKIP') +else + source=() + sha256sums=() +fi _repo() { printf '%s' "${PF_SRCDIR:-$srcdir/punktfunk}"; } diff --git a/packaging/arch/README.md b/packaging/arch/README.md index 8b682c4..02f0d86 100644 --- a/packaging/arch/README.md +++ b/packaging/arch/README.md @@ -23,7 +23,36 @@ default `makepkg` builds only host+client with no JS tooling — mirroring the R > Arch + NVIDIA **and** AMD/Intel (incl. the Steam Deck — see the on-device path above). The client > decodes via VAAPI on AMD/Intel with a software fallback. -## Arch Linux (mutable) +## Install from the binary repo (recommended) + +CI (`.gitea/workflows/arch.yml`) builds this PKGBUILD in an `archlinux:base-devel` container on +every push and publishes the packages to the **Gitea Arch package registry** — a plain pacman +repo, so an Arch box installs and updates punktfunk with `pacman -Syu` like everything else. +Two repos mirror the deb/rpm channels: `punktfunk` (release tags) and `punktfunk-canary` +(rolling main-branch builds, versioned `X.Y.Z-0.` so a later release always outranks +them). Enable exactly one: + +```sh +sudo tee -a /etc/pacman.conf >/dev/null <<'EOF' + +[punktfunk] +SigLevel = Optional TrustAll +Server = https://git.unom.io/api/packages/unom/arch/$repo/$arch +EOF + +sudo pacman -Sy punktfunk-host # gaming rig +sudo pacman -Sy punktfunk-client # couch/Deck side +sudo pacman -Sy punktfunk-web # optional browser management console +``` + +(`SigLevel = Optional TrustAll`: the packages are unsigned; transport security comes from HTTPS +to the registry. Arch is rolling — the packages are built against current Arch sonames, so keep +the box itself updated too.) + +Then the same first-run steps as a source build (printed by the install scriptlet): `input` +group, `host.env`, `systemctl --user enable --now punktfunk-host` — see the next section. + +## Build from source — Arch Linux (mutable) ```sh cd packaging/arch