doc/RELEASE_PROCESS.md
Document ID: REL-PROC-DESKTOP-001
Version: 1.1
Last Updated: 2026-05-09
Owner: Engineering Team
This document defines the release process for draw.io Desktop. Automated controls via GitHub Actions handle repeatable tasks, while manual steps focus on verification and approval.
Repository: https://github.com/jgraph/drawio-desktop
Submodule: drawio (core editor)
CI/CD: GitHub Actions
Tooling versions are pinned in the GitHub Actions workflows to ensure reproducible builds.
| Tool | Version | Controlled In |
|---|---|---|
| Node.js | 24.x (LTS) | .github/workflows/*.yml |
| npm | (bundled with Node) | — |
Note: npm is bundled with Node.js, ensuring consistent versions across environments.
When updating tooling versions:
| Role | Responsibility |
|---|---|
| Release Lead | Triggers workflow, verifies output, approves release |
| Reviewer | Reviews changes, provides approval before publish |
Small Team Note: Release Lead and Reviewer should be different people when possible. For solo releases, rely on automated checks and document the reason.
The prepare-release workflow automates:
npm audit and failing on critical/high vulnerabilitiesnpm outdated for reviewTo trigger:
29.0.4)drawio submodule. Leave empty to keep the current submodule pin — CI builds source the editor from drawio-dev's release branch, so the public submodule only needs to track what out-of-tree builders should see.What happens:
┌─────────────────────────────────────────────────────────────────┐
│ Workflow: prepare-release │
├─────────────────────────────────────────────────────────────────┤
│ 1. Validate version format (X.Y.Z) │
│ 2. Checkout with submodules (recursive) │
│ 3. Setup Node.js 24.x │
│ 4. Update drawio submodule → target ref │
│ └── Update nested submodules (recursive) │
│ 5. Update package.json version │
│ 6. npm ci │
│ 7. npm audit → FAIL if critical/high vulns │
│ 8. npm outdated → report only │
│ 9. Upload evidence artifacts │
│ 10. Commit + push │
│ 11. Create + push tag v{version} │
│ 12. Build workflows trigger automatically │
└─────────────────────────────────────────────────────────────────┘
Evidence produced:
release-evidence-v{VERSION} artifact containing:
audit-results.jsonaudit-report.txtoutdated-report.txtBefore triggering the workflow:
| ✓ | Item |
|---|---|
| ☐ | Release scope documented (what's included) |
| ☐ | All feature changes merged to dev branch |
| ☐ | Target drawio ref exists and is tested |
After the prepare-release workflow completes:
Evidence: Link to successful build run: _______________
After all build workflows complete successfully:
Before publishing, the Reviewer verifies:
| ✓ | Check |
|---|---|
| ☐ | Workflow completed successfully |
| ☐ | npm audit shows no critical/high vulnerabilities |
| ☐ | Build workflows passed for all platforms |
| ☐ | Test cases passed (Section 6) |
| Name | Date | |
|---|---|---|
| Release Lead | ||
| Reviewer |
Solo Release: Document reason, ensure all automated checks pass, perform extended testing.
Run against the built application before publishing.
| ID | Test | Expected | Pass |
|---|---|---|---|
| T01 | Launch application | Main window displays | ☐ |
| T02 | Create new diagram | Blank canvas opens | ☐ |
| T03 | Add shapes | Shapes render, move, resize | ☐ |
| T04 | Save file | Saves without error | ☐ |
| T05 | Open file | Displays correctly | ☐ |
| T06 | Help > About | Shows correct version | ☐ |
| ID | Test | Expected | Pass |
|---|---|---|---|
| T07 | Export PNG/PDF/SVG | Valid output | ☐ |
| T08 | Undo/Redo | Actions reverse | ☐ |
| ID | Check | Method | Pass |
|---|---|---|---|
| S01 | No external scripts | DevTools Network tab | ☐ |
| S02 | No data exfiltration | Monitor during save | ☐ |
Tested by: _______________ Date: _______________
Version: _______________
Issue: _______________________________________________
Root Cause: _______________________________________________
Corrective Action: _______________________________________________
Completed by: _______________ Date: _______________
## v[VERSION] - [DATE]
### Changes
- [Change 1]
- [Change 2]
### Fixes
- [Fix 1]
### Security
- Dependencies updated
### Known Issues
- [If any]
Evidence is automatically retained:
| Evidence | Location | Retention |
|---|---|---|
| Workflow logs | GitHub Actions | 90 days (GitHub default) |
| Audit artifacts | Actions → Artifacts | 365 days (configured) |
| Release assets | GitHub Releases | Permanent |
| Git tags/commits | Repository | Permanent |
For audits requiring longer retention, download artifacts to secure storage.
audit-report.txt in workflow artifactsnpm audit fix locally, commit, re-run workflowgit push --delete origin v{VERSION}drawio_ref input to specify the correct ref — or leave it empty to keep the current submodule pin (the CI build workflows source the editor from drawio-dev, so they are unaffected by a lagging public pin)Windows and macOS builds are signed during CI. Linux artifacts are unsigned (beyond distribution-level signatures applied by the snap store etc.).
Windows binaries (NSIS installer, MSI, portable, inner .exe) are signed via Microsoft Azure Trusted Signing. Microsoft has rebranded this service to "Artifact Signing" — same product, the resource provider is still Microsoft.CodeSigning. The integration uses our own electron-builder sign hook at build/sign-trusted.mjs, invoked from win.signtoolOptions.sign in electron-builder-win.json, electron-builder-win32.json, and electron-builder-win-arm64.json.
Azure resources (region: West Europe):
| Resource | Name |
|---|---|
| Resource group | rg-drawio-signing |
| Artifact Signing account | drawio-signing |
| Certificate profile | drawio-codesign |
| Endpoint | https://weu.codesigning.azure.net |
| Service principal (CI) | drawio-ci-signing |
| Role assigned to SP | Artifact Signing Certificate Profile Signer (scope: account) |
| Identity validation subject | draw.io Ltd (UK organisation) |
GitHub secrets (repository-level on jgraph/drawio-desktop):
| Secret | Source |
|---|---|
AZURE_TENANT_ID | tenant from az ad sp create-for-rbac |
AZURE_CLIENT_ID | appId (the service principal application id) |
AZURE_CLIENT_SECRET | password (rotate via az ad sp credential reset --id $APP_ID) |
Workflow step. .github/workflows/electron-builder-win.yml → Set up signing dependencies (Azure Trusted Signing) downloads the Microsoft.ArtifactSigning.Client NuGet package (pinned, currently 1.0.128), extracts the dlib at bin/x64/Azure.CodeSigning.Dlib.dll, locates signtool.exe from the Windows SDK (filtering out the unsupported 10.0.20348 SDK version), and exports both as env vars consumed by sign-trusted.mjs.
Cert lifecycle. Microsoft auto-rotates the leaf certificate every three days. Signatures remain valid beyond that thanks to RFC 3161 timestamping at http://timestamp.acs.microsoft.com. There is no manual renewal of the certificate itself — only the Azure account, certificate profile, and identity validation need maintenance, and none of those expire under normal usage.
Publisher transition. The current cert subject is CN=draw.io Ltd, O=draw.io Ltd, .... Releases up to v29.x were signed JGraph Ltd via SSL.com. Auto-update bridges both publishers via win.signtoolOptions.publisherName: ["JGraph Ltd", "draw.io Ltd"] in each Windows config. Drop JGraph Ltd once v30.x is well-distributed (a few release cycles).
Verifying a signed build. Right-click any signed .exe → Properties → Digital Signatures and confirm:
draw.io LtdmacOS .app, .dmg, and the .appex Quick Look extension are signed with the Apple Developer ID Application certificate, then notarised by Apple. Implementation is in build/notarize.mjs (the electron-builder afterSign hook).
GitHub secrets (organisation-level on jgraph):
| Secret | Purpose |
|---|---|
CSC_LINK | Apple Developer ID Application .p12, base64-encoded |
CSC_KEY_PASSWORD | .p12 password |
APPLEID | Apple ID for notarisation submission |
APPLEIDPASS | App-specific password for notarisation |
APPLE_TEAM_ID | Apple Developer team identifier |
These are organisation-level (not repository-level) because they're shared with other Apple-signed jgraph projects. The Apple Developer ID Application certificate has a multi-year validity; renewal is a manual annual operation through the Apple Developer portal.
Linux artifacts (.deb, .rpm, .AppImage, .snap) are unsigned by us. The snap store re-signs .snap packages on upload via SNAP_TOKEN; other formats rely on transport-level (HTTPS) trust and the user's distribution package manager.
| Symptom | Likely cause | Action |
|---|---|---|
Windows: SignTool Error: No certificates were found that met all the given criteria. | Azure auth failure (expired SP secret, RBAC not propagated) | Reset SP credential; verify AZURE_* repo secrets match latest values |
Windows: Trusted Signing dlib not found at ... | NuGet package layout changed or version unavailable | Confirm Microsoft.ArtifactSigning.Client version still resolves; bump pinned version |
| Windows: 403 Forbidden during signing | Region/endpoint mismatch | Confirm endpoint URL matches the account's region (weu for West Europe) |
| macOS: notarisation rejected | Apple ID password expired, or app-specific password revoked | Generate a new app-specific password at appleid.apple.com; update APPLEIDPASS secret |
macOS: errSecInternalComponent | .p12 corrupted or wrong password | Re-export .p12 from Keychain Access; update CSC_LINK and CSC_KEY_PASSWORD |
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2026.01.02 | D Benson | Initial release |
| 1.1 | 2026.05.09 | D Benson | Added §11 Code Signing (Windows via Azure Trusted Signing, macOS via Apple Developer ID); fixed stale CSC_LINK reference in §4.4 (it's the macOS secret, not Windows) |