Skip to content

chore(deps): bump the production-minor-patch group across 1 directory with 10 updates #433

chore(deps): bump the production-minor-patch group across 1 directory with 10 updates

chore(deps): bump the production-minor-patch group across 1 directory with 10 updates #433

name: Integration — Supabase (EQL v3)
# Real ZeroKMS ciphertext, a real PostgREST, and `supabase/postgres` — the only
# job that proves the Supabase v3 adapter's queries return the right rows. The
# unit suites drive a mock that records strings; they cannot.
#
# Separate from `tests.yml` on purpose: these suites need CipherStash credentials
# and a database, and they THROW rather than skip when unconfigured. Keeping them
# out of the unit job is what lets `pnpm test` stay runnable with neither.
on:
push:
branches: [main]
paths:
- 'packages/stack-supabase/**'
- 'packages/stack/src/eql/v3/**'
# Source layers the adapter's encoding/round-trip rests on: a break here
# (not just under src/supabase) can produce wrong wire output or rows, so
# trigger the live suite that would catch it.
- 'packages/stack/src/encryption/**'
- 'packages/stack/src/schema/**'
- 'packages/stack/integration/**'
# The DynamoDB adapter, and the entry/type modules the suites import
# directly. `integration/shared/v2-decrypt-compat` is the repo's only live
# EQL v2 read coverage for the native entry (the `integration/wasm/` twin
# runs on the Drizzle job) and it exercises the DynamoDB legacy path, so a
# change here must run it. Pinned by
# scripts/__tests__/integration-workflow-paths.test.mjs.
- 'packages/stack/src/dynamodb/**'
- 'packages/stack/src/index.ts'
- 'packages/stack/src/types.ts'
# That v2 suite mints its fixtures by importing `@cipherstash/protect-ffi`
# directly. A native-module bump is the change most able to break v2
# payload deserialization and it touches NO source directory, so without
# these two entries the only suites that would catch it never start. They
# are the files a bump actually edits: exact pins (`protect-ffi`,
# `@cipherstash/eql`) live in the package manifest, `catalog:` ones
# (`@cipherstash/auth`) in the workspace catalog.
#
# `pnpm-lock.yaml` is deliberately NOT listed. It changes on roughly every
# dependency bump in the monorepo — far more often than either file here —
# and these are credentialed, database-backed jobs. Nothing is lost: a
# protect-ffi or auth version change cannot reach the lockfile without
# editing one of the two manifests below first.
- 'packages/stack/package.json'
- 'pnpm-workspace.yaml'
- 'packages/test-kit/**'
- 'packages/cli/src/installer/**'
- 'local/docker-compose.supabase.yml'
- 'local/supabase-init.sql'
- '.github/workflows/integration-supabase.yml'
- '.github/actions/integration-setup/**'
- '.github/actions/integration-db/**'
- '.github/actions/build-ffi-binding/**'
# The Rust that produces every EQL payload these suites round-trip.
# Absorbing protect-ffi put it in-tree, so a crate change can now
# break them in a PR that touches no TypeScript at all.
#
# The manifests are here for the same reason as the sources: a
# dependency bump in Cargo.lock changes the compiled encryption core
# without touching a .rs file, and package.json / mise.toml carry the
# build scripts and the toolchain pin. Matching the filter in
# tests-rust.yml, which already covers all four.
- 'packages/protect-ffi/crates/**'
- 'packages/protect-ffi/src/**'
- 'packages/protect-ffi/Cargo.toml'
- 'packages/protect-ffi/Cargo.lock'
- 'packages/protect-ffi/package.json'
- 'packages/protect-ffi/mise.toml'
pull_request:
branches: ['**']
paths:
- 'packages/stack-supabase/**'
- 'packages/stack/src/eql/v3/**'
# Source layers the adapter's encoding/round-trip rests on: a break here
# (not just under src/supabase) can produce wrong wire output or rows, so
# trigger the live suite that would catch it.
- 'packages/stack/src/encryption/**'
- 'packages/stack/src/schema/**'
- 'packages/stack/integration/**'
# The DynamoDB adapter, and the entry/type modules the suites import
# directly. `integration/shared/v2-decrypt-compat` is the repo's only live
# EQL v2 read coverage for the native entry (the `integration/wasm/` twin
# runs on the Drizzle job) and it exercises the DynamoDB legacy path, so a
# change here must run it. Pinned by
# scripts/__tests__/integration-workflow-paths.test.mjs.
- 'packages/stack/src/dynamodb/**'
- 'packages/stack/src/index.ts'
- 'packages/stack/src/types.ts'
# That v2 suite mints its fixtures by importing `@cipherstash/protect-ffi`
# directly. A native-module bump is the change most able to break v2
# payload deserialization and it touches NO source directory, so without
# these two entries the only suites that would catch it never start. They
# are the files a bump actually edits: exact pins (`protect-ffi`,
# `@cipherstash/eql`) live in the package manifest, `catalog:` ones
# (`@cipherstash/auth`) in the workspace catalog.
#
# `pnpm-lock.yaml` is deliberately NOT listed. It changes on roughly every
# dependency bump in the monorepo — far more often than either file here —
# and these are credentialed, database-backed jobs. Nothing is lost: a
# protect-ffi or auth version change cannot reach the lockfile without
# editing one of the two manifests below first.
- 'packages/stack/package.json'
- 'pnpm-workspace.yaml'
- 'packages/test-kit/**'
- 'packages/cli/src/installer/**'
- 'local/docker-compose.supabase.yml'
- 'local/supabase-init.sql'
- '.github/workflows/integration-supabase.yml'
- '.github/actions/integration-setup/**'
- '.github/actions/integration-db/**'
- '.github/actions/build-ffi-binding/**'
# The Rust that produces every EQL payload these suites round-trip.
# Absorbing protect-ffi put it in-tree, so a crate change can now
# break them in a PR that touches no TypeScript at all.
#
# The manifests are here for the same reason as the sources: a
# dependency bump in Cargo.lock changes the compiled encryption core
# without touching a .rs file, and package.json / mise.toml carry the
# build scripts and the toolchain pin. Matching the filter in
# tests-rust.yml, which already covers all four.
- 'packages/protect-ffi/crates/**'
- 'packages/protect-ffi/src/**'
- 'packages/protect-ffi/Cargo.toml'
- 'packages/protect-ffi/Cargo.lock'
- 'packages/protect-ffi/package.json'
- 'packages/protect-ffi/mise.toml'
jobs:
integration:
name: Supabase v3 integration (db=${{ matrix.db }})
runs-on: blacksmith-4vcpu-ubuntu-2404
# No concurrency group: `integration-db` gives each job its own compose
# project and ephemeral host ports, so live-DB jobs no longer contend and do
# not need serialising. See that action for why the old
# `integration-live-db-<db>` group had to go (it cancelled a third
# contender rather than queueing it).
#
# Fork PRs have no secrets. Skip cleanly rather than fail loudly on something
# the contributor cannot fix — `tests.yml` still gives them a green signal.
# Every OTHER event runs, which is why this gates on "not a fork PR" rather
# than listing the event names allowed through: the listing form skipped
# the job on `workflow_dispatch` in integration-protect-ffi.yml, making a
# declared manual trigger do nothing. Enforced by
# scripts/__tests__/workflow-dispatch-job-conditions.test.mjs.
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
strategy:
# A one-element matrix, not a cross-product: the Supabase adapter only ever
# runs against the Supabase variant. Kept as a matrix so adding a second
# database is a one-line change.
matrix:
db: [supabase]
env:
CS_WORKSPACE_CRN: ${{ vars.CS_WORKSPACE_CRN }}
CS_CLIENT_ID: ${{ vars.CS_CLIENT_ID }}
CS_CLIENT_KEY: ${{ secrets.CS_CLIENT_KEY }}
CS_CLIENT_ACCESS_KEY: ${{ secrets.CS_CLIENT_ACCESS_KEY }}
# `DATABASE_URL` / `PGRST_URL` are set per step from the `integration-db`
# outputs — the host ports are assigned by Docker at start-up, so they
# cannot be written down here. The role that URL connects as (`postgres`)
# is deliberately NOT a superuser on this image, which is what makes the
# EQL install, the grants, and the ORE opclass skip behave as they do on a
# real Supabase project.
#
# EXPLICIT, never inferred from `PGRST_URL` — see `dbVariant()`.
CS_IT_DB_VARIANT: ${{ matrix.db }}
# Scoped by directory, never by named file, so a renamed suite cannot
# silently drop from CI. `integration/shared/` holds the adapter-agnostic
# suites (harness, bloom, the ope-term tripwire for THIS job's `col->op`
# ordering path, and the crypto/SQL matrices); the Drizzle suites talk to
# plain Postgres and get their own job.
#
# `integration/identity/` runs on the Drizzle job (it needs Postgres +
# Drizzle, not PostgREST), so it is intentionally not listed here.
# The Supabase adapter suites now live in @cipherstash/stack-supabase (run
# below via its own test:integration). This glob scopes the adapter-agnostic
# `shared/` core suites that still live in @cipherstash/stack and run against
# this job's Postgres too.
CS_IT_SUITE: >-
integration/shared/**/*.integration.test.ts
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/integration-setup
# Fast pre-flight: fail in seconds if a secret was rotated or cleared,
# before the binding build and before paying for the ~2 GB
# supabase/postgres pull. The in-test `requireIntegrationEnv` is the
# correctness guarantee; this is the cheap one, so nothing expensive may
# be ordered ahead of it.
- name: Require CipherStash secrets
uses: ./.github/actions/require-cs-secrets
with:
workspace-crn: ${{ vars.CS_WORKSPACE_CRN }}
client-id: ${{ vars.CS_CLIENT_ID }}
client-key: ${{ secrets.CS_CLIENT_KEY }}
client-access-key: ${{ secrets.CS_CLIENT_ACCESS_KEY }}
# No `wasm: true` — this job's CS_IT_SUITE is `integration/shared/**`
# only, which goes through the native binding.
- name: Build the protect-ffi binding
uses: ./.github/actions/build-ffi-binding
# No pre-`up` cleanup step any more: the project name is unique per job, so
# a container leaked by a hard-killed prior run cannot hold this job's
# name or its (ephemeral) port. Blanket-pruning would now be actively
# unsafe — without the concurrency group, another job's stack may be live
# on this runner.
- name: Start ${{ matrix.db }}
id: db
uses: ./.github/actions/integration-db
with:
db: ${{ matrix.db }}
# `globalSetup` installs EQL v3 by shelling out to the real
# `stash eql install --eql-version 3 --supabase --direct`, so an installer
# regression fails here rather than hiding behind a test-only SQL apply.
#
# Step env, not a `.env` file: `dotenv/config` does not override an
# already-set `process.env`, so these win and no secret is written to disk.
- name: Supabase v3 integration suites
run: pnpm exec turbo run test:integration --filter @cipherstash/stack-supabase --env-mode=loose
env:
DATABASE_URL: ${{ steps.db.outputs.database-url }}
PGRST_URL: ${{ steps.db.outputs.pgrest-url }}
# A second vitest invocation (stack's shared/ suites live in a different
# package now). Its globalSetup calls the same EQL v3 install, but
# `isInstalled` short-circuits against the DB the first invocation already
# provisioned — so this is a fast no-op check, not a second schema apply.
- name: Shared core integration suites (against Supabase Postgres)
run: pnpm exec turbo run test:integration --filter @cipherstash/stack --env-mode=loose
env:
DATABASE_URL: ${{ steps.db.outputs.database-url }}
PGRST_URL: ${{ steps.db.outputs.pgrest-url }}
# Guarded on the project being set: if the stack never came up, there is
# nothing to tear down and an unguarded `-p ""` would fail the job with a
# confusing error that masks the real one.
- name: Stop ${{ matrix.db }}
if: always() && env.CS_COMPOSE_PROJECT != ''
run: docker compose -p "$CS_COMPOSE_PROJECT" -f "$CS_COMPOSE_FILE" down -v