Skip to content

fix(cli): port db reset --experimental remote schema-files path to native TS (CLI-1958) - #6062

Merged
Coly010 merged 52 commits into
developfrom
columferry/cli-1958-port-db-reset-experimental-remote-schema-files-path-natively
Aug 10, 2026
Merged

fix(cli): port db reset --experimental remote schema-files path to native TS (CLI-1958)#6062
Coly010 merged 52 commits into
developfrom
columferry/cli-1958-port-db-reset-experimental-remote-schema-files-path-natively

Conversation

@Coly010

@Coly010 Coly010 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What changed

Ports db reset's --experimental remote schema-files path from a Go-binary delegation to native TypeScript, removing the last LegacyGoProxy dependency from db reset's remote branch.

Trigger (matches Go's apply.MigrateAndSeed three-conjunct gate exactly): --experimental/SUPABASE_EXPERIMENTAL set, no explicit --version/--last, and [experimental.pgdelta].enabled unset. Body: globs [db.migrations].schema_paths and execs each matched file with no history tracking (no version row, no RESET ALL between files) — reproducing two undocumented Go quirks byte-for-byte:

  • Default schema_paths = [] makes this a silent no-op (schemas/seeds still drop and reseed, nothing gets applied).
  • A partial glob failure (some patterns match, some don't) is silently swallowed; only a total failure (nothing matches at all) aborts the reset.

New shared primitives: legacyApplySchemaFiles (legacy-migration-apply.ts) and a hoisted legacy-sql-files-glob.ts (replacing three separate hand-rolled copies of Go's Glob.SQLFiles traversal that had existed across db push's seed path, this new schema-files path, and start/migration down's seed path — the third one had already silently diverged, missing directory-entry expansion; that's fixed too).

This path connects directly (no shadow database involved) — confirmed via go-parity-auditor, addressing the issue's own note about overlapping with CLI-1956's shadow-provisioning work (a separate, still-in-progress issue in another PR): there turned out to be no actual dependency.

Known, deliberately-deferred gap (tracked separately)

legacyMigrateAndSeed (shared by migration down and native supabase start's fresh-volume setup) does not yet implement this same schema-files branch, so supabase start --experimental on a fresh volume doesn't reproduce Go's behavior. This is pre-existing (not introduced here) and out of scope for db reset — filed as CLI-2040 with the same go-parity-auditor findings, and the relevant docstring here now points at it instead of asserting (falsely) that the gap doesn't exist.

Review notes

Reviewed independently by go-parity-auditor, engineer-reviewer, and architect-reviewer — all three converged on the same two follow-ups (now fixed): a stale "unreachable" docstring papering over the CLI-2040 gap, and an incomplete hoist that left a third, silently-diverging copy of the shared glob logic in db push/start/migration down's seed path. Consolidating that hoist also surfaced and fixed a real latent bug in the shared glob's Windows-path handling (toSlash was applying backslash-to-slash conversion unconditionally instead of Windows-only, which would have corrupted backslash-escaped glob patterns on non-Windows once rerouted). Added test coverage for schema-file application order, directory-entry expansion, and the new SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS env-override branches.

Fixes CLI-1958

Coly010 added 3 commits August 4, 2026 15:31
…tive TS (CLI-1958)

Ports Go's apply.MigrateAndSeed EXPERIMENTAL declarative branch
(apps/cli-go/internal/migration/apply/apply.go:19,51-68) for db reset's
remote (--linked / remote --db-url) path, replacing the last Go-binary
delegation on that command. A versionless --experimental /
SUPABASE_EXPERIMENTAL reset with pg-delta not enabled now applies
[db.migrations].schema_paths files directly (legacyApplySchemaFiles) instead
of replaying timestamped migrations, faithfully reproducing two undocumented
Go quirks: an empty schema_paths default silently applies nothing, and a
partial glob failure is swallowed once at least one pattern matches.

Hoists the Glob.SQLFiles traversal (legacySqlFilesGlob) out of the seed
pipeline into shared/ so both [db.seed].sql_paths and the new
[db.migrations].schema_paths resolve through one port of Go's glob
semantics. Exposes schema_paths from the db-config TOML reader with the
same env-override/remote-block-merge handling as the sibling seed field.

Removes the remaining LegacyGoProxy delegation from db reset's handler and
runtime layer now that both the remote and local paths are fully native
(the local path's own schema-files branch still runs behind the existing
db __db-bootstrap seam, out of scope here).
Whitespace-only fix following the db reset (CLI-1958) note update — oxfmt
recomputes column widths across the whole markdown table.
…ort (CLI-1958)

Fixes the items three reviewers (go-parity, engineer, architect) converged on:

- Correct legacyMigrateAndSeed's stale docstring: the EXPERIMENTAL schema-files
  branch is reachable from start's fresh-volume setup (version: ""), not just
  migration down, and is deliberately deferred to CLI-2040, not unreachable.
- Route legacy-seed.ts's resolveSeedFiles through the shared legacySqlFilesGlob
  instead of a third hand-rolled glob copy, fixing a silent directory-expansion
  gap on the migration down/start seed path. Remove legacy-seed-ops.ts's now-
  redundant legacyGlobSeedFiles/LegacyGlobResult pass-through shim.
- Add Go's GlobOption surface (skipEmptyGlobs/errorOnAllSkipped) to
  legacySqlFilesGlob for db diff's upcoming declarative path; this issue's own
  callers pass no options, so behavior is unchanged.
- Fix legacy-sql-files-glob.ts's toSlash to only convert on win32, matching Go's
  filepath.ToSlash (a no-op on non-Windows) — otherwise routing legacy-seed.ts's
  backslash-escape patterns through the shared glob would corrupt them.
- Add reset.integration.test.ts coverage for schema_paths declaration order
  across multiple patterns and directory-entry expansion, plus toml-read tests
  for SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS's env-override, string, non-string-
  filter, and remote-suppression branches.
- Correct reset.layers.ts's docstring: the local reset path still reaches
  LegacyGoProxy through the bootstrap seam (CLI-1955's scope), only the remote
  path is fully native.
@Coly010

Coly010 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Coly010 added 2 commits August 4, 2026 17:36
…8-port-db-reset-experimental-remote-schema-files-path-natively

# Conflicts:
#	apps/cli/docs/go-cli-porting-status.md
@Coly010 Coly010 self-assigned this Aug 5, 2026
@Coly010
Coly010 marked this pull request as ready for review August 5, 2026 08:54
@Coly010
Coly010 requested a review from a team as a code owner August 5, 2026 08:54
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@fe3c34fe1b2547c50e6e4c300fb38d48a442836f

Preview package for commit fe3c34f.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ff4485289

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts
Comment thread apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts Outdated
Coly010 added 2 commits August 5, 2026 11:40
… (CLI-1958)

`legacySqlFilesGlob`/`legacyWalkSqlFiles` diverged from Go's
`config.Glob.SQLFiles` (`apps/cli-go/pkg/config/config.go:123-211`) in two
ways, both confirmed empirically against a built `apps/cli-go` probe:

- Directory expansion re-`stat`ed each child, following symlinks. Go's
  `fs.WalkDir` types children from their parent's `ReadDir` entry
  (Lstat-based), so a symlinked `.sql` file or subdirectory below a matched
  schema/seed directory is never included or recursed into
  (`io/fs/walk.go:114-115`). Detect this with `readLink` (succeeds only for
  symlinks) before falling back to `stat`.
- An empty pattern (e.g. `schema_paths = [""]`) resolved via
  `path.join(workdir, "")` to the workdir itself and reported a match. Go's
  `Lstat("")` fails, so `fs.Glob`/`afero.Glob` always report no match for an
  empty pattern. Short-circuit on `pattern.length === 0`.

Review: PR #6062 (chatgpt-codex-connector), threads on
legacy-sql-files-glob.ts:92 and :40.
…I-1958)

`[db.migrations].schema_paths` and `[db.seed].sql_paths` decode through Go's
`v.UnmarshalExact` (`apps/cli-go/pkg/config/config.go:749-756`), whose
decoder config never overrides `WeaklyTypedInput`, so viper's
`defaultDecoderConfig` default of `true` stands. mapstructure's
`decodeString` therefore weakly converts a non-string scalar array element
(bool to "1"/"0", a number to its decimal string) instead of erroring or
dropping it. The TS reader filtered non-string entries out instead, silently
dropping schemas.

Verified empirically against a built `apps/cli-go` probe: `schema_paths =
[42, true, "schemas/*.sql"]` resolves to `supabase/{42,1,schemas/*.sql}`.

Review: PR #6062 (chatgpt-codex-connector), thread on
legacy-db-config.toml-read.ts:1887.
@Coly010

Coly010 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7020d74f0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts Outdated
Coly010 added 2 commits August 5, 2026 13:07
…stion to exec-phase (CLI-1958)

Two Go-parity gaps in the experimental `db reset` remote schema-files path,
both verified empirically against apps/cli-go:

- legacySqlFilesGlob/legacyWalkSqlFiles silently treated a directory-read
  failure during walk as an empty match. Go's fs.WalkDir propagates a ReadDir
  error and walkMatchedDir wraps it as "failed to walk matched directory: ...",
  which applySchemaFiles only discards when at least one OTHER file was still
  found (declared non-empty); with nothing else matched, Go aborts before
  applying anything. The walk failure now surfaces as a warning via
  Effect.result/Result.isFailure, so the existing files.length === 0 gate
  correctly turns it fatal instead of reporting silent success after schemas
  are already dropped.

- legacyApplySchemaFiles attached Go's CmdSuggestion ("See schema file: ...")
  to every legacyExecSqlFile failure, but Go's applySchemaFiles only sets
  CmdSuggestion after ExecBatch (statement execution) fails -- a
  NewMigrationFromFile (file-read) failure returns before CmdSuggestion is
  ever touched. execMigrationBatch's mapError callback now carries a
  "read"/"exec" phase tag so the suggestion is attached only on exec-phase
  failures.

Extracted the ad hoc errMessage helper (legacy-migration-apply.ts) into
shared legacy-error-message.ts so legacy-sql-files-glob.ts can reuse it
without a circular import.
…ies (CLI-1958)

Go's config.Glob decode (UnmarshalExact, config.go:749-756) weakly coerces a
bool/number array element but hits mapstructure's UnconvertibleTypeError for
a non-scalar one (nested array/table), which aborts the ENTIRE config load
with "failed to parse config: decoding failed due to the following
error(s): ...". Verified empirically against apps/cli-go:
`schema_paths = [[]]` / `[{path = "x.sql"}]` both fail config.Load with that
exact message before any schema is dropped; multiple bad entries are
aggregated in one message.

legacyWeakCoerceGlobEntry previously filtered these elements out silently,
which on an experimental remote reset could drop remote schemas and then
apply zero files while reporting success. legacyReadDbToml now fails the
whole config load with the byte-matching mapstructure-style message instead.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1fa1508080

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Coly010 added 2 commits August 5, 2026 14:13
…1958)

Go's mapstructure decode is weakly typed on the whole `[]string` field, not
just on array elements: a top-level scalar (e.g. `schema_paths = 42`) is
wrapped into a synthetic single-element array and decoded through the same
per-element rules as a real array entry, and a non-empty table fails with
the same unconvertible-type error an array element would. The native reader
only applied that weak coercion to array elements, so a scalar fell through
to the empty/default fallback instead of resolving (and potentially
warning) like Go does. Verified empirically against apps/cli-go.
…1958)

Two Go-parity gaps in the shared SQL-file globber:

- A matched path that fails to stat (a broken symlink, or a file that
  disappears between the glob and the stat) was falling back to treating it
  as a regular file. Go's Glob.SQLFiles records a "failed to stat matched
  file" warning and skips the path instead; the fallback here let a later
  read of the nonexistent path turn a warned-but-otherwise-successful reset
  into a hard apply error.

- Splitting an absolute pattern whose meta character is in the first path
  component (e.g. `/*.sql`, `/tmp*/*.sql`) collapsed the root directory to
  `""`, which the globber treats as "use the workdir". Go's real runtime
  glob path (afero.IOFS.Glob -> afero.Glob) explicitly special-cases a bare
  `/` and keeps it, so the pattern resolves against the filesystem root, not
  cwd. Verified empirically against apps/cli-go.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: efbc9a070b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Comment thread apps/cli/src/legacy/commands/db/reset/SIDE_EFFECTS.md Outdated
Coly010 added 2 commits August 5, 2026 15:08
…review: CLI-1958)

