Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/actions/setup-desktop/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,28 @@ inputs:
cache-key:
description: Shared rust-cache key (jobs that build the same artifacts share one).
default: desktop
npm-cache-paths:
description: Lockfiles that key the npm cache (add web/ or supabase/ ones when the job installs them).
default: package-lock.json
runs:
using: composite
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
cache-dependency-path: package-lock.json
cache-dependency-path: ${{ inputs.npm-cache-paths }}

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri -> target
shared-key: ${{ inputs.cache-key }}
# Only main writes Rust caches: PR saves (one per key per OS) evicted
# them from the 10 GB repo quota. PRs restore main's cache.
save-if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
cache-on-failure: true

- name: Install Linux system dependencies
if: runner.os == 'Linux'
Expand Down
31 changes: 29 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ on:
permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
verify:
name: Typecheck
Expand All @@ -38,14 +42,15 @@ jobs:
e2e:
name: End-to-end tests
runs-on: ubuntu-latest
needs: verify
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
cache-dependency-path: web/package-lock.json
cache-dependency-path: |
web/package-lock.json
supabase/functions/package-lock.json
# Same CLI pin as cloud.yml.
- uses: supabase/setup-cli@v1
with:
Expand All @@ -67,12 +72,34 @@ jobs:
- name: Install dependencies
working-directory: web
run: npm ci
# Docusaurus/webpack build cache; restored from the newest entry.
- name: Cache Docusaurus build
uses: actions/cache@v4
with:
path: |
web/.docusaurus
web/node_modules/.cache
key: docusaurus-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }}-${{ github.sha }}
restore-keys: docusaurus-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }}-
- name: Build site
working-directory: web
run: npm run build
# Browser binaries are keyed by the lockfile (it pins the Playwright version).
- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
working-directory: web
run: npx playwright install --with-deps chromium
# Cached browsers still need the system libraries.
- name: Install Playwright system dependencies
if: steps.playwright-cache.outputs.cache-hit == 'true'
working-directory: web
run: npx playwright install-deps chromium
- name: Run Playwright tests
working-directory: web
run: npm run test:e2e
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/cloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ jobs:
- uses: ./.github/actions/setup-desktop
with:
cache-key: cloud
npm-cache-paths: |
package-lock.json
web/package-lock.json
supabase/functions/package-lock.json
# Pinned to the CLI version the stack is developed against. A maintainer
# should also pin this action to a commit SHA.
- uses: supabase/setup-cli@v1
Expand All @@ -77,6 +81,13 @@ jobs:
key=$(sed -n 's/^IXTABLE_CLOUD_PUBLIC_KEY_RAW=//p' supabase/functions/.env.local)
test -n "$key"
echo "IXTABLE_CLOUD_PUBLIC_KEY_RAW=$key" >> "$GITHUB_ENV"
# Deno module cache for the Edge Function type check and tests.
- name: Cache Deno modules
uses: actions/cache@v4
with:
path: ~/.cache/deno
key: deno-${{ runner.os }}-${{ hashFiles('supabase/functions/deno.json', 'supabase/functions/deno.lock', 'scripts/cloud/deno-test.mjs') }}
restore-keys: deno-${{ runner.os }}-
# Deno comes from npm (npx deno@<pinned>) inside the script.
- name: Edge Function type check and Deno unit tests
run: npm run service-qa:deno
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/deploy-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Cache Docusaurus build
uses: actions/cache@v4
with:
path: |
web/.docusaurus
web/node_modules/.cache
key: docusaurus-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }}-${{ github.sha }}
restore-keys: docusaurus-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }}-

- name: Build web app
run: npm run build

Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@ jobs:

# Service containers are Linux-only, so macOS and Windows start PostgreSQL
# natively (scripts/ci/start-postgres.mjs exports IXTABLE_TEST_POSTGRES_URL).
# Main only: PRs get PostgreSQL coverage from the ubuntu job, freeing macOS/Windows runners.
postgres-native:
name: PostgreSQL conformance (${{ matrix.os }})
if: github.event_name != 'pull_request'
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -227,12 +229,13 @@ jobs:
if-no-files-found: ignore
retention-days: 7

