From dae5b435e60a674e242a331f55b56aff7035518c Mon Sep 17 00:00:00 2001 From: mintaka Date: Wed, 9 Sep 2026 23:02:27 -0400 Subject: [PATCH 1/2] fix(ci): generate sqlc drift check out-of-tree (RIG-3591) sqlc-drift ran `sqlc generate` in place, rewriting go/internal/store/db while moon ran build/nilaway/test against that same directory in parallel. A reader could catch a generated file mid-write and fail with `expected 'package', found 'EOF'` on a different random file each run, which aborts the whole push atomically and reads as the submitter's defect. Stage the sqlc inputs into a scratch dir and generate there, so the gate has no shared mutable subject. The drift comparison is unchanged. Co-authored-by: Matt Wilkinson --- go/moon.yml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/go/moon.yml b/go/moon.yml index 4f1ef94a..8ea4f593 100644 --- a/go/moon.yml +++ b/go/moon.yml @@ -251,18 +251,24 @@ tasks: sqlc-drift: # Fail if the checked-in internal/store/db tree is stale vs the query + - # schema sources: snapshot the committed tree, regenerate in place, and fail - # on any byte diff (a query edit committed without regeneration). Unlike - # `drift` above — which delegates to the compass-proto schema pipeline and is - # scheduled through the gen tree, so it is deliberately kept OUT of `ci` — - # sqlc-drift is fully local (no cross-project delegation, no DB), so it joins - # `ci` directly. `git diff --no-index` compares raw file trees (reads no + # schema sources: stage the sources into a scratch dir, generate THERE, and + # fail on any byte diff against the committed tree. Unlike `drift` above — + # which delegates to the compass-proto schema pipeline and is scheduled + # through the gen tree, so it is deliberately kept OUT of `ci` — sqlc-drift + # is fully local (no cross-project delegation, no DB), so it joins `ci` + # directly. `git diff --no-index` compares raw file trees (reads no # index/worktree state, and git is always on PATH — unlike `diff`), so it # runs identically in CI and in a secondary jj workspace; a `git status` - # check would false-green where the workspace is not a git checkout. sqlc has - # no output-redirect flag, so the regenerate is in place and idempotent (a - # no-drift run leaves the byte-identical tree). - script: 'tmp=$(mktemp -d); trap ''rm -rf "$tmp"'' EXIT; cp -R internal/store/db "$tmp/db-committed"; sqlc generate; if ! git diff --no-index --quiet "$tmp/db-committed" internal/store/db; then echo "sqlc drift: internal/store/db is stale — run \`moon run compass-go:sqlc-gen\` and commit:"; git diff --no-index "$tmp/db-committed" internal/store/db; exit 1; fi' + # check would false-green where the workspace is not a git checkout. + # + # WHY OUT-OF-TREE (RIG-3591): this regenerated IN PLACE, and moon schedules + # it in PARALLEL with build/nilaway/test, which compile the same directory. + # A reader caught a generated file mid-write and failed with + # `expected 'package', found 'EOF'` on a different random file each run, + # aborting the whole push. sqlc has no output-redirect flag, so the scratch + # dir carries the inputs (sqlc.yaml + queries + migrations) and `out:` + # resolves relative to it, leaving the working tree untouched. + script: 'tmp=$(mktemp -d); trap ''rm -rf "$tmp"'' EXIT; mkdir -p "$tmp/internal/store"; cp -R internal/store/queries "$tmp/internal/store/queries"; cp -R internal/store/migrations "$tmp/internal/store/migrations"; cp sqlc.yaml "$tmp/sqlc.yaml"; (cd "$tmp" && sqlc generate); if ! git diff --no-index --quiet internal/store/db "$tmp/internal/store/db"; then echo "sqlc drift: internal/store/db is stale — run \`moon run compass-go:sqlc-gen\` and commit:"; git diff --no-index internal/store/db "$tmp/internal/store/db"; exit 1; fi' options: runFromWorkspaceRoot: false inputs: *sqlc_sources From bbc1464542aab5d1a54122ef003889c68f130551 Mon Sep 17 00:00:00 2001 From: mintaka Date: Wed, 9 Sep 2026 23:55:34 -0400 Subject: [PATCH 2/2] fix(ci): fail sqlc-drift closed on a sqlc error, not as false drift (RIG-3591) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review finding: `sqlc generate`'s exit code was discarded, so the gate failed closed only as a side effect — sqlc writing nothing made the comparison path missing, which errored. A broken query therefore reported `internal/store/db is stale` and pointed the operator at a regen that fails the same way. It also left fail-closed depending on sqlc validating every block before writing any, which is observed behaviour of the pinned version, not a contract. `set -e` aborts at the sqlc error instead. Errexit is suspended inside the `if` condition, so the drift comparison is unaffected, and the EXIT trap still fires. Also trims the task comment to the constraint a future editor needs. Co-authored-by: Matt Wilkinson --- go/moon.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/go/moon.yml b/go/moon.yml index 8ea4f593..af66c738 100644 --- a/go/moon.yml +++ b/go/moon.yml @@ -261,14 +261,12 @@ tasks: # runs identically in CI and in a secondary jj workspace; a `git status` # check would false-green where the workspace is not a git checkout. # - # WHY OUT-OF-TREE (RIG-3591): this regenerated IN PLACE, and moon schedules - # it in PARALLEL with build/nilaway/test, which compile the same directory. - # A reader caught a generated file mid-write and failed with - # `expected 'package', found 'EOF'` on a different random file each run, - # aborting the whole push. sqlc has no output-redirect flag, so the scratch - # dir carries the inputs (sqlc.yaml + queries + migrations) and `out:` - # resolves relative to it, leaving the working tree untouched. - script: 'tmp=$(mktemp -d); trap ''rm -rf "$tmp"'' EXIT; mkdir -p "$tmp/internal/store"; cp -R internal/store/queries "$tmp/internal/store/queries"; cp -R internal/store/migrations "$tmp/internal/store/migrations"; cp sqlc.yaml "$tmp/sqlc.yaml"; (cd "$tmp" && sqlc generate); if ! git diff --no-index --quiet internal/store/db "$tmp/internal/store/db"; then echo "sqlc drift: internal/store/db is stale — run \`moon run compass-go:sqlc-gen\` and commit:"; git diff --no-index internal/store/db "$tmp/internal/store/db"; exit 1; fi' + # Generate OUT OF TREE (RIG-3591): moon runs this in parallel with + # build/nilaway/test, so an in-place regenerate raced their reads. sqlc has + # no output-redirect flag, so the scratch dir carries the inputs and `out:` + # resolves relative to it. `set -e` so a failing sqlc aborts here instead of + # reporting its empty output as drift. + script: 'set -e; tmp=$(mktemp -d); trap ''rm -rf "$tmp"'' EXIT; mkdir -p "$tmp/internal/store"; cp -R internal/store/queries "$tmp/internal/store/queries"; cp -R internal/store/migrations "$tmp/internal/store/migrations"; cp sqlc.yaml "$tmp/sqlc.yaml"; (cd "$tmp" && sqlc generate); if ! git diff --no-index --quiet internal/store/db "$tmp/internal/store/db"; then echo "sqlc drift: internal/store/db is stale — run \`moon run compass-go:sqlc-gen\` and commit:"; git diff --no-index internal/store/db "$tmp/internal/store/db"; exit 1; fi' options: runFromWorkspaceRoot: false inputs: *sqlc_sources