* feat(update): Linux AppImage self-update on the nightly channel
Adds a self-update engine for the Linux AppImage build. There's no
Velopack pipeline for Linux (Windows/macOS use it, Linux doesn't), so
this is a small, purpose-built GitHub-releases checker instead:
- On the nightly channel, compares the commit baked into the running
build (dist/main/build-info.json, written at build time) against the
published nightly's target_commitish. A mismatch means the running
build is behind, so it's offered as an update — this sidesteps the
fact that the AppImage's filename and app.getVersion() never change
between nightly builds, so semver comparison can't detect a new one.
- The check returns immediately and the ~1.5GB download runs in the
background with live progress (a new update:progress IPC event), so
the UI never blocks or freezes waiting on it.
- The download streams straight to disk (no buffering the whole file in
memory) and is swapped in with an atomic rename next to the running
AppImage. The stale-generation check (a channel switch or new check
invalidating an in-flight download) runs before that swap, and a
failed or superseded download always cleans up its temp file.
- Applying the update spawns the (already-swapped-in) AppImage as a
detached process and waits for a real 'spawn' confirmation before
quitting this one, rather than assuming success — child_process.spawn
can fail asynchronously, and quitting on an unconfirmed relaunch could
leave the user with nothing running.
- The pure idle/staged/download decision is split into
linux-update-decision.ts with a small truth-table test, and every
main-process decision point (and the equivalent renderer-side
actions, in the companion feedBack PR) is traced through a new
update:diag IPC event that lands in the app's existing "Export
Diagnostics" console-capture bundle — this is how the handful of real
bugs below were actually root-caused, from real device captures
rather than guesswork.
Also removes a forgotten, dead second implementation of the
update-channel UI (src/renderer/screen.js's
setupUpdateChannelControls() + its markup in settings.html), left over
from before this work discovered the real, visible System-tab update
UI lives in the feedBack repo. It was still wired up in the
audio_engine plugin's own settings panel and silently called
setChannel() with a stale channel value every time that panel
rendered — invisibly corrupting the real UI's state. This was the
actual root cause of several rounds of flaky, hard-to-reproduce
on-device behavior (a stuck "unsupported" warning, downloads starting
without an explicit check, etc.) chased down via the diagnostic
tracing above; once found, no other logic needed to change.
Dev tooling only, not used by CI: forces --platform linux/amd64 in the
local Docker build wrapper (the Linux target is x86_64-only end to
end — needed on Apple Silicon, where Rosetta chokes on a foreign-arch
binary inside an otherwise-native container) and adds a SLOPSMITH_REPO
override so a contributor without push access to the core repo can
bundle a fork branch for a local test build.
Verified end-to-end on a Steam Deck across many build/deploy rounds:
fresh launch, channel selection, check, background download with live
progress, atomic swap, and relaunch onto the new build — confirmed via
a real Export Diagnostics capture showing a clean, fully-accounted-for
trace with zero orphaned state transitions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(update): fail safe when nightly release isn't pinned to a commit SHA
GitHub sets a release's target_commitish to whatever it was published
against — a 40-char SHA only if pinned, otherwise a branch name like
"main". The Linux update decision compares it SHA-vs-SHA, so a branch
name would never match the baked SHA and would re-download the ~1.5GB
AppImage on every check forever, never reaching idle. Add isCommitSha()
(pure, unit-tested) and have checkNowLinux() surface an error instead of
entering that loop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Byron Gamatos <xasiklas@gmail.com>
---------
Signed-off-by: Byron Gamatos <xasiklas@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Byron Gamatos <xasiklas@gmail.com>
Adds the Stem Splitter plugin to clone_slopsmith()'s bundled-plugin
list so packaged builds ship it. The repo uses the feedBack-plugin-*
casing (capital B), so the lowercase prefix strip can't derive the
dirname — explicit :stem_splitter, matching the plugin id, same as
rig_builder.
Signed-off-by: topkoa <topkoa@gmail.com>
Add got-feedback/feedback-plugin-bongocat to the clone_slopsmith plugin
list so CI/release builds ship Bongo Cat's Rhythm Trainer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Playlists are integrated into the core app, so the setlist plugin is
obsolete and its repo is being archived.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both derive to dirnames (drum_highway_3d, keys_highway_3d) that core already ships as committed plugins/ dirs. The clone loop runs after core is in place, so these two always fail-to-clone-and-skip (dir exists) — dead entries. Core remains the authoritative source for both; no functional change to the shipped app.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feedBack-plugin-find-more is a deliberately-withheld repo (kept private); it must not be bundled into or shipped with the desktop app. Drop it from the plugin clone/bundle list.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The feedBack-plugin-update-manager repo is private and not being shipped, so drop it from the plugin clone/bundle list in build-common.sh. The desktop app's own Velopack auto-updater (src/main/update-manager.ts) is unrelated and untouched.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Camera Director plugin (got-feedback/cameradirector_feedback, our fork of
nimuart's) only appeared in locally-built AppImages because the entry adding it
to build-common.sh's plugin clone list was never committed — it existed solely
as a working-tree edit. Fresh-clone builds (CI, Windows, tester AppImages) clone
core plus this fixed plugin list and ignore the resources/ copies, so the plugin
showed for the maintainer but not for testers.
Its only dependency, the highway_3d `window.__h3dCamCtl` freecam bridge, is
already on core main, and there is no per-plugin build step, so adding the repo
to the clone list is enough to bundle it for everyone.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The bundled-plugin list cloned got-feedback/rig_builder, a name two
renames behind the current feedBack-plugin-rig-builder. That works only
via GitHub's rename redirect, which silently breaks the moment any new
repo takes the old name — a nightly would then bundle the wrong code
without failing. Point at the canonical repo with an explicit :rig_builder
dirname (capital B means the lowercase feedback-plugin- prefix strip
doesn't apply), which keeps the bundled module name byte-identical.
The other lowercase feedback-plugin-* entries are deliberately untouched:
GitHub repo names are case-insensitively unique, so a case-only mismatch
can never be shadowed or break, and canonicalizing them would force a
case-insensitive rewrite of the prefix strip (risky on the macOS build
host's bash 3.2) for zero functional gain.
Claude-Session: https://claude.ai/code/session_01H1ZBEcZoJinde9ms5fAjwc
Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* build: bundle feedback-plugin-virtuoso (replaces slopscale-fork)
The practice plugin relaunched as Virtuoso (id virtuoso) at got-feedback/feedBack-plugin-virtuoso. Repoint the bundle list off the stale feedback-plugin-slopscale-fork snapshot. The clone-dir derivation strips feedback-plugin- -> dir 'virtuoso', matching plugin.json id; default-branch clone = main. Requested by @xasiklas.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore: tidy bundled-plugins list (review follow-up)
Addresses the two minor notes on this PR:
- Sort virtuoso into its alphabetical slot (after update-manager); it was
left in the old slopscale-fork position between setlist and song-preview.
- Fix the stale dirname comment: the prefix stripped is "feedback-plugin-",
not "slopsmith-plugin-" (pre-existing since the rename; the code at the
${owner_repo##*/} / #feedback-plugin- step is unchanged).
No functional change — clone order/dirname resolution is unaffected.
Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Signed-off-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: ChrisBeWithYou <16130099+ChrisBeWithYou@users.noreply.github.com>
A local macOS tester reported the DMG as "damaged and can't be opened."
Root cause: the bundled tree contained a dangling symlink — rig_builder
ships a build-time link `vst/src/racks/DPF` -> DISTRHO framework that isn't
present at runtime. A broken symlink is harmless on Linux/squashfs (the
AppImage was fine), but on macOS it:
- breaks codesign — `spctl` reports "a sealed resource is missing or
invalid", which Gatekeeper surfaces as "damaged"; and
- breaks `xattr -dr com.apple.quarantine` — it aborts on the dangling
link, so even the quarantine-removal workaround can't complete.
Strip dangling symlinks from the cloned core+plugins tree after bundling
(safe on every platform — they're broken/unused). Verified on-device:
after removal + ad-hoc re-sign the app verifies clean and launches once
quarantine is cleared.
Also fix build-macos.sh's artifact check, which still globbed the
pre-rebrand `Slopsmith.app` and falsely reported "No artifacts found" for
the now `feedback.app` bundle.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add got-feedback/rig_builder to the default bundled-plugin manifest so the
Rig Builder (NAM tone builder) ships with every build. The v3 sidebar now
promotes Rig Builder to a dedicated nav entry, so the plugin should be present.
Note: rig_builder is large (~633 MB of NAM models/assets), so this increases
release artifact size accordingly.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the re-homed feedback-plugin-loosefolder (dir override :loose_folder
since the plugin id is loose_folder) and feedback-plugin-strum-fighter
to the bundled set (now 36 plugins).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The slopsmith org was deleted in the DMCA relaunch; core + plugins now
live under the private got-feedback org. Repoint the whole build:
- core clone (nightly.yml, build-common.sh) -> got-feedback/feedback,
authenticated via GH_CLONE_TOKEN (a PAT with read on the private org;
threaded through build.yml/nightly.yml/release.yml). Local builds
without it fall back to the git credential helper.
- bundled-plugin list -> got-feedback/feedback-plugin-*, pruned to the
set that exists in the org: drops the removed extraction plugins
(profileimport, tones, sloppak-converter) and not-yet-rehomed ones
(nam-rig-builder, tabimport); 34 plugins bundled.
- dirname derivation strips the new feedback-plugin- prefix.
- ghcr image -> ghcr.io/got-feedback/feedback; VERSION-sync dispatch
-> got-feedback/feedback; soundfont + update FEED_URL + docs ->
got-feedback/feedback-desktop.
Two prerequisites remain (owner-only): set the GH_CLONE_TOKEN secret,
and re-upload the soundfonts-v1 release assets to feedback-desktop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>