Go's fs.WalkDir builds each child path via path.Join, which runs path.Clean
and collapses a doubled `/`. The native walkMatchedDir port instead
string-concatenated `${rel}/${name}`, so a literal schema_paths/sql_paths
directory entry ending in `/` (e.g. "/tmp/schemas/") produced
"/tmp/schemas//a.sql" instead of Go's "/tmp/schemas/a.sql" for every child.

Verified empirically: a scratch apps/cli-go probe calling
config.Glob{"<dir>/"}.SQLFiles(...) against a real trailing-slash directory
returns the single-slash path.
…IDE_EFFECTS (review: CLI-1958)

The env var table omitted SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS even though
this change makes the native remote --experimental schema-files branch
resolve [db.migrations].schema_paths through legacy-db-config.toml-read.ts's
generic AutomaticEnv-override reader (LEGACY_ENV_OVERRIDABLE_KEYS), which
this PR newly added for that key. No dedicated CLI flag exists for
schema_paths, so the env var is the only non-config-file override surface.
@Coly010

Coly010 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

pr-autopilot: heads up, this PR now shows mergeable: CONFLICTING against develop (verified via git merge-tree HEAD origin/develop). The conflict is confined to apps/cli/docs/go-cli-porting-status.md — both this branch and develop edited rows in the same shared status table, which reflows column widths across the whole table and produces an overlapping-line conflict. It's unrelated to this PR's own change (the two Codex review threads on legacy-sql-files-glob.ts's trailing-slash handling and the db reset SIDE_EFFECTS.md env-var table, both now fixed/replied/resolved, commits 971b666 and 1dabdb6).

Not auto-resolving this — it needs a manual rebase/merge to reconcile the two sides' table edits rather than a scripted fix.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dabdb6ade

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
…(review: CLI-1958)

Go's fs.WalkDir joins child paths with path.Join, which cleans a bare
`.` root away entirely. schema_paths/sql_paths entries like [".."] can
resolve to exactly "." via config's own path.Join(SupabaseDirPath, ..),
so joinRelChild must special-case rel === "." to match Go's foo.sql
instead of ./foo.sql -- otherwise the seed_files.path hash key diverges
between Go and native tooling, causing seeds to needlessly re-run.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2502f3544f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Coly010 added 2 commits August 5, 2026 17:07
…LI-1958)

