ADM has three distributable components:
- Desktop application (Tauri 2 bundle) — the primary release artifact, includes the daemon sidecar and native host binary.
- Browser extension — maintained in a separate repository; released independently.
- Portable binaries —
adm,adm-daemon,adm-cli,adm-test-serverfor scripting/headless use.
All releases are created through the CI workflow (.github/workflows/release.yml) triggered by
a v* tag push. Manual release via workflow_dispatch is also supported.
Current status: Pre-release (0.0.0-dev). No tagged releases exist yet. The release pipeline
is implemented but requires validation before first use.
ADM follows Semantic Versioning (major.minor.patch) with optional pre-release suffixes:
| Pattern | Example | Type |
|---|---|---|
v0.0.0-dev |
v0.0.0-dev |
Development (untagged) |
v0.1.0 |
v0.1.0 |
Stable release |
v0.2.0-beta.1 |
v0.2.0-beta.1 |
Pre-release |
v0.2.0-rc.1 |
v0.2.0-rc.1 |
Release candidate |
| File | Value | Source of Truth |
|---|---|---|
Cargo.toml (workspace) |
0.0.0-dev |
Yes — single source for Rust crates |
apps/desktop-ui/package.json |
0.0.0-dev |
Mirrors workspace via version.workspace (Cargo) |
package.json (root) |
0.0.0-dev |
Mirrors workspace |
apps/desktop-ui/src-tauri/tauri.conf.json |
0.0.0 |
Hardcoded; overridden at CI time by patch-tauri-ci-config.py |
install.sh |
0.2.0 |
Independent installer script version |
install.ps1 |
0.2.0 |
Independent installer script version |
Version is resolved from git tag or CI environment in this order:
ADM_RELEASE_VERSIONenvironment variableGITHUB_REF_NAME(e.g.,v0.1.0)- Fallback:
0.0.0-dev
The version resolver lives in .github/scripts/release_version.py and produces:
ADM_VERSION_RAW=v0.1.0
ADM_VERSION_DISPLAY=0.1.0
ADM_VERSION_NUMERIC=0.1.0
ADM_VERSION_FILE=0.1.0.0
ADM_VERSION_IS_TAG=1
ADM_VERSION_IS_PRERELEASE=0
A CHANGELOG.md file is required in the repository root. The CI quality gate validates
its presence before proceeding with the release. The changelog must follow common conventions:
# Changelog
## [Unreleased]
### Added
- ...
### Changed
- ...
### Fixed
- ...
## [0.1.0] - 2026-01-15
### Added
- ...
Note: CHANGELOG.md does not currently exist in the repository. One must be created before
the first tagged release or the CI release workflow will fail at the quality gate.
Run these locally before tagging a release:
# 1. Full Rust compilation
cargo check --locked --workspace --all-targets
# 2. Lint
cargo clippy --locked --workspace --all-targets -- -D warnings
# 3. Format
cargo fmt --all --check
# 4. Download engine tests
cargo test --locked -p adm-download-engine
# 5. Full workspace tests
cargo test --locked --workspace --all-features
# 6. Security audit
cargo deny check
cargo audit
# 7. Desktop UI
pnpm install --frozen-lockfile
pnpm --filter @adm/desktop typecheck
pnpm --filter @adm/desktop lint
pnpm --filter @adm/desktop build
# 8. Desktop UI full Tauri build (produces bundle)
pnpm tauri buildThe CI quality job runs automatically on every tag push:
cargo fmt --checkcargo clippy -D warningscargo build --workspace --exclude adm-desktopcargo test --workspace --exclude adm-desktopcargo check -p adm-desktoppnpm install --frozen-lockfile && pnpm --filter @adm/desktop buildcargo deny checkcargo audit- Validate repository release hygiene (CHANGELOG.md, CONTRIBUTING.md, LICENSE, README.md, .gitignore, .editorconfig, .gitattributes, dependabot.yml all present)
The CI build job produces artifacts for 6 targets across 3 platforms:
| Target | Tier | Arch | OS | Package Formats | Portable Format |
|---|---|---|---|---|---|
linux-x64 |
Required | x86_64 | Linux | AppImage, deb, rpm | tar.gz |
linux-arm64 |
Experimental | aarch64 | Linux | AppImage, deb, rpm | tar.gz |
windows-x64 |
Required | x86_64 | Windows | NSIS (.exe), MSI | zip |
windows-arm64 |
Experimental | aarch64 | Windows | NSIS (.exe), MSI | zip |
macos-x64 |
Required | x86_64 | macOS | DMG, .app | zip |
macos-arm64 |
Required | aarch64 | macOS | DMG, .app | zip |
Each target produces:
- Portable archive — Contains
adm+adm-daemon+adm-cli+adm-test-serverbinaries - Platform installer — Native bundle format for the OS
- SHA256 checksum —
SHA256SUMS.txtand per-file.sha256files - Tauri updater signature (if signing configured) —
.sigfile for the installer
The daemon (adm-daemon) and CLI (adm-cli) are compiled as separate release binaries
and staged into the Tauri bundle via stage-tauri-sidecars.mjs:
apps/desktop-ui/src-tauri/
binaries/
adm-daemon-x86_64-pc-windows-msvc.exe
adm-daemon-x86_64-unknown-linux-gnu
adm-daemon-aarch64-apple-darwin
...
resources/
adm-cli-x86_64-pc-windows-msvc.exe
...
The Tauri config references binaries/adm-daemon as an externalBin and resources/adm-cli*
as a resource. Tauri locates the correct triple-qualified file at runtime.
The Vite/React frontend is built once in the frontend-assets CI job and shared across all
build targets via GitHub Actions artifact upload/download.
Run from apps/desktop-ui/:
# Stage sidecars (builds daemon + CLI in release mode)
node scripts/stage-sidecars.mjs
# Build Tauri bundle
node scripts/tauri-cli.mjs buildThe tauri-cli.mjs wrapper strips CARGO_BUILD_TARGET before invoking cargo tauri build
to avoid cargo path conflicts.
Tauri tauri.conf.json bundle configuration:
| Field | Value |
|---|---|
bundle.active |
true |
bundle.targets |
"all" |
bundle.category |
"Utility" |
bundle.externalBin |
["binaries/adm-daemon"] |
bundle.resources |
["resources/adm-cli*"] |
bundle.windows.nsis.installMode |
"perMachine" (installs to %ProgramFiles%\APEX Download Manager, requires admin elevation) |
bundle.windows.nsis.languages |
["English", "Arabic"] |
bundle.windows.nsis.installerHooks |
"./windows/installer-hooks.nsh" — kills adm.exe/adm-daemon.exe before install/uninstall and removes settings/logs/database directories on uninstall |
Portable archives are collected after Tauri builds the desktop binary. They contain:
adm (or adm.exe) # Tauri desktop shell (includes daemon sidecar)
adm-daemon (or .exe) # Standalone daemon binary
adm-cli (or .exe) # CLI client
adm-test-server (or .exe) # Test HTTP server
Implemented (installer/windows-sign-artifacts.ps1):
- Signs
.exeand.msifiles usingsigntool.exefrom Windows SDK - Algorithm: SHA256 (
/fd SHA256) - Timestamp: RFC 3161 (
/tr+/td SHA256) - Certificate source:
WINDOWS_SIGNING_CERT_BASE64orWINDOWS_SIGNING_CERT_PATH - Certificate password:
WINDOWS_SIGNING_CERT_PASSWORD - Timestamp URL:
WINDOWS_SIGNING_TIMESTAMP_URL(default:http://timestamp.digicert.com)
Signing runs twice in CI:
- Portable binaries (pattern:
*.exe) - Installers (patterns:
*.exe,*.msi)
Prerequisites: Install Windows SDK (includes signtool.exe).
Implemented (CI secrets):
- Private key:
TAURI_SIGNING_PRIVATE_KEY - Key password:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD - Public key:
TAURI_UPDATER_PUBKEY - Updater is disabled by default in
tauri.conf.json(active: false,pubkey: "") - CI enables it at build time via
patch-tauri-ci-config.pywhen secrets are present - The
release-metadata.pyscript validates that stable releases have.sigfiles
Not implemented. macOS targets use ad-hoc signing (APPLE_SIGNING_IDENTITY: "-" in CI).
Notarization via xcrun notarytool would need to be added before distributing macOS builds
outside a developer's direct control.
The final CI job (release) creates a GitHub Release with:
- Release notes — Generated from
CHANGELOG.mdcontent for the version. Generated by.github/scripts/release-metadata.py. - Artifacts — All installer bundles, portable archives, checksums, and updater metadata from all targets.
- Metadata files:
release-manifest.json— Full artifact listing with checksums and platform infoSHA256SUMS.txt+ per-file.sha256— Checksum verificationlatest.json— Tauri updater metadata (only on stable releases with signatures)release-notification.json— Webhook notification payload
{
"version": "0.1.0",
"created_at": "2026-01-15T10:00:00Z",
"artifacts": {
"linux-x64": {
"portable": { "filename": "adm-0.1.0-linux-x64.tar.gz", "sha256": "abc...", "size": 123456 },
"package": { "filename": "adm_0.1.0_amd64.AppImage", "sha256": "def...", "size": 789012 }
},
"windows-x64": { ... },
"macos-arm64": { ... }
}
}After the release is published:
- Download and verify: Download the portable archive for your platform, verify SHA256 checksum.
- Run the daemon:
./adm-daemon— should start and listen on127.0.0.1:57423. - Run the CLI:
./adm-cli status— should show daemon is connected. - Test downloads: Use the desktop UI or CLI to initiate a download.
- Check updater: If updater was enabled, verify the
latest.jsonendpoint returns correct data. - Test installer: Run the platform installer on a clean machine, verify sidecar is registered.
- Test browser integration: Install extension, verify pairing flow works.
- Verify signatures: On Windows, check digital signatures on
.exeand.msifiles.
- Do not delete the release — GitHub Releases are permanent. Mark the release as "Pre-release" or draft a new release note with a warning.
- Create a patch release — Increment the patch version, fix the bug, tag
v0.1.1. - Update
latest.json— The Tauri updater readslatest.jsonfrom the latest GitHub Release. Pointing to a fixed version is automatic if it's the newest tag. - Notify distribution channels — Post a notice in the GitHub Release description.
- Update
latest.jsondirectly via the GitHub Releases API to point to the correct artifact. - The
release-metadata.pyscript generates this; re-run with corrected version and upload.
- All CI checks pass locally:
cargo check,clippy,fmt,test -
CHANGELOG.mdexists and contains the release entry - All commits since last release are documented in changelog
-
cargo deny checkandcargo auditpass with no yanked/unmaintained advisories - Desktop UI builds:
pnpm typecheck && pnpm lint && pnpm build - No placeholder or dummy values in
tauri.conf.json - Updater public key is configured (if applicable)
- Windows signing certificate is available (if applicable)
- Extension IDs for native host are set:
ADM_CHROME_EXTENSION_ID,ADM_EDGE_EXTENSION_ID,ADM_FIREFOX_EXTENSION_ID - No placeholder extension IDs remain in
production.rs(noREPLACE_WITH_*or<CHROME_WEB_STORE_ID>) - Test tag locally:
git tag v0.1.0 && git push origin v0.1.0and monitor CI
- Verify GitHub Release was created with all expected artifacts
- Download and verify SHA256 checksums
- Smoke-test the portable archive on each platform
- Test the installer on a clean machine (Windows NSIS/MSI, macOS DMG, Linux AppImage/deb/rpm)
- Verify daemon starts from Tauri desktop shell
- Verify browser extension can pair (via native host)
- If updater enabled: verify
latest.jsonis accessible and the app can detect the update - Update documentation if any release process steps changed
| Variable | Required | Purpose |
|---|---|---|
ADM_RELEASE_VERSION |
For CI | Override version (default: from git tag) |
ADM_CHROME_EXTENSION_ID |
For native host | Chrome Web Store extension ID |
ADM_EDGE_EXTENSION_ID |
For native host | Edge Add-ons extension ID |
ADM_FIREFOX_EXTENSION_ID |
For native host | Firefox Add-ons extension ID |
WINDOWS_SIGNING_CERT_BASE64 |
For Windows signing | Base64-encoded Authenticode certificate |
WINDOWS_SIGNING_CERT_PASSWORD |
For Windows signing | Certificate private key password |
WINDOWS_SIGNING_TIMESTAMP_URL |
For Windows signing | RFC 3161 timestamp server URL |
TAURI_SIGNING_PRIVATE_KEY |
For updater | Tauri updater private key |
TAURI_SIGNING_PRIVATE_KEY_PASSWORD |
For updater | Tauri updater key password |
TAURI_UPDATER_PUBKEY |
For updater | Tauri updater public key |
APPLE_SIGNING_IDENTITY |
For macOS | Code signing identity (currently "-" ad-hoc) |
- Rust: 1.96.0 (from
rust-toolchain.toml), edition 2021 - Node: 24+, pnpm: 11.8.0 (from
packageManagerfield) - Tauri CLI: ^2.2.7 (from root
devDependencies) - Cross-compilation: Not done in CI — each target builds natively on a platform-specific runner
- Tauri bundler: Must be installed (
cargo install tauri-cli --version "^2") or available viapnpm tauri(which invokes the local@tauri-apps/clipackage) - Windows signing: Requires Windows SDK (for
signtool.exe) and a valid code signing certificate - macOS notarization: Not implemented; requires Apple Developer account and
xcrun notarytool
| Gap | Impact | Status |
|---|---|---|
CHANGELOG.md missing |
CI release quality gate will fail | ❌ Needs creation before first release |
CONTRIBUTING.md missing |
CI release quality gate will fail | ❌ Needs creation before first release |
| No git tags exist | First release will be tagged v0.1.0 |
— |
| Updater disabled by default | No in-app update notifications | 🟡 Enable when Tauri signing keys are set |
| macOS notarization absent | Gatekeeper warning on first launch | 📝 Planned for v1 readiness |
Version inconsistency (tauri.conf.json hardcodes 0.0.0) |
Overridden by CI patching; manual builds use wrong version | 🟡 Acceptable |
| Browser extension in separate repo | ADM release does not publish extension | 🔄 Separate workflow |
| Release approval gating | No manual approval step before publish | 🟡 Can be added to CI if needed |