# Release Checklist This document covers the unified release workflow for stable and nightly desktop releases. ## What the workflow does - Workflow: `.github/workflows/release.yml` - Triggers: - push tag matching `v*.*.*` for stable releases - scheduled nightly at `09:00 UTC` - manual `workflow_dispatch` for either channel - Runs quality gates first: lint, typecheck, test. - Builds four artifacts in parallel for both channels: - macOS `arm64` DMG - macOS `x64` DMG - Linux `x64` AppImage - Windows `x64` NSIS installer - Publishes one GitHub Release with all produced files. - Stable tags with a suffix after `X.Y.Z` (for example `1.2.3-alpha.1`) are published as GitHub prereleases. - Only plain stable `X.Y.Z` releases are marked as the repository's latest release. - Nightly runs are always GitHub prereleases and never marked latest. - Automatically generated release notes are pinned to the previous tag in the same channel, so stable compares to the previous stable tag and nightly compares to the previous nightly tag. - Includes Electron auto-update metadata (for example `latest*.yml`, `nightly*.yml`, and `*.blockmap`) in release assets. - Publishes the CLI package (`apps/server`, npm package `ryco`) with OIDC trusted publishing from the same workflow file: - stable releases publish npm dist-tag `latest` - nightly releases publish npm dist-tag `nightly` - Signing is optional and auto-detected per platform from secrets. ## Nightly builds - Workflow: `.github/workflows/release.yml` - Triggers: - scheduled every day at `09:00 UTC` - manual `workflow_dispatch` with `channel=nightly` - Runs the same desktop quality gates and artifact matrix as the tagged release flow. - Publishes a GitHub prerelease only: - tag format: `nightly-vX.Y.Z-nightly.YYYYMMDD.` - release name includes the short commit SHA - `make_latest` is always `false` - Uses the next stable patch version as the nightly base. For example, `0.0.17` produces nightlies on `0.0.18-nightly.*`. - Publishes Electron auto-update metadata to the dedicated `nightly` updater channel, so desktop users can opt into that track independently from stable. - Publishes the CLI package (`apps/server`, npm package `ryco`) to the `nightly` npm dist-tag using the same nightly version. - Does not commit version bumps back to `main`. ## Desktop auto-update notes - Runtime updater: `electron-updater` in `apps/desktop/src/main.ts`. - Update UX: - Background checks run on startup delay + interval. - No automatic download or install. - The desktop UI shows a rocket update button when an update is available; click once to download, click again after download to restart/install. - Provider: GitHub Releases (`provider: github`) configured at build time. - Repository slug source: - `RYCO_DESKTOP_UPDATE_REPOSITORY` (format `owner/repo`), if set. - otherwise `GITHUB_REPOSITORY` from GitHub Actions. - Temporary private-repo auth workaround: - set `RYCO_DESKTOP_UPDATE_GITHUB_TOKEN` (or `GH_TOKEN`) in the desktop app runtime environment. - the app forwards it as an `Authorization: Bearer ` request header for updater HTTP calls. - Required release assets for updater: - platform installers (`.exe`, `.dmg`, `.AppImage`, plus macOS `.zip` for Squirrel.Mac update payloads) - channel metadata: `latest*.yml` for stable releases, `nightly*.yml` for nightly releases - `*.blockmap` files (used for differential downloads) - macOS metadata note: - `electron-updater` reads `latest-mac.yml` on stable and `nightly-mac.yml` on nightly, for both Intel and Apple Silicon. - The workflow merges the per-arch mac manifests into one channel-specific mac manifest before publishing the GitHub Release. ## 0) npm OIDC trusted publishing setup (CLI) The workflow publishes the CLI with `npm publish` from `apps/server` after bumping the package version to the release tag version. Checklist: 1. Confirm npm org/user owns package `ryco` (or rename package first if needed). 2. In npm package settings, configure Trusted Publisher: - Provider: GitHub Actions - Repository: this repo - Workflow file: `.github/workflows/release.yml` - Environment (if used): match your npm trusted publishing config 3. Ensure npm account and org policies allow trusted publishing for the package. 4. Create release tag `vX.Y.Z` and push; workflow will: - set `apps/server/package.json` version to `X.Y.Z` - build web + server - run `npm publish --access public --tag latest` 5. Nightly runs from the same workflow file publish with `npm publish --access public --tag nightly`. ## 1) Dry-run release without signing Use this first to validate the release pipeline. 1. Confirm no signing secrets are required for this test. 2. Create a test tag: - `git tag v0.0.0-test.1` - `git push origin v0.0.0-test.1` 3. Wait for `.github/workflows/release.yml` to finish. 4. Verify the GitHub Release contains all platform artifacts. 5. Download each artifact and sanity-check installation on each OS. ## 2) Apple signing + notarization setup (macOS) Required secrets used by the workflow: - `CSC_LINK` - `CSC_KEY_PASSWORD` - `APPLE_API_KEY` - `APPLE_API_KEY_ID` - `APPLE_API_ISSUER` Checklist: 1. Apple Developer account access: - Team has rights to create Developer ID certificates. 2. Create `Developer ID Application` certificate. 3. Export certificate + private key as `.p12` from Keychain. 4. Base64-encode the `.p12` and store as `CSC_LINK`. 5. Store the `.p12` export password as `CSC_KEY_PASSWORD`. 6. In App Store Connect, create an API key (Team key). 7. Add API key values: - `APPLE_API_KEY`: contents of the downloaded `.p8` - `APPLE_API_KEY_ID`: Key ID - `APPLE_API_ISSUER`: Issuer ID 8. Re-run a tag release and confirm macOS artifacts are signed/notarized. Notes: - `APPLE_API_KEY` is stored as raw key text in secrets. - The workflow writes it to a temporary `AuthKey_.p8` file at runtime. ## 3) Azure Trusted Signing setup (Windows) Required secrets used by the workflow: - `AZURE_TENANT_ID` - `AZURE_CLIENT_ID` - `AZURE_CLIENT_SECRET` - `AZURE_TRUSTED_SIGNING_ENDPOINT` - `AZURE_TRUSTED_SIGNING_ACCOUNT_NAME` - `AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE_NAME` - `AZURE_TRUSTED_SIGNING_PUBLISHER_NAME` Checklist: 1. Create Azure Trusted Signing account and certificate profile. 2. Record ATS values: - Endpoint - Account name - Certificate profile name - Publisher name 3. Create/choose an Entra app registration (service principal). 4. Grant service principal permissions required by Trusted Signing. 5. Create a client secret for the service principal. 6. Add Azure secrets listed above in GitHub Actions secrets. 7. Re-run a tag release and confirm Windows installer is signed. ## 4) Ongoing release checklist 1. Ensure `main` is green in CI. 2. Bump app version as needed. 3. Create release tag: `vX.Y.Z`. 4. Push tag. 5. Verify workflow steps: - preflight passes - all matrix builds pass - release job uploads expected files 6. Smoke test downloaded artifacts. ## 5) Troubleshooting - macOS build unsigned when expected signed: - Check all Apple secrets are populated and non-empty. - Windows build unsigned when expected signed: - Check all Azure ATS and auth secrets are populated and non-empty. - Build fails with signing error: - Retry with secrets removed to confirm unsigned path still works. - Re-check certificate/profile names and tenant/client credentials.