joinRelChild string-concatenated rel/name instead of running Go's
path.Clean-equivalent lexical cleaning, so a directory configured with a
cleanable segment (e.g. "/tmp/x/../schemas") produced a literal
".."-containing path instead of matching Go's fs.WalkDir output. Verified
empirically that Node's path.join matches Go's path.Join byte-for-byte
across dot-root, trailing-slash, and embedded "."/".." cases, so delegate
to the injected Path service instead of special-casing more segment shapes.
…iew: CLI-1958)

Go's fs.WalkDir types each child from the DirEntry its parent ReadDir
already returned and never re-Stats through it, so a .sql file removed
between ReadDir and the walk callback's own visit stays in Go's declared
file list; only the later, real file-open fails loudly. This port's
follow-up fs.stat call opens a race window Go doesn't have, and on
failure silently classified the child as Unknown and dropped it with no
warning - an experimental reset whose only schema file hit this race
would "succeed" having applied nothing.

Verified empirically with a scratch filepath.WalkDir probe that deletes a
sibling .sql file between ReadDir and that file's own visit: Go still
reports it IsRegular from the cached DirEntry, keeps it declared, and the
later os.Open fails with "no such file or directory" - never a silent
drop. Match that outcome: on a stat failure, best-effort include a '.sql'-
named child anyway and let the real downstream read surface the failure.
@Coly010

