Repository navigation
Conversation
The history regex captures `(^|\n)` before the path, so destructuring `[, relativePath]` read that group: every committed fixture was keyed by "" or "\n", none ever matched, and every fixture was included in every migration. Use the path group, and normalise it so `./x.sql` and `x.sql` are the same fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixtures elsewhere (indexes, constraints, anything else that should not be re-run on change) are only included manually. Fixtures in fixtures/auto must not use --!include, so none is run more than once through nesting and each one's hash comes straight from its file. Also record which fixtures are empty or only comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Put the automatic fixtures after the headers and `--! no-transaction`, so `commit` keeps the message and no-transaction migrations stay outside a transaction; strip only that section on uncommit, so headers such as the message survive it too. - Read already-included fixtures from the compiled migration, so other spellings (`./auto/x.sql`) and includes through another fixture count. - Ignore new fixtures that are empty or only comments. - Let uncommit check the current migration without automatic fixtures; they are derived again afterwards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the autoIncludeFixtures setting: the folder's presence is the opt-in. Without it, reading the current migration skips the committed fixture history entirely. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The automatic section always runs inside the migration's transaction, so a fixture in fixtures/auto that declares --! no-transaction is now an error instead of being skipped with an easy-to-miss warning. Keep such fixtures in another folder and include them manually. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
uncommit again checks the compiled current migration, as in graphile#269, so it refuses while a fixture has pending changes; commit or revert the edit first. Nothing is lost either way, and readCurrentMigration keeps its original signature. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| const autoIncludes = await compileIncludes( | ||
| parsedSettings, | ||
| changedFixtures | ||
| .map((relativePath) => `--!include ${relativePath}`) | ||
| .join("\n") + | ||
| "\n\n--!endAuto\n\n" + | ||
| compiled; | ||
| .join("\n"), | ||
| new Set(paths), | ||
| ); |
There was a problem hiding this comment.
This should forbid any --!include auto/* imports; could be done via extending the paths set, but I'd instead pass a boolean to a new forbidAutoIncludes = false param.
There was a problem hiding this comment.
From claude opus:
Done in ddf3d1c: compileIncludes now has a forbidAutoIncludes = false param, passed down to nested includes. readCurrentMigration sets it, so neither the current migration nor any fixture it includes can --!include auto/*, whatever the spelling (the check uses the resolved path). Auto fixtures themselves already can't contain any --!include (see getLocalFixtures), so they only ever run in the automatic section. The "already included" detection is gone, and the README now says that a fixture change depending on the rest of the migration goes in the next migration. The compile and run commands keep the default.
There was a problem hiding this comment.
From claude opus:
Update in 4fb10f6, following the Discord discussion: this is now a middle ground.
- The current migration may
--!include auto/…directly again, to run a fixture after something it depends on, such as a policy after thecreate tablein the same migration. That fixture is then not added at the start. - No fixture can include an auto fixture:
compileIncludesnow always passesforbidAutoIncludes = trueto nested includes, so only the top-level file can include one. Auto fixtures themselves still can't contain any--!include.
The reason: with auto fixtures only ever running first, every new table with its policies in auto/ needs two migrations, or the policy written inline first. watch also fails as soon as the policy file is saved, because the automatic section runs before the create table. Running the section at the end instead would only flip the problem: dropping a column that a view uses needs the updated view first.
Fixtures in fixtures/auto now only ever run in the automatic section: compileIncludes takes a forbidAutoIncludes flag, which readCurrentMigration sets, so neither the current migration nor a fixture it includes can --!include one. That removes the already-included detection. AUTO_FIXTURES_FOLDER moves to migration.ts to avoid a circular import. The compile and run commands are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The current migration may again --!include a fixture from fixtures/auto, for example after creating the table a policy applies to; that fixture is then not added at the start. Only the top-level file may do so: compileIncludes now always sets forbidAutoIncludes for nested includes, so no fixture can include an automatic fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Builds on #269 (this PR targets its
watch-fixturesbranch). Following the Discord discussion, it limits automatic inclusion tomigrations/fixtures/auto/, makes creating that folder the opt-in instead of a setting, fixes a bug in the committed history lookup, and adds tests and docs. The earlier design of this PR, which wrote generated blocks into the current migration, is dropped.Each commit stands on its own:
(^|\n)before the path, soconst [, relativePath] = matchread that group. Every committed fixture was keyed by""or"\n", none ever matched, and every fixture was included again in every migration. This fix is independent of the rest and can be cherry-picked.fixtures/autoautomatically. Other fixtures (indexes, constraints, anything that shouldn't re-run on change) are only included manually.--!includeinsidefixtures/autois an error, so no fixture runs more than once through nesting and no DAG is needed. Each fixture's hash comes straight from its file.--! no-transaction, socommitkeeps--! Message:and a no-transaction migration stays outside a transaction. Only that section is stripped on uncommit, so headers survive it too.current.sqlandcurrent/modes; the commit message surviving commit and uncommit; uncommit while a fixture edit is pending; a failed commit restoring what you wrote). Before the setting was removed, I ran them against Add opt-in setting to automatically include fixtures in migrations on change #269 with it switched on, and 14 of them failed. The README gains a section covering the folder rule, ordering by path, changes that need aDROP(such as a new function parameter), adoption by moving files into the folder (each runs once), locks, and the pg-minify dollar-quoting limitation.fixtures/auto. TheautoIncludeFixturessetting is removed; the folder's presence is the opt-in. Without the folder, reading the current migration skips the committed fixture history entirely.--! no-transactionin automatic fixtures. The automatic section always runs inside the migration's transaction, so a fixture infixtures/autothat declares it is now an error instead of being skipped with an easy-to-miss warning. Keep such fixtures in another folder and include them manually.readCurrentMigrationoption. An earlier commit letuncommitignore automatic fixtures when checking that the current migration is blank. That needed an extra option onreadCurrentMigrationfor one rare case, so it is dropped: as in Add opt-in setting to automatically include fixtures in migrations on change #269,uncommitrefuses while a fixture has pending changes, and you commit or revert the edit first. Nothing is lost either way, anduncommit.tsis unchanged from Add opt-in setting to automatically include fixtures in migrations on change #269.--!include. Following review,compileIncludestakes aforbidAutoIncludesflag, passed down to nested includes, whichreadCurrentMigrationsets. Neither the current migration nor a fixture it includes can include a file fromfixtures/auto/, whatever the spelling, so automatic fixtures only ever run in the automatic section. That removes the already-included detection, replacing the TODO. A fixture change that depends on the rest of the migration goes in the next migration, as the README now says. Thecompileandruncommands are unchanged.For discussion:
fixtures/auto/folder for something else would switch this on when they upgrade. Is a release note enough, or would a more distinctive folder name be better? At least any--!includeof files in such a folder now fails with a clear error.Validation: TypeScript build (every commit), ESLint, Prettier and the Jest suite. 118 of 119 tests pass;
migrate.test.ts› "handles errors during migration gracefully" fails locally on Node 22, and fails the same way onmain.🤖 Generated with Claude Code