This document covers the repeatable macOS release path for ChaosEngineAI's native desktop bundle.
releases/macos/ChaosEngineAI.appreleases/macos/ChaosEngineAI_<version>_aarch64.dmg
npm run release:macosThe release scripts automatically read .env and .env.local if present.
The release script performs these steps:
- Builds the production frontend and native Tauri app bundle.
- Stages the embedded Python, MLX, and llama.cpp runtime archive.
- Signs embedded runtime binaries when a signing identity is configured.
- Copies the built
.appintoreleases/macos/. - Signs and verifies the
.appwhen a signing identity is configured. - Creates a distribution DMG with an
Applicationsshortcut. - Signs, notarizes, staples, and validates the DMG when Apple credentials are configured.
Set one of these before running npm run release:macos:
CHAOSENGINE_APPLE_SIGNING_IDENTITYAPPLE_SIGNING_IDENTITY
Typical value:
export CHAOSENGINE_APPLE_SIGNING_IDENTITY="Developer ID Application: Your Company, Inc. (TEAMID1234)"The script supports three authentication styles, in this order:
- Keychain profile
- App Store Connect API key
- Apple ID + app-specific password
Recommended for local release work.
xcrun notarytool store-credentials chaosengine-notary \
--apple-id "you@example.com" \
--team-id "TEAMID1234" \
--password "app-specific-password"
export CHAOSENGINE_NOTARY_KEYCHAIN_PROFILE="chaosengine-notary"export CHAOSENGINE_APPLE_API_KEY_ID="ABC123DEFG"
export CHAOSENGINE_APPLE_API_KEY_PATH="/absolute/path/AuthKey_ABC123DEFG.p8"
export CHAOSENGINE_APPLE_API_ISSUER="00000000-0000-0000-0000-000000000000"The script also accepts Tauri-compatible aliases:
APPLE_API_KEYAPPLE_API_KEY_PATHAPPLE_API_ISSUER
export CHAOSENGINE_APPLE_ID="you@example.com"
export CHAOSENGINE_APPLE_PASSWORD="app-specific-password"
export CHAOSENGINE_APPLE_TEAM_ID="TEAMID1234"--skip-sign: build unsigned artifacts--skip-notarize: sign artifacts but skip notarizationCHAOSENGINE_SKIP_NOTARIZE=1: env alternative to--skip-notarize
Examples:
npm run release:macos -- --skip-signCHAOSENGINE_SKIP_NOTARIZE=1 npm run release:macos- Confirm
python3 -m unittest tests/test_backend_service.pypasses. - Confirm
npm testpasses. - Confirm
npm run buildpasses. - Confirm
/src-tauri && cargo checkpasses. - Run
npm run release:macos. - Verify the signed app with
codesign --verify --deep --strict --verbose=2 releases/macos/ChaosEngineAI.app. - Verify Gatekeeper with
spctl --assess --type execute -vv releases/macos/ChaosEngineAI.app. - If notarized, verify stapling with
xcrun stapler validate -v releases/macos/ChaosEngineAI_<version>_aarch64.dmg. - Launch the packaged app and smoke:
GET /api/health- MLX model load and generate
- GGUF model load and generate
- GGUF or HF to MLX conversion
- Archive the final
.appand.dmgplus release notes.
- The Codex sandbox can block Metal or DMG tooling even when the packaged app works normally on macOS. Final release validation should always use the packaged app outside the sandbox.
- ChaosEngineAI's embedded runtime is delivered as an archive and unpacked on first launch. The release staging step signs embedded Mach-O payloads before that archive is bundled.