Coly010 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8e8393d526

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts Outdated
Comment thread apps/cli/src/legacy/commands/db/reset/reset.handler.ts Outdated
Comment thread apps/cli/src/legacy/commands/db/reset/SIDE_EFFECTS.md Outdated
Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts Outdated
Comment thread apps/cli/src/legacy/commands/db/reset/reset.handler.ts
Coly010 added 5 commits August 6, 2026 04:50
…1958)

legacyDbResetRuntimeLayer omitted LegacyPgDeltaSslProbe, LegacyEdgeRuntimeScript,
and LegacyDockerRun, unlike legacyDbPushRuntimeLayer. When pg-delta caching is
enabled, the post-reset catalog cache reaches those services via
legacyExportCatalogPgDelta; missing them is an untyped missing-service defect
the handler's Effect.catch cannot recover from, crashing the process after the
remote database has already been reset instead of writing the catalog or
emitting Go's best-effort warning. Compose the same three layers db push uses.

Added a regression test that builds the real legacyDbResetRuntimeLayer (not a
mocked service) and asserts both services are actually exposed.
…egers (review: CLI-1958)

parseGoBaseZeroInt rejected underscore digit separators outright (e.g.
"1_048_576"), silently falling back to the 256KiB default even though Go's
strconv.ParseInt(s, 0, 64) accepts them per its integer-literal grammar. A
statement between the two limits would apply in TS but Go would already have
failed with "bufio.Scanner: token too long".

Implemented Go's exact underscore-placement grammar, verified empirically
against a real Go strconv.ParseInt(s, 0, 64): a single underscore may sit
immediately after a base prefix (0x/0o/0b, or the bare leading "0" of legacy
octal) or between two digits — never doubled, never leading a plain decimal
literal, never trailing.
…efore (review: CLI-1958)

Both db reset and db push captured the snapshot's Clock.currentTimeMillis
before calling legacyTryCacheMigrationsCatalog, i.e. before the hash and the
pg-delta export (a network round-trip) resolved. Go's real
WriteMigrationCatalogSnapshot reads time.Now().UTC() internally, after
TryCacheMigrationsCatalog has already resolved hash and snapshot, immediately
before the write. The early capture could make a concurrent cache write from
another process sort in the wrong order during catalog resolution/retention.

Moved the clock read inside legacyTryCacheMigrationsCatalog itself, right
before the write, fixing both callers at their shared root. Added a
regression test that proves the timestamp reflects a real time gap the
mocked export takes before resolving.
…view: CLI-1958)

