Releasing Persyk
Persyk is distributed outside the Mac App Store as a signed DMG containing a notarized application. Releases currently support Apple Silicon only (aarch64-apple-darwin). The permanent release bundle identifier is ai.persyk; the development configuration retains persyk-dev.
Credentials
The release workflow uses these GitHub Actions repository secrets:
APPLE_CERTIFICATE: base64-encoded Developer ID Application certificate and private key exported as a password-protected.p12.APPLE_CERTIFICATE_PASSWORD: password for that export.KEYCHAIN_PASSWORD: password for the temporary CI keychain.APPLE_ID,APPLE_PASSWORD,APPLE_TEAM_ID: Apple ID, app-specific password, and developer team ID for notarization.TAURI_SIGNING_PRIVATE_KEY,TAURI_SIGNING_PRIVATE_KEY_PASSWORD: the updater signing key and its password.
The updater key is separate from Apple code signing. It must match the public key in src-tauri/tauri.conf.json. Preserve and back it up securely: replacing it without a migration prevents existing installations from accepting updates. Never commit private keys or print their values in logs. GitHub only exposes secret names, not their stored values.
Apple Developer agreements must be current. A notarization HTTP 403 mentioning a missing or expired agreement requires the account holder to accept the agreement at https://developer.apple.com/account/.
Local release build
Use Node.js 22, pnpm 11.25.0, the standard Rust toolchain installed through rustup, and Apple’s Xcode or Command Line Tools. Run outside a Nix development shell: inherited compiler/linker flags and DEVELOPER_DIR/SDKROOT can select a Nix SDK or link /nix/store/ libraries into the executable. Use a clean build directory after changing toolchains.
Install your Developer ID Application certificate and private key in the login keychain. Keep its Trust settings at Use System Defaults. The appropriate Apple Developer ID intermediate certificate must also be available. Inspect signing identity names with:
security find-identity -v -p codesigningStart in a clean shell without signing credentials or provider secrets in its environment. Install dependencies and compile from the repository root first:
pnpm install --frozen-lockfilepnpm tauri build --target aarch64-apple-darwin --no-bundle --ci -- --lockedThen load the Apple notarization and updater signing environment variables listed above using your secure credential setup. For local builds using the installed keychain identity, leave APPLE_CERTIFICATE and APPLE_CERTIFICATE_PASSWORD unset; those are only needed for importing the exported certificate in CI. Set APPLE_SIGNING_IDENTITY to the Developer ID Application identity name.
pnpm exec tauri bundle --target aarch64-apple-darwin --bundles app,dmg --ci \ --config '{"build":{"beforeBundleCommand":null}}'bash scripts/verify-macos-release.shThe build signs and notarizes the application, staples Apple’s ticket, creates and signs the DMG, and signs the updater archive. Verification checks the app’s identity and ARM64 architecture, Gatekeeper acceptance, stapled ticket, system-only dynamic dependencies, and the app inside both the updater archive and mounted DMG. It checks that the updater signature file exists; it does not independently verify the Minisign signature against the configured updater public key.
Artifacts appear under src-tauri/target/aarch64-apple-darwin/release/bundle/:
dmg/persyk_<version>_aarch64.dmg: installer for users.macos/persyk.app.tar.gz: updater payload.macos/persyk.app.tar.gz.sig: updater signature.
If CARGO_TARGET_DIR is set, pass the resulting bundle directory to the verifier:
bash scripts/verify-macos-release.sh "$CARGO_TARGET_DIR/aarch64-apple-darwin/release/bundle"To retry packaging/notarization without recompiling after resolving an Apple account issue:
pnpm tauri bundle --target aarch64-apple-darwin --bundles app,dmg --ciTest launch, microphone permissions, recording, and settings on another Mac before public distribution. Artifact verification does not replace that runtime smoke test or a real upgrade from an older version.
GitHub release
Release workflows are restricted to authorized maintainers. Release sources must already be merged into master; unmerged development branches cannot be signed.
- Update versions consistently in
package.json,src-tauri/tauri.conf.json, andsrc-tauri/Cargo.toml; refresh the package entry insrc-tauri/Cargo.lockwith Cargo. - Run the project checks and commit the release changes.
- Push the matching tag, for example
v0.2.0for application version0.2.0. - Wait for the Release workflow to finish successfully. It compiles with a read-only token and no signing secrets, then transfers only the binary and generated schema to an isolated signing job. That job installs bundling tools without dependency scripts, signs without application build hooks, removes its temporary keychain, and verifies the bundles. It prepares all five assets, uploads a draft, and checks the manifest version, final ARM64 URL, uploaded asset names, and signature-file contents.
- Download and smoke-test the draft’s DMG. Check that
latest.jsoncontains the release version, adarwin-aarch64platform entry, and the updater archive URL and signature. - Publish the draft. Do not publish a draft left by a failed workflow.
Manual workflow_dispatch runs with an empty release_tag build and validate without creating a release. Download their files from the workflow’s persyk-macos-arm64 artifact.
To retry a draft using the latest workflow fixes without moving its tag, run the workflow from master and set release_tag to the existing tag (for example v0.2.0). The workflow checks out that tag’s source and validates its version and ancestry. Release helper scripts come from the running workflow’s immutable commit, allowing workflow fixes to be applied to older source tags. It refuses to overwrite a published release.
GitHub exposes temporary untagged-... download URLs for draft assets. The verifier checks the manifest’s final tagged URL against the uploaded asset names instead. Run python3 scripts/test-release-workflow.py to exercise these checks locally; CI also runs these regression tests.
Existing installations check https://github.com/fedirz/persyk/releases/latest/download/latest.json. The website links to the latest published GitHub release; drafts are not selected by that link. Automatic updates require publicly accessible release assets because the updater does not authenticate to GitHub.
Identifier change
Changing from persyk to ai.persyk changes the release application data directory on macOS to ~/Library/Application Support/ai.persyk/. Settings are not automatically migrated. Quit the old app, back up its data, and copy only settings.json5 if needed, reconciling existing configuration first. Sessions now use configurable file-backed roots, defaulting to ~/Documents/persyk/sessions/ (development: ~/Documents/persyk-dev/sessions/). Old databases are not imported; leave old files intact. macOS may request permissions again for the new identity.