Commit Graph

14 Commits

Author SHA1 Message Date
enricobuehler 0052a6ae30 fix(packaging): vulkan-headers build dep + ship punktfunk-session across desktop packages
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Failing after 13s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 8s
apple / swift (push) Successful in 1m13s
apple / screenshots (push) Successful in 5m57s
android / android (push) Successful in 3m58s
ci / rust (push) Successful in 4m10s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 1m0s
arch / build-publish (push) Successful in 9m35s
deb / build-publish (push) Successful in 3m59s
decky / build-publish (push) Successful in 15s
ci / bench (push) Successful in 4m51s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 2m38s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m31s
flatpak / build-publish (push) Successful in 4m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 9m13s
docker / deploy-docs (push) Successful in 6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows-host / package (push) Successful in 23m50s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m15s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m56s
The re-architecture split the Linux client into two binaries (shell + Vulkan
session streamer) and added the pf-ffvk crate, whose build.rs runs bindgen over
FFmpeg's libavutil/hwcontext_vulkan.h (#include <vulkan/vulkan.h>). Two release
regressions fell out of that on the desktop-package legs:

1. Missing build dep. The Arch build (archlinux:base-devel + its own pacman list)
   fatal-errored at `vulkan/vulkan.h file not found`. Add the Vulkan dev headers
   wherever the client compiles from a self-managed dep set: arch (PKGBUILD
   makedepends + arch.yml), rpm (spec BuildRequires + rpm.yml + fedora image),
   deb.yml (belt-and-suspenders; the rust-ci image already bakes libvulkan-dev),
   and the screenshots job. The flatpak builds offline against the GNOME SDK, so
   install Vulkan-Headers into /app as a pinned module and point pf-ffvk's bindgen
   at it via PF_FFVK_VULKAN_INCLUDE.