SIDE_EFFECTS.md labeled the migrations-catalog cache write as remote-path
only. Go's start.SetupLocalDatabase (called by the local reset's PG15 recreate
branch, behind this port's db __db-bootstrap seam) also calls
pgcache.TryCacheMigrationsCatalog after MigrateAndSeed, with a "local" prefix
— inherited automatically since the local path delegates to the real Go
binary rather than being reimplemented in TS. The PG<=14 branch never calls
it at all. Documented both paths and the PG14/PG15 split.
…Dir order (review: CLI-1958)

legacyWalkSqlFiles iterated a directory's readDirectory() result in raw
filesystem enumeration order. Go's fs.WalkDir visits entries in lexical byte
order (os.ReadDir's own "sorted by filename" contract), so when a matched
directory has multiple problematic children (e.g. two unreadable
subdirectories), Go deterministically fails on the lexically-first one. This
port's unsorted iteration could pick a different one depending on filesystem
enumeration order, surfacing a different fatal/WARN message than Go.

Sorted directory entries with the existing UTF-8 byte-order comparator before
recursing. Added a regression test using a fake FileSystem that deliberately
returns entries in reverse order to prove the fix, independent of what the
real OS happens to return.
@Coly010

Coly010 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89acd6c011

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts
Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts
Comment thread apps/cli/src/legacy/commands/db/reset/reset.handler.ts
Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts Outdated
Coly010 added 2 commits August 6, 2026 06:03
…log export (review: CLI-1958)

db push scopes legacyApplyProjectEnv(projectEnv) around its whole run so a
SUPABASE_INTERNAL_IMAGE_REGISTRY/PGDELTA_NPM_REGISTRY set only in
supabase/.env reaches the pg-delta edge-runtime helpers, which read
process.env directly. db reset loaded the same projectEnv but never applied
it, so the same override was silently ignored for its post-reset
migrations-catalog export, falling back to the default registries.
…r text (review: CLI-1958)

Two follow-ups on the SUPABASE_SCANNER_BUFFER_SIZE parsing work:

- Reject a magnitude outside Go's signed int64 range (e.g.
  "9223372036854775808", one over math.MaxInt64) the same way
  cast.ToInt does: strconv.ParseInt(s, 0, 0) returns a range error, and
  cast.ToInt discards ANY parseFn error and returns exactly 0 (falls back to
  the 256KiB default), not the huge value Number.parseInt would silently
  round to. Verified against the pinned spf13/cast@v1.10.0
  (cast.ToInt("9223372036854775808") -> 0).

- Track the last RAW scanned token unconditionally, matching Go's
  `token = scanner.Text()` (runs on every successful Scan(), before the
  len(trim) > 0 append gate). A statement that trims to empty right before
  an oversized one (e.g. a lone ";") must still show in the "After
  statement N: ..." error text, not a blank token.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ac66092de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-sql-files-glob.ts
Comment thread apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts Outdated
Coly010 added 3 commits August 6, 2026 06:43
… treating as empty (review: CLI-1958)

smol-toml parses every TOML datetime variant to a TomlDate (a Date
subclass) that stores its value internally, not as an enumerable own
property, so it satisfies the same zero-enumerable-key test this reader
used to detect an empty inline table (`schema_paths = {}`). A bare
datetime therefore silently resolved to an empty pattern list instead of
failing config load.

Verified empirically against the real apps/cli-go config.Load: Go's
mapstructure decoder reports a bare datetime as unconvertible and aborts
the whole load, with a distinct Go type per TOML datetime variant
(time.Time for offset date-time, toml.LocalDateTime/LocalDate/LocalTime
for the three zone-less "local" variants). Exclude TomlDate from the
empty-table special case and teach legacyGoUnconvertibleType to name the
correct per-variant Go type, matching Go's error text exactly whether the
datetime is a top-level scalar or an array element.
…8-port-db-reset-experimental-remote-schema-files-path-natively

# Conflicts:
#	apps/cli/docs/go-cli-porting-status.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d7e1f8ab1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/commands/db/reset/reset.handler.ts
Comment thread apps/cli/src/legacy/commands/db/reset/reset.handler.ts
Comment thread apps/cli/src/legacy/commands/db/reset/reset.handler.ts
Coly010 added 2 commits August 6, 2026 17:12
…8-port-db-reset-experimental-remote-schema-files-path-natively

# Conflicts:
#	apps/cli/docs/go-cli-porting-status.md
#	apps/cli/src/legacy/commands/db/reset/reset.handler.ts
#	apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts
#	apps/cli/src/legacy/shared/legacy-migrate-and-seed.ts
#	apps/cli/src/legacy/shared/legacy-pgdelta.cache.unit.test.ts
#	apps/cli/src/legacy/shared/legacy-seed.ts
- legacy-sql-split.ts: match Go's unicode.IsDigit (decimal digits only,
  \p{Nd}) for dollar-quote tag/identifier characters instead of \p{N}
  (all Unicode numbers), which wrongly accepted non-decimal digit runes
  like superscript-2 and could split schema SQL differently than Go.
