Skip to content

macOS app: in-app update checks, release notes, and one-click install - #310

Open
tekgnosis-net wants to merge 2 commits into
jamesyc:mainfrom
tekgnosis-net:feature/app-updater
Open

tekgnosis-net wants to merge 2 commits into
jamesyc:mainfrom
tekgnosis-net:feature/app-updater

Conversation

@tekgnosis-net

Copy link
Copy Markdown

First, thank you for TimeCapsuleSMB. Getting modern Samba onto these old Time Capsules with a proper macOS app is a genuinely impressive piece of work, and it revived my own device. This PR is a small contribution back.

What this adds

  • Periodic update checks (on launch plus a configurable interval, default 24h) and a TimeCapsuleSMB → Check for Updates… menu item next to About.
  • A release-notes sheet fed by the GitHub Releases API, with Download, Remind Me Later, and Skip This Version. Required updates (below min_supported_version) cannot be skipped.
  • One-click Install Update: download TimeCapsuleSMB.app.zip, verify the SHA256 against the release asset digest, expand with ditto, check bundle identifier and version, codesign --verify --strict, require the same Team ID as the running app, spctl acceptance, then swap the bundle and relaunch. Quarantine is never modified, so this relies on your releases staying notarized (they are).

Design notes

  • version.json remains the authority for "update available / required"; GitHub only supplies notes and the asset. Implemented as a new update-check helper operation; version-check is untouched.
  • The version and release caches now record their source URL, so changing the metadata URL in Settings takes effect immediately instead of after the 3h TTL. This also fixes the pre-existing Version metadata URL behaviour.
  • All new thresholds are env knobs (TCAPSULE_RELEASE_API_URL, TCAPSULE_RELEASE_TIMEOUT_SECONDS, TCAPSULE_RELEASE_CACHE_SECONDS) or app settings; documented in DETAIL.md and RELEASE.md.
  • Two commits so the install step can be reviewed, or dropped, independently of the check-and-notes step.
  • Translations for the nine non-English tables are machine-assisted; corrections welcome.

Testing

  • Python: make lint, full pytest (1825 passed). Swift: swift test (572 passed) on macOS 26 / Xcode 26.
  • Manual on a MacBook Pro with a packaged build against a local HTTP server serving version.json and a GitHub-shaped latest.json: launch prompt, menu item, Remind Me Later, Skip This Version, required-update variant, and Install Update through download, digest, expansion, bundle and signature checks up to the Team ID gate, where an unsigned local build is correctly refused. The final swap and relaunch could only be exercised with a Developer ID signed build, so I would appreciate a check on your side.

…dates menu item

Add an `update-check` helper operation that combines the existing version.json
check with GitHub Releases metadata (release notes, release page, app zip asset
and its SHA256 digest). The app runs it on launch and on a configurable interval,
shows a release-notes sheet with Download / Remind Me Later / Skip This Version,
and adds "Check for Updates…" under the application menu. Required updates cannot
be skipped. New helper env knobs and app settings are documented in DETAIL.md.
…eeper checks

The update sheet gains Install Update. The app downloads TimeCapsuleSMB.app.zip
from the GitHub release, verifies the SHA256 digest, expands it with ditto,
checks bundle identifier and version, requires a valid Developer ID signature
with the same Team ID as the running app and a passing spctl assessment, then
moves the old bundle to the Trash, moves the new one into place and relaunches.
Quarantine is never modified. Install is unavailable from source checkouts,
read-only locations, ad-hoc builds, or while device operations run; the sheet
falls back to Download in those cases.
@tekgnosis-net

Copy link
Copy Markdown
Author

Rebased on current main (b11f69d); the conflicts were only in the localization tables. Python suite passes; the Swift suite passes except for the 9 Simplified Chinese wording assertions that currently fail on main as well. Context and rationale are written up in #330.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant