From e1eeaad925ef214383a99411c39ddaad27f9e00e Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Thu, 22 Oct 2026 07:19:28 -0700 Subject: [PATCH] Use one build number across phone, Mac and Status --- AGENTS.md | 4 +- api/openapi.yaml | 3 +- docs/iphone.md | 2 +- docs/operations.md | 2 +- internal/agents/clients.go | 2 +- internal/api/api.gen.go | 699 +++++++++++++++++----------------- internal/clients/clients.go | 18 +- internal/server/clients.go | 4 +- internal/server/server.go | 3 +- mac/Sources/Byre/API.swift | 1 + mac/Sources/Byre/Status.swift | 2 +- mac/bundle.sh | 2 +- mac/install.sh | 1 + mac/phone.sh | 2 +- 14 files changed, 377 insertions(+), 368 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cac7327..488b899 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,8 +13,8 @@ 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: 1. Run `mac/deploy.sh`, always as the last action of the turn. It runs `mac/package.sh` (the build, both notarizations and the disk image, as for a release, into `mac/.build/release//`), builds the iPhone app with `mac/phone.sh` and uploads it to TestFlight (`docs/iphone.md`), and installs the image's app as `/Applications/Byre.app` with `mac/install.sh`. 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. -2. 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 what you deployed and what you checked. -3. Once the service is confirmed healthy, update each client Mac whose app is running, through the client tools and without asking first: upload the disk image (`mac/.build/release//byre-.dmg`) and `mac/install.sh`, quit the app, run `install.sh `, and `open /Applications/Byre.app`. The app reads its server address from its iCloud-synced SwiftData store, so it reconnects to prod with no setup. Report each Mac's app commit (`install.sh` prints it). +2. 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; the iPhone build uploaded to TestFlight has the same one), then what you deployed and what you checked. +3. Once the service is confirmed healthy, update each client Mac whose app is running, through the client tools and without asking first: upload the disk image (`mac/.build/release//byre-.dmg`) and `mac/install.sh`, quit the app, run `install.sh `, and `open /Applications/Byre.app`. The app reads its server address from its iCloud-synced SwiftData store, so it reconnects to prod with no setup. Report each Mac's build number (`install.sh` prints it, then the commit). 4. 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 ..HEAD`, not just the commit subjects, and leave out changes no user sees. Deploying means running `mac/deploy.sh` on iso. Never stand in for it by running `mac/package.sh` and `mac/install.sh` yourself, not even to build once for several Macs. Every other Mac gets the disk image `mac/deploy.sh` built, after iso is confirmed healthy (step 3). diff --git a/api/openapi.yaml b/api/openapi.yaml index b65de1c..c0c1d2d 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -2312,13 +2312,14 @@ components: ConnectedClient: type: object - required: [id, login, host, device, commit, connected_at] + required: [id, login, host, device, commit, build, connected_at] properties: id: { type: string, description: The ID the app made up when it started, from its Byre-Client header. } login: { type: string } host: { type: string, description: The device's name from its Byre-Host header. } device: { type: string, description: "The kind of device the app runs on (Mac or iPhone), from its Byre-Device header." } commit: { type: string, description: The git commit the app was built from, from its Byre-Commit header; empty when the client sent none. } + build: { type: string, description: "The app's build number (its CFBundleVersion, the Unix time of that commit), from its Byre-Build header; empty when the client sent none." } connected_at: { type: string, format: date-time, description: When the client's WebSocket connected. } last_action_at: { type: string, format: date-time, description: When byre last received a request the human made from this client since byre started; absent when none. } sync: { $ref: "#/components/schemas/ClientSync" } diff --git a/docs/iphone.md b/docs/iphone.md index 8fba1bf..4682c00 100644 --- a/docs/iphone.md +++ b/docs/iphone.md @@ -8,7 +8,7 @@ Left out on the phone: the Server tab and running byre locally, the shell, file, ## Building -`mac/phone.sh` builds the app with `xcodebuild` (a Swift package can't be built for iOS by `swift build`) in the same shared directory and under the same lock as `mac/bundle.sh`, assembles `Byre.app` itself (icon through `actool`, fonts, `Info.plist` from `mac/phone/Info.plist` plus the version, commit and `DT*` keys App Store Connect checks), signs it ad hoc with `mac/phone/byre.entitlements`, and wraps it in `mac/.build/phone/iphoneos/Byre.xcarchive`. Release only, like the Mac app. `xcodebuild -exportArchive -archivePath -exportOptionsPlist mac/phone/export.plist -exportPath -allowProvisioningUpdates` re-signs it for the App Store and uploads it to TestFlight, using the Apple account Xcode is signed into: Xcode makes the distribution certificate and profile itself, so none are kept in the repo. Uploading needs the App ID `run.fc.byre.ios` (iCloud with the container `iCloud.run.fc.byre.mac`, and Push Notifications) and its app record in App Store Connect; neither can be made through Apple's API. The version is the last release tag's (App Store Connect takes only numbers) and the build number the UTC build time, `YYYYMMDD.HHMMSS`: App Store Connect refuses a build number that isn't higher than every earlier upload, and a commit count can go down when a branch with many commits uploads before its squash merge lands on main. +`mac/phone.sh` builds the app with `xcodebuild` (a Swift package can't be built for iOS by `swift build`) in the same shared directory and under the same lock as `mac/bundle.sh`, assembles `Byre.app` itself (icon through `actool`, fonts, `Info.plist` from `mac/phone/Info.plist` plus the version, commit and `DT*` keys App Store Connect checks), signs it ad hoc with `mac/phone/byre.entitlements`, and wraps it in `mac/.build/phone/iphoneos/Byre.xcarchive`. Release only, like the Mac app. `xcodebuild -exportArchive -archivePath -exportOptionsPlist mac/phone/export.plist -exportPath -allowProvisioningUpdates` re-signs it for the App Store and uploads it to TestFlight, using the Apple account Xcode is signed into: Xcode makes the distribution certificate and profile itself, so none are kept in the repo. Uploading needs the App ID `run.fc.byre.ios` (iCloud with the container `iCloud.run.fc.byre.mac`, and Push Notifications) and its app record in App Store Connect; neither can be made through Apple's API. The version is the last release tag's (App Store Connect takes only numbers) and the build number is the Mac app's (`docs/operations.md`, "Releases"). App Store Connect refuses a build number that isn't higher than every earlier upload, so a second upload of the same commit fails; a commit count wouldn't do, since it can go down when a branch with many commits uploads before its squash merge lands on main. `mac/phone.sh --simulator` builds an ad-hoc-signed app for the iOS simulator instead, at `mac/.build/phone/iphonesimulator/Byre.app`; install it with `xcrun simctl install ` and start it with `xcrun simctl launch run.fc.byre.ios`. The simulator ignores entitlements given to `codesign` and refuses to launch an ad-hoc app signed with restricted ones, so the script links `mac/phone/byre.entitlements` into the binary's `__TEXT,__entitlements` section, as Xcode does; without the iCloud entitlement CloudKit raises at launch. Its node signs in to Tailscale like any other: `xcrun simctl launch --console-pty` prints libtailscale's sign-in URL, which changes on every launch. diff --git a/docs/operations.md b/docs/operations.md index 0884dca..9a956f1 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -36,7 +36,7 @@ Each preview gets its own port on byre's node rather than a path under byre's or ## Releases -A release is one notarized disk image, `byre-.dmg`, holding `Byre.app` with the server, `byre-hands` and `byre-update` in `Contents/Helpers`. Images are served from `https://dl.byre.run/`; each release's notes are on `https://g.fc.run/ai/byre/releases`. `mac/package.sh` builds one, `mac/deploy.sh` installs it locally (see `AGENTS.md`, "Deploying"), and `mac/release.sh ` publishes it from a clean checkout at a pushed `v` tag. A deployed build's `CFBundleVersion` is at least the last release's, so the updater never offers to go back to it. +A release is one notarized disk image, `byre-.dmg`, holding `Byre.app` with the server, `byre-hands` and `byre-update` in `Contents/Helpers`. Images are served from `https://dl.byre.run/`; each release's notes are on `https://g.fc.run/ai/byre/releases`. `mac/package.sh` builds one, `mac/deploy.sh` installs it locally (see `AGENTS.md`, "Deploying"), and `mac/release.sh ` publishes it from a clean checkout at a pushed `v` tag. The build number (`CFBundleVersion`) of both the Mac and iPhone apps is the Unix time of the commit they were built from (`git log -1 --format=%ct`), so one deploy's apps share it; the apps send it in their `Byre-Build` header and the Status tab's client list shows it. A deployed build's `CFBundleVersion` is at least the last release's, so the updater never offers to go back to it. The appcast must never name an image that isn't available yet, and a published g.fc.run release must already have its attachments. If a failed release run leaves a draft on the releases page, delete it there before running again. diff --git a/internal/agents/clients.go b/internal/agents/clients.go index b8d080f..beeea23 100644 --- a/internal/agents/clients.go +++ b/internal/agents/clients.go @@ -296,7 +296,7 @@ func (m *Manager) listClients() string { } else { fmt.Fprintf(b, "last action %s ago", now.Sub(*r.LastActionAt).Round(time.Second)) } - fmt.Fprintf(b, ", connected %s ago, app built from %s", now.Sub(r.ConnectedAt).Round(time.Second), r.Commit) + fmt.Fprintf(b, ", connected %s ago, app build %s from %s", now.Sub(r.ConnectedAt).Round(time.Second), r.Build, r.Commit) if r.Sync != nil && !r.Sync.Ok { fmt.Fprintf(b, ", iCloud sync failing since %s ago: %s", now.Sub(r.Sync.At).Round(time.Second), *r.Sync.Error) } diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index 5e743d6..6a2a54a 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -882,6 +882,9 @@ type CompactCreate struct { // ConnectedClient defines model for ConnectedClient. type ConnectedClient struct { + // Build The app's build number (its CFBundleVersion, the Unix time of that commit), from its Byre-Build header; empty when the client sent none. + Build string `json:"build"` + // Commit The git commit the app was built from Commit string `json:"commit"` @@ -4793,354 +4796,354 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "H/+/AQA=", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/clients/clients.go b/internal/clients/clients.go index d056fc1..ba6774e 100644 --- a/internal/clients/clients.go +++ b/internal/clients/clients.go @@ -33,6 +33,7 @@ type Client struct { Login string Host string Commit string + Build string Device string ConnectedAt time.Time LastActionAt *time.Time @@ -70,7 +71,7 @@ func New(changed func()) *Registry { return &Registry{clients: map[string]*entry{}, transfers: map[string]Transfer{}, changed: changed} } -func (r *Registry) entry(id, login, host, commit string, now time.Time) *entry { +func (r *Registry) entry(id, login, host, commit, build string, now time.Time) *entry { for k, e := range r.clients { if e.conn == nil && now.Sub(e.seen) > expireAfter { delete(r.clients, k) @@ -84,18 +85,19 @@ func (r *Registry) entry(id, login, host, commit string, now time.Time) *entry { e.Login = login e.Host = host e.Commit = commit + e.Build = build e.seen = now return e } -func (r *Registry) Acted(id, login, host, commit string) bool { +func (r *Registry) Acted(id, login, host, commit, build string) bool { if id == "" { return false } r.mu.Lock() defer r.mu.Unlock() now := time.Now() - e := r.entry(id, login, host, commit, now) + e := r.entry(id, login, host, commit, build, now) e.LastActionAt = &now if now.Sub(e.notified) < time.Second { return false @@ -104,19 +106,19 @@ func (r *Registry) Acted(id, login, host, commit string) bool { return true } -func (r *Registry) Synced(id, login, host, commit string, sync api.ClientSync) { +func (r *Registry) Synced(id, login, host, commit, build string, sync api.ClientSync) { r.mu.Lock() defer r.mu.Unlock() - r.entry(id, login, host, commit, time.Now()).Sync = &sync + r.entry(id, login, host, commit, build, time.Now()).Sync = &sync } -func (r *Registry) Serve(ctx context.Context, ws *websocket.Conn, id, login, host, commit, device string) { +func (r *Registry) Serve(ctx context.Context, ws *websocket.Conn, id, login, host, commit, build, device string) { ws.SetReadLimit(readLimit) c := &conn{ws: ws, done: make(chan struct{}), pending: map[string]chan api.ClientReply{}} r.mu.Lock() now := time.Now().UTC() - e := r.entry(id, login, host, commit, now) + e := r.entry(id, login, host, commit, build, now) old := e.conn e.conn = c e.Device = device @@ -125,7 +127,7 @@ func (r *Registry) Serve(ctx context.Context, ws *websocket.Conn, id, login, hos if old != nil { old.ws.Close(websocket.StatusGoingAway, "replaced by a newer connection from this client") } - slog.Info("client connected", "id", id, "host", host, "device", device, "login", login, "commit", commit) + slog.Info("client connected", "id", id, "host", host, "device", device, "login", login, "build", build, "commit", commit) r.changed() defer func() { diff --git a/internal/server/clients.go b/internal/server/clients.go index 3f62b96..47560df 100644 --- a/internal/server/clients.go +++ b/internal/server/clients.go @@ -35,7 +35,7 @@ func (s *Server) ConnectClient(w http.ResponseWriter, r *http.Request) { } defer ws.CloseNow() - s.clients.Serve(r.Context(), ws, id, actor(r), host, r.Header.Get("Byre-Commit"), r.Header.Get("Byre-Device")) + s.clients.Serve(r.Context(), ws, id, actor(r), host, r.Header.Get("Byre-Commit"), r.Header.Get("Byre-Build"), r.Header.Get("Byre-Device")) } func (s *Server) SetClientSync(w http.ResponseWriter, r *http.Request) { @@ -58,7 +58,7 @@ func (s *Server) SetClientSync(w http.ResponseWriter, r *http.Request) { } slog.Warn("client icloud sync failing", "id", id, "host", host, "error", *sync.Error) } - s.clients.Synced(id, actor(r), host, r.Header.Get("Byre-Commit"), sync) + s.clients.Synced(id, actor(r), host, r.Header.Get("Byre-Commit"), r.Header.Get("Byre-Build"), sync) s.clientsChanged() w.WriteHeader(http.StatusNoContent) } diff --git a/internal/server/server.go b/internal/server/server.go index 51b02f5..681f08b 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -200,7 +200,7 @@ func (s *Server) identify(next http.Handler) http.Handler { } func (s *Server) acted(login string, r *http.Request) { - if s.clients.Acted(r.Header.Get("Byre-Client"), login, r.Header.Get("Byre-Host"), r.Header.Get("Byre-Commit")) { + if s.clients.Acted(r.Header.Get("Byre-Client"), login, r.Header.Get("Byre-Host"), r.Header.Get("Byre-Commit"), r.Header.Get("Byre-Build")) { s.clientsChanged() } } @@ -214,6 +214,7 @@ func (s *Server) connectedClients() []api.ConnectedClient { Host: c.Host, Device: c.Device, Commit: c.Commit, + Build: c.Build, ConnectedAt: c.ConnectedAt, LastActionAt: c.LastActionAt, Sync: c.Sync, diff --git a/mac/Sources/Byre/API.swift b/mac/Sources/Byre/API.swift index 1947bb4..68bcbb9 100644 --- a/mac/Sources/Byre/API.swift +++ b/mac/Sources/Byre/API.swift @@ -116,6 +116,7 @@ final class API: Sendable { self.origin = origin let config = URLSessionConfiguration.default config.httpAdditionalHeaders = [ + "Byre-Build": Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String, "Byre-Client": clientID, "Byre-Commit": Bundle.main.object(forInfoDictionaryKey: "ByreCommit") as! String, "Byre-Device": deviceKind, diff --git a/mac/Sources/Byre/Status.swift b/mac/Sources/Byre/Status.swift index 31303bc..bf40d09 100644 --- a/mac/Sources/Byre/Status.swift +++ b/mac/Sources/Byre/Status.swift @@ -499,7 +499,7 @@ private struct ClientTable: View { } private func build(_ c: ConnectedClient) -> String { - c.commit.isEmpty ? "—" : String(c.commit.prefix(8)) + c.build.isEmpty ? "—" : c.build } } diff --git a/mac/bundle.sh b/mac/bundle.sh index 8335b01..feddb3a 100755 --- a/mac/bundle.sh +++ b/mac/bundle.sh @@ -49,7 +49,7 @@ ditto "$build/TailscaleKit.framework" "$app/Contents/Frameworks/TailscaleKit.fra cp "$mac/Info.plist" "$app/Contents/Info.plist" plutil -insert ByreCommit -string "$(git -C "$root" rev-parse HEAD)" "$app/Contents/Info.plist" plutil -insert CFBundleShortVersionString -string "$version" "$app/Contents/Info.plist" -plutil -insert CFBundleVersion -string "$(git -C "$root" rev-list --count HEAD)" "$app/Contents/Info.plist" +plutil -insert CFBundleVersion -string "$(git -C "$root" log -1 --format=%ct)" "$app/Contents/Info.plist" cp "$mac"/fonts/*.woff2 "$app/Contents/Resources/fonts/" cp "$icns" "$app/Contents/Resources/byre.icns" cp "$mac/byre.provisionprofile" "$app/Contents/embedded.provisionprofile" diff --git a/mac/install.sh b/mac/install.sh index dd1837b..2d728b1 100755 --- a/mac/install.sh +++ b/mac/install.sh @@ -8,4 +8,5 @@ ditto "$mount/Byre.app" /Applications/Byre.app.new hdiutil detach "$mount" rm -rf /Applications/Byre.app mv /Applications/Byre.app.new /Applications/Byre.app +plutil -extract CFBundleVersion raw /Applications/Byre.app/Contents/Info.plist plutil -extract ByreCommit raw /Applications/Byre.app/Contents/Info.plist diff --git a/mac/phone.sh b/mac/phone.sh index b42559f..e209231 100755 --- a/mac/phone.sh +++ b/mac/phone.sh @@ -40,7 +40,7 @@ plutil -insert CFBundleIcons -xml "$(plutil -extract CFBundleIcons xml1 -o - "$b plutil -insert ByreCommit -string "$(git -C "$root" rev-parse HEAD)" "$plist" version=$(git -C "$root" describe --tags --abbrev=0) plutil -insert CFBundleShortVersionString -string "${version#v}" "$plist" -plutil -insert CFBundleVersion -string "$(date -u +%Y%m%d.%H%M%S)" "$plist" +plutil -insert CFBundleVersion -string "$(git -C "$root" log -1 --format=%ct)" "$plist" platform=$(xcrun --sdk "$sdk" --show-sdk-platform-version) sdkbuild=$(xcrun --sdk "$sdk" --show-sdk-build-version) plutil -insert CFBundleSupportedPlatforms -xml "$(if [ "$sdk" = iphoneos ]; then echo iPhoneOS; else echo iPhoneSimulator; fi)" "$plist"