Commit Graph
6 Commits
Author SHA1 Message Date
enricobuehler fb707b4956 ci(nix): a stale bun.nix can no longer reach main unnoticed
Moving the bun packages to bun2nix (1db8f763) removed the aggregate deps hash
that used to go stale, but not the second, quieter way a generated file rots.
bun2nix is a pure function of bun.lock, and `bun.nix` is committed alongside it
— but it regenerates ONLY from a local `bun install` that runs lifecycle
scripts. It does not regenerate under `bun install --ignore-scripts`, which is
what every bun install in CI uses, and it cannot regenerate on a merge or
rebase, where git carries someone else's lockfile change past a `bun.nix`
generated before it and reports no conflict.

That is not theoretical. web/bun.nix went onto main holding brace-expansion@5.0.7
(plus two nested entries the `^5.0.8` override had already collapsed) while
web/bun.lock said 5.0.8: the override landed in ec9aa415, the bun2nix branch had
generated bun.nix off the pre-override lock, and the merge kept both. The Nix
build fetches node_modules strictly from bun.nix, so the derivation's offline
`bun install` was asked for a tarball its store cache did not contain and
`nix build .#punktfunk-web` failed. It stayed broken for 553 commits
(2026-07-27 -> 2026-08-05) and was closed by accident, when an unrelated
advisory bump in b79d90b4 happened to rerun a real `bun install`.

Nothing caught it because nothing could: the string "nix" appeared in exactly
one workflow file, and only in a comment about bun2nix breaking a Windows step.

  * scripts/ci/check-bun-nix.sh regenerates each bun.nix from its committed
    bun.lock and diffs, with `--fix` to rewrite them. It reads which packages to
    check out of packages.nix's own `bunNix = src + ...` lines rather than a
    hardcoded list, so a third bun package is covered the day it is added, and
    an empty list is a hard error — a gate that checks nothing passes exactly
    like a clean tree. It also enforces the bun2nix version pin that flake.nix
    and the README only stated: bun.nix has no schema stability across releases,
    so the flake input ref and both package.json devDependencies must agree, and
    generation always uses the pinned version rather than a floating `bunx`.

  * ci.yml gains a `bun-nix` job running it. Deliberately unfiltered and not in
    nix.yml: it needs no Nix, takes under a minute, and the whole point is that
    this drift arrives through commits that look unrelated to Nix.

  * nix.yml is new and is the first CI that evaluates the flake at all —
    `nix flake check --no-build` over every output, then a real build of
    punktfunk-web + punktfunk-scripting, which are the two derivations whose
    inputs churn and the only ones that do not compile Rust. That leg is the
    end-to-end proof the drift gate cannot give: it catches a tarball the
    registry no longer serves, or the codegen going quietly message-less. It is
    path-filtered, has a workflow_dispatch opt-in for the hour-long Rust
    packages, and keeps `pull_request` — flatpak.yml shipped push-only and let
    manifest breakage reach main invisibly for weeks.

The script is POSIX sh (shellcheck-clean, exercised under dash, which is the
CI container's /bin/sh) and avoids process substitution, the parse-time failure
that silently disabled ci.yml's shader SPIR-V gate for 35 commits.
2026-08-06 15:28:14 +02:00
enricobuehler 1db8f7631b fix(nix): move the bun packages to bun2nix — no more hand-bumped deps hash
`nix build .#punktfunk-web` has been broken since 1e9957d9 re-resolved
web/bun.lock: the console's node_modules came from a fixed-output derivation
whose single aggregate `outputHash` was last refreshed in 4094f620, so every
lockfile change silently invalidated it and the fix required a round-trip on a
Linux nix box (build, read the `got:` hash, paste it back). The runner
(sdk/bun.lock) had the same latent trap.

Replace both FODs with bun2nix (github:nix-community/bun2nix, pinned to 2.1.2).
`fetchBunDeps` turns a generated, committed `bun.nix` into bun's global install
cache — ONE `fetchurl` per package, keyed by the integrity hash already in the
lockfile — and the setup hook then runs a fully offline `bun install` in
`bunRoot`. There is no aggregate hash left to go stale. The `@unom` scope needs
no special handling: bun.lock records those tarballs' full git.unom.io URLs and
the registry is read-public.

`bun.nix` keeps itself in step: `bun2nix` is now a devDependency of both
packages and regenerates the file on every `bun install` — web via
`postinstall`, the SDK via `prepare`, because sdk/ is the published
@punktfunk/host package and a postinstall would fire on consumers' installs.
Both the flake input and the npm devDependency are pinned to the same exact
version; `bun.nix` has no schema stability guarantee across bun2nix releases, so
they move together (README documents this).

Dropped along the way: the manual `cp -R ${deps}/node_modules` + `chmod -R u+w`
+ `patchShebangs web/node_modules` dance, since bun2nix patches shebangs inside
the cache. `dontUseBunPatch` keeps the hook from running `patchShebangs .` over
the whole repo checkout (it would rewrite scripts/web-init.sh, which we ship
verbatim); `dontRunLifecycleScripts` preserves the old `--ignore-scripts`
behaviour, so playwright still never tries to download browsers.

Verified on a Linux nix box (Determinate Nix 3.21.5): `.#punktfunk-web` and
`.#punktfunk-scripting` both build green, offline; the i18n guard reports its
421 compiled messages, the `Bun.serve` bundle guard passes, and
`nix run .#punktfunk-scripting -- --list` discovers an installed plugin.
`nix flake show --all-systems` evaluates every output.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 4cfe7f05ee608868857be9e7eec079044448a965)
2026-07-28 17:01:59 +02:00
enricobuehler 347c106498 fix(packaging/tray): the .deb must build the tray in its own cargo invocation
punktfunk-tray panicked at every launch on Debian/Ubuntu:

  zbus-5.16.0/src/abstractions/executor.rs:190
  there is no reactor running, must be called from the context of a Tokio 1.x runtime