- legacy-seed-ops.ts / legacy-seed.ts: enforce SUPABASE_SCANNER_BUFFER_SIZE
  on seed file parsing via the shared checkScannerBufferSize, matching
  Go's SeedFile.ExecBatchWithCache, which parses through the same
  parseFile every other file type does.
- legacy-pgdelta.cache.ts: listJsonEntries now only swallows a genuinely
  missing catalog directory and propagates every other read failure
  (e.g. permission denied), matching Go's ReadDir usage after
  ensureTempDir — previously every failure was treated as empty,
  silently defeating catalog retention and cache resolution.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d1eb7a2b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-seed-ops.ts

@avallete avallete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified at head 9df1d7b: the two blocking parity bugs (Kong --nginx-conf, PG14 toml.schemaPaths) are fixed and now pinned by tests — confirmed the new integration test fails on the reverted code. None of the items below are merge-blockers; batching them here so they don't get lost. Note several of these were raised by Codex in earlier rounds and their threads were marked resolved without a corresponding commit — worth checking why the autopilot closes threads it hasn't acted on.

Behavior / UX

  • Reset-failure suggestions are dropped by the declarative wrap. LegacyDeclarativeApplyError carries only message (declarative.errors.ts:80-82), so the Kong-reload recovery hint, health-timeout architecture hints, etc. never reach the renderer from declarative.smart-target.ts:181-186 and sync.handler.ts:403-405. Go preserves CmdSuggestion; the old subprocess printed it on inherited stderr. Add an optional suggestion to the error (or propagate the reset failure unwrapped, matching Go's return resetErr) — and drop the extra database reset failed: prefix in sync's recovery path, which currently prints Database reset also failed: database reset failed: … where Go prints the error once.
  • Ctrl-C during sync's recovery reset becomes a fake error. sync.handler.ts:397-398 extracts only fail reasons from the exit cause, so an interrupt (or defect) surfaces as database reset failed: unknown error and the command continues writing debug bundles instead of propagating cancellation. Capture typed failures only; let interrupts/defects propagate (smart-target's Effect.mapError already behaves correctly).
  • JSON --output-format error codes changed. The tag renames (LegacyStartNetworkCreateErrorLegacyNetworkCreateError etc. in container-lifecycle.ts:65-90, LegacyStartDbSetupErrorLegacyDbSetupError in db-setup.ts:148, LegacyDbResetNotRunningErrorLegacyResetLocalDbNotRunningError in reset-local-database.ts:69) are surfaced verbatim as the JSON code via normalizeCliError. Keep the class renames but retain the original tag strings so machine consumers don't break.
  • Bucket seeding skips where Go seeds. reset-local-database.ts:224's legacySeedBucketsRun reloads config through the narrower .env/.env.local set, so env(VAR) backed by .env.<SUPABASE_ENV> triggers the warn-and-skip path where Go (env already os.Setenv'd) seeded successfully. The divergence is documented in-code, but the fully resolved config is already in scope — thread it through instead of tolerating the gap.

Code health

  • collectText (legacy-container-cli.ts:131) and runContainerCliExpectSuccess (:174) are bare exports from src/legacy/ — rename with the legacy prefix per the workspace rule.
  • legacyBuildLocalDbContainerInputs (local-container-inputs.ts:97) is only called by the reset path; db start still carries its byte-identical ~130-line inline copy (start.handler.ts:916-1125) while the module header claims both callers share it. Either finish the hoist or fix the header — as-is the two copies can silently drift.
  • PG14 DROP/CREATE DATABASE failures (recreate-local-database.ts:300-306, same for the disconnect trio at :231-239) surface only the bare driver error. Go routes these through ExecBatch's formatter (At statement: <i> + failing SQL, pkg/migration/file.go:124-146); the TS port of that formatter already exists in legacy-migration-apply.ts and just isn't used here.
  • Dead test knob: storageUnhealthy (reset.integration.test.ts:361) is declared and wired into the route but never used by any test — exercise it (storage-timeout-fails-reset at integration level) or delete it.

Docs

  • db/reset/SIDE_EFFECTS.md:67,103-104 still documents the pre-fix bare kong reload; the argv now includes --nginx-conf /home/kong/custom_nginx.template and the flag is load-bearing (#6059). The env-var table is also missing SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS, now genuinely effective on the experimental local reset.
  • The new modules cite reset.go line numbers from before this PR's own 32-line Go deletion (e.g. recreate-local-database.ts header's reset.go:146-174, await-storage-ready.ts citing lines this PR removes) — all off by ~32 once merged; refresh the parity-oracle citations.
  • start/SIDE_EFFECTS.md:59 still says legacyStartVolumeExists (renamed to legacyVolumeExists everywhere else).

