Skip to content

Commit 5b4fc83

Browse files
wmadden-electricclaude
authored andcommitted
fix(regen): produce canonical biome-formatted output on UPDATE path
The regen script was writing migration.json, ops.json, and head.json via raw JSON.stringify without biome formatting, producing files that diverged from the committed canonical format (inline short arrays, trailing newline). Fix: pipe each touched JSON file through `biome format --stdin-file-path` after writing. The stdin approach bypasses biome's files.includes exclusion globs (which exclude migration.json/ops.json/end-contract.json from the normal check pass) while still applying the project's formatter settings, yielding byte-identical output. Also reconcile the stale committed end-contract.d.ts for all three extension packs (paradedb, pgvector, postgis): the previously-committed files had `export type Models` at the bottom after `Namespaces`, while the current src/contract.d.ts emitter places `Models` before `Contract`. Copying the current src output makes committed == what syncEndContract produces, so the forced-drift probe returns zero diff. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
1 parent 3acde5e commit 5b4fc83

4 files changed

Lines changed: 43 additions & 6 deletions

File tree

packages/3-extensions/paradedb/migrations/20260601T0000_install_pg_search_extension/end-contract.d.ts

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/3-extensions/pgvector/migrations/20260601T0000_install_vector_extension/end-contract.d.ts

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/3-extensions/postgis/migrations/20260601T0000_install_postgis_extension/end-contract.d.ts

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/regen-extension-migrations.mjs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
* 5. Re-pins `migrations/refs/head.json` with the new hash, preserving
2323
* the existing `invariants` array verbatim.
2424
* 6. Syncs `end-contract.{json,d.ts}` from `src/contract.{json,d.ts}`.
25+
* 7. Runs `biome format` via stdin on each touched JSON file so output is
26+
* byte-identical to the committed canonical format (biome keeps short
27+
* arrays inline and adds a trailing newline).
2528
*
2629
* If the new storageHash already matches the published `head.json` hash the
2730
* extension is skipped (already consistent) - making the script idempotent.
@@ -35,12 +38,13 @@
3538

3639
import { execFileSync } from 'node:child_process';
3740
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
38-
import { dirname, join, resolve } from 'node:path';
41+
import { basename, dirname, join, resolve } from 'node:path';
3942
import { fileURLToPath } from 'node:url';
4043

4144
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
4245
const extensionsDir = join(repoRoot, 'packages', '3-extensions');
4346
const tsx = join(repoRoot, 'node_modules', '.bin', 'tsx');
47+
const biome = join(repoRoot, 'node_modules', '.bin', 'biome');
4448

4549
/**
4650
* Read and parse a JSON file, returning the parsed object.
@@ -60,6 +64,27 @@ function readJson(filePath) {
6064
}
6165
}
6266

67+
/**
68+
* Format a file's content through `biome format --stdin-file-path <basename>`
69+
* and write the result back in place.
70+
*
71+
* Using stdin bypasses biome's `files.includes` exclusion globs (which exclude
72+
* migration.json, ops.json, end-contract.json, and *.d.ts from the normal
73+
* check/format pass) while still applying the project's formatter settings
74+
* (lineWidth, indentStyle, etc.). The result is byte-identical to what biome
75+
* would produce if the file were not excluded — short arrays stay inline,
76+
* trailing newline is present — matching the committed canonical format.
77+
*/
78+
function biomeFormatInPlace(filePath) {
79+
const content = readFileSync(filePath, 'utf8');
80+
const formatted = execFileSync(biome, ['format', '--stdin-file-path', basename(filePath)], {
81+
input: content,
82+
encoding: 'utf8',
83+
cwd: repoRoot,
84+
});
85+
writeFileSync(filePath, formatted, 'utf8');
86+
}
87+
6388
/**
6489
* Find the migration directory whose `migration.json` has a `to` field
6590
* matching `headHash`. Returns the directory path.
@@ -152,12 +177,15 @@ function reemitMigrationArtifacts(extDir, migrationTsPath) {
152177

153178
/**
154179
* Rewrite `migrations/refs/head.json`, replacing `hash` with `newHash`
155-
* and preserving the existing `invariants` array verbatim.
180+
* and preserving the existing `invariants` array verbatim. The file is
181+
* then passed through `biome format` (via stdin) so the output matches
182+
* the committed canonical format: short arrays inline, trailing newline.
156183
*/
157184
function repinHeadRef(headRefPath, newHash) {
158185
const existing = readJson(headRefPath);
159186
const updated = { hash: newHash, invariants: existing.invariants };
160-
writeFileSync(headRefPath, `${JSON.stringify(updated, null, 2)}\n`, 'utf8');
187+
writeFileSync(headRefPath, JSON.stringify(updated, null, 2), 'utf8');
188+
biomeFormatInPlace(headRefPath);
161189
}
162190

163191
/**
@@ -167,6 +195,9 @@ function repinHeadRef(headRefPath, newHash) {
167195
* `src/contract.json` is emitted without a trailing newline; the on-disk
168196
* end-contract.json convention includes one. A trailing newline is added
169197
* if absent so idempotence holds on the first run.
198+
*
199+
* `src/contract.d.ts` is formatted by prettier during emission and already
200+
* carries a trailing newline; it is copied verbatim.
170201
*/
171202
function syncEndContract(extDir, headMigrationDir) {
172203
for (const ext of ['json', 'd.ts']) {
@@ -225,8 +256,11 @@ function processExtension(extDir) {
225256

226257
rewriteMigrationToHash(migrationTsPath, newHash);
227258
reemitMigrationArtifacts(extDir, migrationTsPath);
259+
biomeFormatInPlace(join(headMigrationDir, 'migration.json'));
260+
biomeFormatInPlace(join(headMigrationDir, 'ops.json'));
228261
repinHeadRef(headRefPath, newHash);
229262
syncEndContract(extDir, headMigrationDir);
263+
biomeFormatInPlace(join(headMigrationDir, 'end-contract.json'));
230264

231265
return 'updated';
232266
}

0 commit comments

Comments
 (0)