feat(macos): Ulk.app v0.3 — Sparkle 2.x + tag-triggered release pipeline#148
feat(macos): Ulk.app v0.3 — Sparkle 2.x + tag-triggered release pipeline#148
Conversation
Replaces the GitHub-API stub UpdateChecker with a real Sparkle 2.x integration. UpdateChecker is now a SwiftUI-friendly facade over SPUStandardUpdaterController that surfaces six states (idle, checking, upToDate, updateAvailable, downloading, readyToInstall, failed) via @published — DashboardShell sidebar binds directly to those. - project.yml : adds sparkle-project/Sparkle ≥ 2.6 SPM package and declares it as a dependency of the Ulk app target. Bumps MARKETING_VERSION to 0.3.0 / CURRENT_PROJECT_VERSION to 3. - Package.swift : same Sparkle dep on UlkCore so the SPM CI job that syntax-checks the library still builds (UpdateChecker imports Sparkle). - UpdateChecker.swift : rewritten as ObservableObject + NSObject conforming to SPUUpdaterDelegate. Exposes checkNow() (user-triggered) and checkInBackground() (silent at launch). Delegate callbacks are nonisolated and hop to @mainactor before mutating state. bundleVersion helper is nonisolated static for thread safety. - DashboardShell.swift : sidebar update badge handles the two new states (downloading with progress + readyToInstall with restart hint). Real release pipeline lives in scripts/sign-and-notarize.sh and .github/workflows/macos-release.yml — see README for the 7 GitHub secrets to configure. https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
Two scripts that produce a publishable Ulk.app DMG: - scripts/sign-and-notarize.sh — xcodegen → xcodebuild archive → exportArchive (developer-id) → create-dmg → codesign → notarytool submit --wait → stapler staple → sign with Sparkle EdDSA key. Reads APPLE_TEAM_ID, APPLE_SIGNING_IDENTITY, APPLE_NOTARY_PROFILE, SPARKLE_PRIVATE_KEY_FILE from env. - scripts/generate-appcast.sh — appends a fully-formed Sparkle 2 <item> to site/public/appcast.xml using a Python helper for safe XML edits (regex + str.replace are too brittle for nested CDATA notes). Pulls the Sparkle signature from the .eddsa sidecar produced above. Both scripts are idempotent and can be invoked locally or by the new .github/workflows/macos-release.yml workflow (next commit). https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
Pushing a tag matching macos-v* (e.g. macos-v0.3.0) now triggers a full
end-to-end release on macos-14 :
1. Resolve version from tag (or workflow_dispatch input)
2. Install xcodegen + create-dmg
3. Import .p12 cert into a temporary keychain (APPLE_CERTIFICATE_BASE64
+ APPLE_CERTIFICATE_PASSWORD)
4. Store notary credentials via xcrun notarytool store-credentials
(APPLE_NOTARY_APPLE_ID + APPLE_NOTARY_APP_SPECIFIC_PASSWORD +
APPLE_TEAM_ID)
5. Decode Sparkle private key from SPARKLE_PRIVATE_KEY (base64)
6. Run scripts/sign-and-notarize.sh → produces signed DMG + .eddsa
7. Run scripts/generate-appcast.sh → updates site/public/appcast.xml
8. Publish GitHub release with DMG, .eddsa and appcast as assets
9. Open a chore/appcast-<version> PR with the updated appcast so the
site (Astro static at https://ulk.regrets.app) deploys the new feed
site/public/appcast.xml seeded as an empty Sparkle 2 RSS skeleton ;
each release inserts a new <item> right after the <description>.
Required GitHub Secrets are documented in workflow comments and in
apps/macos/Ulk/README.md (Release pipeline section).
https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
- README : new "Auto-update (Sparkle 2.x)" + "Release pipeline" sections detailing the 7 GitHub Secrets, how to generate the EdDSA keypair with Sparkle's generate_keys tool, how to cut a release (`git tag macos-v0.3.0 && git push`), and how to do a manual local release as a fallback. - Spec card : v0.3 roadmap entry promoted to "in this branch" with full checklist done ; v0.4+ section absorbs the post-MVP extras formerly labelled v1.0 (settings.json editor, accountability viewer, Cloud Routines / Managed Agents tabs, plus deferred MCP/CLI toggles). https://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
|
Warning Rate limit exceeded
To continue reviewing without waiting, purchase usage credits in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
v0.3 — l'app a maintenant un vrai auto-update Sparkle + un pipeline release CI signé/notarié de bout en bout. Quatre commits atomiques :
feat(macos)— Sparkle 2.6+ ajouté en SPM (project.yml + Package.swift) ;UpdateCheckerréécrit comme façade SwiftUI au-dessus deSPUStandardUpdaterController/SPUUpdaterDelegate;DashboardShellsidebar gère les nouveaux états (download progress + restart-to-install)build(macos)—scripts/sign-and-notarize.sh(xcodebuild → DMG → notarytool wait → stapler → sign Sparkle) +scripts/generate-appcast.sh(append d'un<item>àsite/public/appcast.xmlvia Python)ci(macos)—.github/workflows/macos-release.ymltriggered par tagmacos-v*: import certif, store notary, run pipeline, publish GitHub release, ouvre une PR pour le site avec le nouvel appcastdocs(macos)— README : runbook complet + 7 GitHub Secrets requis + génération keypair EdDSA ; CARD.md changelog v0.3Pour activer le pipeline (côté toi)
Configurer les 7 secrets GitHub (Settings → Secrets and variables → Actions) — détaillé dans
apps/macos/Ulk/README.md§ Release pipeline :APPLE_TEAM_IDAPPLE_SIGNING_IDENTITYsecurity find-identity -v -p codesigningAPPLE_CERTIFICATE_BASE64.p12depuis Keychain Access →base64 -i cert.p12APPLE_CERTIFICATE_PASSWORDAPPLE_NOTARY_APPLE_IDAPPLE_NOTARY_APP_SPECIFIC_PASSWORDSPARKLE_PRIVATE_KEYgenerate_keysSparkle → export keychain →base64 -i ed25519_priv.pemUne fois en place, clé publique Sparkle à coller dans
apps/macos/Ulk/Ulk/Resources/Info.plist(SUPublicEDKey, actuellement placeholder).Couper la première release
Architecture
Test plan
SwiftPM build + testpasse (Sparkle SPM resolve → UlkCore link → tests pass)XcodeGen + xcodebuildpasse (Sparkle SPM resolve dans Xcode → app build sans signing)macos-v0.3.0-rc1, vérifier GitHub release + PR appcastLimites assumées
Ulk.appdirect (on notarise le DMG, ça notarise tout dedans)Note sur les rouges attendus
Spec :
docs/backlog/2026-05-06-FEATURE-MACOS-COMPANION-APP/CARD.mdhttps://claude.ai/code/session_01TyhPjizanX1g8xSQ6chwTu
Generated by Claude Code