112 lines
4 KiB
Markdown
112 lines
4 KiB
Markdown
# Release
|
|
|
|
`@mac-sync` ships three artefacts: the Mac client, the server, and the web
|
|
SPA. They are deployed independently.
|
|
|
|
## Version source
|
|
|
|
`VERSION.json` at the repo root is the canonical version. `app.manifest.yaml:5`
|
|
duplicates it for the manage-apps CLI. Bump both together.
|
|
|
|
## Mac client — `MacSyncApp`
|
|
|
|
Build (release):
|
|
|
|
```sh
|
|
make build-release # Makefile:63-65 -> swift build -c release --product MacSyncApp
|
|
```
|
|
|
|
Output: `.build/release/MacSyncApp`. The binary is a menu-bar executable; for
|
|
distribution wrap it as a `.app` bundle including:
|
|
|
|
- The binary itself
|
|
- A `webapp/` resource directory built from `web/dist/`
|
|
(`LocalWebServer.swift:138-141` looks here first)
|
|
- Info.plist with `LSUIElement=true` (menu-bar only)
|
|
- Privacy usage strings: `NSCalendarsFullAccessUsageDescription`,
|
|
`NSRemindersFullAccessUsageDescription`, `NSAppleEventsUsageDescription`,
|
|
`NSPhotoLibraryUsageDescription`, plus Full Disk Access via signed entitlement
|
|
|
|
The user instals through `deploy/install.sh` and a LaunchAgent
|
|
(`app.manifest.yaml:20-22`):
|
|
|
|
```sh
|
|
ssh plum 'bash -s' < deploy/install.sh
|
|
```
|
|
|
|
Or via the manage-apps CLI (`app.manifest.yaml:24-30`):
|
|
|
|
```sh
|
|
manage-apps start mac-sync plum # runs deploy/deploy-remote.sh
|
|
manage-apps stop mac-sync plum # launchctl unload
|
|
manage-apps status mac-sync # ssh plum 'pgrep -x MacSyncApp'
|
|
manage-apps logs mac-sync # tail of ~/Library/Application Support/MacSync/stderr.log
|
|
```
|
|
|
|
## Server — `mac-sync-server`
|
|
|
|
Build is implicit (Bun runs TypeScript directly). The systemd unit lives in
|
|
`deploy/systemd/` and is referenced by `app.manifest.yaml:42-44`.
|
|
|
|
```sh
|
|
manage-apps start mac-sync black # deploy/deploy-server.sh
|
|
manage-apps status mac-sync black # curl http://localhost:3201/health
|
|
manage-apps logs mac-sync black # journalctl -u mac-sync-server
|
|
manage-apps stop mac-sync black # sudo systemctl stop mac-sync-server
|
|
```
|
|
|
|
Migrations apply automatically on boot
|
|
(`src/server/src/app/server.ts:36-52`). To verify a fresh deploy:
|
|
|
|
```sh
|
|
curl http://10.0.0.11:3201/health/deep
|
|
# {"ok":true,"checks":{"db":"ok"}}
|
|
```
|
|
|
|
Environment is loaded by `loadConfig()` (`src/server/src/app/config.ts`);
|
|
required vars are documented in [dev-setup](./dev-setup.md#boot-the-server).
|
|
|
|
## Web SPA
|
|
|
|
Two distribution paths:
|
|
|
|
1. **Bundled with the Mac client.** Run `cd web && bun run build` before
|
|
`make build-release`; copy `web/dist/` into the `.app` bundle's
|
|
`webapp/` resource directory. Served at `http://localhost:8765/` by
|
|
`LocalWebServer` (`@packages/shared/Sources/MacSyncShared/WebServer/LocalWebServer.swift:94-109`).
|
|
|
|
2. **Hosted by the server.** The nginx config in `deploy/nginx/` (referenced
|
|
from the deploy scripts) can serve `web/dist/` from the same origin as the
|
|
API.
|
|
|
|
```sh
|
|
cd web
|
|
bun install
|
|
bun run build # tsc --noEmit && vite build (web/package.json:8)
|
|
```
|
|
|
|
Output goes to `web/dist/`. Verify with `bun run preview`.
|
|
|
|
## Rollback
|
|
|
|
- Mac client: previous `.app` bundle is preserved alongside the new one on
|
|
`plum`; relaunch via `launchctl load`.
|
|
- Server: `sudo systemctl restart mac-sync-server` after reverting the
|
|
source tree. Migrations are forward-only — see Caveats below.
|
|
- Web: redeploy the previous `web/dist/`. The bundle is fingerprinted by
|
|
Vite, so cache invalidation is automatic.
|
|
|
|
## Caveats
|
|
|
|
- **Migrations are forward-only.** `runMigrations(db, [...])`
|
|
(`src/server/src/app/server.ts:36-52`) appends; there is no `down` script.
|
|
A schema-breaking change requires manual SQL on the database.
|
|
- **iMessage `icloud.send_queue` is on a bespoke schema.** Versioning it is
|
|
independent of the generic per-module tables. Don't drop and recreate it on
|
|
a release — outgoing messages will be lost.
|
|
- **The Mac client retains `UserDefaults` watermarks across releases.** If a
|
|
release changes the inbound payload shape, bump `SyncManager.syncSchemaVersion`
|
|
(`@packages/imessage/Sources/IMessageSync/SyncManager.swift:47` for iMessage)
|
|
so the bootstrap resets the watermark.
|
|
- **Don't commit from a release script.** External tooling owns commits
|
|
(`CLAUDE.md:46`).
|