5 Commits
Author SHA1 Message Date
Tobias Gesellchen 97caea112f feat(cli): add on-demand update-check command to soundtouch-cli and soundtouch-backup
Answers #591's open question 2: CLI-only users get no update notice
from soundtouch-service's periodic background check. Both binaries
gain a soundtouch-cli/soundtouch-backup update-check command that
does a single, on-demand GitHub Releases check via the existing
pkg/service/updatecheck package. Running the command is itself the
opt-in, so unlike the service there's no config flag or persisted
state.

pkg/service/updatecheck.Checker was already designed decoupled from
handlers.Server/main.go specifically so other binaries could import
it directly; this is that follow-through.
2026-08-11 09:27:54 +02:00
Tobias GesellchenandClaude Opus 4.8 1c6f4c9eb8 fix(release): build the tagged commit and stamp the real version (#525)
v0.114.0 binaries reported version 0.0.0 in the web UI. Two root causes,
both fixed here.

1. The release build relied solely on Go's VCS stamping of
   info.Main.Version and never injected a version. When v0.114.0 was
   re-released via workflow_dispatch from `main` (one commit past the
   tag) with a shallow checkout, no tag was reachable, so Go stamped a
   v0.0.0-<ts>-<sha> pseudo-version. The asset filenames used the
   validated input version, so the files were named v0.114.0 but
   reported 0.0.0 at runtime.

2. The `release` and `workflow_dispatch` triggers followed two distinct
   patterns. On `release` every job's checkout landed on the tagged
   commit (GITHUB_SHA == tag); on `workflow_dispatch` they all built
   whatever branch the run started from. So a manual dispatch built the
   wrong source entirely (binaries and Docker images alike).

Changes:

- Unify both triggers on the git tag. `validate` resolves the tag once
  (inputs.tag on dispatch, release.tag_name on a release event), verifies
  it exists in git, and exposes it as an output. Every other job checks
  out `ref: needs.validate.outputs.tag`, so the build is always the
  tagged commit regardless of trigger. The dispatch path now re-releases
  an existing tag (push the tag first) instead of creating one from a
  branch; it fails fast if the tag is missing.
- Inject -X main.version/commit/date into the release binaries, mirroring
  the Dockerfile (which has done this since #422). version/commit no
  longer depend on git stamping; commit is read from the checked-out HEAD
  (not github.sha, which on dispatch is the branch HEAD). Both binaries
  and Docker images take the v-prefixed tag (needs.validate.outputs.tag)
  so the displayed version stays "v0.114.0", matching prior releases.
- Guard updateBuildInfo() in all four cmd/*/main.go so an injected
  version (version != "dev") is never clobbered by a VCS pseudo-version.
  `go install …@vX.Y.Z` still resolves the tag via build info as before.
- Collapse the duplicated `if event_name == workflow_dispatch` tag
  derivations and route tag/version through needs.validate.outputs.*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 09:33:48 +02:00
Tobias GesellchenandClaude Sonnet 4.6 96a8eda1a4 fix: update cross-repo doc links after Jekyll-to-Hugo restructure
Files in cmd/ examples/ scripts/ referenced docs/guides/ and docs/reference/
which moved to docs/content/docs/guides/ and docs/content/docs/reference/.
A few links to loose files at the docs/ root were updated to their new
location under docs/content/docs/appendix/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 13:30:36 +02:00
Tobias GesellchenandClaude Opus 4.7 51d196dd03 docs: replace personal LAN IPs and device names with placeholders
Public-repo hygiene: docs and READMEs carried the maintainer's home
LAN range (192.168.178.x) and personal speaker names ("Sound
Machinechen", "A Sound Machine"). Swapped to RFC-5737 documentation
IPs (192.0.2.x — reserved for examples, won't collide with anyone's
real network) and generic names ("Living Room SoundTouch",
"Kitchen SoundTouch").

12 files touched, all .md / .txt documentation. No code or tests
changed in this commit; subsequent commits will address the
docs/analysis/ANONYMIZATION-SUMMARY.md mapping log and the wider
real-MAC/real-account-ID footprint surfaced by the audit at
_/RFC-5737-cleanup/assessment.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:05:13 +02:00
86825c44af feat(backup): add soundtouch-backup tool for cloud and local speaker backup (#197)
Introduces a standalone `soundtouch-backup` CLI with three subcommands:
- `all`: authenticates with the Bose cloud, backs up account data, then
reads device IPs from devices.xml and backs up each reachable speaker
- `cloud`: fetches account profile, devices, sources, presets, and full
endpoint from streaming.bose.com
- `local`: backs up each speaker via HTTP API (12 endpoints) and
optionally via SSH (individual files + /opt/Bose/etc/ and
/mnt/nv/BoseApp-Persistence/1/ directories)

Also centralises pkg/service/ssh → pkg/ssh so both the service and the
backup tool share the same SSH client; adds ReadFile and ReadDir
methods, and handles the firmware quirk where cat exits 1 on empty
files.

Output is a single dated .tar.gz or .zip archive.

Example flow:

```shell
gesellix@Mac Bose-SoundTouch % go run ./cmd/soundtouch-backup all --output _/cloud-backup --email user@example.com
Password: 
Authenticating as user@example.com...
  ✓ Authenticated (account ID: 1234567)
  ✓ email address (107 bytes)
  ✓ devices (1492 bytes)
  ✓ sources (1111 bytes)
  ✓ presets (2585 bytes)
  ✓ full account (55037 bytes)
Found 2 device(s) in cloud account, attempting local backup...
  ✓ ST20: 12 files via HTTP
  ⚠ ST20: SSH skipped /etc/remote_services (Process exited with status 1)
  ⚠ ST20: SSH empty file /mnt/nv/remote_services
  ✓ ST20: 64 files via SSH
  ✓ ST10: 12 files via HTTP
  ⚠ ST10: SSH empty file /etc/remote_services
  ⚠ ST10: SSH skipped /mnt/nv/remote_services (Process exited with status 1)
  ✓ ST10: 48 files via SSH
Archive written: _/cloud-backup/soundtouch-backup-2026-05-02.tar.gz (141 files)
```

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 14:00:23 +02:00