Skip to content

CI on the escape for every job, the nightly cold clone, and e2e through the lookup - #1227

Merged
borisno2 merged 2 commits into
prisma-8from
claude/issue-1160-ci-nightly-e2e
Sep 6, 2026
Merged

CI on the escape for every job, the nightly cold clone, and e2e through the lookup#1227
borisno2 merged 2 commits into
prisma-8from
claude/issue-1160-ci-nightly-e2e

Conversation

@borisno2

@borisno2 borisno2 commented Sep 6, 2026

Copy link
Copy Markdown
Member

Implements #1160. Part of #1125.

Already in place before this PR

The test job's service container was already a pgvector-capable Postgres 17 (pgvector/pgvector@sha256:cf134a…, pinned by digest), and the four integration-branch test steps already set DATABASE_URL at it — both landed with #1157. The plain-Node anchor already imports .opensaas/context.ts (packages/cli/tests/bundle-node-load.test.ts, from #1138); nothing to re-target.

What changed

.github/workflows/test.ymlDATABASE_URL moves from four steps to the test job, so the step that was missing it (Run browser tests with coverage) and every future step carry it. The value stays branch-discriminated: file:./dev.db for PRs into main, the service container for the integration branch. The e2e job's two step-level copies (and its BETTER_AUTH_* / NEXT_PUBLIC_APP_URL) are hoisted to the job the same way.

.github/workflows/nightly.yml — a cold-clone job: create then dev on a runner with no database installed, then a poll on the served app and an assertion that the Dev database's state file exists. It sets no DATABASE_URL on purpose — one would be the Database escape and no sidecar would start, which is exactly the property under test. The scaffolded project borrows examples/starter's installed node_modules (the PR-gate scaffold guard's trick) because the integration branch's packages are not published. published-create-e2e and examples-build are gated to main, whose Prisma 7 scaffold and SQLite examples they exercise.

e2e/utils/db.ts, e2e/global-setup.ts, e2e/global-teardown.ts — the seed helper no longer deletes a SQLite file and runs db:push. It calls core's lookup: an already-resolvable connection (CI's container) is used as-is; with nothing set, startDevDatabase() runs under the project's .opensaas/, and generate, prisma db update and the Next server Playwright starts all read it back from the state file. Nothing is injected into the app, so provenance stays 'dev-database' locally and 'env' in CI. Teardown stops the sidecar. The .env the setup writes no longer carries a DATABASE_URL.

package.json@opensaas/stack-core, @opensaas/stack-cli and the three PGlite packages (at the versions the CLI already pins) become root devDependencies so the e2e harness can call the lookup and the sidecar.

Scope

