Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
b70255d
fix(cli): port db reset --experimental remote schema-files path to na…
Coly010 Aug 4, 2026
7d33278
docs(cli): reformat go-cli-porting-status.md table (oxfmt column widths)
Coly010 Aug 4, 2026
873c3d3
fix(cli): address review findings on db reset --experimental native p…
Coly010 Aug 4, 2026
93617dc
Merge remote-tracking branch 'origin/develop' into columferry/cli-195…
Coly010 Aug 4, 2026
8ff4485
docs(cli): reformat go-cli-porting-status.md table (oxfmt column widths)
Coly010 Aug 4, 2026
4bdb3bd
fix(cli): match Go's Glob.SQLFiles symlink and empty-pattern handling…
Coly010 Aug 5, 2026
7020d74
fix(cli): weakly coerce non-string schema_paths/sql_paths entries (CL…
Coly010 Aug 5, 2026
4024640
fix(cli): propagate SQL-glob walk failures and gate schema-file sugge…
Coly010 Aug 5, 2026
1fa1508
fix(cli): abort config load on non-scalar schema_paths/sql_paths entr…
Coly010 Aug 5, 2026
e781d2e
fix(cli): weakly coerce top-level scalar schema_paths/sql_paths (CLI-…
Coly010 Aug 5, 2026
efbc9a0
fix(cli): stop misreading stat failures and absolute glob roots (CLI-…
Coly010 Aug 5, 2026
971b666
fix(cli): normalize doubled slash under trailing-slash matched dirs (…
Coly010 Aug 5, 2026
1dabdb6
docs(cli): document SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS in db reset S…
Coly010 Aug 5, 2026
2502f35
fix(cli): drop './' prefix when a walked SQL directory cleans to '.' …
Coly010 Aug 5, 2026
f0fc52c
fix(cli): clean walked SQL child paths like Go's path.Join (review: C…
Coly010 Aug 5, 2026
95f3108
fix(cli): keep a raced '.sql' child declared when its stat fails (rev…
Coly010 Aug 5, 2026
40f597f
fix(cli): clean direct SQL glob matches like Go's afero.Glob (review:…
Coly010 Aug 5, 2026
a3a846c
fix(cli): preserve Windows drive roots when splitting SQL glob patter…
Coly010 Aug 5, 2026
35204d5
fix(cli): wrap migration read failures with Go's parse-file error tex…
Coly010 Aug 5, 2026
5331b1b
docs(cli): correct db reset SIDE_EFFECTS on encrypted vault secrets (…
Coly010 Aug 5, 2026
f37fe32
fix(cli): format large numeric schema_paths entries as fixed decimal …
Coly010 Aug 5, 2026
3da79a8
fix(cli): report workdir-relative path in schema-file read errors (re…
Coly010 Aug 5, 2026
17f2960
docs(cli): document SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED reset gate …
Coly010 Aug 5, 2026
e37fc5c
fix(cli): sort SQL glob matches by UTF-8 byte order like Go (review: …
Coly010 Aug 5, 2026
cf49af6
fix(cli): fail walk on a raced disappearing subdirectory like Go's Wa…
Coly010 Aug 5, 2026
08b4dd8
fix(cli): preserve raw Windows glob pattern in "no files matched" war…
Coly010 Aug 5, 2026
873f12a
fix(cli): report workdir-relative path in SQL glob stat-failure warni…
Coly010 Aug 5, 2026
95072d7
fix(cli): keep SQL glob walk/stat errors and Windows match order Go-f…
Coly010 Aug 5, 2026
e61a58c
fix(cli): match Go's filepath.IsAbs for Windows-rooted schema/seed pa…
Coly010 Aug 5, 2026
30bf58a
fix(cli): match Go's Lstat glob fast path, scanner buffer limit, and …
Coly010 Aug 5, 2026
525d855
fix(cli): strictly parse SUPABASE_SCANNER_BUFFER_SIZE and honor proje…
Coly010 Aug 6, 2026
c405fc9
fix(cli): format TOML inf/-inf/nan glob entries as Go's strconv.Forma…
Coly010 Aug 6, 2026
f8a544d
fix(cli): reject an unterminated scanner token exactly at the buffer …
Coly010 Aug 6, 2026
3fce530
fix(cli): preserve negative zero when weakly formatting glob entries …
Coly010 Aug 6, 2026
2b232d0
fix(cli): cache the pg-delta migrations catalog after a remote reset …
Coly010 Aug 6, 2026
c06bc55
fix(cli): parse SUPABASE_SCANNER_BUFFER_SIZE with Go's base-0 int gra…
Coly010 Aug 6, 2026
560ff8a
docs(cli): document the ported pg-delta catalog cache in db reset (re…
Coly010 Aug 6, 2026
8e8393d
fix(cli): aggregate glob decode issues across sql_paths and schema_pa…
Coly010 Aug 6, 2026
8e886ce
fix(cli): provide pg-delta runtime services to db reset (review: CLI-…
Coly010 Aug 6, 2026
c9ecd15
fix(cli): accept Go's underscore digit separators in scanner-size int…
Coly010 Aug 6, 2026
f119a1c
fix(cli): read the pg-delta catalog timestamp after the export, not b…
Coly010 Aug 6, 2026
319e84e
docs(cli): document the local reset path's pg-delta catalog write (re…
Coly010 Aug 6, 2026
89acd6c
fix(cli): sort directory entries before walking to match Go's fs.Walk…
Coly010 Aug 6, 2026
ed712c6
fix(cli): scope project-env registry overrides around db reset's cata…
Coly010 Aug 6, 2026
1ac6609
fix(cli): match Go's scanner-size range rejection and last-token erro…
Coly010 Aug 6, 2026
da39dd0
fix(cli): reject bare TOML datetime schema_paths/sql_paths instead of…
Coly010 Aug 6, 2026
f0b0a42
Merge remote-tracking branch 'origin/develop' into columferry/cli-195…
Coly010 Aug 6, 2026
6d7e1f8
chore(cli): fix markdown table formatting after develop merge
Coly010 Aug 6, 2026
96f55b9
Merge remote-tracking branch 'origin/develop' into columferry/cli-195…
Coly010 Aug 6, 2026
9d1eb7a
fix(cli): close 3 db reset --experimental Go-parity gaps found in review
Coly010 Aug 6, 2026
2e55868
Merge branch 'develop' into columferry/cli-1958-port-db-reset-experim…
Coly010 Aug 10, 2026
fe3c34f
Merge branch 'develop' into columferry/cli-1958-port-db-reset-experim…
Coly010 Aug 10, 2026
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
90 changes: 45 additions & 45 deletions apps/cli/docs/go-cli-porting-status.md

Large diffs are not rendered by default.

210 changes: 129 additions & 81 deletions apps/cli/src/legacy/commands/db/reset/SIDE_EFFECTS.md

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion apps/cli/src/legacy/commands/db/reset/reset.errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,15 @@ export class LegacyDbResetCancelledError extends Data.TaggedError("LegacyDbReset
}
}

/** A drop / migrate / seed / vault statement failed during the remote reset. */
/**
* A drop / migrate / seed / vault statement failed during the remote reset. `suggestion`
* is Go's `CmdSuggestion` — set only by the `--experimental` schema-files apply branch
* (`"See schema file: <Bold(fp)>"`, `apply.go:63`); every other apply failure on this
* command leaves it unset, matching Go.
*/
export class LegacyDbResetApplyError extends Data.TaggedError("LegacyDbResetApplyError")<{
readonly message: string;
readonly suggestion?: string;
}> {
get [ErrorActionabilityId](): CliErrorActionabilityDeclaration {
return actionability.dbFinding;
Expand Down
241 changes: 116 additions & 125 deletions apps/cli/src/legacy/commands/db/reset/reset.handler.ts

Large diffs are not rendered by default.

735 changes: 536 additions & 199 deletions apps/cli/src/legacy/commands/db/reset/reset.integration.test.ts

Large diffs are not rendered by default.

34 changes: 21 additions & 13 deletions apps/cli/src/legacy/commands/db/reset/reset.layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,25 @@ import { legacyTelemetryStateLayer } from "../../../telemetry/legacy-telemetry-s
* Runtime layer for `supabase db reset`. Same composition as `db push` / `db lint`:
* the Postgres connection, the db-config resolver, project-ref resolution, and the
* linked-project cache, all over the lazy management-API factory so the local /
* `--db-url` paths never resolve an access token at layer-build time. `LegacyGoProxy`
* (used to delegate the remaining `--experimental` reset path) is ambient from the
* root. `legacyDockerRunLayer` backs the native local recreate's PG15+ one-shot
* migrate jobs (`legacyStartSetupLocalDatabase`, reused via
* `legacyRecreateLocalDatabase`) — same reasoning as `db start`'s own
* `start.layers.ts`. `legacyEdgeRuntimeScriptLayer`/`legacyPgDeltaSslProbeLayer` back
* that same shared setup pipeline's best-effort pg-delta migrations-catalog warmup
* (`db-setup.ts`'s `legacyTryCacheMigrationsCatalog` call, reachable from `db reset`'s
* PG15 recreate too) — the exact same pair `db start`/`db push` already compose for
* their own calls to that function (`db/start/start.layers.ts`, `push.layers.ts`).
* `LegacyCliConfig`/`ChildProcessSpawner`/`FileSystem`/`Path`/`RuntimeInfo` are
* ambient from the root runtime (`shared/cli/run.ts`).
* `--db-url` paths never resolve an access token at layer-build time. Both targets
* are fully native (CLI-1955/CLI-2062 for the local container-recreate primitives,
* CLI-1958 for the remote `--experimental` schema-files apply) — no Go delegation
* remains on this command, so `LegacyGoProxy` is not composed here.
*
* `legacyDockerRunLayer` backs the native local recreate's PG15+ one-shot migrate
* jobs (`legacyStartSetupLocalDatabase`, reused via `legacyRecreateLocalDatabase`)
* — same reasoning as `db start`'s own `start.layers.ts`.
* `legacyEdgeRuntimeScriptLayer`/`legacyPgDeltaSslProbeLayer` back that same shared
* setup pipeline's best-effort pg-delta migrations-catalog warmup (`db-setup.ts`'s
* `legacyTryCacheMigrationsCatalog` call, reachable from `db reset`'s PG15 recreate
* too) AND the remote path's own post-reset catalog-cache call — the exact same
* pair `db start`/`db push` already compose for their own calls to that function
* (`db/start/start.layers.ts`, `push.layers.ts`). Without them, a versionless reset
* with pg-delta enabled would hit an unhandled missing-service defect — not caught
* by the handler's typed `Effect.catch` — AFTER the database has already been
* reset, instead of writing the catalog or emitting Go's best-effort warning
* (review CLI-1958). `LegacyCliConfig`/`ChildProcessSpawner`/`FileSystem`/`Path`/
* `RuntimeInfo` are ambient from the root runtime (`shared/cli/run.ts`).
*/
const cliConfig = legacyCliConfigLayer.pipe(Layer.provide(legacyDebugLoggerLayer));
const httpClient = legacyHttpClientLayer.pipe(Layer.provide(legacyDebugLoggerLayer));
Expand Down Expand Up @@ -90,7 +97,8 @@ export const legacyDbResetRuntimeLayer = Layer.mergeAll(
// `console.ReadLine`); without it a CI/piped remote `db reset` that reaches the
// confirmation prompt fails with a missing-service defect instead of the default.
stdinLayer,
// Backs the native local recreate's PG15+ one-shot migrate jobs.
// Backs the native local recreate's PG15+ one-shot migrate jobs, and the remote
// path's own post-reset pg-delta catalog-cache call.
legacyDockerRunLayer,
edgeRuntime,
legacyPgDeltaSslProbeLayer,
Expand Down
146 changes: 146 additions & 0 deletions apps/cli/src/legacy/commands/db/reset/reset.layers.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* Layer-exposure test for `legacyDbResetRuntimeLayer`.
*
* Regression guard (review CLI-1958): the post-reset best-effort pg-delta
* catalog cache (`legacyTryCacheMigrationsCatalog` in `reset.handler.ts`, gated
* on `[experimental.pgdelta].enabled` / `SUPABASE_EXPERIMENTAL_PG_DELTA`) reaches
* `LegacyEdgeRuntimeScript` and `LegacyPgDeltaSslProbe` via
* `legacyExportCatalogPgDelta` (`legacy-pgdelta.ts`). `legacyDbResetRuntimeLayer`
* previously omitted both services (and the `LegacyDockerRun` layer the real
* edge-runtime implementation needs) — unlike `legacyDbPushRuntimeLayer`, which
* already composes all three. That gap was invisible to `reset.integration.test.ts`
* because that suite drives `legacyDbReset` directly with its own hand-built layer
* (which mocks `LegacyEdgeRuntimeScript`/`LegacyPgDeltaSslProbe` in), bypassing
* `reset.layers.ts` entirely — so a versionless remote reset with pg-delta enabled
* would crash on a missing-service defect (uncaught by the handler's typed
* `Effect.catch`) AFTER the remote database was already reset. This test builds
* the REAL `legacyDbResetRuntimeLayer` (not a mock of the pg-delta services) and
* asserts both are actually present in its context.
*
* See `db/lint/lint.layers.unit.test.ts` for the canonical ambient-stub pattern.
*/

import { describe, expect, it } from "@effect/vitest";
import { BunServices } from "@effect/platform-bun";
import { Effect, Layer, Option } from "effect";

import {
mockAnalytics,
mockOutput,
mockProcessControl,
mockRuntimeInfo,
mockStdin,
mockTelemetryRuntime,
mockTty,
} from "../../../../../tests/helpers/mocks.ts";
import {
mockLegacyCliConfig,
mockLegacyCredentialsLayer,
mockLegacyLinkedProjectCacheLayer,
mockLegacyTelemetryStateLayer,
} from "../../../../../tests/helpers/legacy-mocks.ts";

import { CliArgs } from "../../../../shared/cli/cli-args.service.ts";
import {
LegacyDebugFlag,
LegacyDnsResolverFlag,
LegacyExperimentalFlag,
LegacyNetworkIdFlag,
LegacyOutputFlag,
LegacyProfileFlag,
LegacyWorkdirFlag,
} from "../../../../shared/legacy/global-flags.ts";

import { LegacyPlatformApiFactory } from "../../../auth/legacy-platform-api-factory.service.ts";
import { LegacyProjectRefResolver } from "../../../config/legacy-project-ref.service.ts";
import { LegacyDbConfigResolver } from "../../../shared/legacy-db-config.service.ts";
import { LegacyDbConnection } from "../../../shared/legacy-db-connection.service.ts";
import { LegacyEdgeRuntimeScript } from "../../../shared/legacy-edge-runtime-script.service.ts";
import { LegacyPgDeltaSslProbe } from "../../../shared/legacy-pgdelta-ssl-probe.service.ts";

import { legacyDbResetRuntimeLayer } from "./reset.layers.ts";

/**
* Builds a stub ambient layer that satisfies every external service required by
* `legacyDbResetRuntimeLayer` from the root runtime. Services whose logic is not
* under test are no-op stubs; `LegacyEdgeRuntimeScript` and `LegacyPgDeltaSslProbe`
* are deliberately NOT stubbed here — the point of this test is to prove the real
* `legacyDbResetRuntimeLayer` provides them itself.
*/
function ambientStubs() {
const analytics = mockAnalytics();
const out = mockOutput();

const flagLayers = Layer.mergeAll(
Layer.succeed(LegacyDebugFlag, false),
Layer.succeed(LegacyProfileFlag, "supabase"),
Layer.succeed(LegacyWorkdirFlag, Option.none()),
Layer.succeed(LegacyOutputFlag, Option.none()),
Layer.succeed(LegacyDnsResolverFlag, "native"),
Layer.succeed(LegacyNetworkIdFlag, Option.none()),
Layer.succeed(LegacyExperimentalFlag, false),
Layer.succeed(CliArgs, { args: ["db", "reset"] }),
);

// Stub out the heavy service layers so layer construction doesn't require a
// real DB, real API, or real credentials.
const heavyServiceStubs = Layer.mergeAll(
Layer.succeed(LegacyDbConnection, {
connect: () => Effect.die("db-connection not needed for layer-exposure test"),
}),
Layer.succeed(LegacyDbConfigResolver, {
resolve: () => Effect.die("db-config-resolver not needed for layer-exposure test"),
resolvePoolerFallback: () =>
Effect.die("db-config-resolver not needed for layer-exposure test"),
}),
Layer.succeed(LegacyProjectRefResolver, {
resolve: () => Effect.die("project-ref-resolver not needed for layer-exposure test"),
resolveForLink: () => Effect.die("project-ref-resolver not needed for layer-exposure test"),
resolveOptional: () => Effect.die("project-ref-resolver not needed for layer-exposure test"),
loadProjectRef: () => Effect.die("project-ref-resolver not needed for layer-exposure test"),
promptProjectRef: () => Effect.die("project-ref-resolver not needed for layer-exposure test"),
}),
Layer.succeed(LegacyPlatformApiFactory, {
make: Effect.die("platform-api-factory not needed for layer-exposure test"),
}),
);

return Layer.mergeAll(
BunServices.layer,
mockRuntimeInfo(),
mockTty(),
mockProcessControl().layer,
mockStdin(false),
analytics.layer,
mockTelemetryRuntime(),
out.layer,
flagLayers,
mockLegacyCliConfig({ workdir: "/tmp/reset-layers-test" }),
mockLegacyCredentialsLayer,
mockLegacyLinkedProjectCacheLayer,
mockLegacyTelemetryStateLayer,
heavyServiceStubs,
);
}

describe("legacyDbResetRuntimeLayer — pg-delta service exposure (regression guard, review CLI-1958)", () => {
it.live(
"exposes LegacyEdgeRuntimeScript so the post-reset pg-delta catalog cache does not crash on a missing-service defect",
() => {
return Effect.gen(function* () {
const edgeRuntime = yield* Effect.serviceOption(LegacyEdgeRuntimeScript);
expect(Option.isSome(edgeRuntime)).toBe(true);
}).pipe(Effect.provide(legacyDbResetRuntimeLayer), Effect.provide(ambientStubs()));
},
);

it.live(
"exposes LegacyPgDeltaSslProbe so the post-reset pg-delta catalog cache does not crash on a missing-service defect",
() => {
return Effect.gen(function* () {
const sslProbe = yield* Effect.serviceOption(LegacyPgDeltaSslProbe);
expect(Option.isSome(sslProbe)).toBe(true);
}).pipe(Effect.provide(legacyDbResetRuntimeLayer), Effect.provide(ambientStubs()));
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ export class LegacyDeclarativeApplyError extends Data.TaggedError("LegacyDeclara
* (`dbConnection.connect`) rather than the migration SQL failing to apply.
*/
readonly connect?: boolean;
/**
* Forwarded from the underlying typed failure this wraps (e.g. a
* `LegacyKongReloadError`'s recovery hint, or a health-timeout architecture
* hint) when the local-reset recovery path fails — the wrap must not drop it
* (review CLI-1958).
*/
readonly suggestion?: string;
}> {
get [ErrorActionabilityId](): CliErrorActionabilityDeclaration {
if (this.connect === true) {
Expand All @@ -123,6 +130,18 @@ export class LegacyDeclarativeApplyError extends Data.TaggedError("LegacyDeclara
}
}

/**
* Duck-types an optional `suggestion: string` off an arbitrary typed failure —
* used when wrapping a lower-level error (e.g. `legacyResetLocalDatabase`'s
* `LegacyKongReloadError`) into a {@link LegacyDeclarativeApplyError} so its
* recovery hint isn't silently dropped by the wrap.
*/
export function legacyReadErrorSuggestion(error: unknown): string | undefined {
if (typeof error !== "object" || error === null || !("suggestion" in error)) return undefined;
const { suggestion } = error as { suggestion: unknown };
Comment thread
Coly010 marked this conversation as resolved.
return typeof suggestion === "string" ? suggestion : undefined;
}

/**
* Materializing the declarative export on disk failed. Byte-matches Go's
* `WriteDeclarativeSchemas` errors (`declarative.go:239`):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { legacyToPostgresURL } from "../../../../shared/legacy-postgres-url.ts";
import {
LegacyDeclarativeApplyError,
LegacyDeclarativeInvalidDbUrlError,
legacyReadErrorSuggestion,
} from "./declarative.errors.ts";
import type { LegacyDeclarativeShadowDbError } from "../../shared/legacy-pgdelta.errors.ts";
import { LegacyDeclarativeSeam } from "../../shared/legacy-pgdelta.seam.service.ts";
Expand Down Expand Up @@ -181,7 +182,10 @@ export const legacyResolveSmartTargetUrl = Effect.fnUntraced(function* (
yield* legacyResetLocalDatabase().pipe(
Effect.mapError(
(error) =>
new LegacyDeclarativeApplyError({ message: `database reset failed: ${error.message}` }),
new LegacyDeclarativeApplyError({
message: `database reset failed: ${error.message}`,
suggestion: legacyReadErrorSuggestion(error),
}),
),
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Cause, Clock, Effect, Exit, FileSystem, Option, Path } from "effect";
import { Cause, Clock, Effect, Exit, FileSystem, Option, Path, Result } from "effect";

import {
LegacyDnsResolverFlag,
Expand Down Expand Up @@ -42,6 +42,7 @@ import {
LegacyDeclarativeMutuallyExclusiveFlagsError,
LegacyDeclarativeNoFilesGeneratedError,
LegacyDeclarativeNonInteractiveError,
legacyReadErrorSuggestion,
} from "../declarative.errors.ts";
import {
legacyResolveDeclarativeMigrationName,
Expand Down Expand Up @@ -372,10 +373,16 @@ export const legacyDbSchemaDeclarativeSync = Effect.fn("legacy.db.schema.declara
return;
}

// A Ctrl-C or defect during the apply is not a migration-apply failure —
// propagate it unchanged instead of synthesizing a fake
// `LegacyDeclarativeApplyError` (review CLI-1958).
const applyFailure = Cause.findFail(applyExit.cause);
if (Result.isFailure(applyFailure)) {
return yield* Effect.failCause(applyFailure.failure);
}

// Apply failed: print, save a debug bundle, and (in a TTY) offer reset+reapply.
const applyError =
applyExit.cause.reasons.find(Cause.isFailReason)?.error ??
new LegacyDeclarativeApplyError({ message: "failed to apply migration" });
const applyError = applyFailure.success.error;
yield* output.raw(
`${legacyRed(`Migration failed to apply: ${applyError.message}`)}\n`,
"stderr",
Expand Down Expand Up @@ -404,13 +411,22 @@ export const legacyDbSchemaDeclarativeSync = Effect.fn("legacy.db.schema.declara
// argv-forwarding is needed to stay on a custom network.
const resetExit = yield* legacyResetLocalDatabase().pipe(Effect.exit);
if (Exit.isFailure(resetExit)) {
// A Ctrl-C or defect during the recovery reset must cancel the command,
// not get rewritten into a synthetic "unknown error" apply failure —
// propagate it unchanged (review CLI-1958).
const resetFailure = Cause.findFail(resetExit.cause);
if (Result.isFailure(resetFailure)) {
return yield* Effect.failCause(resetFailure.failure);
}
// Go returns `resetErr` here, surfacing the failure that actually blocked
// recovery — not the original apply error. Build the reset error from the
// real typed failure and use that one value for the message, debug bundle,
// and return.
const resetFailure = resetExit.cause.reasons.find(Cause.isFailReason)?.error;
// recovery — not the original apply error — and prints it exactly once (no
// extra "database reset failed:" wrapper). Build the reset error from the
// real typed failure and use that one value for the message, suggestion,
// debug bundle, and return.
const rawResetFailure = resetFailure.success.error;
const resetError = new LegacyDeclarativeApplyError({
message: `database reset failed: ${resetFailure?.message ?? "unknown error"}`,
message: rawResetFailure.message,
suggestion: legacyReadErrorSuggestion(rawResetFailure),
});
yield* output.raw(
`${legacyRed(`Database reset also failed: ${resetError.message}`)}\n`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -992,13 +992,12 @@ describe("legacy db schema declarative sync integration", () => {
);
expect(Exit.isFailure(exit)).toBe(true);
expect(failError(exit)).toMatchObject({
message: "database reset failed: supabase start is not running.",
message: "supabase start is not running.",
});
// Printed exactly once — no "database reset failed:" double-wrap (review CLI-1958).
expect(
s.out.rawChunks.some((c) =>
c.text.includes(
"Database reset also failed: database reset failed: supabase start is not running.",
),
c.text.includes("Database reset also failed: supabase start is not running."),
),
).toBe(true);
// A real failure, before any destructive container work.
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/src/legacy/commands/start/SIDE_EFFECTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ documented at its exact Go call site in `start.handler.ts`:

Ported: Go's `SetupLocalDatabase` → `initSchema` →
`initRealtimeJob`/`initStorageJob`/`initAuthJob` pipeline (`internal/db/start/`). Gated on
`isFreshVolume` (`legacyStartVolumeExists` on the Postgres volume, checked BEFORE the
`isFreshVolume` (`legacyVolumeExists` on the Postgres volume, checked BEFORE the
volume is created), matching Go's `NoBackupVolume` — this same check also selects which of
`Starting database...`/`Starting database from backup...` prints to stderr immediately
before Postgres's container is created (`db/start/start.go:165-175`). Runs immediately
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* Port of Go's `AwaitStorageReady` (`apps/cli-go/internal/db/reset/reset.go:115-126`) —
* the storage-health gate local `db reset` runs before seeding buckets. Two things the
* seam this replaces got subtly wrong, corrected here:
* Port of the storage-health gate `Run` runs inline before seeding buckets — not a
* standalone Go function despite the name here (`apps/cli-go/internal/db/reset/
* reset.go:66-71`). Two things the seam this replaces got subtly wrong, corrected
* here:
*
* 1. `resp, err := utils.Docker.ContainerInspect(ctx, utils.StorageId); if err != nil {
* return false, nil }` — ANY inspect error (not just "not found") maps to "absent"
Expand Down Expand Up @@ -36,7 +37,7 @@ import {

type Spawner = ChildProcessSpawner["Service"];

/** Go's hardcoded `30*time.Second` (`reset.go:121`) — independent of `db.health_timeout`. */
/** Go's hardcoded `30*time.Second` (`reset.go:68`) — independent of `db.health_timeout`. */
const LEGACY_AWAIT_STORAGE_READY_TIMEOUT_SECONDS = 30;

/**
Expand Down
Loading
Loading