Speed up deploy steps: notes first, parallel clients, prompt servers

This commit is contained in:
Ian Gulliver
2026-10-23 09:06:08 -07:00
parent 324c6f8652
commit 41335867ef
+9 -9
View File
@@ -12,22 +12,22 @@ These are requirements, not preferences. Changing one needs the owner's agreemen
A deploy is a release that isn't uploaded: the same notarized disk image, installed on the owner's Macs instead of published. When asked to deploy, do exactly this, from the worktree root: A deploy is a release that isn't uploaded: the same notarized disk image, installed on the owner's Macs instead of published. When asked to deploy, do exactly this, from the worktree root:
1. Run `mac/deploy.sh`. It runs `mac/package.sh` (the build, both notarizations and the disk image, as for a release, into `mac/.build/release/<version>/`), builds the iPhone app with `mac/phone.sh` and uploads it to TestFlight (`docs/iphone.md`), and copies the disk image and `mac/install.sh` to `~/byre-deploy/byre.dmg` and `~/byre-deploy/install.sh`. That copy stays there for installing by hand on Macs that aren't connected. It installs nothing. 1. Before anything else, write the release notes for everything on main since the last release tag (`git describe --tags --abbrev=0` names it), for a byre user in the "Releasing" shape (`## New` and `## Fixed`, each a bullet with a bold short name and what it does or what now works; no `## Install`). Read `git diff <tag>..HEAD`, not just the commit subjects, and leave out changes no user sees. Once the installs start, nothing may sit between one step and the next, so the notes are done by then.
2. Sort the client Macs `list_clients` shows (leaving out the iPhone) by whether they run a byre server of their own: one does when `launchctl print gui/$(id -u)/run.fc.byre` exits 0 there (`client_bash`). Update the app on each one that runs no server, one Mac at a time, through the client tools and without asking first: upload `~/byre-deploy/byre.dmg` and `~/byre-deploy/install.sh` to the same paths there (`client_upload`), then run `~/byre-deploy/install.sh ~/byre-deploy/byre.dmg` there through `client_bash`. It installs, prints the build number and the commit, then quits the app if it is running and reopens it on the new build, which ends the `client_bash` call as the client disconnects while the script carries on. Wait until `list_clients` shows that Mac back on the new build and commit, and report them. Every one of these must be done before any server restarts, since a protocol change can leave an old client unable to reach a new server to be updated. 2. Run `mac/deploy.sh`. It runs `mac/package.sh` (the build, both notarizations and the disk image, as for a release, into `mac/.build/release/<version>/`), builds the iPhone app with `mac/phone.sh` and uploads it to TestFlight (`docs/iphone.md`), and copies the disk image and `mac/install.sh` to `~/byre-deploy/byre.dmg` and `~/byre-deploy/install.sh`. That copy stays there for installing by hand on Macs that aren't connected. It installs nothing.
3. Only then update each client Mac that runs a server, the same way. Its server sees its executable replaced and restarts on the new build. 3. Sort the client Macs `list_clients` shows (leaving out the iPhone) by whether they run a byre server of their own: one does when `launchctl print gui/$(id -u)/run.fc.byre` exits 0 there (`client_bash`). Then, without asking first, update every one that runs no server, all in parallel (one batch of tool calls): upload `~/byre-deploy/byre.dmg` and `~/byre-deploy/install.sh` to the same paths there (`client_upload`), then run `~/byre-deploy/install.sh ~/byre-deploy/byre.dmg` there through `client_bash`. It installs, prints the build number and the commit, then quits the app if it is running and reopens it on the new build, which ends the `client_bash` call as the client disconnects while the script carries on. Don't wait for these Macs to reconnect: after a protocol change the new app can't reach the old servers, so each one stays broken until the servers are updated. They must be updated before any server restarts, since an old client may be unable to reach a new server to be updated.
4. Install on the Mac you run on with `mac/install.sh ~/byre-deploy/byre.dmg`, always as the last action of the turn. The service runs `/Applications/Byre.app/Contents/Helpers/byre`; within 5 seconds it sees that file replaced and exits, and launchd starts the new server and `byre-hands`. Everything is signed with Developer ID, so the macOS privacy grants (Screen Recording, Accessibility, Automation) survive. `install.sh` relaunches its app if it is running, and leaves it closed if not. 4. Immediately after, update every client Mac that runs a server the same way, in parallel. Its server sees its executable replaced and restarts on the new build.
5. When you resume, confirm it came up: read the tail of `~/Library/Logs/byre.log`, and `GET /api/tailnet` at the loopback address (`byre check` prints it as `loopback`), whose `state` must be `Running`. Report the new build number first (`plutil -extract CFBundleVersion raw /Applications/Byre.app/Contents/Info.plist` prints it; it is the Unix time of the build, and the iPhone build uploaded to TestFlight has its own, a few minutes later), then what you deployed and what you checked. 5. Immediately after that, install on the Mac you run on with `mac/install.sh ~/byre-deploy/byre.dmg`. The service runs `/Applications/Byre.app/Contents/Helpers/byre`; within 5 seconds it sees that file replaced and exits, and launchd starts the new server and `byre-hands`. Everything is signed with Developer ID, so the macOS privacy grants (Screen Recording, Accessibility, Automation) survive. `install.sh` relaunches its app if it is running, and leaves it closed if not.
6. End the report with release notes for everything on main since the last release tag (`git describe --tags --abbrev=0` names it), written for a byre user in the "Releasing" shape (`## New` and `## Fixed`, each a bullet with a bold short name and what it does or what now works; no `## Install`). Read `git diff <tag>..HEAD`, not just the commit subjects, and leave out changes no user sees. 6. Confirm it came up: read the tail of `~/Library/Logs/byre.log`, and `GET /api/tailnet` at the loopback address (`byre check` prints it as `loopback`), whose `state` must be `Running`. Check that `list_clients` shows every updated Mac back on the new build and commit. Report the new build number first (`plutil -extract CFBundleVersion raw /Applications/Byre.app/Contents/Info.plist` prints it; it is the Unix time of the build, and the iPhone build uploaded to TestFlight has its own, a few minutes later), then what you deployed and what you checked, and end with the release notes from step 1.
Deploying means building with `mac/deploy.sh` on the Mac you run on. Never stand in for it by running `mac/package.sh` yourself, not even to build once for several Macs. Every Mac, this one included, gets the disk image `mac/deploy.sh` left in `~/byre-deploy/`. Deploying means building with `mac/deploy.sh` on the Mac you run on. Never stand in for it by running `mac/package.sh` yourself, not even to build once for several Macs. Every Mac, this one included, gets the disk image `mac/deploy.sh` left in `~/byre-deploy/`.
Check each server (this Mac's and each client Mac's from step 3) with the bearer token in `~/Library/Application Support/byre/loopback-token`: `GET https://byre-<host>.tailcecab.ts.net/api/tailnet` (`state` is `Running`) and `/api/admin/status` (report zombies, protocol errors, rate limits). The loopback address serves `/api/tailnet` but not `/api/admin/status`. Check each server (this Mac's and each client Mac's from step 4) with the bearer token in `~/Library/Application Support/byre/loopback-token`: `GET https://byre-<host>.tailcecab.ts.net/api/tailnet` (`state` is `Running`) and `/api/admin/status` (report zombies, protocol errors, rate limits). The loopback address serves `/api/tailnet` but not `/api/admin/status`.
What to expect: What to expect:
- The notarizations take a minute or two each; `notarytool` prints "In Progress" until "Accepted". A rejection stops the script before anything is installed; `xcrun notarytool log <id> --keychain-profile byre-notary` says why. - The notarizations take a minute or two each; `notarytool` prints "In Progress" until "Accepted". A rejection stops the script before anything is installed; `xcrun notarytool log <id> --keychain-profile byre-notary` says why.
- You run inside byre, so the restart kills your own turn just after the install. That is expected, not a reason to skip it. You resume with a "byre restarted while you were mid-turn" message; do the checks then, and confirm the service started after your install (the log shows `executable replaced, exiting` just before it). - You run inside byre, so this Mac's restart interrupts your turn, and the new server wakes you again at once with a "byre restarted while you were mid-turn" message. Carry on with step 6: confirm the service started after your install (the log shows `executable replaced, exiting` just before the last `listening` line).
- The restart can cut off the record of the last tool call, so you may resume with no memory of having deployed. Before concluding that another agent restarted byre, compare the service's start time (the last `listening` line in the log) with when you ran `mac/install.sh`: a restart within seconds of it is most likely your install. If byre restarts without your install, another agent deployed its own branch, and the running build is theirs. - If byre restarts without your install, another agent deployed its own branch, and the running build is theirs.
## Releasing ## Releasing