-
Notifications
You must be signed in to change notification settings - Fork 523
feat(cli): add experimental stack list #6509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jgoux
wants to merge
43
commits into
feat/experimental-stack-status
from
feat/experimental-stack-list
+4,888
−53
Open
Changes from all commits
Commits
Show all changes
43 commits
Select commit
Hold shift + click to select a range
c249464
feat(cli): add experimental stack start
jgoux c370b5a
fix(cli): validate experimental stack config listeners
jgoux ea97377
fix(cli): omit empty experimental stack listeners
jgoux 2290b64
fix(cli): tighten experimental stack start config
jgoux 02c669c
test(stack): stabilize ingress listener fixtures
jgoux 99873ec
fix(cli): harden experimental stack config paths
jgoux e44ab9f
test(stack): stabilize ingress listener fixtures
jgoux 9acb080
test(stack): stabilize remaining ingress ports
jgoux 8c29ef7
fix(cli): scope stack config path service
jgoux cb78d99
fix(cli): clarify stack state recovery guidance
jgoux ef2ab0a
style(cli): format stack start handler
jgoux 3055b18
test(cli): consume exported stack config errors
jgoux 03ccaa6
chore(cli): extend experimental stack effect lint
jgoux bf1269f
fix(stack): explain signing key path restrictions
jgoux 99d490c
fix(cli): retain the API listener for analytics
jgoux 6a5fac6
feat(cli): add experimental stack stop
jgoux d0733f8
docs(cli): document experimental stack stop effects
jgoux 08de239
fix(cli): refine experimental stack stop output
jgoux a2035be
fix(cli): classify invalid stack stop names
jgoux 4b59856
test(cli): cover experimental stack stop parsing
jgoux b0a2677
test(cli): cover experimental stack stop errors
jgoux 52f511d
chore(cli): annotate stack stop fixtures
jgoux 63c9f23
test(cli): complete stack stop service mocks
jgoux c911669
feat(cli): expose stack discovery service
jgoux 865c92f
test(cli): scope stop mock to available stack methods
jgoux d876873
feat(stack): report redacted configuration drift
jgoux 9f2a37a
feat(cli): add experimental stack status
jgoux aacd97b
fix(cli): classify experimental stack status errors
jgoux a8de60a
fix(cli): refine experimental stack status reporting
jgoux 551ef2d
test(cli): cover experimental stack status output parity
jgoux e460c13
fix(cli): clarify experimental stack status
jgoux 4cb228f
fix(cli): clarify missing stack status guidance
jgoux 67db1a8
chore(cli): annotate stack status fixtures
jgoux 0a7ef7d
test(cli): complete stack status service mocks
jgoux 34ca600
test(cli): scope status mock to available stack methods
jgoux a1946b6
feat(cli): add experimental stack list
jgoux 7d36677
fix(cli): refine experimental stack list reporting
jgoux 664e029
test(cli): fix list container fixture
jgoux 77028b2
test(cli): strengthen stack list ordering assertion
jgoux 88add78
test(cli): require both stack sort entries
jgoux f4553d7
fix(cli): address experimental stack list review
jgoux ca4f2b2
fix(stack): satisfy effect lint in stack discovery
jgoux edeccb4
test(cli): add list operation to stack service fixtures
jgoux File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
apps/cli/src/commands/experimental/stack/list/SIDE_EFFECTS.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # `supabase experimental stack list` | ||
|
|
||
| Lists persisted managed local stacks discovered in the global stack registry. | ||
| The command includes stopped stacks and performs no config loading, owner RPC, | ||
| activation, or lifecycle mutation. Registry discovery is currently fail-fast: a | ||
| corrupt or unsupported entry can prevent other entries from being listed. | ||
|
|
||
| Entries are sorted by project root, stack name, and id. Text output includes the | ||
| identity, project root, branch context, runtime, and desired lifecycle. Structured | ||
| output returns the same fields under `stacks`. The legacy `-o/--output` flag is | ||
| rejected; use `--output-format json`. | ||
|
|
||
| The command reads `${SUPABASE_HOME ?? $HOME/.supabase}/managed/stacks/<stack-id>/`, | ||
| including each persisted state document and state remnant metadata. It consumes | ||
| `SUPABASE_HOME`, falling back to `HOME/.supabase`. Exit code 0 indicates success; | ||
| exit code 1 indicates a registry read error or rejected legacy output flag. |
12 changes: 12 additions & 0 deletions
12
apps/cli/src/commands/experimental/stack/list/list.command.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { Command } from "effect/unstable/cli"; | ||
| import { withJsonErrorHandling } from "../../../../shared/output/json-error-handling.ts"; | ||
| import { withLegacyCommandInstrumentation } from "../../../../telemetry/legacy-command-instrumentation.ts"; | ||
| import { legacyExperimentalStackList } from "./list.handler.ts"; | ||
|
|
||
| export const legacyExperimentalStackListCommand = Command.make("list").pipe( | ||
| Command.withDescription("List persisted managed local Supabase stacks."), | ||
| Command.withShortDescription("List managed local stacks"), | ||
| Command.withHandler(() => | ||
| legacyExperimentalStackList().pipe(withLegacyCommandInstrumentation(), withJsonErrorHandling), | ||
| ), | ||
| ); |
20 changes: 20 additions & 0 deletions
20
apps/cli/src/commands/experimental/stack/list/list.errors.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { Data } from "effect"; | ||
| import { | ||
| actionability, | ||
| type CliErrorActionabilityDeclaration, | ||
| ErrorActionabilityId, | ||
| } from "../../../../shared/telemetry/error-actionability.ts"; | ||
|
|
||
| export class LegacyExperimentalStackListError extends Data.TaggedError( | ||
| "LegacyExperimentalStackListError", | ||
| )<{ | ||
| readonly message: string; | ||
| readonly reason: "flags" | "invalid-config"; | ||
| readonly suggestion?: string; | ||
| readonly cause?: unknown; | ||
| }> { | ||
| get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { | ||
| if (this.reason === "flags") return actionability.provideFlags; | ||
| return actionability.invalidConfig; | ||
| } | ||
| } |
81 changes: 81 additions & 0 deletions
81
apps/cli/src/commands/experimental/stack/list/list.handler.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| import { Effect, Match, Option } from "effect"; | ||
| import { | ||
| type StackDescriptor, | ||
| type StackDiscoveryError, | ||
| type StackRuntime, | ||
| } from "@supabase/stack/effect"; | ||
| import { Output } from "../../../../shared/output/output.service.ts"; | ||
| import { LegacyOutputFlag } from "../../../../shared/legacy/global-flags.ts"; | ||
| import { LegacyExperimentalStackApi } from "../stack.shared.ts"; | ||
| import { LegacyExperimentalStackListError } from "./list.errors.ts"; | ||
|
|
||
| const entry = (descriptor: StackDescriptor) => ({ | ||
| id: descriptor.id, | ||
| project_root: descriptor.projectRoot, | ||
| name: descriptor.name, | ||
| branch_context: descriptor.branchContext, | ||
| runtime: descriptor.runtime, | ||
| desired_lifecycle: descriptor.desiredLifecycle, | ||
| }); | ||
|
|
||
| const compareCodeunit = (left: string, right: string): number => | ||
| left === right ? 0 : left < right ? -1 : 1; | ||
|
|
||
| const compareEntries = ( | ||
| left: ReturnType<typeof entry>, | ||
| right: ReturnType<typeof entry>, | ||
| ): number => { | ||
| const project = compareCodeunit(left.project_root, right.project_root); | ||
| if (project !== 0) return project; | ||
| const name = compareCodeunit(left.name, right.name); | ||
| return name !== 0 ? name : compareCodeunit(left.id, right.id); | ||
| }; | ||
|
|
||
| const mapStackError = (error: StackDiscoveryError) => | ||
| new LegacyExperimentalStackListError({ | ||
| reason: "invalid-config", | ||
| message: error.message, | ||
| suggestion: | ||
| "Inspect the managed stack registry under $SUPABASE_HOME/managed/stacks or ~/.supabase/managed/stacks.", | ||
| cause: error, | ||
| }); | ||
|
|
||
| const renderRuntime = (runtime: StackRuntime): string => | ||
| Match.value(runtime).pipe( | ||
| Match.when({ kind: "native" }, () => "native"), | ||
| Match.when({ kind: "container" }, ({ engine }) => `container (${engine})`), | ||
| Match.exhaustive, | ||
| ); | ||
|
|
||
| const render = (stacks: ReadonlyArray<ReturnType<typeof entry>>): string => { | ||
| if (stacks.length === 0) return "No managed stacks found.\n"; | ||
| const lines = stacks.flatMap((stack, index) => [ | ||
| ...(index === 0 ? [] : [""]), | ||
| `${stack.name} (${stack.id})`, | ||
| ` Project: ${stack.project_root}`, | ||
| ` Branch: ${stack.branch_context}`, | ||
| ` Runtime: ${renderRuntime(stack.runtime)}`, | ||
| ` Desired lifecycle: ${stack.desired_lifecycle}`, | ||
| ]); | ||
| return `${lines.join("\n")}\n`; | ||
| }; | ||
|
jgoux marked this conversation as resolved.
|
||
|
|
||
| export const legacyExperimentalStackList = Effect.fn("legacy.experimental.stack.list")( | ||
| function* () { | ||
| const output = yield* Output; | ||
| const legacyOutput = yield* Effect.serviceOption(LegacyOutputFlag); | ||
| if (Option.isSome(legacyOutput) && Option.isSome(legacyOutput.value)) | ||
| return yield* new LegacyExperimentalStackListError({ | ||
| reason: "flags", | ||
| message: "The legacy -o/--output flag is not supported here; use --output-format json.", | ||
| suggestion: "Use --output-format json or --output-format text.", | ||
| }); | ||
|
jgoux marked this conversation as resolved.
|
||
| const api = yield* LegacyExperimentalStackApi; | ||
| const stacks = (yield* api.listStacks().pipe(Effect.mapError(mapStackError))) | ||
| .map(entry) | ||
| .sort(compareEntries); | ||
|
jgoux marked this conversation as resolved.
|
||
| if (output.format === "text") yield* output.raw(render(stacks)); | ||
| else yield* output.success("", { stacks }); | ||
| return stacks; | ||
| }, | ||
| ); | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 MINOR ·
error-handling· source: claudeAll stack-discovery failures are classified as invalid configuration, including registry filesystem and permission failures.
Evidence: apps/cli/src/commands/experimental/stack/list/list.handler.ts:34-41 always assigns reason "invalid-config". packages/stack/src/public/EffectStack.ts:1089-1097 converts failures from exists/readDirectory into StackStateInvalidError, so platform I/O failures reach that classification.
Suggested fix: Preserve enough platform-error information in the stack API to distinguish registry I/O failures, then give those failures a non-configuration actionability and targeted filesystem guidance.