name: PR Checks # The thin trusted merge gate (docs/plans/2026-06-04-001-refactor-fast-trusted-test-gate-plan.md). # Blocking checks are exactly: Lint, Typecheck, Build, Gate. # # BRANCH-PROTECTION CUTOVER: required status checks are matched by job name. # When this file changes job names, update the repo's branch-protection # required checks to exactly [Lint, Typecheck, Build, Gate] — a stale required # name (e.g. "Test shard 1/4") that no longer reports will block every PR # with "Expected — waiting for status". Open PRs must rebase onto main after # the cutover so they run this workflow shape. # # Everything that used to run here as shards / slow tier / inventory guard is # non-blocking and lives in full-suite.yml (push to main). on: pull_request: branches: [main] concurrency: group: pr-checks-${{ github.ref }} cancel-in-progress: true # Least-privilege token: every job here only reads the repo (checkout + cache). permissions: contents: read # FN-4863: Opt JavaScript actions into Node 24 ahead of GitHub's forced cutover on 2026-06-02. env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" jobs: lint: name: Lint runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js and pnpm uses: ./.github/actions/setup-node-pnpm - name: Lint run: pnpm lint - name: Changeset format run: pnpm check:changesets typecheck: name: Typecheck runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js and pnpm uses: ./.github/actions/setup-node-pnpm - name: Typecheck run: pnpm typecheck build: name: Build runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js and pnpm uses: ./.github/actions/setup-node-pnpm - name: Build run: pnpm build # The only merge-blocking TEST signal (R3). Runs the boot smoke (the app # starts and serves) plus the curated engine-core suite and the CI-shape # test — see `test:gate` in the root package.json. Gate membership is the # explicit allow-list in packages/engine/vitest.config.ts (engine-core # project); a flaky gate test is evicted by removing it from that list. gate: name: Gate runs-on: ubuntu-latest # FNXC:FixPgTestsAndCi 2026-06-26-09:10: # Provision a PostgreSQL service container so the postgres/*.pg.test.ts # suites (pgDescribe) run in the merge gate. The pg-test-harness probe # detects reachability via a TCP probe on localhost:5432 and skips when # unavailable, so this service is what makes the 57 PG twin tests actually # execute instead of being silently skipped. services: postgres: image: postgres:15 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: postgres ports: - 5432:5432 # Mark the service healthy only when pg_isready succeeds on the mapped # port, so job steps don't start before Postgres accepts connections. options: >- --health-cmd "pg_isready -h localhost -p 5432 -U postgres" --health-interval 5s --health-timeout 5s --health-retries 10 env: # Point the PG test harness at the service container. psql admin DDL # (CREATE/DROP DATABASE) runs against this URL's maintenance database. FUSION_PG_TEST_URL_BASE: "postgresql://postgres:postgres@localhost:5432" PGPASSWORD: "postgres" # The gate's value is speed; without a job timeout a hung build or # deadlocked vitest worker blocks every PR for GitHub's default 6 hours. # Expected runtime is ~3-5 min. timeout-minutes: 15 steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js and pnpm uses: ./.github/actions/setup-node-pnpm # Dist-artifact cache (same contract as full-suite.yml): exact-match # key only, NO restore-keys (stale dist is the known failure mode, # FN-4232/FN-4605), NEVER node_modules (breaks Windows pnpm junctions). - name: Compute dist source hash id: dist-hash run: echo "hash=$(node scripts/ensure-test-artifacts.mjs --print-source-hash)" >> "$GITHUB_OUTPUT" - name: Cache built dist artifacts id: dist-cache uses: actions/cache@v4 with: path: | packages/core/dist packages/dashboard/dist packages/engine/dist packages/plugin-sdk/dist plugins/fusion-plugin-dependency-graph/dist plugins/fusion-plugin-hermes-runtime/dist plugins/fusion-plugin-openclaw-runtime/dist plugins/fusion-plugin-paperclip-runtime/dist key: dist-${{ runner.os }}-${{ steps.dist-hash.outputs.hash }} - name: Seed artifact hash-cache on cache hit if: steps.dist-cache.outputs.cache-hit == 'true' run: node scripts/ensure-test-artifacts.mjs --seed-artifact-cache # Boot smoke needs the full built workspace (CLI dist is not in the # cache list above); cached packages make this incremental-fast. - name: Build run: pnpm build - name: Boot smoke (app starts and serves) run: node scripts/boot-smoke.mjs - name: Gate tests (curated engine-core + CI-shape) run: pnpm test:gate # Advisory desktop-packaging validation lives in its OWN workflow (desktop-packaging.yml) so this # thin gate stays exactly [Lint, Typecheck, Build, Gate] — the job set here maps 1:1 to the # branch-protection required checks (CI-shape test enforces the invariant).