# PRs run golden apps on ubuntu only to free macOS/Windows runners; main runs all three.
golden:
name: Golden apps (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: ${{ fromJSON(github.event_name == 'pull_request' && '["ubuntu-latest"]' || '["ubuntu-latest","macos-latest","windows-latest"]') }}
runs-on: ${{ matrix.os }}
steps:
# Keep LF endings so fixtures and snapshots match on Windows.
Expand Down Expand Up @@ -278,8 +281,10 @@ jobs:

# Performance budgets (PRD 搂27.3, docs/decisions/performance-budgets.md). Report-only:
# results go to the job summary and an artifact, and a budget miss never fails CI.
# Runs on main only: a report-only release build is not worth a PR runner.
perf:
name: Performance budgets (report-only)
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
continue-on-error: true
services:
Expand Down
7 changes: 4 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ the UI with `userEvent`, query by role/label, use `findBy*` with

`.github/workflows/desktop.yml`: lint, then tests on ubuntu/macos/windows
(with the 500 MB archive test, `IXTABLE_HEAVY_TESTS=1`), PostgreSQL
conformance on all three (ubuntu service container, native server elsewhere
via `scripts/ci/start-postgres.mjs`), golden suites
(`tests/integration/golden/`), and a debug `tauri build` on ubuntu. Shared
conformance (ubuntu service container; on `main` also macOS/Windows with a
native server via `scripts/ci/start-postgres.mjs`), golden suites
(`tests/integration/golden/`; PRs ubuntu only, `main` all three), perf
budgets (`main` only), and a debug `tauri build` on ubuntu. Shared
setup is `.github/actions/setup-desktop`. Keep commands cross-platform: use
Node scripts under `scripts/ci/` instead of POSIX shell in `package.json`.

Expand Down
3 changes: 2 additions & 1 deletion docs/decisions/performance-budgets.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ remove that build first when one exists.

### CI

The `perf` job in `.github/workflows/desktop.yml` runs both halves in release
The `perf` job in `.github/workflows/desktop.yml` runs on pushes to `main`
(not on pull requests, to keep PR runners free). It runs both halves in release
mode on `ubuntu-latest` with a PostgreSQL 16 service, publishes the table to
the job summary, and uploads `reports/perf/*.json` and `summary.md` as the
`performance-budgets` artifact. The job has `continue-on-error: true` and no
Expand Down
5 changes: 4 additions & 1 deletion docs/decisions/windows-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Status: accepted, pending Windows CI. Windows is a release-blocking platform (PRD 搂6.1).
Green Desktop CI on Windows, macOS, and Linux is the `green-ci-all-os` gate in
[the release gates](../release-checklist.md).
[the release gates](../release-checklist.md). Pull requests run the golden
suite on Linux only; `main` and the release workflow run it on all three.

## What failed

Expand Down Expand Up @@ -93,3 +94,5 @@ The `dumpbin /imports` diagnostic step stays until the Windows jobs are green.
unchanged.
- 2026-10-05 (later): runners returned. Recorded the first Windows results and
the fixes (global.db race, data gate starvation, basename, state dir cleanup).
- 2026-10-06: golden suite runs on Linux only for pull requests; `main`
and release still run it on Windows, macOS, and Linux.
3 changes: 2 additions & 1 deletion scripts/ci/release-gates.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ export const GATES = [
check: (root) => {
const problems = [];
const desktop = file(root, ".github/workflows/desktop.yml");
const matrices = desktop.match(/os: \[[^\]]+\]/g) ?? [];
// A literal `os: [...]` list, or the push branch of a PR-conditional fromJSON matrix.
const matrices = desktop.match(/os: \[[^\]]+\]|'\["ubuntu-latest","macos-latest","windows-latest"\]'/g) ?? [];
if (matrices.filter((m) => THREE_OS.test(m)).length < 2)
problems.push("desktop.yml test and golden jobs must both run on all three OSes");
if (
Expand Down
Loading