No packages/* source changed, so no changeset. No example script, README or .env.example touched — those are #1159's.

Known dependencies

The cold-clone job cannot go green until #1159 converts examples/starter's config and drops the scaffolder's db:push post-step and its .env DATABASE_URL; it fails loudly rather than skipping until then. Likewise the e2e job stays gated to main until #1129 converts starter-auth.

🤖 Generated with Claude Code

…gh the lookup

The `test` job's `DATABASE_URL` moves from four individual steps to the job,
so the browser-test step and every other step that runs tests carry it too and
an escape-only suite can no longer read as coverage while silently skipping.
The `e2e` job's copies are hoisted the same way.

Nightly gains a cold-clone job: `create` then `dev` on a runner with no
database installed, deliberately without `DATABASE_URL` so the Dev database
sidecar is what the app is served by. The published-npm and examples-build
jobs are gated to `main`, whose published Prisma 7 scaffold they exercise.

The e2e global setup and its seed helper now reach the database through core's
lookup: `DATABASE_URL` (the CI container) or, with nothing set, a Dev database
started under the project's Generated bundle, which `generate`, `prisma db
update` and the Next server all read back from the state file.

Implements #1160. Part of #1125.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel

vercel Bot commented Sep 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
stack-docs Ready Ready Preview Sep 6, 2026 9:12pm UTC

@changeset-bot

changeset-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: f7374d6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Core Package Coverage (./packages/core)

Status Category Percentage Covered / Total
🟢 Lines 94.26% (🎯 65%) 2810 / 2981
🟢 Statements 92.96% (🎯 65%) 3078 / 3311
🟢 Functions 96.68% (🎯 62%) 555 / 574
🟢 Branches 87.76% (🎯 50%) 2167 / 2469
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for UI Package Coverage (./packages/ui)

Status Category Percentage Covered / Total
🔵 Lines 78.45% 244 / 311
🔵 Statements 77.95% 251 / 322
🔵 Functions 69.81% 74 / 106
🔵 Branches 66.94% 160 / 239
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for CLI Package Coverage (./packages/cli)

Status Category Percentage Covered / Total
🔵 Lines 73.64% 1646 / 2235
🔵 Statements 73.23% 1765 / 2410
🔵 Functions 82.42% 286 / 347
🔵 Branches 60.62% 819 / 1351
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Auth Package Coverage (./packages/auth)

Status Category Percentage Covered / Total
🔵 Lines 99.48% 195 / 196
🔵 Statements 98.13% 210 / 214
🔵 Functions 100% 44 / 44
🔵 Branches 90.77% 187 / 206
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Package Coverage (./packages/storage)

Status Category Percentage Covered / Total
🔵 Lines 79.66% 235 / 295
🔵 Statements 81.17% 263 / 324
🔵 Functions 87.91% 80 / 91
🔵 Branches 77.46% 220 / 284
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for RAG Package Coverage (./packages/rag)

Status Category Percentage Covered / Total
🔵 Lines 54.38% 397 / 730
🔵 Statements 53.85% 419 / 778
🔵 Functions 64.06% 82 / 128
🔵 Branches 47.25% 198 / 419
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)

Status Category Percentage Covered / Total
🔵 Lines 100% 40 / 40
🔵 Statements 100% 40 / 40
🔵 Functions 100% 9 / 9
🔵 Branches 100% 19 / 19
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)

Status Category Percentage Covered / Total
🔵 Lines 100% 68 / 68
🔵 Statements 100% 71 / 71
🔵 Functions 100% 15 / 15
🔵 Branches 97.87% 46 / 47
File CoverageNo changed files found.
Generated in workflow #2011 for commit f7374d6 by the Vitest Coverage Report Action

Comment thread e2e/utils/db.ts
Comment on lines +50 to 57
const existing = findDatabaseConnection({ cwd: projectDir })
if (existing === undefined) {
started = await startDevDatabase({
dataDir: path.join(projectDir, '.opensaas', 'dev-db'),
extensions: ['vector'],
cwd: projectDir,
})
} catch (error) {
console.error('Failed to generate schema')
throw error
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Generated bundle directory is not created before PGlite opens its data directory.

startDevDatabase({ dataDir: <projectDir>/.opensaas/dev-db }) is called here as the first thing setupDatabase does — before generate runs. packages/cli/src/commands/dev.ts guards exactly this case immediately before its own call:

// PGlite's own `mkdir` of the data directory is not recursive, so the
// Generated bundle directory has to exist before it runs.
const dataDir = path.join(cwd, DEV_DATABASE_DIR)
fs.mkdirSync(path.dirname(dataDir), { recursive: true })

This caller has no such guard. .opensaas/ is gitignored, so on a clean checkout examples/starter-auth/.opensaas does not exist, and a local pnpm test:e2e with no DATABASE_URL set dies in globalSetup with PGlite's ENOENT before generate ever gets a chance to create the bundle directory.

Suggested change
const existing = findDatabaseConnection({ cwd: projectDir })
if (existing === undefined) {
started = await startDevDatabase({
dataDir: path.join(projectDir, '.opensaas', 'dev-db'),
extensions: ['vector'],
cwd: projectDir,
})
} catch (error) {
console.error('Failed to generate schema')
throw error
}
const existing = findDatabaseConnection({ cwd: projectDir })
if (existing === undefined) {
const dataDir = path.join(projectDir, '.opensaas', 'dev-db')
// PGlite's own `mkdir` of the data directory is not recursive.
fs.mkdirSync(path.dirname(dataDir), { recursive: true })
started = await startDevDatabase({
dataDir,
extensions: ['vector'],
cwd: projectDir,
})
}

(plus import * as fs from 'node:fs')

Comment thread e2e/utils/db.ts
Comment on lines +76 to 80
/** Stops the Dev database, if this process started one. */
export async function cleanupDatabase(): Promise<void> {
await started?.stop()
started = undefined
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The e2e run no longer starts from a clean database, and nothing ever removes the persisted one.

The old helper deleted dev.db and re-pushed the schema on every run; cleanupDatabase deleted it again afterwards. The replacement resets nothing: setupDatabase only reconciles the schema, and cleanupDatabase stops the sidecar but leaves examples/starter-auth/.opensaas/dev-db (a persistent dataDir) on disk with all its rows.

Concrete failure: Post.slug is isIndexed: 'unique' in examples/starter-auth/opensaas.config.ts, and the specs create posts under fixed slugs — apples/bananas/draft-one/published-one (05-filter.spec.ts, 06-filter-builder.spec.ts), unique-slug (02-posts-access-control.spec.ts), test-post/full-post/edit-test-post (03-admin-ui.spec.ts). On the second local pnpm test:e2e every one of those creates hits a unique violation against rows the previous run left behind. Because waitForURL(/admin\/post/) also matches /admin/post/create, the failed create does not fail the test — the assertions then pass against the stale rows, so these specs stop testing what they claim to and only break later, opaquely.

CI is masked from this because the service container is fresh per job; only local runs accumulate. Either rmSync the dev-db data dir in cleanupDatabase, or drop/recreate the schema in setupDatabase.

Comment thread .github/workflows/nightly.yml Outdated
# published, so the workspace is the only source of the toolchain.
cold-clone:
name: Cold clone — create then dev
if: github.ref_name != 'main'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

github.ref_name != 'main' means the nightly cold clone never runs on the nightly.

A schedule trigger always fires on the repository's default branch, so for the 03:17 cron github.ref_name is main and this job is skipped every single night. The only way it executes is a manual workflow_dispatch explicitly targeting prisma-8 — and once prisma-8 merges into main, ref_name is main for every trigger and the job is dead permanently. The two jobs above it (published-create-e2e, examples-build) are gated == 'main', so they do run nightly; this one is the odd one out.

Since the workflow file on prisma-8 is only ever used when dispatched on prisma-8, the branch discrimination isn't buying anything here — the job can just run unconditionally on this branch, and the gate re-added (as an == 'main'-compatible condition) when the branch lands.

Comment on lines +156 to +160
env:
DATABASE_URL: 'file:./dev.db'
BETTER_AUTH_URL: 'http://localhost:3000'
BETTER_AUTH_SECRET: 'secret-for-teating-in-github-actions-with-numbers1234'
NEXT_PUBLIC_APP_URL: 'http://localhost:3000'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This DATABASE_URL is now incompatible with the harness the same PR rewrote, and nothing in CI catches it.

e2e/utils/db.ts now calls findDatabaseConnection(), startDevDatabase() (PGlite) and prisma db update. file:./dev.db is a set value, so the lookup returns provenance: 'env' and the harness:

  1. never starts the Dev database (so the 'dev-database' branch the rewrite exists to exercise is unreachable in CI), and
  2. runs prisma db update against a SQLite URL, which the Prisma 8 toolchain cannot use — packages/core/src/testing/escape.ts calls out this exact value ("a stale SQLite DATABASE_URL in CI") as the misconfiguration it refuses.

Combined with if: github.base_ref == 'main' on line 149, the e2e job is skipped for every PR into prisma-8, so none of the rewritten e2e/utils/db.ts, global-setup.ts or global-teardown.ts is executed by any CI job on this branch — the rewrite lands entirely unverified, and the first run that does exercise it (spec 9, or the merge to main) will hit both problems at once. Worth at least dropping DATABASE_URL from this block now so the harness takes its intended branch, rather than leaving a value that is wrong for the code it feeds.

Comment thread e2e/global-setup.ts
Comment on lines +12 to +23
function writeEnvFile(exampleDir: string): void {
fs.writeFileSync(
path.join(exampleDir, '.env'),
[
'BETTER_AUTH_SECRET="test-secret-key-for-e2e-tests-only-not-for-production-use"',
'BETTER_AUTH_URL="http://localhost:3000"',
'NEXT_PUBLIC_APP_URL="http://localhost:3000"',
'',
].join('\n'),
'utf8',
)
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now clobbers a developer's local .env unconditionally.

The old code was guarded by if (!fs.existsSync(envPath)) — it only ever created a missing .env. This version writes over whatever is there on every pnpm test:e2e, with no backup and no warning. A contributor who put real OAuth client secrets, an OPENAI_API_KEY, or a DATABASE_URL pointing at their own Postgres into examples/starter-auth/.env loses all of it the first time they run the e2e suite.

The DATABASE_URL case is the sharpest: the harness deliberately wants that variable absent, so a developer who set it to their own server gets it silently deleted and gets a PGlite sidecar started instead — the opposite of the escape the file's own docblock describes. Reading the existing file and stripping/merging keys (or refusing to overwrite a .env that has content the harness didn't write) would keep the same guarantee without the data loss.

sleep 2
done
curl -sf http://localhost:3000 > /dev/null
test -f .opensaas/dev-db.json

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written this assertion cannot pass, because the scaffolder hands dev the escape it is supposed to avoid.

create-opensaas-app still calls writeEnvFile(...) unconditionally (packages/create-opensaas-app/src/index.ts), which emits DATABASE_URL="file:./dev.db" into myapp/.env. devCommand calls loadProjectEnvFile(cwd) before deciding the branch, so findDatabaseConnection({ cwd })?.provenance === 'env' is true, it prints "DATABASE_URL is set: using it, and starting no dev database", and .opensaas/dev-db.json is never written. It will also then try to reconcile a Prisma 8 contract against a SQLite URL.

The PR body notes this is blocked on #1159, which is fair — but flagging it here because the job is red-by-construction rather than merely unverified, and (given the ref_name != 'main' gate above) that redness won't surface anywhere until someone dispatches it by hand. A short-lived unset/sed of DATABASE_URL from the scaffolded .env in the scaffold step would let the job actually prove the sidecar today.

@borisno2 borisno2 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

High-effort review of the CI env hoisting, the nightly cold-clone job, and the e2e harness rewrite. Six findings are posted as inline comments; this is the summary plus the checks that came back clean.

Blocking

1. cold-clone never runs on the nightly schedule.github/workflows/nightly.yml:148

if: github.ref_name != 'main'. This workflow fires only on schedule and workflow_dispatch, and a scheduled run always fires on the default branch, so ref_name is always main on the cron. The job is reachable only by a manual dispatch on prisma-8, and once this branch merges to main it is dead permanently — the acceptance criterion it exists to satisfy would then be silently uncovered rather than red.

This also corrects the PR body's framing. The job does not "currently fail" on the nightly; it does not run there at all. Failing loudly is the right posture to merge in — a cold start that cannot start is exactly what the job should report, and disabling it would be worse — but that argument only holds once the gate actually lets the cron reach it. Gate on the content (e.g. run always, or github.event_name == 'workflow_dispatch' || <branch condition on the checked-out ref>), not on ref_name.

2. e2e harness: PGlite data dir is not createde2e/utils/db.ts:52

startDevDatabase({ dataDir: <projectDir>/.opensaas/dev-db }) runs before generate, with no mkdirSync. packages/cli/src/commands/dev.ts:293 guards this exact case ("PGlite's own mkdir of the data directory is not recursive"), and .opensaas/ is gitignored — a local pnpm test:e2e on a clean checkout with no DATABASE_URL dies in globalSetup with ENOENT.

3. e2e harness: no reset, persistent data dire2e/utils/db.ts:77

cleanupDatabase leaves the dev-db data dir on disk and the harness no longer resets. Post.slug is isIndexed: 'unique' and the specs use fixed slugs (apples, unique-slug, test-post), so a second local run hits unique violations — which waitForURL(/admin\/post/) swallows, since it also matches /admin/post/create. The specs then assert against stale rows instead of failing.

Non-blocking but should be addressed

4. The e2e job's DATABASE_URL defeats the new harness.github/workflows/test.yml:157. Pinning file:./dev.db at job level makes the rewritten harness take the 'env' branch and never exercise the Dev database, running prisma db update against a SQLite URL — the misconfiguration packages/core/src/testing/escape.ts refuses by name. Combined with the job's pre-existing if: github.base_ref == 'main', no CI job on this branch executes the new e2e/ code, so the rewrite lands unverified.

5. writeEnvFile now clobberse2e/global-setup.ts:12. Previously create-if-missing; now unconditional overwrite of examples/starter-auth/.env, silently destroying a contributor's local secrets.

6. test -f .opensaas/dev-db.json cannot pass today.github/workflows/nightly.yml:193. The scaffolder writes DATABASE_URL="file:./dev.db" into the project .env and devCommand loads it before branching, so no sidecar starts. Acknowledged as blocked on #1159 — worth naming in the job comment so the red is legible to whoever sees it first.

Checked and cleared

  • Branch discrimination. test.yml fires on pull_request only (branches: [main, prisma-8]), so github.base_ref is always populated and both arms of the DATABASE_URL ternary are correct. No push trigger, so the "a PR run's ref is not the target branch" trap does not apply here.
  • Nothing silently changed by inheritance. The three auth guard steps (rate-limit, MCP OAuth cascade, credential read-deny) previously ran with no DATABASE_URL and now inherit one — but each assigns process.env.DATABASE_URL to its own absolute temp path before use and sets its own BETTER_AUTH_SECRET/BETTER_AUTH_URL, so the hoisted values are overridden, not consumed. No step needed a different value than the one it was flattened to. The fixture-regeneration step does not read DATABASE_URL, and packages/ui browser tests do not use the DB harness.
  • No DATABASE_URL leaks into cold-clone. No workflow-level env, no job-level env, no vars/secrets reference. The only leak vector is the scaffolder's own .env (finding 6) — which is the failure, not a hidden pass.
  • The success condition is genuine. The poll breaks only on a successful curl -sf, exits early with the log if the dev process dies, and re-runs curl -sf unguarded after the loop, so a 120-iteration timeout fails rather than falling through. It proves the app served, not merely that a process started.
  • Gating published-create-e2e / examples-build to main removes no coverage. Both are nightly-only, and the cron always runs as main. They are skipped only on a manual dispatch from another branch, where they could not pass anyway.
  • Root dependency versions match the CLI's pins exactly@electric-sql/pglite 0.5.8, pglite-pgvector 0.0.9, pglite-socket 0.2.11, identical in packages/cli/package.json and packages/core/package.json. @opensaas/stack-core / @opensaas/stack-cli as workspace:* root devDeps is the standard pnpm form for root-level tooling; it does not shadow workspace resolution and creates no cycle (the root package is not itself a dependency of any workspace package).
  • No changeset needed. The diff touches only .github/workflows/{nightly,test}.yml, e2e/{global-setup,global-teardown,utils/db}.ts, package.json and pnpm-lock.yaml. No packages/* source file is modified — the author's claim holds.
  • No scope collision with #1228. No examples/** file, README, or .env.example is touched.
  • Repo rules. No any and no type casting in the changed TypeScript. The YAML comments carry why the gates and pins exist (ADR references, issue numbers) rather than restating the lines — they earn their place.
  • Teardown. Ordering does stop the sidecar even when globalSetup throws; no leaked in-process PGlite on the failure path.

…non-destructive .env

- `cold-clone` loses its `github.ref_name != 'main'` gate. A scheduled run
  always fires on the default branch, so that gate skipped the job on every
  cron and would have been permanently dead once this lands on `main`. It is
  expected to fail until #1129 converts `examples/starter`; that redness is
  the point.
- The e2e harness creates the Generated bundle directory before PGlite opens
  its data directory, matching `dev.ts`, and discards the persistent data
  directory first so a second local run does not inherit the previous run's
  rows.
- Post-submit `waitForURL(/admin\/post/)` is anchored to `/\/admin\/post$/`,
  so a create that failed and stayed on `/admin/post/create` fails the wait
  instead of passing against stale rows.
- The `e2e` job no longer pins a SQLite `DATABASE_URL`, so the harness takes
  the Dev database branch it exists to exercise.
- `writeEnvFile` appends only the variables that are missing, leaving a
  contributor's own `.env` intact.
- The nightly's `pnpm db:push` / `test -f dev.db` are dropped: neither exists
  under Prisma 8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@borisno2

borisno2 commented Sep 6, 2026

Copy link
Copy Markdown
Member Author

Review findings addressed in f7374d6.

1 (blocking) — cold-clone unreachable on the nightly. Dropped the if: github.ref_name != 'main' entirely rather than rewriting it. A schedule run always fires on the default branch, so any ref_name gate skips the job on every cron, and once this lands on main no value of that expression distinguishes the cron from anything else. The job now carries no if:, so the cron reaches it. The comment above it records that it is expected to fail until #1129 converts examples/starter, and that it must not be disabled or given continue-on-error.

Proven with a real dispatch on this branch: https://github.com/OpenSaasAU/stack/actions/runs/34060337801Cold clone — create then dev ran and failed; Published npm create e2e and Full examples build skipped (their == 'main' gates, ref is this branch). It failed at Cannot find module '@prisma/adapter-better-sqlite3' from the scaffolded opensaas.config.ts, i.e. #1129, having first printed "DATABASE_URL is set: using it, and starting no dev database" — your finding 6, blocked on #1159. Under cron the ref is main, the other two jobs run, and cold-clone now runs alongside them rather than being skipped.

2 (blocking) — PGlite data dir. e2e/utils/db.ts now does fs.mkdirSync(path.dirname(dataDir), { recursive: true }) before startDevDatabase, matching packages/cli/src/commands/dev.ts:293. Reproduced the pre-fix failure locally on a clean checkout with no DATABASE_URLENOENT: no such file or directory, mkdir '.../examples/starter-auth/.opensaas/dev-db' from PGlite's nodefs.ts:15 — and confirmed the fixed version starts the sidecar and writes .opensaas/dev-db.json.

3 (blocking) — no reset on a persistent data dir. setupDatabase now rmSynces the dev-db data directory before starting, so every run begins empty. Verified by planting a marker file inside dev-db/ plus a full first run, then a second run: the marker was gone and a fresh instance came up. The 'env' branch is deliberately not reset — a server named by DATABASE_URL belongs to whoever set it, and CI's container is fresh per job; that is stated in the docblock.

The URL assertion is tightened too: every post-submit waitForURL(/admin\/post/) is now waitForURL(/\/admin\/post$/) across 02, 03, 05-bulk-delete, 05-filter, 06-filter-builder, 08-custom-bulk-actions and 09. ItemFormClient pushes to ${basePath}/${urlKey} on success, so the list page is the correct target and a create that failed and stayed on /admin/post/create now times out the wait instead of passing against stale rows.

4 — the e2e job's DATABASE_URL. Removed from the job's env. The harness now takes the 'dev-database' branch there, which is the branch the rewrite exists to exercise, and no SQLite URL is fed to the Prisma 8 toolchain. The four guard steps in that job each assign their own DATABASE_URL before use, so none of them depended on the job-level value.

You are right that no CI job on this branch executes the new e2e/ code (the job's pre-existing base_ref == 'main' gate), so these changes land unverified by CI. I verified them locally instead, by driving globalSetup + cleanupDatabase directly against examples/starter-auth: clean state with no DATABASE_URL (item 2 above), then a second run (item 3 above). Both runs get as far as the sidecar being up and then stop at generate, because examples/starter-auth/opensaas.config.ts still imports @prisma/adapter-better-sqlite3 — the same #1129/#1228 conversion the cold-clone job is red on. So the database half of the harness is verified end to end locally; the specs themselves are not runnable on this branch yet by anyone.

5 — writeEnvFile clobbering. Now additive: it reads the existing .env, and appends only the required keys that are not already assigned there. Nothing is overwritten or stripped. A DATABASE_URL a contributor put there themselves is left alone — that escape is theirs to take. Verified by appending GITHUB_CLIENT_SECRET="..." to a generated .env and re-running: the secret survived and no duplicate keys were added.

6 — stale db:push in the nightly. Removed pnpm db:push and test -f dev.db from published-create-e2e, and updated the two comments that named that flow. Neither exists under Prisma 8, and #1228 removes the script from the examples; since this PR merges first the sibling will not land on a workflow calling a script it just deleted. The job's own DATABASE_URL is left as-is — it feeds the currently-published Prisma 7 package, and changing it is #1159's call.

Not touched, per scope: examples/**, READMEs, .env.example; #1224 and #1229.

pnpm build, pnpm lint, pnpm manypkg fix, pnpm format all clean; turbo run test --filter='./packages/*' green (19/19 tasks, including pglite-absence). Still no packages/* change, so still no changeset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant