Skip to content

Latest commit

 

History

History
228 lines (186 loc) · 9.68 KB

File metadata and controls

228 lines (186 loc) · 9.68 KB

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 t3) with OIDC trusted publishing from the same workflow file:
    • stable releases publish npm dist-tag latest
    • nightly releases publish npm dist-tag nightly
  • Deploys the hosted web app to Vercel only after a release is published:
    • stable releases are aliased to the latest hosted app channel
    • nightly releases are aliased to the nightly hosted app channel
  • Signing is optional and auto-detected per platform from secrets.

Hosted web app release deployment

The hosted app is intentionally not deployed by Vercel's Git integration. The web project disables automatic Git deployments in apps/web/vercel.ts via git.deploymentEnabled: false, and .github/workflows/release.yml deploys the web app with Vercel CLI after the GitHub Release succeeds.

Required GitHub Actions secrets:

  • VERCEL_TOKEN
  • VERCEL_ORG_ID
  • VERCEL_PROJECT_ID

Optional GitHub Actions variables:

  • VERCEL_TEAM_SLUG: overrides the Vercel CLI scope when the team slug is preferred over the VERCEL_ORG_ID secret.
  • T3CODE_WEB_ROUTER_URL: defaults to https://app.t3.codes.
  • T3CODE_WEB_LATEST_DOMAIN: defaults to latest.app.t3.codes.
  • T3CODE_WEB_NIGHTLY_DOMAIN: defaults to nightly.app.t3.codes.

Required Vercel domains:

  • app.t3.codes: the stable router domain users open.
  • latest.app.t3.codes: channel alias updated by stable releases.
  • nightly.app.t3.codes: channel alias updated by nightly releases.

The router domain uses apps/web/vercel.ts routes. Users opt into a channel by visiting /__t3code/channel?channel=latest or /__t3code/channel?channel=nightly; the router stores the t3code_web_channel cookie and rewrites future requests on app.t3.codes to the matching channel alias.

The release deploy job rewrites release package versions before upload so the hosted app's About panel renders the release version. It also passes VITE_HOSTED_APP_CHANNEL=latest|nightly, which renders the hosted update track selector in the About panel. Changing the selector navigates through /__t3code/channel on the router domain so the user's channel cookie is updated before redirecting to the hosted app root.

One-time Vercel dashboard setup:

  1. Confirm the web project root directory remains apps/web.
  2. Add the three domains above to the web project.
  3. Disable automatic Git deployments in the dashboard if desired; the committed vercel.ts setting is the source-of-truth, but disconnecting Git in the dashboard is also safe.
  4. Promote or alias one deployment containing the router rules in apps/web/vercel.ts to app.t3.codes once. Future release jobs should only update the channel aliases.

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.<run_number>
    • 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 t3) 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:
    • T3CODE_DESKTOP_UPDATE_REPOSITORY (format owner/repo), if set.
    • otherwise GITHUB_REPOSITORY from GitHub Actions.
  • Temporary private-repo auth workaround:
    • set T3CODE_DESKTOP_UPDATE_GITHUB_TOKEN (or GH_TOKEN) in the desktop app runtime environment.
    • the app forwards it as an Authorization: Bearer <token> 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 t3 (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_<id>.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.