Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .changeset/22554-migration-registry-generated-at-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
'@objectstack/spec': patch
---

The migration registry `src/migrations/registry.ts` is generated at build and no longer committed

Clause-②: no

`src/migrations/registry.ts` keeps its path and its exports, and the built package carries the same
`./migrations` entry as before. What changes is where the file comes from in this repository: it is
git-ignored and written whole by `gen:migration-registry` from two committed sources,
`src/migrations/registry.ts.template` (the hand-written step rationale, doc comments and table
skeleton) and `src/migrations/entries/` (one file per entry). The generator runs on `pnpm install`
(the package's new `prepare` script), as the first step of `build`, and before `typecheck`, `test`
and `test:repo`; its self-test runs inside every generation. `check:migration-registry` is removed,
since there is no committed copy left to compare.

For a contributor: add a migration entry as a file under `src/migrations/entries/` and edit any other
registry prose in `registry.ts.template`. An edit to `registry.ts` itself is never committed, and the
next install or build overwrites it.

Measured with `pnpm pack` against the previous build: 2,070 files each, and 4 differ. Those are
`package.json`'s `scripts` (`build`, `typecheck`, `test` and `test:repo` now start with the generation,
and `check:migration-registry` is gone; `pnpm pack` leaves `prepare` out of the packed manifest) and the
three `.build-input-hash` stamps that record the build's inputs. Every `dist` file, declaration, source
map and JSON Schema is byte-identical. No schema, type, export or runtime behaviour changes.
9 changes: 4 additions & 5 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@
# The migrations registry is the interesting one since #7297: its three append
# tables now come from `packages/spec/src/migrations/entries/` (one file per
# entry, the `.changeset/*.md` shape), so the conflict two retirement cards used
# to have is gone at the SOURCE — different entries are different files. The
# file stays out of this list anyway, because it is now MIXED: a driver that
# deferred it whole would resolve its still-hand-written prose by regenerating,
# which loses an edit rather than a merge. `check:migration-registry` is what
# guards the generated half instead.
# to have is gone at the SOURCE — different entries are different files. Since
# #22554 the registry itself is git-ignored and generated whole at install and
# build, so git never merges it; its hand-written prose lives in
# `registry.ts.template`, which is plain source and text-merges like any other.
#
# The strictness ledger's COUNTS file joined at #5107 — the ledger's numbers were
# the repo's hottest conflict surface and merged in the one way that hides: two
Expand Down
30 changes: 9 additions & 21 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,11 @@ jobs:
# over the ten merge-group runs measured for #16496; the PM dispatch-gates
# self-test alone 597 s), and none of its expensive steps read a
# merge group's file surface: a docs-only group paid the full battery.
# So on `merge_group` and `pull_request` the TEN scoped families below
# So on `merge_group` and `pull_request` the NINE scoped families below
# -- each step carrying `if: steps.gate-families.outputs.<id> != 'skip'`
# -- run only when the changed paths touch the files that family reads.
# One of the ten, `migration_registry` (#19753), is a gate this job did
# not run before at all; the other nine were scoped away from it.
# (A tenth, `migration_registry` (#19753), retired with its gate in
# #22554: the registry it compared is no longer committed.)
# `push` on main and the scheduled full run keep the whole battery: the
# script runs everything for any event it does not scope.
#
Expand Down Expand Up @@ -399,24 +399,12 @@ jobs:
- name: ADR anchors + number uniqueness (governed code names its decision)
run: pnpm check:adr-anchors

# Migration registry matches its entry files (#19753). `registry.ts` is
# the generated concatenation of `packages/spec/src/migrations/entries/`,
# it ships in the spec package's `dist`, and this check is the only
# proof the two agree -- `check:generated --reconcile-only` (in the
# `Type Check · source gates` job) proves the script is classified,
# never that the artifact is current. It ran
# in no CI step, so an entry edited without `gen:migration-registry`
# shipped the old text with every required check green.
#
# Scoped, on the maintainer's ruling for that card: a step in THIS
# required job, run when the change touches what the check reads
# (`migration_registry` in the selector above). ⛔ Not a separate
# `paths:`-filtered job: one that never reports on an unrelated PR
# leaves a required context pending forever. Cheap -- tsx over one
# directory, no build (~1.4 s measured locally) -- so it sits early.
- name: Migration registry matches its entry files
if: steps.gate-families.outputs.migration_registry != 'skip'
run: pnpm --filter @objectstack/spec check:migration-registry
# No "migration registry matches its entry files" step since #22554:
# `packages/spec/src/migrations/registry.ts` is git-ignored and generated
# whole from `registry.ts.template` + `entries/` by `gen:migration-registry`,
# which `pnpm install` above already ran (spec's `prepare`, self-test
# included). There is no committed copy left to compare, and an entry the
# generator refuses fails that install step, loudly, in every job.