…ental-remote-schema-files-path-natively

Resolves conflicts from develop's CLI-1955/CLI-2062 local-reset native
port (legacyResetLocalDatabase, hoisted db-bootstrap primitives) by
layering this branch's remote schema-files native port on top: the
local target already went fully native on develop; this branch now
makes the remote --experimental schema-files path native too, closing
the last Go delegation on db reset.

Also addresses avallete's review (PR #6062, review 4895183734):
- LegacyDeclarativeApplyError now carries the wrapped failure's
  suggestion (e.g. a Kong-reload recovery hint) instead of dropping it;
  sync's recovery-reset path no longer double-prefixes the reset
  failure's message and now propagates a Ctrl-C/defect instead of
  synthesizing a fake "unknown error".
- db reset's local bucket seeding now threads the already-resolved
  project config into legacySeedBucketsRun (resolvedConfig), closing
  the narrower-env-file-set gap that could wrongly warn-and-skip
  buckets Go would have seeded.
- collectText/runContainerCliExpectSuccess renamed with the mandatory
  legacy prefix.
- local-container-inputs.ts's header now accurately says only db reset
  consumes the hoisted prelude today (db start still has its own
  inline copy) instead of claiming both callers already share it.
- PG14's DROP/CREATE DATABASE statements now get Go's ExecBatch error
  context (At statement: N + caret-marked SQL) via a newly exported
  legacyFormatExecBatchError, instead of a bare driver error.
