Skip to content

sql-orm-client: run update and delete through a mutation graph #2988

sql-orm-client: run update and delete through a mutation graph

sql-orm-client: run update and delete through a mutation graph #2988

Workflow file for this run

name: CI (PR)
on:
pull_request:
merge_group:
# Least-privilege GITHUB_TOKEN: only repo checkout needs a scope here. The
# pnpm/Turbo caches (actions/cache) use the runner's cache runtime token, not
# GITHUB_TOKEN, so no `actions` scope is required.
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.sha }}
cancel-in-progress: true
jobs:
# Classifies the PR diff as "inert" (touches only files that cannot affect
# build/test/fixture results) so heavy jobs can skip their expensive steps.
# Fail-safe: a diff is inert only if *every* changed file matches the
# allow-list below; any unrecognized path forces a full run. Required jobs
# still launch and report (Pattern 1), so the branch ruleset stays satisfied
# on docs-only PRs while the Postgres-backed work is skipped.
changes:
name: Detect inert diff
runs-on: ubuntu-latest
outputs:
inert: ${{ steps.detect.outputs.inert }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- id: detect
uses: ./.github/actions/detect-inert-diff
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Check working tree is clean
run: pnpm check:clean-tree
typecheck:
name: Type Check
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter prisma-orm-demo prisma:generate
- name: Build packages (restored from Turbo cache)
run: pnpm build
- name: Type check packages
run: pnpm typecheck:packages
- name: Type check examples
run: pnpm typecheck:examples
lint:
name: Lint
# Depends on build only for cache coherence: build is the single writer of
# the shared Turbo/pnpm caches, so every other job restores an exact-key
# hit and skips saving. The build step below just restores that cache.
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# The per-PR gates diff HEAD against the branch this PR targets;
# needs enough history for `git diff origin/<base>..HEAD` to resolve.
fetch-depth: 0
- name: Fetch the base branch this PR targets
env:
BASE: ${{ github.base_ref || 'main' }}
run: git fetch --no-tags origin "$BASE:refs/remotes/origin/$BASE"
- uses: ./.github/actions/setup
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages (restored from Turbo cache)
run: pnpm build
- name: Lint dependencies
run: pnpm lint:deps
- name: Lint code shape
run: pnpm lint:code
- name: Lint packages
run: pnpm lint:packages
- name: Lint examples
run: pnpm lint:examples
- name: Validate rules
run: pnpm lint:rules
- name: Validate rule symlinks
run: pnpm lint:rules:symlinks
- name: Validate skills
run: pnpm lint:skills
- name: Check rules footprint
run: pnpm lint:rules:footprint
- name: Validate package READMEs
run: pnpm lint:docs
- name: Validate package manifests (license declarations)
run: pnpm lint:manifests
- name: Lint workflow triggers (forbid Pwn Request pattern)
run: pnpm lint:workflows
- name: Test scripts/
run: pnpm test:scripts
- name: Lint casts
run: pnpm lint:casts
- name: Lint throws
run: pnpm lint:throws
- name: Lint framework vocabulary
run: pnpm lint:framework-vocabulary
- name: Lint consumer internal imports
run: pnpm lint:consumer-internal-imports
- name: Lint the legacy product name
run: pnpm lint:legacy-name
- name: Lint vitest timeout budgets
run: pnpm lint:vitest-timeouts
- name: Lint publishability matches the directory layout
run: pnpm lint:publishability
- name: Check upgrade-instruction coverage
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }}
HEAD_SHA: ${{ github.event.merge_group.head_sha || github.sha }}
run: pnpm check:upgrade-coverage --mode pr --prev "$BASE_SHA" --head "$HEAD_SHA"
- name: Check error-reference completeness
run: pnpm check:error-reference
- name: Check release notes
env:
BASE: ${{ github.base_ref || 'main' }}
run: pnpm check:release-notes --mode pr --prev "origin/$BASE"
fixtures:
name: Fixtures
needs: [build, changes]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies
if: needs.changes.outputs.inert != 'true'
run: pnpm install --frozen-lockfile
- name: Build (restored from Turbo cache)
if: needs.changes.outputs.inert != 'true'
run: pnpm build
- name: Link built binaries
if: needs.changes.outputs.inert != 'true'
run: pnpm install --frozen-lockfile
- name: Check fixtures are up to date
if: needs.changes.outputs.inert != 'true'
run: pnpm fixtures:check
test-packages:
name: Package Tests (${{ matrix.index }}/4)
needs: [build, changes]
if: needs.changes.outputs.inert != 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
index: [1, 2, 3, 4]
env:
TEST_TIMEOUT_MULTIPLIER: 2
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U postgres"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies (skip bin linking)
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Build packages (restored from Turbo cache; needed for bin linking)
run: pnpm build
- name: Link bins
run: pnpm install --frozen-lockfile
- name: Run package tests with coverage
id: package-tests
continue-on-error: true
env:
VITEST_COVERAGE_SHARD: ${{ matrix.index }}
run: pnpm coverage:packages --reporter=default --reporter=github-actions --reporter=blob --shard=${{ matrix.index }}/4
- name: Upload package coverage shard
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: package-coverage-${{ matrix.index }}
path: .vitest/blob/blob-${{ matrix.index }}-4.json
if-no-files-found: error
include-hidden-files: true
retention-days: 1
- name: Propagate package test failure
if: steps.package-tests.outcome == 'failure'
run: exit 1
test-examples:
name: Test Examples
needs: [build, changes]
if: needs.changes.outputs.inert != 'true'
runs-on: ubuntu-latest
env:
TEST_TIMEOUT_MULTIPLIER: 2
# Used by examples/prisma-8-cloudflare-worker's vitest-pool-workers
# integration test. Mirrors the .env.example pattern; the container is
# brought up by `pnpm db:up` below (docker-compose, not a service
# container, because GitHub Actions service containers can't override
# the postgres CMD to enable shared_preload_libraries=pg_stat_statements).
WRANGLER_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE: postgres://postgres:postgres@127.0.0.1:5433/prisma_8_cloudflare_worker
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U postgres"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies (skip bin linking)
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Build packages (restored from Turbo cache; needed for bin linking)
run: pnpm build
- name: Link bins
run: pnpm install --frozen-lockfile
- name: Start cloudflare-worker Postgres (5433, pg_stat_statements)
run: pnpm --filter prisma-8-cloudflare-worker db:up
# Fetch Prisma 7's schema engine, which the install does not download,
# so a slow or unreachable binary host fails this step within 5 minutes
# instead of timing out inside the example test.
- name: Fetch the Prisma 7 schema engine (prisma7-adoption)
timeout-minutes: 5
run: pnpm --filter prisma7-adoption exec prisma7 --version --config prisma7.config.ts
- name: Test examples
run: pnpm test:examples
- name: Check working tree is clean
run: pnpm check:clean-tree
coverage:
name: Coverage
needs: [build, changes, test-packages]
if: ${{ !cancelled() && needs.build.result == 'success' && needs.changes.result == 'success' && needs.changes.outputs.inert != 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Build packages (restored from Turbo cache)
run: pnpm build
- name: Download package coverage shards
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: package-coverage-*
path: .vitest/blob
merge-multiple: true
- name: Verify package coverage shards
run: |
test -f .vitest/blob/blob-1-4.json
test -f .vitest/blob/blob-2-4.json
test -f .vitest/blob/blob-3-4.json
test -f .vitest/blob/blob-4-4.json
- name: Merge package tests and coverage
run: pnpm coverage:packages:merge
- name: Report package coverage
if: ${{ !cancelled() }}
run: pnpm coverage:report
- name: Check working tree is clean
if: ${{ !cancelled() }}
run: pnpm check:clean-tree
test:
name: Test
needs: [build, changes, test-packages, test-examples, coverage, test-integration]
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
- name: Propagate test failures
if: ${{ needs.build.result != 'success' || needs.changes.result != 'success' || (needs.changes.outputs.inert != 'true' && (needs.test-packages.result != 'success' || needs.test-examples.result != 'success' || needs.coverage.result != 'success')) }}
run: exit 1
- name: Require integration tests in the merge queue
if: ${{ github.event_name == 'merge_group' && needs.changes.outputs.inert != 'true' && needs.test-integration.result != 'success' }}
run: exit 1
test-e2e:
name: E2E Tests
needs: [build, changes]
runs-on: ubuntu-latest
env:
TEST_TIMEOUT_MULTIPLIER: 2
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U postgres"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install dependencies
if: needs.changes.outputs.inert != 'true'
run: pnpm install --frozen-lockfile
- name: Build (restored from Turbo cache)
if: needs.changes.outputs.inert != 'true'
run: pnpm build
- name: Run E2E tests
if: needs.changes.outputs.inert != 'true'
run: pnpm test:e2e
- name: Check working tree is clean
if: needs.changes.outputs.inert != 'true'
run: pnpm check:clean-tree
test-integration:
name: Integration Tests (${{ matrix.shard }})
needs: [build, changes]
# Runs only in the merge queue, where `Test` requires it. The suite is
# slow, so pull requests do not run it; run it on a branch with
# `gh workflow run integration.yml --ref <branch>`.
if: github.event_name == 'merge_group' && needs.changes.outputs.inert != 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: ['1/4', '2/4', '3/4', '4/4']
env:
TEST_TIMEOUT_MULTIPLIER: 2
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/integration-tests
with:
shard: ${{ matrix.shard }}
# Runs the real-Supabase acceptance harness against a live local Supabase
# stack (`supabase start`), so the extension's role/grant/JWT behaviour is
# proven against real platform defaults on every PR — the hermetic shim
# alone let fidelity bugs ship (TML-3035 findings §5/§6/§8). Skips its
# steps only on inert (docs-only) diffs; any change under packages/** or
# examples/** is non-inert, so extension-supabase, examples/supabase, and
# postgres target/adapter changes always run it. The stack's Docker images
# are loaded from a cache that supabase-images.yml writes on main, because
# public.ecr.aws rate-limits anonymous pulls; on a cache miss
# `supabase start` pulls them from the registry.
supabase-acceptance:
name: Supabase Acceptance
needs: [build, changes]
runs-on: ubuntu-latest
timeout-minutes: 25
env:
TEST_TIMEOUT_MULTIPLIER: 2
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup
- name: Install Supabase CLI
id: supabase-cli
if: needs.changes.outputs.inert != 'true'
uses: ./.github/actions/supabase-cli
- name: Restore Supabase Docker images
id: supabase-images
if: needs.changes.outputs.inert != 'true'
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ steps.supabase-cli.outputs.images-archive }}
key: ${{ steps.supabase-cli.outputs.images-cache-key }}
# Deleting the archive after loading frees its disk space for the build.
- name: Load Supabase Docker images
if: needs.changes.outputs.inert != 'true' && steps.supabase-images.outputs.cache-hit == 'true'
env:
ARCHIVE: ${{ steps.supabase-cli.outputs.images-archive }}
run: |
docker load --input "$ARCHIVE"
rm "$ARCHIVE"
- name: Install dependencies
if: needs.changes.outputs.inert != 'true'
run: pnpm install --frozen-lockfile
- name: Build (restored from Turbo cache)
if: needs.changes.outputs.inert != 'true'
run: pnpm build
- name: Start local Supabase stack
if: needs.changes.outputs.inert != 'true'
working-directory: examples/supabase
run: supabase start
- name: Export stack credentials for the acceptance harness
if: needs.changes.outputs.inert != 'true'
working-directory: examples/supabase
run: |
set -euo pipefail
supabase status -o env > "$RUNNER_TEMP/supabase-status.env"
set -a
# shellcheck disable=SC1091
. "$RUNNER_TEMP/supabase-status.env"
set +a
{
echo "DATABASE_URL=$DB_URL"
echo "SUPABASE_JWT_SECRET=$JWT_SECRET"
echo "SUPABASE_URL=$API_URL"
echo "SUPABASE_ANON_KEY=$ANON_KEY"
} >> "$GITHUB_ENV"
- name: Run the real-Supabase acceptance harness
if: needs.changes.outputs.inert != 'true'
run: pnpm --filter supabase-example test test/real-supabase.acceptance.test.ts