ci / web (push) Successful in 1m9s
ci / docs-site (push) Successful in 1m14s
ci / rust-arm64 (push) Successful in 3m28s
deb / build-publish-client-arm64 (push) Successful in 2m28s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 10s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 9s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 11s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 29s
android / android (push) Successful in 5m47s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m16s
docker / builders-arm64cross (push) Successful in 9s
deb / build-publish (push) Successful in 6m5s
docker / deploy-docs (push) Successful in 35s
deb / build-publish-host (push) Successful in 6m35s
ci / rust (push) Successful in 6m38s
arch / build-publish (push) Successful in 9m13s
apple / swift (push) Failing after 13m37s
apple / screenshots (push) Skipped
windows-host / package (push) Successful in 17m4s
windows-host / winget-source (push) Skipped
windows-host / canary-manifest (push) Successful in 20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m17s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 39s
Field report (RX 5700 / SteamOS): 10-bit HEVC "unsupported" — but the GPU was
never the blocker (RADV probed Main10 fine on that box). The session stayed SDR
because stock gamescope offers no 10-bit PQ capture formats and nothing shipped
our pipewire-hdr build outside the Bazzite sysext, while PUNKTFUNK_GAMESCOPE_HDR
additionally defaulted off everywhere. Close all three gaps:
- PUNKTFUNK_GAMESCOPE_HDR now defaults ON (explicit-off grammar, the flip the
config comment planned post-canary). Safe by construction: the +pfhdr banner
probe, managed-spawn term, and client 10-bit cap keep stock-gamescope boxes on
the exact 8-bit path. The nix module's gamescopeHdr (default true now) only
controls whether the patched binary is on PATH; it no longer sets the env.
- SteamOS: new scripts/steamdeck/build-gamescope.sh builds the HDR gamescope in
the same pf2 trixie distrobox (apt dep list validated by a full build in a
debian:trixie container), installs ~/.local/bin/punktfunk-gamescope, and
maintains PUNKTFUNK_GAMESCOPE_BIN in host.env ONLY while the binary passes its
on-glass --version/+pfhdr check — a stale absolute override would break
session spawning, not just HDR. Wired into install.sh (§3b), update.sh
(retrofit), and rebuild-check.sh (ldd-probes it like the host binary).
- Arch: build-sysext.sh gains a --gamescope fold-in (banner-verified by
execution, host-image-only), and punktfunk-host optdepends the companion.
Deliberately NO CI-published host sysext: per the 2026-07-22 packaging
verdict a prebuilt SteamOS host breaks on A/B soname bumps (and /var is
per-partition-set), so arch.yml records that instead — SteamOS hosts use the
distrobox flow above.
Also fixes a latent bug that made build-sysext.sh fail every invocation as
documented: a literal `}` inside `${1:?usage …{host,client}…}` terminates the
expansion early and corrupts $PKG (caught by the new synthetic-package test,
which also covers the fold-in, the unmarked-gamescope refusal, and the
client-image guard).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
85 lines
4.2 KiB
Bash
Executable File
85 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Wrap a built punktfunk pacman package into a systemd-sysext image — the update-survivable way to
|
|
# add it to an immutable Arch-derived distro (SteamOS 3): the .raw overlays /usr read-only from the
|
|
# writable /var/lib/extensions/, so it persists across A/B OS updates with no `steamos-readonly
|
|
# disable`. Works for either split package — on a Steam Deck you'd wrap the CLIENT. Needs
|
|
# `bsdtar`/`tar`, `squashfs-tools` (mksquashfs).
|
|
#
|
|
# Usage: bash build-sysext.sh [--gamescope <punktfunk-gamescope-*.pkg.tar.zst>] \
|
|
# <punktfunk-{host,client}-*.pkg.tar.zst>
|
|
# Output: <pkgname>.raw (e.g. punktfunk-client.raw)
|
|
#
|
|
# --gamescope folds the HDR-capable gamescope companion package (packaging/gamescope) into a HOST
|
|
# image as /usr/bin/punktfunk-gamescope — what lets the gamescope backend stream 10-bit BT.2020 PQ
|
|
# instead of 8-bit SDR (the host prefers that name on PATH and attempts HDR by default). Mirrors
|
|
# the Bazzite image's fold-in, including the honesty check: the binary is verified by executing
|
|
# its `+pfhdr` banner, never trusted by filename. Omit it and the image is exactly what it was —
|
|
# the host then stays SDR on that backend, by design. (No CAP_SYS_NICE inside the image: file
|
|
# capabilities don't survive this squashfs path — gamescope runs without it, pacing slightly
|
|
# worse, same as the Bazzite sysext.)
|
|
set -euo pipefail
|
|
|
|
GAMESCOPE=""
|
|
if [ "${1:-}" = "--gamescope" ]; then
|
|
GAMESCOPE="${2:?--gamescope needs a punktfunk-gamescope package}"; shift 2
|
|
fi
|
|
# No braces in the message: a literal `}` inside ${1:?...} terminates the expansion early and
|
|
# corrupts $PKG (the tail of the message gets appended to the value — a real field bug).
|
|
PKG="${1:?usage: build-sysext.sh [--gamescope <pkg>] <punktfunk-host|client pkg.tar.zst>}"
|
|
[ -f "$PKG" ] || { echo "no such package: $PKG" >&2; exit 1; }
|
|
# Derive the package name from the file (pkgname is everything before the -<version>).
|
|
NAME="$(basename "$PKG" | sed -E 's/-[0-9].*//')"
|
|
[ -n "$NAME" ] || { echo "could not derive package name from $PKG" >&2; exit 1; }
|
|
if [ -n "$GAMESCOPE" ] && [ "$NAME" != "punktfunk-host" ]; then
|
|
echo "--gamescope only makes sense for a punktfunk-host image (got: $NAME)" >&2; exit 1
|
|
fi
|
|
|
|
STAGE="$(mktemp -d)"
|
|
trap 'rm -rf "$STAGE"' EXIT
|
|
|
|
# A pacman package is a (zstd) tarball; a sysext only carries /usr (the host /etc, /var are the
|
|
# system's). Extract just usr/ from the payload.
|
|
if command -v bsdtar >/dev/null 2>&1; then
|
|
bsdtar -C "$STAGE" -xf "$PKG" usr
|
|
else
|
|
tar -C "$STAGE" -xf "$PKG" usr
|
|
fi
|
|
|
|
# The HDR gamescope companion (see --gamescope in the header). Verified by its banner marker
|
|
# rather than trusted by filename: an unpatched gamescope shipped under this name would make the
|
|
# host promise HDR it cannot deliver, and the punktfunk/1 Welcome cannot take that back
|
|
# mid-session. Executing the staged binary needs a build box the binary runs on (the Arch CI
|
|
# container qualifies; it built it).
|
|
if [ -n "$GAMESCOPE" ]; then
|
|
[ -f "$GAMESCOPE" ] || { echo "no such package: $GAMESCOPE" >&2; exit 1; }
|
|
if command -v bsdtar >/dev/null 2>&1; then
|
|
bsdtar -C "$STAGE" -xf "$GAMESCOPE" usr
|
|
else
|
|
tar -C "$STAGE" -xf "$GAMESCOPE" usr
|
|
fi
|
|
GS_BIN="$STAGE/usr/bin/punktfunk-gamescope"
|
|
[ -x "$GS_BIN" ] || { echo "$GAMESCOPE did not provide usr/bin/punktfunk-gamescope" >&2; exit 1; }
|
|
"$GS_BIN" --version 2>&1 | grep -q '+pfhdr' || {
|
|
echo "$GAMESCOPE's binary has no +pfhdr marker — it is not a punktfunk HDR build" >&2; exit 1; }
|
|
echo "folded in $("$GS_BIN" --version 2>&1 | head -1)"
|
|
fi
|
|
|
|
# The marker systemd-sysext requires to merge the image. ID=_any merges onto ANY host os-release
|
|
# (SteamOS, Arch, Bazzite); ARCHITECTURE pins it to x86-64 so it's never merged on the wrong arch.
|
|
install -d "$STAGE/usr/lib/extension-release.d"
|
|
cat > "$STAGE/usr/lib/extension-release.d/extension-release.$NAME" <<EOF
|
|
ID=_any
|
|
ARCHITECTURE=x86-64
|
|
EOF
|
|
|
|
OUT="$NAME.raw"
|
|
rm -f "$OUT"
|
|
mksquashfs "$STAGE" "$OUT" -all-root -noappend -quiet
|
|
echo "built $OUT"
|
|
echo " install: sudo cp $OUT /var/lib/extensions/ && sudo systemctl enable --now systemd-sysext"
|
|
if [ "$NAME" = "punktfunk-host" ]; then
|
|
echo " then: systemctl --user enable --now punktfunk-host"
|
|
else
|
|
echo " then: run 'punktfunk-client' (or let the Decky plugin launch it)"
|
|
fi
|