2. Only the shell shipped. arch/deb/rpm built and installed just punktfunk-client;
   the shell execs its sibling punktfunk-session for a connect, so desktop
   streaming would break exactly as Decky's did. Build and install BOTH binaries
   in all three, and declare the runtime Vulkan loader the session binary dlopens
   (vulkan-icd-loader / vulkan-loader / libvulkan1 — not a DT_NEEDED, so
   shlibdeps/auto-requires can't see it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 23:41:10 +02:00
enricobuehler e459109818 ci(release): derive canary version from git tags (single source of truth)
Every release workflow hardcoded a canary base version (0.5.0 in
Apple/Android/rpm/flatpak/deb, 0.3 in windows-msix/windows-host/decky) that
had to be hand-bumped on each stable release and wasn't. With stable at
v0.6.0, every canary was a version *behind* stable — e.g. the Apple canary
showed up on TestFlight as 0.5.0 while 0.6.0 was already published.

Add scripts/ci/pf-version.{sh,ps1} (bash + pwsh twin) as the single source of
truth: stable = the vX.Y.Z tag; canary = latest stable tag with minor+1,
patch 0 (v0.6.0 -> 0.7.0), so canary is always exactly one minor ahead of the
newest release with zero maintenance. Falls back to the workspace Cargo.toml
version when no tag is fetchable. All workflows now eval/call it and format
their own channel suffix off $PF_BASE; only the canary branch changed, stable
branches and per-channel suffixes are untouched. channels.md drops the old
manual "bump the canary base" release step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 22:40:25 +00:00
enricobuehler 3a813b79e1 ci(release): idempotent registry publish — survive re-tagged releases
A moved release tag re-fires the publish workflows, and the Gitea
registries reject duplicate uploads with 409 (deb pool, rpm group, and
the generic packages' versioned URLs; the channel aliases already
pre-deleted). Delete any prior copy of the exact version before
uploading (404 on first publish tolerated), so a republished tag
overwrites instead of wedging — v0.5.0's retag left stale no-port-change
artifacts published and every re-run red.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 19:23:04 +00:00
enricobuehler a384f7db45 chore(release): bump workspace version to 0.4.1; canary base to 0.5.0
The [workspace.package] version (inherited by every crate via version.workspace)
lagged at 0.3.0 through the 0.4.0 release — bump it to 0.4.1, the release being
cut, and refresh the 8 workspace entries in Cargo.lock to match (CI builds
--locked).

Also advance the CI canary-base fallbacks (deb/rpm/flatpak/android/release
workflows + build-rpm.sh) from 0.3.0 to 0.5.0 so main/canary builds sort one
minor ahead of the latest stable line, per the documented channel convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:22:42 +02:00
enricobuehler ae51276a03 feat(web): consolidate paired devices, self-contained sections, docs + lint
Web console
- Pairing/Library/Stats refactored into self-contained subsections that each own
  their own queries + mutations; a shared slot-based layout (view.tsx) is filled by
  the live page (containers) and Storybook (pure cards + fixtures) so the layout can't
  drift.
- All paired devices in one list on Pairing with a protocol column (punktfunk/1 +
  Moonlight), routing each unpair to the right endpoint; the redundant Clients page is
  removed.
- Library: overview grid split from the add/edit form into separate files.
- Login screen links out to the docs.

Docs
- "Console login password" section on every host page (apt/RPM/Bazzite/SteamOS/Windows)
  plus a new "Forgot your Password?" troubleshooting page, linked from the login screen.
- Console served as HTTP/1.1 over TLS (drop the unusable HTTP/3 advertising) across the
  Bun entry, launchers, systemd units, and packaging.

Tooling
- Biome now respects .gitignore (stops linting generated code), config migrated to
  2.5.1; all lint issues fixed cleanly.

Also includes this branch's in-progress host, Apple client, packaging, and CI changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:05:22 +02:00
enricobuehler 6d370f7ed9 ci(release): split canary/stable tracks + unified Gitea Releases
A push to main publishes canary builds to canary channels (fast iteration,
unchanged); a single vX.Y.Z tag releases every platform at one version to the
stable channels and attaches all artifacts (.deb/.rpm/.msix/.apk/.aab/.dmg +
flatpak/decky/host-installer) to one Gitea Release. Collapses the
host-v*/win-v*/host-win-v* tag namespaces into v* — the channel split makes the
version-shadow bug structurally impossible (canary and stable are separate repos,
never a shared version line).

- scripts/ci/gitea-release.{sh,ps1}: one idempotent release helper
  (create-or-fetch + delete-before-upload), replacing 3 copy-pasted inline blocks
  and fixing their latent 409-on-reupload bug; prerelease flag auto-derived from
  the tag (an -rc tag won't shadow "Latest")
- channels: apt canary/stable distributions; rpm *-canary/base groups; flatpak
  canary/stable OSTree branches + a 2nd .Canary.flatpakref; generic-registry
  canary/ vs latest/ aliases; Play internal/alpha; Apple TestFlight vs notarized DMG
- android versionName threaded through gradle (versionCode stays run_number);
  Apple canary = TestFlight-only (no DMG/tvOS); canary base bumped to 0.3.0
- docs: new docs-site channels.md (subscribe table + cut-a-release runbook +
  box migration), refreshed ci.md workflow table + packaging READMEs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 17:26:38 +00:00
enricobuehler d0f6c02349 ci: bust the re-poisoned cargo cache (v3) + burst-guard the runner prune
This session's push storm refilled the runner to 100% WITHIN the prune timer's 24h window
(it only trims >24h), so a build hit ENOSPC and actions/cache saved a truncated target/ ->
`error[E0463]: can't find crate for shlex` in ci.yml's clippy. Two fixes:

- Bump cargo-target-v2- -> v3- in ci.yml + deb.yml so the poisoned tarball is bypassed (a
  suffix bump can't — restore-keys falls back to the old prefix; same as the v1->v2 fix).
- Harden scripts/ci/docker-prune: run HOURLY (was 6h) with a burst guard — if the disk is
  still >85% after the normal until=12h trim, prune ALL idle images + build cache (in-use
  protected). A fast push-burst can fill 99 GB inside any time window, so the disk-pressure
  trigger, not the age filter, is the real backstop. Applied live on home-runner-1 (reclaimed
  95%->66%) and checked in.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 14:25:40 +00:00
enricobuehler cd395f0c22 fix(ci): provide bun for deb.yml's web-console build
deb.yml builds the punktfunk-web .output in the rust-ci image, but that image had no bun
(only ci.yml's web/docs jobs use the oven/bun image) -> "bun: not found". Bake bun (+ unzip
for its installer) into ci/rust-ci.Dockerfile, and bootstrap it in the deb web step too so the
job is green against the previous image (docker.yml rebuild lag) — mirroring the rpm.yml fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 14:06:12 +00:00
enricobuehler 663e046fe6 fix(dist): kill the version-shadow + add build provenance (P0)
The stale code a default install/upgrade got was a TAG LEAK: deb.yml/rpm.yml shared
`tags: ['v*']` with the Apple-client release.yml, so the v0.1.0/v0.1.1 tags cut to ship
the macOS app ALSO published host packages versioned 0.1.1 — which outranks every rolling
0.0.1~ciN / 0.0.1-0.ciN build in both registries (dpkg/rpm version compares confirm), so
`apt install`/`rpm-ostree install` silently fetched ~99-commits-stale code while the READMEs
claimed auto-tracking. Two fixes:

- Decouple host publishing from Apple `v*` tags: deb.yml/rpm.yml now trigger on `host-v*`
  only, so a client tag can never poison the host channel again.
- Bump the rolling base 0.0.1 -> 0.2.0 (deb `0.2.0~ciN`, rpm `0.2.0-0.ciN`): sits ABOVE the
  stray 0.1.1 yet BELOW a future 0.2.0 tag, and still climbs monotonically by run number — so
  `apt upgrade`/`rpm-ostree upgrade` genuinely move forward. Spec default + build scripts +
  PKGBUILD pkgver bumped to match.

Build provenance (so a stale/shadowed host is detectable): build.rs stamps PUNKTFUNK_BUILD_VERSION
(set by CI = the full package version, e.g. 0.2.0~ci120.g802e98d; falls back to the crate version
for a plain `cargo build`) into the binary via rustc-env. Surfaced in `punktfunk-host --version`,
the startup log, and the mgmt /health + /host `version` field (was a hardcoded CARGO_PKG_VERSION).
Deliberately env-driven, not git-derived — the RPM builds from a git-archive tarball with no .git.
Version computed BEFORE the build in deb.yml; the spec %build exports it from %{version}-%{release}
(and gains --locked for reproducibility parity with the .deb path). Validated: plain build reports
0.0.1, env-stamped build reports 0.2.0~ci999.gdeadbee.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:30:21 +00:00
enricobuehler 84fff71a6d ci: bound runner disk + bust the disk-full-corrupted cargo target cache
The self-hosted runner filled its disk (95%, builds failing on ENOSPC): every CI
push builds a sha-<commit>-tagged Docker image per pipeline, and since those tags
are never dangling a plain `docker image prune` skips them — they piled up to 589
images / ~85 GB plus 18 GB of build cache. Two parts:

- scripts/ci/docker-prune.{service,timer}: a host-level systemd timer (every 6h,
  Persistent) that prunes images/build-cache/containers older than 24h — in-use
  images stay protected. Checked in (the runner is hand-provisioned and shared
  across orgs) and already installed live; reclaimed 89 GB -> 39 GB (95% -> 42%).

- ci.yml / deb.yml: bump the `cargo-target-<rustc>-*` cache key to `-v2-`. The
  disk-full build let actions/cache save a truncated target/ (a dep's .rmeta went
  missing -> "error[E0463]: can't find crate for pem_rfc7468" while compiling der).
  A suffix bump is useless here — restore-keys would fall back to the poisoned
  prefix — so the prefix is versioned to force one clean rebuild. cargo-home is
  untouched (sources were intact; the failure was a missing build artifact).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 09:10:56 +00:00
enricobuehler 4a7cf9af7b feat(packaging/web): bundle the web console into the apt install (punktfunk-web)
Every user needs the console for pairing, so ship it via apt, auto-wired to the
host — no manual bun/env setup. New punktfunk-web .deb (Architecture: all,
Depends: nodejs >= 20 — runs the node-server build under apt-native node, no
bundled bun):

- packaging/debian/build-web-deb.sh: stages web/.output (server + public) + a
  /usr/bin/punktfunk-web-server wrapper (node) + the systemd --user units + the
  web.env template + docs. Refuses a bun bundle (Bun.serve) as a wrong-preset guard.
- scripts/punktfunk-web.service: --user unit on :3000, EnvironmentFile sources the
  host's ~/.config/punktfunk/mgmt-token (the shared bearer) + the generated
  web-password; sets PUNKTFUNK_MGMT_URL=https://127.0.0.1:47990 +
  NODE_TLS_REJECT_UNAUTHORIZED=0 (loopback self-signed cert). Restart=on-failure
  rides out the host-writes-token-first ordering.
- scripts/punktfunk-web-init.service + web-init.sh: --user one-shot that generates
  the login password (a .deb postinst runs as root → wrong $HOME) and surfaces it
  to the journal.
- build-deb.sh: punktfunk-host now Recommends punktfunk-web (apt pulls it by
  default; headless boxes opt out with --no-install-recommends).
- deb.yml: build the web console + smoke-boot it under node (gate the .deb on a
  real /login 200) + build-web-deb.sh; the publish loop globs it automatically.
- web/{.env.example,web.env.example}: document the auto-wiring vs a manual deploy.

End state: `apt install punktfunk-host` pulls punktfunk-web; enable both --user
services; the console logs in (password from the journal) and proxies the host's
HTTPS mgmt API with the shared token — zero hand-edited env. Local .deb build +
node smoke-boot verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 08:50:40 +00:00
enricobuehler 7bda3d8059 ci(packaging): punktfunk-client .deb + RPM subpackage
Hook the Linux client into the existing packaging CI:

- deb.yml builds both binaries and publishes punktfunk-host AND
  punktfunk-client to the Gitea apt registry; new
  packaging/debian/build-client-deb.sh mirrors the host script
  (shlibdeps auto-Depends — GTK4/libadwaita/SDL3/FFmpeg/PipeWire
  sonames; no NVIDIA filter, the client links no CUDA). Built and
  inspected locally on Ubuntu 26.04.
- punktfunk.spec gains a "client" subpackage (binary + desktop entry +
  udev rule); rpm.yml's publish loop picks it up unchanged.
- New shared assets: packaging/linux/io.unom.Punktfunk.desktop and
  scripts/70-punktfunk-client.rules — DualSense hidraw uaccess (USB +
  Bluetooth, steam-devices style) so SDL's HIDAPI driver gets
  touchpad/motion/lightbar/triggers instead of degrading to evdev.
- Builder images learn the client link deps (rust-ci already had
  them; fedora-rpm adds gtk4/libadwaita/SDL3-devel) with idempotent
  install steps in deb.yml/rpm.yml since jobs run against the
  previous push's image.

Workspace check CI (build/clippy/test) already covers the crate since
a601022.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 23:18:12 +00:00
enricobuehler 1fd4524510 fix(ci): POSIX shell in deb/rpm Version step (dash "Bad substitution")
deb.yml runs in the Ubuntu rust-ci image whose /bin/sh is dash, where the bash
substring `${GITHUB_SHA::8}` is a "Bad substitution" — the deb build failed at the
Version step every run. Compute the short SHA with `cut` instead. (rpm.yml ran fine
because the Fedora image's /bin/sh is bash, but fix it the same way for robustness.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 22:48:12 +00:00
enricobuehler ba65febe84 ci(deb): publish punktfunk-host .deb to the Gitea apt registry
Wires up the half-built Debian packaging: build-deb.sh existed but nothing
invoked or published it. Adds a `deb` workflow that builds the release host in
the Ubuntu 26.04 rust-ci image, packages it (dpkg-shlibdeps-resolved Depends,
NVIDIA driver filtered out), and uploads to Gitea's public Debian registry on
every main push (rolling 0.0.1~ciN.<sha>) and v* tag (clean X.Y.Z). Ubuntu hosts
then track it with `apt update && apt upgrade`.

Also: box-setup docs (packaging/debian/README.md), a pointer from the packaging
README, ignore dist/, and drop backticks from the package Description (the
unquoted control heredoc ran them as a command substitution).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:14:40 +00:00