mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
Base SQLite serves one write connection. `prisma.$transaction(async (tx)
=> …)` holds it for as long as the callback runs, so a call in the
callback that reaches the global client queues behind a lock that call is
itself blocking. It waits out the busy timeout and the transaction dies
with P2028 — at runtime, on a green build. That is what stopped every
document creation at 0.1.4, across nine sites; moving the side effects
after the commit fixed them but left nothing to stop the next one.
packages/eslint-config/transaction.cjs states the invariant once, as
three esquery selectors: the global client named inside a $transaction
callback, and the two side effects that reach it without naming it,
triggerJob and triggerWebhook. Two callers read it — the shared config,
so an editor says it while you type, and `npm run lint:tx`, which runs it
alone over packages/{lib,trpc,api} and apps/remix in three seconds and is
now the first thing the gate does, ahead of the build that cannot see
this. Inline comments are off there, so the invariant is not silenced by
a comment.
The rule alone would rot into a no-op unnoticed, so lint:tx first runs
the eslint-config tests, which assert each selector still fires and that
`tx` on its own, and the non-interactive batch form, stay clean.
It reads the call site, not the call graph: a helper that reaches the
global client from its own body is still invisible to it.
24 lines
1.1 KiB
YAML
24 lines
1.1 KiB
YAML
# Hanzo eSign — a turborepo whose deployable artifact is the remix app.
|
|
#
|
|
# Gate only. The image is already built and pushed by the native builder in this
|
|
# repo (.hanzo/workflows/deploy.yml → ghcr.io/hanzoai/sign:<tag>), so declaring
|
|
# `images:` here would publish a second copy of the same commit.
|
|
#
|
|
# The gate is the real build of the app the cluster runs: npm ci against the
|
|
# committed lockfile (postinstall generates the Prisma client), then turbo's
|
|
# build of @hanzo/esign-remix, which type-checks every workspace package it
|
|
# depends on. A type error anywhere under packages/ fails here.
|
|
#
|
|
# `lint:tx` runs first because it takes seconds and answers a question the build
|
|
# cannot: whether anything inside a `$transaction` reaches the global Prisma
|
|
# client. Base SQLite serves one write connection, so such a call waits on a
|
|
# lock the transaction holds and the transaction dies (`P2028`) — at runtime,
|
|
# with a green build. See packages/eslint-config/transaction.cjs.
|
|
test:
|
|
- name: build
|
|
run: |
|
|
set -euo pipefail
|
|
npm ci --no-audit --no-fund
|
|
npm run lint:tx
|
|
npx turbo run build --filter=@hanzo/esign-remix
|