This document explains how releases are automated via GitHub Actions.
When you push a version tag, GitHub Actions automatically:
- Builds the desktop app for Windows, macOS, and Linux
- Builds the browser extension for Chrome and Firefox
- Creates ZIPs for the extensions
- Uploads all artifacts to the GitHub Release
No manual building or uploading needed! ✅
Versions are defined in multiple files (all synced):
Cargo.toml (workspace version)
package.json (root)
apps/desktop/package.json
apps/desktop/src-tauri/tauri.conf.json
apps/extension/package.json
apps/extension/wxt.config.ts (manifest version)
All should be bumped together. Example for v1.6.0:
# Root
sed -i '' 's/"version": "1.5.0"/"version": "1.6.0"/' package.json
# Desktop
sed -i '' 's/"version": "1.5.0"/"version": "1.6.0"/' apps/desktop/package.json
sed -i '' 's/"version": "1.5.0"/"version": "1.6.0"/' apps/desktop/src-tauri/tauri.conf.json
# Extension
sed -i '' 's/"version": "1.0.0"/"version": "1.6.0"/' apps/extension/package.json
sed -i '' 's/version: '"'"'1.0.0'"'"'/version: '"'"'1.6.0'"'"'/' apps/extension/wxt.config.ts
# Cargo
sed -i '' 's/version = "1.5.0"/version = "1.6.0"/' Cargo.tomlOr manually edit the files - they're clearly marked.
git add .
git commit -m "Bump version to 1.6.0"
git tag v1.6.0
git push origin main
git push origin v1.6.0Two workflows trigger automatically:
- Runs on: Windows, macOS (Intel & Apple Silicon), Linux
- Builds the desktop app
- Creates platform-specific installers (
.msi,.dmg,.deb,.rpm,.AppImage) - Uploads to GitHub Release
- Builds Chrome extension
- Builds Firefox extension
- Creates ZIPs:
dlman-extension-chrome.zip,dlman-extension-firefox.zip - Uploads to the same GitHub Release
Total time: ~5-10 minutes
- Go to GitHub Releases
- Check that the latest release has:
- Desktop app binaries for all platforms
- Browser extension ZIPs
- Changelog extracted from CHANGELOG.md
Done! Users can download everything.
Both workflows use GitHub's cache to speed up builds:
pnpm Cache:
- name: Setup pnpm cache
uses: actions/cache@v3
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-Rust Cache:
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: '. -> target'- Ensures exact versions from
pnpm-lock.yamlare used - Prevents dependency updates during CI
- Cache works properly with exact hash
- Reproducible builds
To test the build locally before releasing:
# Install
pnpm install --frozen-lockfile
# Copy icons
pnpm --filter @dlman/extension run copy-icons
# Build extensions
pnpm --filter @dlman/extension run build:chrome
pnpm --filter @dlman/extension run build:firefox
# Build desktop
pnpm buildThe extension ZIPs are automatically created in .github/workflows/build-extensions.yml.
Check the workflow logs:
- Go to Actions
- Find the failed workflow
- Check the step logs for errors
Common causes:
pnpm-lock.yamlout of sync: Runpnpm installlocally- Icons not copied: Check
scripts/copy-icons.js - WXT build error: Run
pnpm --filter @dlman/extension run build:chromelocally
If extension version doesn't match app version:
- Edit
apps/extension/package.json - Edit
apps/extension/wxt.config.ts(manifest version) - Both must match for release
- Automated changelog generation from commits
- Signed binaries for macOS
- Notarization for macOS
- Browser extension store submissions