- Removed the dead storageUnhealthy test knob (the behaviour it would
  exercise is already covered precisely by
  await-storage-ready.unit.test.ts's fake-clock tests).
- Refreshed ~20 stale Go reset.go line-number citations across
  recreate-local-database.ts/await-storage-ready.ts/restart-services.ts,
  and the legacyStartVolumeExists -> legacyVolumeExists rename in
  start/SIDE_EFFECTS.md.

Not addressed (left as-is, with rationale):
- The LegacyStartNetworkCreateError/LegacyStartDbSetupError/
  LegacyDbResetNotRunningError tag renames predate this PR (already
  shipped in develop as CLI-1955, PR #6026) and are out of scope here.
- Finishing db start's hoist onto legacyBuildLocalDbContainerInputs is
  tracked as a follow-up rather than folded into this db-reset change,
  given how much db-start-specific nuance sits in its current inline
  copy.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e55868cee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts
Comment thread apps/cli/src/legacy/shared/legacy-db-config.toml-read.ts
…ental-remote-schema-files-path-natively

A second develop commit (CLI-1956, shadow database provisioning)
landed concurrently with the first merge, reintroducing conflicts.
Resolves them the same way: takes develop's newer/hoisted shared
primitives (legacySqlFilesGlob, LegacyPgDeltaContext.projectEnv,
schema_paths resolution in legacy-db-config.toml-read.ts) over this
branch's now-superseded inline duplicates, and fixes the fallout:

- reset.handler.ts's pgDeltaCtx now supplies the newly-required
  projectEnv field (toml.projectEnv).
- shadow-database.ts's import updated to the legacyCollectText rename.
- legacy-db-config.toml-read.ts's schemaPathPatterns (the new raw,
  pre-join form CLI-1956 added for db diff/db pull's shadow
  provisioning) now sourced from the same schemaPathsResolved.patterns
  this branch's own schema_paths resolution already computes.
- Corrected local-container-inputs.ts's header: CLI-1956 concurrently
  finished the exact db-start hoist flagged as a follow-up in the
  first merge commit (db start/db diff/db pull all call
  legacyBuildLocalDbContainerInputs now), so that follow-up note no
  longer applies.

All 7362 tests pass; types/lint/fmt/knip clean.
@Coly010

Coly010 commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review — went through every item below, accept/reject, all accepted items fixed directly in this PR (nothing deferred). Pushed as two follow-up merge commits (2e55868c, fe3c34fe1) since develop moved twice while resolving conflicts.

Behavior / UX

  • Reset-failure suggestions dropped by the declarative wrap — accepted. LegacyDeclarativeApplyError now carries an optional suggestion, threaded through from the wrapped failure via a new legacyReadErrorSuggestion helper in both declarative.smart-target.ts and sync.handler.ts. Also dropped the double database reset failed: database reset failed: … prefix in sync's recovery path — it now prints the underlying error's message once, matching Go's resetErr passthrough.
  • Ctrl-C during sync's recovery reset becomes a fake error — accepted, and I found the identical bug one line above it (the initial apply-failure extraction, not just the recovery reset) and fixed both. Both now use Cause.findFail to distinguish a genuine typed failure from an interrupt/defect; a non-Fail cause now propagates via Effect.failCause instead of being coerced into a synthetic LegacyDeclarativeApplyError.
  • ⏸️ JSON --output-format error codes changed (tag renames) — rejected for this PR. Checked: all three renames (LegacyStartNetworkCreateErrorLegacyNetworkCreateError, LegacyStartDbSetupErrorLegacyDbSetupError) shipped already in the separate, already-merged CLI-1955 (fix(cli): port db reset local recreate to native TS (CLI-1955) #6026) — this PR's diff doesn't touch them, it just inherited them via the develop merge. The third one you flagged, LegacyDbResetNotRunningErrorLegacyResetLocalDbNotRunningError in reset-local-database.ts, isn't actually a rename in the shipped sense — LegacyDbResetNotRunningError was dead code this branch had declared (in reset.errors.ts) but never instantiated; I deleted it during merge resolution rather than reconcile it. If tag stability for --output-format json becomes a real requirement, I'd rather see it land as its own deliberate policy (maybe riding on the error-taxonomy work that just merged, chore(cli): define error taxonomy #6132) than re-litigate an already-shipped rename here.
  • Bucket seeding skips where Go seeds — accepted. legacySeedBucketsRun already has a resolvedConfig escape hatch for exactly this (db start already uses it) — reset-local-database.ts now passes the config it already resolved via legacyBuildLocalDbContainerInputs instead of letting the call reload from disk through the narrower @supabase/config path.

Code health

  • collectText/runContainerCliExpectSuccess bare exports — accepted, renamed to legacyCollectText/legacyRunContainerCliExpectSuccess (legacy-container-cli.ts + all call sites, including the ones the concurrently-merging CLI-1956 shadow-database work added).
  • ⏸️→✅ (superseded) legacyBuildLocalDbContainerInputs hoist incomplete — accepted the underlying concern, but by the time I'd verified it and gone with the lower-risk of your two options (fix the header rather than refactor db start's handler in an unrelated PR), CLI-1956 landed concurrently and actually finished the hoist — db start now calls legacyBuildLocalDbContainerInputs (via a preloadedContext param), and db diff/db pull's shadow provisioning does too. So the header is accurate again as originally written; no further action needed.
  • PG14 DROP/CREATE DATABASE failures surface only the bare driver error — accepted. Extracted the atStatement closure out of legacy-migration-apply.ts's migration-batch runner into an exported legacyFormatExecBatchError, and legacyResetRecreateDatabases (recreate-local-database.ts) now runs its four statements through it — same At statement: N + caret-marked SQL + Detail line + 42704 hint Go's own ExecBatch produces. Added an integration test pinning this.
  • Dead test knob storageUnhealthy — accepted, but exercised it in the sense of confirming it's genuinely redundant rather than adding an it.live for it: the behavior it would cover (unhealthy-but-present storage → 30s wait → timeout fails the whole reset) is already pinned precisely, at the exact 30s boundary, by await-storage-ready.unit.test.ts's fake-clock tests. Deleted the knob instead of duplicating that coverage in a much slower integration test.

Docs

  • SIDE_EFFECTS.md stale Kong reload + missing env var — accepted. Kong reload row now includes the load-bearing --nginx-conf /home/kong/custom_nginx.template flag and why it matters (db reset against an already-running stack leaves Kong's outbound template-serving listener (8088) permanently unbound #6059); SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS was already in my table from this PR's own work, confirmed still there post-merge.
  • Go line-number citations off by ~32 — accepted, refreshed every citation in recreate-local-database.ts/await-storage-ready.ts/restart-services.ts against the current reset.go (also corrected await-storage-ready.ts's citation, which claimed a standalone AwaitStorageReady Go function that doesn't exist — it's the inline storage-check block inside Run, reset.go:66-71).
  • start/SIDE_EFFECTS.md's stale legacyStartVolumeExists — accepted, renamed to legacyVolumeExists.

Also re: "the autopilot closes threads it hasn't acted on" — noted, not something I can fix retroactively here, but flagging it back since you raised it: if that's still happening on future rounds it's worth someone looking at the autopilot's thread-resolution logic directly.

All checks green: types/lint/fmt/knip clean, 7362 tests passing.

@Coly010
Coly010 added this pull request to the merge queue Aug 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe3c34fe1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts
Comment thread apps/cli/src/legacy/shared/legacy-migration-apply.ts
Comment thread apps/cli/src/legacy/shared/legacy-sql-split.ts
Merged via the queue into develop with commit 77b631c Aug 10, 2026
21 checks passed
@Coly010
Coly010 deleted the columferry/cli-1958-port-db-reset-experimental-remote-schema-files-path-natively branch August 10, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants