From c79f36d153792e44a3e5eed20c54d9ebe963a9bc Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 19 Aug 2026 10:23:50 +0000 Subject: [PATCH] ci: run only fast checks per PR; batch heavy builds to main/nightly/release Add concurrency:cancel-in-progress across CI workflows so rapid pushes cancel superseded runs. Split desktop_ci/mobile_ci into a Linux fast lane on PRs (typecheck, unit tests, cargo check/test x64) and gate macOS/Windows/Swift/arm64 + iOS/watchOS/Android builds to push:main, nightly schedule, and workflow_dispatch. Move pro_api_e2e (live provider APIs) off PRs. Add RELEASE_AUDIT.md documenting the per-PR/nightly/release model. Co-authored-by: John Jeong --- .github/workflows/api_ci.yaml | 5 +++ .github/workflows/bot_ci.yaml | 5 +++ .github/workflows/chrome_ci.yaml | 4 +++ .github/workflows/db_ci.yaml | 4 +++ .github/workflows/desktop_ci.yaml | 45 +++++++++++++++------------ .github/workflows/fmt.yaml | 5 +++ .github/workflows/lint.yaml | 5 +++ .github/workflows/mobile_ci.yaml | 19 +++++++++++- .github/workflows/pro_api_e2e.yaml | 12 +++---- .github/workflows/web_ci.yaml | 5 +++ .github/workflows/zizmor.yaml | 4 +++ RELEASE_AUDIT.md | 50 ++++++++++++++++++++++++++++++ 12 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 RELEASE_AUDIT.md diff --git a/.github/workflows/api_ci.yaml b/.github/workflows/api_ci.yaml index 8832a96dee..2e52612ace 100644 --- a/.github/workflows/api_ci.yaml +++ b/.github/workflows/api_ci.yaml @@ -22,6 +22,11 @@ on: - crates/api-sync/** - crates/llm-proxy/** - crates/transcribe-proxy/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: ci: runs-on: ubuntu-latest diff --git a/.github/workflows/bot_ci.yaml b/.github/workflows/bot_ci.yaml index 7c965848b9..d7ad1bb264 100644 --- a/.github/workflows/bot_ci.yaml +++ b/.github/workflows/bot_ci.yaml @@ -3,6 +3,11 @@ on: pull_request: paths: - apps/bot/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: ci: runs-on: ubuntu-24.04 diff --git a/.github/workflows/chrome_ci.yaml b/.github/workflows/chrome_ci.yaml index 0bc5b2ebc3..915bc08bb7 100644 --- a/.github/workflows/chrome_ci.yaml +++ b/.github/workflows/chrome_ci.yaml @@ -19,6 +19,10 @@ on: - .github/actions/pnpm_install/** - .github/workflows/chrome_ci.yaml +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: chrome_ci: runs-on: ubuntu-24.04 diff --git a/.github/workflows/db_ci.yaml b/.github/workflows/db_ci.yaml index ae65edf0d5..7a332f778a 100644 --- a/.github/workflows/db_ci.yaml +++ b/.github/workflows/db_ci.yaml @@ -10,6 +10,10 @@ on: paths: - supabase/** +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: tests: runs-on: ubuntu-latest diff --git a/.github/workflows/desktop_ci.yaml b/.github/workflows/desktop_ci.yaml index 6e9222a0b9..409ef8eec3 100644 --- a/.github/workflows/desktop_ci.yaml +++ b/.github/workflows/desktop_ci.yaml @@ -1,6 +1,8 @@ # https://github.com/tauri-apps/tauri-action/blob/3013cac/examples/test-build-only.yml on: workflow_dispatch: + schedule: + - cron: "0 9 * * *" push: branches: - main @@ -27,9 +29,27 @@ on: - crates/** - Cargo.toml - Cargo.lock + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - macos_ci: + js_ci: if: ${{ !startsWith(github.head_ref || '', 'blog/') }} + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + - uses: ./.github/actions/pnpm_install + - run: pnpm -F ui build + - run: pnpm -F desktop typecheck + - run: pnpm -F desktop test + + macos_ci: + if: ${{ github.event_name != 'pull_request' && !startsWith(github.head_ref || '', 'blog/') }} defaults: run: shell: bash @@ -171,7 +191,7 @@ jobs: plugins/db/permissions/schemas/schema.json windows_ci: - if: ${{ !startsWith(github.head_ref || '', 'blog/') }} + if: ${{ github.event_name != 'pull_request' && !startsWith(github.head_ref || '', 'blog/') }} runs-on: windows-latest steps: - uses: actions/checkout@v4 @@ -388,23 +408,7 @@ jobs: strategy: fail-fast: false matrix: - include: - - runner: ubuntu-24.04 - target: x86_64-unknown-linux-gnu - rust_platform: linux-x86_64 - artifact_name: x64 - debian_arch: amd64 - file_arch: x86-64 - docker_arch: amd64 - cloudsync_arch: x86_64 - - runner: ubuntu-24.04-arm - target: aarch64-unknown-linux-gnu - rust_platform: linux-aarch64 - artifact_name: arm64 - debian_arch: arm64 - file_arch: ARM aarch64 - docker_arch: arm64 - cloudsync_arch: aarch64 + include: ${{ github.event_name == 'pull_request' && fromJSON('[{"runner":"ubuntu-24.04","target":"x86_64-unknown-linux-gnu","rust_platform":"linux-x86_64","artifact_name":"x64","debian_arch":"amd64","file_arch":"x86-64","docker_arch":"amd64","cloudsync_arch":"x86_64"}]') || fromJSON('[{"runner":"ubuntu-24.04","target":"x86_64-unknown-linux-gnu","rust_platform":"linux-x86_64","artifact_name":"x64","debian_arch":"amd64","file_arch":"x86-64","docker_arch":"amd64","cloudsync_arch":"x86_64"},{"runner":"ubuntu-24.04-arm","target":"aarch64-unknown-linux-gnu","rust_platform":"linux-aarch64","artifact_name":"arm64","debian_arch":"arm64","file_arch":"ARM aarch64","docker_arch":"arm64","cloudsync_arch":"aarch64"}]') }} runs-on: ${{ matrix.runner }} defaults: run: @@ -614,7 +618,7 @@ jobs: - run: pnpm -F desktop i18n:check desktop_swift: - if: ${{ !startsWith(github.head_ref || '', 'blog/') }} + if: ${{ github.event_name != 'pull_request' && !startsWith(github.head_ref || '', 'blog/') }} runs-on: depot-macos-15 defaults: run: @@ -629,6 +633,7 @@ jobs: ci: if: always() needs: [ + js_ci, macos_ci, windows_ci, linux_ci, diff --git a/.github/workflows/fmt.yaml b/.github/workflows/fmt.yaml index 6fd826f690..3026855b67 100644 --- a/.github/workflows/fmt.yaml +++ b/.github/workflows/fmt.yaml @@ -6,6 +6,11 @@ on: - main - .github/workflows/fmt.yaml pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: fmt: runs-on: ubuntu-24.04 diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index bc383061fc..ff253aa80c 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -5,6 +5,11 @@ on: branches: - main pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: lint: runs-on: ubuntu-24.04 diff --git a/.github/workflows/mobile_ci.yaml b/.github/workflows/mobile_ci.yaml index 942be46f78..d672f3cfb2 100644 --- a/.github/workflows/mobile_ci.yaml +++ b/.github/workflows/mobile_ci.yaml @@ -2,6 +2,8 @@ name: mobile_ci on: workflow_dispatch: + schedule: + - cron: "0 9 * * *" push: branches: - main @@ -42,13 +44,26 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: CI: "1" EXPO_NO_GIT_STATUS: "1" SENTRY_DISABLE_AUTO_UPLOAD: "true" jobs: + mobile_checks: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/pnpm_install + - run: pnpm -F @anlg/mobile typecheck + - run: pnpm -F @anlg/mobile test + watchos_build: + if: ${{ github.event_name != 'pull_request' }} runs-on: depot-macos-26 timeout-minutes: 30 steps: @@ -64,6 +79,7 @@ jobs: build ios_build: + if: ${{ github.event_name != 'pull_request' }} runs-on: depot-macos-26 timeout-minutes: 45 steps: @@ -81,6 +97,7 @@ jobs: --no-bundler android_build: + if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-24.04 timeout-minutes: 45 steps: @@ -107,7 +124,7 @@ jobs: mobile_ci: if: always() - needs: [watchos_build, ios_build, android_build] + needs: [mobile_checks, watchos_build, ios_build, android_build] runs-on: ubuntu-latest steps: - run: exit 1 diff --git a/.github/workflows/pro_api_e2e.yaml b/.github/workflows/pro_api_e2e.yaml index 628794f8a3..e033eadf52 100644 --- a/.github/workflows/pro_api_e2e.yaml +++ b/.github/workflows/pro_api_e2e.yaml @@ -2,6 +2,8 @@ name: Pro API E2E on: workflow_dispatch: + schedule: + - cron: "0 9 * * *" push: branches: - main @@ -11,13 +13,9 @@ on: - crates/owhisper-client/** - crates/soniox/** - crates/transcribe-proxy/** - pull_request: - paths: - - .github/workflows/pro_api_e2e.yaml - - crates/llm-proxy/** - - crates/owhisper-client/** - - crates/soniox/** - - crates/transcribe-proxy/** +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: pro-transcription: diff --git a/.github/workflows/web_ci.yaml b/.github/workflows/web_ci.yaml index 72bdf998a9..52cfd86c72 100644 --- a/.github/workflows/web_ci.yaml +++ b/.github/workflows/web_ci.yaml @@ -13,6 +13,11 @@ on: paths: - apps/web/** - packages/** + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: ci: runs-on: ubuntu-24.04 diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml index efe09d2303..9df3e8d84d 100644 --- a/.github/workflows/zizmor.yaml +++ b/.github/workflows/zizmor.yaml @@ -3,6 +3,10 @@ on: branches: ["main"] pull_request: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: zizmor: runs-on: ubuntu-24.04 diff --git a/RELEASE_AUDIT.md b/RELEASE_AUDIT.md new file mode 100644 index 0000000000..37e3da66f3 --- /dev/null +++ b/RELEASE_AUDIT.md @@ -0,0 +1,50 @@ +# Release audit + +Heavy, cross-platform verification is deliberately **not** run on every PR. It is +batched into a short audit performed just before cutting a release. This keeps +per-PR feedback fast (so the Bugbot → fix → push loop stays cheap) while the real +"moment of truth" happens once, on purpose. + +## CI model + +- **Per PR (fast lane, Linux only):** lint, format, typecheck, unit/integration + tests, and Linux `cargo check`/`cargo test`. Deduplicated via + `concurrency: cancel-in-progress`, so rapid pushes cancel superseded runs. +- **On merge to `main` + nightly (`schedule`):** the full desktop matrix + (macOS, Windows, Linux arm64, Swift) and the mobile native builds + (iOS, watchOS, Android). Nightly catches platform breakage within a day and + attributes it to a small window — keeping the release audit a clean diff review + rather than a regression hunt. +- **Release (this audit):** full builds + signing + real-hardware QA. + +## Audit checklist + +Run these before publishing a stable desktop release. + +1. **Read the cumulative diff since the last version.** + `git diff ..main -- apps/desktop/src-tauri plugins crates apps/desktop/src` + (see the `diff` task in `Taskfile.yaml`). Polish from first principles: + simplify, delete dead code, reconcile inconsistencies introduced across PRs. + +2. **Confirm the heavy suites are green** on the release candidate: + - `desktop_ci` and `mobile_ci` — trigger via `workflow_dispatch` on the + candidate (or confirm the latest nightly on `main` passed). + - `pro_api_e2e` — nightly/dispatch (live provider APIs). + +3. **Build + sign all platforms** via `desktop_cd` (`staging` first, then + `stable`). This produces the signed macOS/Windows/Linux artifacts. + +4. **Real-hardware QA** (cannot run in CI/Cloud Agent): + - Critical Pro user journey on a Mac — follow `.agents/skills/qa-critical-ux`. + - Linux system-audio capture — `desktop_linux_audio_qa` against the candidate. + +5. **Changelog** — add the entry via `.agents/skills/new-changelog`. + +6. **Cut the release** — follow `.agents/skills/release-new-version`. + +## Notes + +- Anything that fails incidentally but is out of scope for the release gate is + tracked in Linear, not patched into the candidate (see `qa-critical-ux`). +- macOS/iOS/watchOS/Windows verification requires real Apple/Windows machines; + the Linux Cloud Agent covers authoring + Linux-native checks only.