# Enforces the no-restricted-imports guard against @objectstack/spec root
# namespace imports (the dormant rule was never run in CI). Syntactic
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ packages/*/*.tsbuildinfo
# Generated JSON Schema (rebuilt by `pnpm gen:schema` during build)
packages/spec/json-schema/

# Generated migration registry (rebuilt by `pnpm gen:migration-registry` on
# install and as the first step of build, from registry.ts.template + entries/),
# and the staging file its atomic write renames into place.
packages/spec/src/migrations/registry.ts
packages/spec/src/migrations/registry.ts.*.tmp

# Generated bundle size reports
packages/spec/bundle-size-report.json

Expand Down
10 changes: 5 additions & 5 deletions packages/spec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@
"protocol-upgrade-guide.md"
],
"scripts": {
"build": "pnpm gen:schema && pnpm gen:openapi && tsup && if [ -z \"$OS_SKIP_DTS\" ]; then NODE_OPTIONS=\"--max-old-space-size=6144\" BUILD_DTS=true tsup; fi && node ../../scripts/check-dts-emitted.mjs && node ../../scripts/check-dts-references.mjs && node ../../scripts/check-dev-prereqs.mjs --stamp",
"build": "pnpm gen:migration-registry && pnpm gen:schema && pnpm gen:openapi && tsup && if [ -z \"$OS_SKIP_DTS\" ]; then NODE_OPTIONS=\"--max-old-space-size=6144\" BUILD_DTS=true tsup; fi && node ../../scripts/check-dts-emitted.mjs && node ../../scripts/check-dts-references.mjs && node ../../scripts/check-dev-prereqs.mjs --stamp",
"prepare": "pnpm gen:migration-registry",
"dev": "tsc --watch",
"clean": "rm -rf dist",
"gen:schema": "OS_EAGER_SCHEMAS=1 tsx scripts/build-schemas.ts",
Expand Down Expand Up @@ -295,13 +296,12 @@
"check:llms-txt": "tsx scripts/check-llms-txt.ts --self-test && tsx scripts/check-llms-txt.ts",
"check:authorable-surface": "OS_EAGER_SCHEMAS=1 tsx scripts/build-schemas.ts --check",
"gen:migration-registry": "tsx scripts/build-migration-registry.ts",
"check:migration-registry": "tsx scripts/build-migration-registry.ts --self-test --check",
"gen:spec-changes": "tsx scripts/build-spec-changes.ts",
"check:spec-changes": "tsx scripts/build-spec-changes.ts --check",
"gen:upgrade-guide": "tsx scripts/build-upgrade-guide.ts",
"check:upgrade-guide": "tsx scripts/build-upgrade-guide.ts --check",
"test": "vitest run --project local",
"test:repo": "vitest run --project repo",
"test": "pnpm gen:migration-registry && vitest run --project local",
"test:repo": "pnpm gen:migration-registry && vitest run --project repo",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"check:liveness": "tsx scripts/liveness/check-liveness.mts",
Expand All @@ -320,7 +320,7 @@
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/spec --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/spec --project tsconfig.test.json",
"check:scripts-typecheck": "tsc --noEmit -p tsconfig.scripts.json",
"typecheck": "tsc --noEmit && pnpm check:scripts-typecheck && pnpm check:test-typecheck"
"typecheck": "pnpm gen:migration-registry && tsc --noEmit && pnpm check:scripts-typecheck && pnpm check:test-typecheck"
},
"keywords": [
"objectstack",
Expand Down
10 changes: 6 additions & 4 deletions packages/spec/scripts/build-migration-registry-entry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
// `build-migration-registry.ts` has TWO kinds of caller now, and its entry guard
// is the only thing telling them apart:
//
// - pnpm RUNS it (`gen:migration-registry`, `check:migration-registry`), and
// write mode rewrites `src/migrations/registry.ts`;
// - pnpm RUNS it (`gen:migration-registry`, on install, in `build`, before
// `typecheck` and `test`), and every run rewrites `src/migrations/registry.ts`
// from the template and the entries;
// - `build-schemas.ts` IMPORTS it, for `shardNameFor` — so the entry file each
// registration remedy names is the one name the generator accepts, read from
// the rule `entries/README.md` documents instead of restated beside it.
Expand Down Expand Up @@ -66,8 +67,9 @@ describe('build-migration-registry.ts — run, it speaks; import, it runs nothin
);
const r = tsx([probe]);
expect(r.status, r.stderr).toBe(0);
// Write mode would have printed `✓ wrote src/migrations/registry.ts (…)`, and
// check mode `✓ … is current` — any line beyond the probe's own is the defect.
// A run would have printed its self-test line and then `✓ wrote
// src/migrations/registry.ts (…)` or `✓ … is current` — any line beyond the
// probe's own is the defect.
expect(r.stdout).toBe('17.data__AggregationNode__distinct.ts\n');
expect(r.stderr).toBe('');
});
Expand Down
Loading
Loading