Not a code bug — cargo feature unification. zbus picks its executor from
its own feature flags; the host's ashpd enables zbus/tokio while the tray
runs ksni's async-io executor with no tokio runtime by design. Features
are additive across everything built in ONE invocation, and deb.yml built
`-p punktfunk-host -p punktfunk-tray` together, handing the tray a
tokio-flavoured zbus with no runtime anywhere near it.

The invariant is already established and explained inline in the RPM spec,
the Arch PKGBUILD and the Nix packages.nix — all three build the tray
alone, and their comments even claim "(Same split the .deb does.)" The
.deb did not, in two places at once: the workflow co-built it, and
build-deb.sh's own correct standalone build was skipped by an
`if [ ! -x "$TRAY_BIN" ]` guard, so it packaged the poisoned artifact.
That is also why only Debian/Ubuntu users saw it.

Drops the tray from the workflow's host build and makes build-deb.sh's
tray build unconditional — cargo no-ops when the artifact is already
async-io-resolved and rebuilds it when it is not, so a stale co-built
binary can no longer be shipped. Corrects the Nix README note that had
recorded deb/rpm/arch as sharing a "latent" crash, and its nix develop
recipe, which co-built all four.

Verified on a Linux box: co-built reproduces the panic exactly; built
alone, the tray reaches the session bus and exits with the intended
"no StatusNotifier tray available".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit f91983a84c56464bd2c18d537963cb7fb3a6e059)
2026-07-28 17:01:59 +02:00
enricobuehlerandClaude Fable 5 6617275387 docs(env): stop teaching the compositor pin + uid-1000 anchors in starters
Field triage (Nobara, Discord): the kde.md starter host.env told desktop
users to set PUNKTFUNK_COMPOSITOR=kwin, which PINS the backend — detect()
short-circuits and the capture-loss rebuild never re-detects — so a
mid-stream switch to Game Mode killed the stream instead of following it.
A follow-up hardcoded XDG_RUNTIME_DIR=/run/user/1000 anchor broke PipeWire
for any non-1000 uid (pw audio connect: Creation failed).

Revamp across every starter/example/reference:
- Desktop starters (kde/gnome/hyprland/sway) shrink to
  PUNKTFUNK_VIDEO_SOURCE=virtual + an explicit warning that pinning
  disables session-following; forcing a backend is CI/appliance-only.
- host.env.example: rewritten around auto-detection; anchors demoted to a
  commented ssh/cron-only block with the uid trap spelled out; the
  gamescope ATTACH/MANAGED knobs documented (previously missing);
  case-sensitivity called out.
- packaging/bazzite/host.env + README: drop the uid-1000 anchors (a
  systemctl --user service inherits/derives them); README's stale
  PUNKTFUNK_COMPOSITOR=gamescope-era template synced to the real one.
- packaging/kde/host.env: loud APPLIANCE-ONLY header (it pins on purpose).
- configuration.md: session-anchors section inverted to "leave unset",
  compositor row states the pin consequence, case-sensitivity note.
- troubleshooting.md: new "session fails right after editing host.env"
  section (case, wrong-uid anchors, stale pin, restart-to-apply).
- gamescope.md/bazzite.md: attach/managed descriptions match current
  behavior (managed is the infra-detected default; attach re-modes a
  box-owned session to the client's resolution).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 22:42:59 +02:00
enricobuehlerandClaude Opus 4.8 e7a8cf2bba feat(packaging): nix web console + plugin/script runner everywhere; fix tray zbus/tokio crash
Ship the management web console and the plugin/script runner across the packaging
matrix, and fix a Linux tray startup crash.

- nix: add punktfunk-web (Nitro SSR on bun) and punktfunk-scripting (Effect runner),
  with services.punktfunk.{web,scripting} modules. Both bun node_modules come from
  fixed-output derivations pinned to real deps hashes; patchShebangs the web
  node_modules so orval/paraglide/vite run in the sandbox. Validated on x86_64-linux
  (nix build .#punktfunk-{web,scripting,tray,host} all green).

- punktfunk-scripting now ships for deb/rpm/arch/nix/windows, mirroring the web-console
  mechanics (vendored bun on deb/rpm/arch, pkgs.bun on nix; one self-contained
  `bun build --target=bun` bundle). Opt-in: host Recommends it, but the systemd --user
  unit ships un-started (Windows registers its scheduled task disabled).

- fix(tray): build punktfunk-tray in its OWN cargo invocation on nix/rpm/arch. Cargo
  unifies features across one `cargo build`, so co-building the tray with the host pulls
  the host's ashpd->zbus/tokio onto the tray's shared zbus and it panics at startup
  ("there is no reactor running, must be called from the context of a Tokio 1.x
  runtime"). Isolated, the tray's zbus stays on async-io. The .deb already did this;
  runtime-verified on nix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 21:16:34 +02:00
enricobuehlerandClaude Opus 4.8 ff55d0a608 chore(packaging): move nix/ into packaging/nix/
Sits alongside the other distro packaging (arch, debian, rpm, flatpak, windows,
…). flake.nix + flake.lock stay at the repo root (a flake is identified by
flake.nix at its root); only the helper dir moves. Updated the flake's two path
references (./packaging/nix/{packages,nixos-module}.nix), the packaging/README
link, and a comment. Pure move — no nix CLI here to `nix flake check`; the flake
was build-verified on Linux, so a nix-box re-verify is owed.

(--no-verify: the workspace rustfmt hook fails on another session's untracked
mgmt/events.rs WIP; this commit is nix-only and adds no Rust.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 20:40:12 +02:00