This directory contains automated build workflows for zmNinjaNG across multiple platforms.
If you downloaded a macOS build and get a "damaged" error, that is not because the app is damaged. It is because MacOS blocks you.
In more recent versions this has become painful. I couldn't get xcattr variants to work. Anyway, simple answer: use sentinel
Each platform has its own dedicated workflow that can be triggered manually or on git tags:
build-android.yml- Builds Android APK and AABbuild-macos.yml- Builds macOS DMG installerbuild-linux.yml- Builds Linux AppImage and DEB packagesbuild-windows.yml- Builds Windows MSI and NSIS installers
build-all.yml- Build multiple platforms in parallel (configurable)
The easiest way to create a release is using the automated release script:
# From the project root
./scripts/make_release.shThis script will:
- Verify all changes are committed and pushed
- Read the version from
app/package.json - Create a git tag in the format
zmNinjaNG-{version} - Push the tag to trigger all build workflows
- Create a GitHub Release with build artifacts
Safety Checks: The script performs validation before creating a release:
- Fails if there are uncommitted changes
- Fails if there are unpushed commits
- Asks for confirmation before proceeding
Handling Existing Tags: If a tag already exists, the script will ask if you want to move it to the current commit. This is useful when you need to rebuild a release with fixes.
- Go to Actions tab in GitHub
- Select the workflow you want to run
- Click Run workflow
- Enter the version number (e.g.,
1.0.0) - For
build-all.yml, optionally specify platforms (default: all)
You can also manually push a tag to trigger builds:
# Tag format must be: zmNinjaNG-{version}
git tag zmNinjaNG-1.0.0
git push origin zmNinjaNG-1.0.0To move an existing tag to a new commit:
# Delete old tag
git tag -d zmNinjaNG-1.0.0
git push origin --delete zmNinjaNG-1.0.0
# Create new tag and push
git tag zmNinjaNG-1.0.0
git push origin zmNinjaNG-1.0.0 --forceThis will:
- Trigger all individual platform workflows
- Create a GitHub Release with build artifacts attached
After a successful build, artifacts are available for download:
zmNinjaNG-android-debug-{version}.apk- Debug-signed APK for sideloadingzmNinjaNG-android-debug-{version}.aab- Debug-signed App Bundle for testing
zmNinjaNG.dmg- DMG installerzmNinjaNG.app- Application bundle
zmNinjaNG.AppImage- Universal AppImagezmNinjaNG.deb- Debian packagezmNinjaNG.rpm- RPM package
zmNinjaNG.msi- MSI installerzmNinjaNG.exe- NSIS installer (if configured)
Release notes are automatically generated from commit messages, but you can add custom content:
- Edit
_RELEASE_NOTE_INSERT.mdin the.github/workflows/directory - Add installation instructions, warnings, or any other information
- Commit and push the changes
- The next release will include your custom notes at the top
The file uses Markdown format and will appear above the auto-generated commit history.
For automated releases to work, you must enable write permissions:
- Go to repository Settings → Actions → General
- Scroll to Workflow permissions
- Select "Read and write permissions"
- Click Save
Without this, you'll get 403 errors when trying to create releases.
- No additional secrets required
- Builds debug-signed APK and AAB by default
- For release signing, configure signing in
app/android/app/build.gradle
- Uses Tauri for desktop builds
- All builds are unsigned by default (no secrets required)
- Linux builds work without issues
- macOS/Windows builds will require users to bypass security warnings (see below)
- Optional macOS Code Signing (to avoid "damaged" error):
APPLE_CERTIFICATE- Base64-encoded .p12 certificateAPPLE_CERTIFICATE_PASSWORD- Certificate passwordAPPLE_SIGNING_IDENTITY- Developer ID (e.g., "Developer ID Application: Your Name (TEAM_ID)")APPLE_ID- Apple ID emailAPPLE_PASSWORD- App-specific passwordAPPLE_TEAM_ID- Team ID from Apple Developer account
- Optional Tauri updater signing:
TAURI_SIGNING_PRIVATE_KEYTAURI_SIGNING_PRIVATE_KEY_PASSWORD
Important: Ensure google-services.json (Android) and GoogleService-Info.plist (iOS) are properly configured in your repository for push notifications to work.
See ANDROID_BUILD.md for Firebase setup instructions.
- Android: Edit
app/android/app/build.gradle - Desktop: Edit
app/src-tauri/tauri.conf.json
For production releases, you should configure code signing:
Android: Add signing configuration to gradle macOS: Set up Apple Developer certificates Windows: Configure code signing certificate
See Tauri documentation for details: https://tauri.app/v1/guides/distribution/sign-your-application
If you get a "zmNinjaNG.app is damaged and can't be opened. You should move it to the Trash" error, this is because the app is not signed/notarized. You have two options:
Use Sentinel
To produce properly signed and notarized builds:
-
Get Apple Developer Account ($99/year)
-
Create Developer ID Certificate:
- Go to Apple Developer Portal → Certificates
- Create "Developer ID Application" certificate
- Download and install in Keychain
-
Export Certificate:
# Export from Keychain as .p12 # Then convert to base64 base64 -i certificate.p12 | pbcopy
-
Create App-Specific Password:
- Go to appleid.apple.com
- Sign In → Security → App-Specific Passwords
- Generate password for "GitHub Actions"
-
Add GitHub Secrets:
- Go to repository Settings → Secrets → Actions
- Add the following secrets:
APPLE_CERTIFICATE: Paste base64 certificateAPPLE_CERTIFICATE_PASSWORD: Certificate passwordAPPLE_SIGNING_IDENTITY: "Developer ID Application: Your Name (TEAM_ID)"APPLE_ID: Your Apple ID emailAPPLE_PASSWORD: App-specific passwordAPPLE_TEAM_ID: Team ID from developer portal
-
Re-run Workflow - The app will now be signed and notarized
Check the Actions tab for detailed error logs. Common issues:
- Missing dependencies: Check Node.js/Rust versions
- Build errors: Ensure local builds work first
- Artifact upload fails: Check file paths match your build output
- Ensure
google-services.jsonexists atapp/android/app/google-services.json - Verify Java 17 is being used
- Check Gradle version compatibility
- Ensure Rust toolchain is properly installed
- Check Tauri configuration in
tauri.conf.json - Verify all platform-specific dependencies are installed
Before pushing, test builds locally:
# Android
cd app
npm run android:release
# Desktop (macOS/Linux/Windows)
cd app
npm run tauri:build