This guide explains how to deploy the ScanCorrect desktop app with automated builds and releases.
The deployment process is fully automated using GitHub Actions:
- Make changes to the desktop app
- Run release script to create a new version tag
- GitHub Actions automatically builds for macOS, Windows, and Linux
- GitHub Release is created with downloadable installers
- Link to releases from your website
-
Push your code to GitHub
git remote add origin https://github.com/YOUR_USERNAME/film-exif-editor.git git push -u origin main
-
Create your first release
./scripts/create-release.sh
Enter version
0.1.0when prompted. -
Wait for builds (~15-20 minutes)
- Check progress: https://github.com/YOUR_USERNAME/film-exif-editor/actions
- Builds run in parallel for all platforms
-
Download links are ready!
- Go to: https://github.com/YOUR_USERNAME/film-exif-editor/releases
- Copy download URLs for each platform
- Add to website download buttons
# 1. Make your changes
git add .
git commit -m "feat: add new feature"
# 2. Create a release (this handles everything)
./scripts/create-release.shThe script will:
- ✅ Ask for the new version number
- ✅ Update
packages/desktop/package.json - ✅ Create a git commit
- ✅ Create a git tag (e.g.,
v0.2.0) - ✅ Push to GitHub
- ✅ Trigger automated builds
When you push a version tag:
-
Build Job (runs on 3 machines in parallel):
- macOS runner builds DMG and ZIP
- Windows runner builds NSIS installer and portable exe
- Linux runner builds AppImage and DEB
-
Release Job:
- Collects all build artifacts
- Creates GitHub Release with version tag
- Uploads all installers to the release
- Generates release notes from commits
Use Semantic Versioning:
MAJOR.MINOR.PATCH(e.g.,1.2.3)- MAJOR: Breaking changes (rare for desktop apps)
- MINOR: New features (e.g.,
0.1.0→0.2.0) - PATCH: Bug fixes (e.g.,
0.1.0→0.1.1)
Examples:
0.1.0- Initial release0.2.0- Added new EXIF fields support0.2.1- Fixed crash bug1.0.0- First stable release
After a release builds, you'll have these URLs:
https://github.com/YOUR_USERNAME/film-exif-editor/releases/latest/download/Film-EXIF-Editor-{version}.dmg
https://github.com/YOUR_USERNAME/film-exif-editor/releases/latest/download/Film-EXIF-Editor-Setup-{version}.exe
https://github.com/YOUR_USERNAME/film-exif-editor/releases/latest/download/Film-EXIF-Editor-{version}.AppImage
Replace v0.1.0 with your version:
https://github.com/YOUR_USERNAME/film-exif-editor/releases/download/v0.1.0/Film-EXIF-Editor-0.1.0.dmg
https://github.com/YOUR_USERNAME/film-exif-editor/releases/download/v0.1.0/Film-EXIF-Editor-Setup-0.1.0.exe
https://github.com/YOUR_USERNAME/film-exif-editor/releases/download/v0.1.0/Film-EXIF-Editor-0.1.0.AppImage
Update your website download buttons with GitHub release URLs:
// packages/website/app/page.tsx
<button onClick={() => window.location.href = 'https://github.com/YOUR_USERNAME/film-exif-editor/releases/latest'}>
Download for macOS
</button>const GITHUB_RELEASES = 'https://github.com/YOUR_USERNAME/film-exif-editor/releases/latest/download';
<button onClick={() => window.location.href = `${GITHUB_RELEASES}/Film-EXIF-Editor-latest.dmg`}>
Download for macOS
</button>Fetch latest release info from GitHub API to show version numbers:
// Example: Display "Download v0.1.0"
const response = await fetch('https://api.github.com/repos/YOUR_USERNAME/film-exif-editor/releases/latest');
const data = await response.json();
const version = data.tag_name; // "v0.1.0"Each release produces:
- DMG (~50-70 MB): Standard drag-to-Applications installer
- ZIP (~50-70 MB): Portable archive format
- NSIS Installer (~40-60 MB): Full Windows installer with options
- Portable EXE (~40-60 MB): Standalone executable (no installation)
- AppImage (~60-80 MB): Universal Linux package
- DEB (~60-80 MB): Debian/Ubuntu package
- Triggers: Every push to
mainbranch - Purpose: Verify builds don't break
- Artifacts: Kept for 7 days (for testing)
- No release: Just builds, doesn't publish
- Triggers: Push version tag (e.g.,
v0.1.0) - Purpose: Create production releases
- Artifacts: Published as GitHub Release
- Public: Anyone can download
For production apps, code signing prevents "untrusted developer" warnings.
- Get Apple Developer Account ($99/year)
- Create Developer ID Certificate in Xcode
- Export certificate as P12 file
- Add GitHub Secrets:
MAC_CERT_P12_BASE64: Base64-encoded P12 fileMAC_CERT_PASSWORD: Certificate password
# Convert P12 to base64
base64 -i certificate.p12 | pbcopy
# Paste into GitHub SecretAdd these secrets:
APPLE_ID: Your Apple ID emailAPPLE_APP_PASSWORD: App-specific password
- Get Code Signing Certificate (e.g., from DigiCert, ~$200/year)
- Export as P12 file
- Add GitHub Secrets:
WIN_CERT_P12_BASE64: Base64-encoded P12WIN_CERT_PASSWORD: Certificate password
Note: Code signing is optional for initial releases. You can add it later.
- Check the Actions tab: https://github.com/YOUR_USERNAME/film-exif-editor/actions
- Click the failed workflow
- Expand the failed step to see error logs
Common issues:
- Missing dependencies: Run
npm cilocally to verify - TypeScript errors: Run
npm run build -w desktoplocally - Build timeout: Usually macOS notarization (optional, can disable)
- Ensure you pushed both commit AND tag:
git push origin main git push origin v0.1.0
- Check that tag matches pattern
v*.*.*(e.g.,v0.1.0, not0.1.0)
- Wait for all builds to complete (~15-20 min)
- Check GitHub Releases page to verify files uploaded
- Ensure URL matches exact filename (case-sensitive)
Go to: Settings → Secrets and variables → Actions → New repository secret
Required secrets (for code signing only):
MAC_CERT_P12_BASE64MAC_CERT_PASSWORDAPPLE_IDAPPLE_APP_PASSWORDWIN_CERT_P12_BASE64WIN_CERT_PASSWORD
Note: App works without code signing, but users will see security warnings.
# Build for your current platform
npm run build -w desktop
npm run dist -w desktop
# Test the installer from release/ directory- Push to a branch (not main)
- Create a test tag:
git tag v0.0.1-test && git push origin v0.0.1-test - Check builds in Actions tab
- Delete tag after testing:
git tag -d v0.0.1-test && git push origin :refs/tags/v0.0.1-test
Before creating a release:
- Test app locally on your platform
- Update version number appropriately (semantic versioning)
- Update CHANGELOG.md before tagging
- Commit all changes to main branch
- Run
./scripts/create-release.sh - Wait for GitHub Actions to complete
- Test download links from GitHub Releases
- Update website download buttons if needed
- Announce release (social media, blog, etc.)
- GitHub Actions: https://github.com/YOUR_USERNAME/film-exif-editor/actions
- Latest Release: https://github.com/YOUR_USERNAME/film-exif-editor/releases/latest
Consider adding:
- Download counters from GitHub API
- Error reporting (Sentry, BugSnag)
- Auto-updater (electron-updater)
- Create your first release:
./scripts/create-release.sh - Update website: Add download links to landing page
- Set up analytics: Track downloads and usage
- Add auto-updates: Use electron-updater for seamless updates
- Submit to app stores: Mac App Store, Microsoft Store (optional)