Reported from the field: update.sh --pull aborted with
error: Your local changes to the following files would be overwritten by merge:
web/bun.nix
Please commit your changes or stash them before you merge.
before a single service restarted, and the only way past it was to delete web/bun.nix by hand.
The updater did it to itself
web/bun.nix is generated — bun2nix is a pure function of web/bun.lock (packaging/nix/README.md) — but it is committed, because the Nix build fetches node_modules only from it. The web step ran:
cd"$SRC/web"&& bun install --frozen-lockfile && bun run build
with no --ignore-scripts, so web's postinstall (bun2nix -o bun.nix) fired and rewrote that tracked file on every single update. The SDK step directly below has always passed --ignore-scripts — which is exactly why only web/bun.nix ever went dirty. That asymmetry is the whole bug.
It stays invisible while the committed file is in sync. But main carried a staleweb/bun.nix from 1db8f763 (07-27) through b79d90b4 (08-05) — the drift scripts/ci/check-bun-nix.sh was later written to catch. Any Deck updated in that window had the file rewritten to the correct content and has been sitting dirty ever since, so the next --pull that touches it aborts.
What changed
Both scripts/steamdeck/update.sh and scripts/steamdeck/install.sh:
1. Stop creating the dirt. The web install becomes bun install --frozen-lockfile --ignore-scripts && bun run codegen && bun run build. Web has two install lifecycle scripts and we want exactly one of them:
prepare is literally "bun run codegen" (orval + paraglide + the i18n check) and is required — src/api/gen, src/paraglide and src/routeTree.gen.ts are gitignored, and prebuild only re-runs orval, so dropping codegen would ship a build with no i18n messages.
postinstall is the one that writes a committed file.
Running codegen explicitly is therefore provably equivalent to the old behaviour minus bun2nix.
2. Unstick the Decks already broken.--pull restores web/bun.nix and sdk/bun.nix before pulling. Lossless by construction: regenerating them from the lockfiles is precisely what bun2nix does.
Deliberately not git reset --hard
$SRC defaults to $HOME/punktfunk — the operator's own checkout, which may carry a patched source file or a cherry-pick. Silently destroying that to save an update is a worse trade than one legible error, and a blanket reset would have hidden this bug indefinitely instead of surfacing it. A still-dirty tree now fails with a message naming the files, the way out, and "Nothing was rebuilt or restarted" — rather than git's raw abort mid-script.
Verification
bash -n clean on both scripts; shellcheck 0.11.0 clean at -S warning
the embedded bash -lc command bodies parse standalone
exec bits preserved
prepare == bun run codegen confirmed from web/package.json
scripts/ci/check-bun-nix.sh passes on main today (both packages in sync, bun2nix pinned at 2.1.2 everywhere), so the drift that made this visible cannot recur
Not fixed here, deliberately: packaging/debian/build-web-deb.sh, packaging/arch/PKGBUILD and packaging/rpm/punktfunk.spec have the same missing --ignore-scripts for web. Those run against throwaway build trees so the dirt is harmless, though it does make each package build depend on bun2nix for nothing. Easy follow-up if we want the consistency.
Reported from the field: `update.sh --pull` aborted with
```
error: Your local changes to the following files would be overwritten by merge:
web/bun.nix
Please commit your changes or stash them before you merge.
```
before a single service restarted, and the only way past it was to delete `web/bun.nix` by hand.
## The updater did it to itself
`web/bun.nix` is **generated** — bun2nix is a pure function of `web/bun.lock` (`packaging/nix/README.md`) — but it is **committed**, because the Nix build fetches `node_modules` only from it. The web step ran:
```sh
cd "$SRC/web" && bun install --frozen-lockfile && bun run build
```
with no `--ignore-scripts`, so web's `postinstall` (`bun2nix -o bun.nix`) fired and rewrote that tracked file on *every single update*. The SDK step directly below has always passed `--ignore-scripts` — which is exactly why only `web/bun.nix` ever went dirty. That asymmetry is the whole bug.
It stays invisible while the committed file is in sync. But main carried a **stale** `web/bun.nix` from `1db8f763` (07-27) through `b79d90b4` (08-05) — the drift `scripts/ci/check-bun-nix.sh` was later written to catch. Any Deck updated in that window had the file rewritten to the *correct* content and has been sitting dirty ever since, so the next `--pull` that touches it aborts.
## What changed
Both `scripts/steamdeck/update.sh` and `scripts/steamdeck/install.sh`:
**1. Stop creating the dirt.** The web install becomes `bun install --frozen-lockfile --ignore-scripts && bun run codegen && bun run build`. Web has two install lifecycle scripts and we want exactly one of them:
- `prepare` is literally `"bun run codegen"` (orval + paraglide + the i18n check) and is **required** — `src/api/gen`, `src/paraglide` and `src/routeTree.gen.ts` are gitignored, and `prebuild` only re-runs orval, so dropping codegen would ship a build with no i18n messages.
- `postinstall` is the one that writes a committed file.
Running codegen explicitly is therefore *provably equivalent* to the old behaviour minus bun2nix.
**2. Unstick the Decks already broken.** `--pull` restores `web/bun.nix` and `sdk/bun.nix` before pulling. Lossless by construction: regenerating them from the lockfiles is precisely what bun2nix does.
## Deliberately not `git reset --hard`
`$SRC` defaults to `$HOME/punktfunk` — the operator's own checkout, which may carry a patched source file or a cherry-pick. Silently destroying that to save an update is a worse trade than one legible error, and a blanket reset would have hidden this bug indefinitely instead of surfacing it. A still-dirty tree now fails with a message naming the files, the way out, and "Nothing was rebuilt or restarted" — rather than git's raw abort mid-script.
## Verification
- `bash -n` clean on both scripts; shellcheck 0.11.0 clean at `-S warning`
- the embedded `bash -lc` command bodies parse standalone
- exec bits preserved
- `prepare == bun run codegen` confirmed from `web/package.json`
- `scripts/ci/check-bun-nix.sh` passes on main today (both packages in sync, bun2nix pinned at 2.1.2 everywhere), so the drift that made this visible cannot recur
Not fixed here, deliberately: `packaging/debian/build-web-deb.sh`, `packaging/arch/PKGBUILD` and `packaging/rpm/punktfunk.spec` have the same missing `--ignore-scripts` for web. Those run against throwaway build trees so the dirt is harmless, though it does make each package build depend on bun2nix for nothing. Easy follow-up if we want the consistency.
`update.sh --pull` could abort with "Your local changes to the following files
would be overwritten by merge: web/bun.nix" — before a single service was
restarted — and the only way past it was to delete the file by hand.
The updater did it to itself. web/bun.nix is generated (bun2nix, a pure
function of web/bun.lock) but committed, because the Nix build fetches
node_modules only from it. The web step ran `bun install --frozen-lockfile`
without --ignore-scripts, so web's `postinstall` (`bun2nix -o bun.nix`)
rewrote that tracked file on every update. Harmless while the committed file
is in sync — but main carried a stale web/bun.nix from 1db8f763 to b79d90b4,
so any Deck updated in that window had it rewritten to the *correct* content
and has been sitting dirty ever since. The SDK step has always passed
--ignore-scripts, which is why only web/bun.nix ever went dirty.
Two changes, both in install.sh and update.sh:
* the web install now passes --ignore-scripts and runs `bun run codegen`
explicitly. web has two install lifecycle scripts and we want exactly one:
`prepare` IS `bun run codegen` (orval + paraglide + the i18n check) and is
required, since src/api/gen, src/paraglide and src/routeTree.gen.ts are
gitignored and `prebuild` only re-runs orval; `postinstall` is the one that
writes a committed file. Equivalent to the old behaviour minus bun2nix.
* --pull restores web/bun.nix and sdk/bun.nix before pulling, which unsticks
the installs already broken out there. Deliberately NOT `git reset --hard`:
$SRC is the operator's own checkout and may carry real local work, so a
still-dirty tree now fails with a message that names the files and the way
out instead of git's raw abort. Discarding these two is provably lossless —
regenerating them from the lockfiles is exactly what bun2nix does.
CI already gates the drift that made this visible (scripts/ci/check-bun-nix.sh,
ci.yml), so main cannot ship a stale bun.nix again.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Reported from the field:
update.sh --pullaborted withbefore a single service restarted, and the only way past it was to delete
web/bun.nixby hand.The updater did it to itself
web/bun.nixis generated — bun2nix is a pure function ofweb/bun.lock(packaging/nix/README.md) — but it is committed, because the Nix build fetchesnode_modulesonly from it. The web step ran:with no
--ignore-scripts, so web'spostinstall(bun2nix -o bun.nix) fired and rewrote that tracked file on every single update. The SDK step directly below has always passed--ignore-scripts— which is exactly why onlyweb/bun.nixever went dirty. That asymmetry is the whole bug.It stays invisible while the committed file is in sync. But main carried a stale
web/bun.nixfrom1db8f763(07-27) throughb79d90b4(08-05) — the driftscripts/ci/check-bun-nix.shwas later written to catch. Any Deck updated in that window had the file rewritten to the correct content and has been sitting dirty ever since, so the next--pullthat touches it aborts.What changed
Both
scripts/steamdeck/update.shandscripts/steamdeck/install.sh:1. Stop creating the dirt. The web install becomes
bun install --frozen-lockfile --ignore-scripts && bun run codegen && bun run build. Web has two install lifecycle scripts and we want exactly one of them:prepareis literally"bun run codegen"(orval + paraglide + the i18n check) and is required —src/api/gen,src/paraglideandsrc/routeTree.gen.tsare gitignored, andprebuildonly re-runs orval, so dropping codegen would ship a build with no i18n messages.postinstallis the one that writes a committed file.Running codegen explicitly is therefore provably equivalent to the old behaviour minus bun2nix.
2. Unstick the Decks already broken.
--pullrestoresweb/bun.nixandsdk/bun.nixbefore pulling. Lossless by construction: regenerating them from the lockfiles is precisely what bun2nix does.Deliberately not
git reset --hard$SRCdefaults to$HOME/punktfunk— the operator's own checkout, which may carry a patched source file or a cherry-pick. Silently destroying that to save an update is a worse trade than one legible error, and a blanket reset would have hidden this bug indefinitely instead of surfacing it. A still-dirty tree now fails with a message naming the files, the way out, and "Nothing was rebuilt or restarted" — rather than git's raw abort mid-script.Verification
bash -nclean on both scripts; shellcheck 0.11.0 clean at-S warningbash -lccommand bodies parse standaloneprepare == bun run codegenconfirmed fromweb/package.jsonscripts/ci/check-bun-nix.shpasses on main today (both packages in sync, bun2nix pinned at 2.1.2 everywhere), so the drift that made this visible cannot recurNot fixed here, deliberately:
packaging/debian/build-web-deb.sh,packaging/arch/PKGBUILDandpackaging/rpm/punktfunk.spechave the same missing--ignore-scriptsfor web. Those run against throwaway build trees so the dirt is harmless, though it does make each package build depend on bun2nix for nothing. Easy follow-up if we want the consistency.