Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
640c103
feat(cli): add supabase workers list, status and delete
johnstonmatt Aug 18, 2026
17a9058
feat(config): add the [workers] section to the project config schema
johnstonmatt Aug 18, 2026
0b1b9b3
feat(cli): add supabase workers new
johnstonmatt Aug 18, 2026
905115b
feat(cli): add supabase workers push
johnstonmatt Aug 18, 2026
69c83d2
feat(config): add the [workers] section to the project config schema
johnstonmatt Aug 18, 2026
7baf0ee
feat(cli): add supabase workers new
johnstonmatt Aug 18, 2026
160a3a5
feat(cli): add supabase workers push
johnstonmatt Aug 18, 2026
da11ea0
feat(cli): add supabase workers list, status and delete
johnstonmatt Aug 18, 2026
9542588
Merge branch 'FUNC-753/workers-read' of https://github.com/supabase/c…
johnstonmatt Aug 25, 2026
81cfd54
Merge branch 'FUNC-753/workers-config' of https://github.com/supabase…
johnstonmatt Aug 25, 2026
9c5cd2d
Merge branch 'develop' of https://github.com/supabase/cli into FUNC-7…
johnstonmatt Aug 25, 2026
2ea6b94
fix(config): let the Go config loader accept the [workers] section
johnstonmatt Aug 25, 2026
3408a66
test(config): add workers.ts to the pure runtime graph allowlist
johnstonmatt Aug 25, 2026
66a8383
Merge branch 'FUNC-753/workers-config' into FUNC-753/workers-new
johnstonmatt Aug 25, 2026
3a8de31
Merge branch 'FUNC-753/workers-new' into FUNC-753/workers-push
johnstonmatt Aug 25, 2026
065cb8c
Merge branch 'FUNC-753/workers-push' into FUNC-753/workers-read
johnstonmatt Aug 25, 2026
d50c763
fix(cli): import loadProjectConfig from the effect entrypoint
johnstonmatt Aug 25, 2026
b84900b
Merge branch 'FUNC-753/workers-new' into FUNC-753/workers-push
johnstonmatt Aug 25, 2026
f6445d3
Merge branch 'FUNC-753/workers-push' into FUNC-753/workers-read
johnstonmatt Aug 25, 2026
58302a4
refactor(cli): read Option through its public helpers in workers
johnstonmatt Aug 25, 2026
59707a6
docs(cli): give the first workers new example its required name
johnstonmatt Aug 25, 2026
93bcf8e
docs(cli): stop pointing users at a [workers] root that no longer exists
johnstonmatt Aug 25, 2026
32d265f
docs(cli): describe the shipped refusal semantics in workers new SIDE…
johnstonmatt Aug 25, 2026
fb04deb
fix(cli): keep workers new out of config.json
johnstonmatt Aug 25, 2026
e528a4f
Merge branch 'FUNC-753/workers-new' into FUNC-753/workers-push
johnstonmatt Aug 25, 2026
e8141ec
refactor(cli): read Option through its public helpers in workers push
johnstonmatt Aug 25, 2026
b69cfce
Merge branch 'FUNC-753/workers-push' into FUNC-753/workers-read
johnstonmatt Aug 25, 2026
cb51281
refactor(cli): read Option through its public helpers in workers read
johnstonmatt Aug 25, 2026
72ec632
Merge remote-tracking branch 'origin/develop' into FUNC-753/workers-new
johnstonmatt Aug 25, 2026
3ecbd3f
Merge branch 'FUNC-753/workers-new' into FUNC-753/workers-push
johnstonmatt Aug 25, 2026
c51d62e
fix(cli): follow the LegacyCliSettings rename in workers push
johnstonmatt Aug 25, 2026
bac46c2
Merge branch 'FUNC-753/workers-push' into FUNC-753/workers-read
johnstonmatt Aug 25, 2026
baf57a2
fix(cli): follow the LegacyCliSettings rename in workers list and status
johnstonmatt Aug 25, 2026
3d25f92
feat(cli): add supabase workers push
johnstonmatt Aug 18, 2026
d5b804f
refactor(cli): read Option through its public helpers in workers push
johnstonmatt Aug 25, 2026
0fef65e
fix(cli): follow the LegacyCliSettings rename in workers push
johnstonmatt Aug 25, 2026
a595b60
fix(cli): reject tar header values octal fields cannot represent
johnstonmatt Aug 26, 2026
3a78cd0
fix(cli): keep out-of-range tar fields in the failure channel
johnstonmatt Aug 26, 2026
323852d
fix(cli): recover only a missing source, not every filesystem error
johnstonmatt Aug 26, 2026
3130525
fix(cli): stop pointing an empty worker source at `workers new`
johnstonmatt Aug 26, 2026
e831044
docs(cli): say why the tar writer does not use Bun.Archive
johnstonmatt Aug 26, 2026
1e96661
fix(cli): report a non-directory worker source as what it is
johnstonmatt Aug 26, 2026
f0d3477
fix(cli): suggest a scaffold only where `workers new` would work
johnstonmatt Aug 26, 2026
e14bedc
test(cli): make the unreadable-source test survive a root runner
johnstonmatt Aug 26, 2026
e41948b
fix(cli): render transport failures without reaching for `_tag`
johnstonmatt Aug 26, 2026
c2a6eaf
fix(cli): read JSON project config when deploying workers
johnstonmatt Aug 26, 2026
db35bce
fix(cli): refuse a build context that links outside itself
johnstonmatt Aug 26, 2026
9690274
fix(cli): stop reading an unlistable workers root as an empty one
johnstonmatt Aug 26, 2026
8bac2f2
fix(cli): refuse a Dockerfile worker with no Dockerfile
johnstonmatt Aug 26, 2026
9619d2e
Revert "fix(cli): refuse a Dockerfile worker with no Dockerfile"
johnstonmatt Aug 26, 2026
c58c9b8
Merge branch 'FUNC-753/workers-push' into FUNC-753/workers-read
johnstonmatt Aug 26, 2026
dd1306a
Merge branch 'develop' into FUNC-753/workers-read
johnstonmatt Aug 26, 2026
c99ea48
fix(cli): reject -o env before workers read and delete touch the API
johnstonmatt Aug 26, 2026
6f904a7
fix(cli): keep an explicit --project-ref in workers retry suggestions
johnstonmatt Aug 26, 2026
4e5b97f
fix(cli): make workers delete --yes idempotent for an absent worker
johnstonmatt Aug 26, 2026
7abf565
fix(cli): point a failed workers delete at list, not push
johnstonmatt Aug 26, 2026
23a222f
refactor(cli): pick workers -o payload formats from an allowlist
johnstonmatt Aug 26, 2026
8cc3204
test(cli): pin sparse workers payloads encoding to TOML
johnstonmatt Aug 26, 2026
0cdfa42
fix(cli): require a terminal stdin before prompting to delete a worker
johnstonmatt Aug 26, 2026
1579a20
fix(cli): report the workers status tally from a single snapshot
johnstonmatt Aug 26, 2026
b80e41c
fix(cli): stop a broken local config blocking workers status and delete
johnstonmatt Aug 26, 2026
2f05f94
fix(cli): only report local worker state the project establishes
johnstonmatt Aug 26, 2026
986b0d1
fix(cli): do not require read scope to delete a worker
johnstonmatt Aug 26, 2026
eb94457
docs(cli): complete the workers read and delete side-effect checklists
johnstonmatt Aug 27, 2026
5ce8598
docs(cli): record the real workers root, which is not configurable
johnstonmatt Aug 27, 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
87 changes: 87 additions & 0 deletions apps/cli/src/legacy/commands/workers/delete/SIDE_EFFECTS.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
# `supabase workers delete <name>`

> **No live test yet.** `workers` runs against the v2 Management API, which the
> supabase/cli-e2e-ci supabox stack is not expected to serve, so a `*.live.test.ts`
> here would be permanently skipped or permanently red. Revisit when the v2
> Workers routes are available on that stack.

## Files Read

| Path | Format | When |
| --------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<workdir>/supabase/config.json` | JSON | when present — preferred over `config.toml`; the source directory it kept. Best-effort: a config that will not load degrades to "nothing local" rather than failing the command |
| `<workdir>/supabase/config.toml` | TOML | when no `config.json` exists — the same, on the same best-effort terms |
| `<worker source>/` | directory | canonicalised and stat'd, to decide whether the kept-source line is stated at all |
| `<SUPABASE_HOME or ~/.supabase>/access-token` | plain text | when `SUPABASE_ACCESS_TOKEN` is unset and the keyring holds no credential |
| `<workdir>/supabase/.temp/project-ref` | plain text | when neither `--project-ref` nor `SUPABASE_PROJECT_ID` is set — names the linked project |
| `<SUPABASE_HOME or ~/.supabase>/profile` | plain text | when neither `--profile` nor `SUPABASE_PROFILE` is set — names the profile, defaulting to `supabase` |
| `<SUPABASE_PROFILE>` (YAML) | YAML | when `SUPABASE_PROFILE` is a filesystem path rather than a built-in name; a read failure aborts the command |

## Files Written

| Path | Format | When |
| ----------------------------------------------- | ------ | --------------------------------------------------------------- |
| `<SUPABASE_HOME or ~/.supabase>/telemetry.json` | JSON | always — flushed on success and on failure |
| `<workdir>/supabase/.temp/linked-project.json` | JSON | after the project ref resolves, when the cache does not hold it |

The worker's directory and its `[workers.<name>]` entry are deliberately left
on disk; only the remote worker is deleted.

## Confirmation

Interactively, the worker's name has to be typed back before anything is
deleted. `--yes` (the root persistent flag) or `SUPABASE_YES` skips that. With
neither — and no interactive terminal to prompt on, which includes a redirected
stdout and any `--output-format json`/`stream-json` run — the command refuses
rather than deleting unasked.

## API Routes

| Method | Path | Auth | Request body | Response (used fields) |
| -------- | ----------------------------------- | ------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/v2/projects/{ref}/workers/{name}` | Bearer token | none | `instances.live` when present, else `spec.instances` (for the confirmation). A `403` is tolerated: the worker is treated as unknown and the `DELETE` still runs, since the two endpoints are granted separately (`edge_functions:read` vs `edge_functions:write`) |
| `DELETE` | `/v2/projects/{ref}/workers/{name}` | Bearer token | none | status only |
| `GET` | `/v1/projects` | Bearer token | none | `id`, `name`, `organization_slug`, `region` — only when no ref resolved and the session is interactive, to populate the project picker |

## Exit Codes

| Code | Condition |
| ---- | ------------------------------------------------------------------------- |
| `0` | success (a `404` on DELETE counts — it is already gone) |
| `0` | nothing deployed under that name, with `--yes` (teardown is idempotent) |
| `1` | invalid worker name |
| `1` | nothing deployed under that name, without `--yes` |
| `1` | the typed confirmation did not match the worker's name |
| `1` | confirmation needed but no interactive terminal to ask on, and no `--yes` |
| `1` | API error, or project not enrolled in the alpha |

## Environment Variables

| Variable | Purpose | Required? |
| ----------------------- | ---------------------------------------------------- | ---------------------------------------------------------------- |
| `SUPABASE_ACCESS_TOKEN` | auth token (bypasses credential file/keyring lookup) | no (falls back to keyring → `~/.supabase/access-token`) |
| `SUPABASE_PROFILE` | built-in profile name or YAML file path | no (falls back to `~/.supabase/profile` -> `supabase`) |
| `SUPABASE_PROJECT_ID` | project ref, consulted after `--project-ref` | no (falls back to `supabase/.temp/project-ref`, then the picker) |
| `SUPABASE_WORKDIR` | project directory the command acts on | no (falls back to `--workdir`, then the ancestor walk) |
| `SUPABASE_HOME` | directory holding `telemetry.json` | no (falls back to `~/.supabase`) |
| `SUPABASE_YES` | auto-confirms the deletion, as `--yes` does | no (defaults to prompting) |

## Telemetry Events Fired

| Event | When | Notable properties / groups |
| ---------------------- | ------------------------------------------ | ----------------------------------- |
| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` |

No custom events — only the `cli_command_executed` that the instrumentation
wrapper emits for every command.

## Output Formats

| Mode | stdout | stderr |
| ----------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------- |
| text (default) | the confirmation prompt, then what was deleted and kept | that nothing local was kept, when nothing was |
| `--output-format json` | one structured result carrying `worker_name`, `project_ref`, `kept_*` | as above |
| `--output-format stream-json` | the same result as a single terminal event | as above |
| `-o json` / `yaml` / `toml` | the same payload in that encoding, and nothing else | as above |
| `-o pretty` / `table` / `csv` | the text rendering — these fall through rather than encoding | as above |
| `-o env` | refused **before** the DELETE; discovering it at emit time deleted the worker and then failed | the error |
43 changes: 43 additions & 0 deletions apps/cli/src/legacy/commands/workers/delete/delete.command.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
import { Argument, Command, Flag } from "effect/unstable/cli";
import type * as CliCommand from "effect/unstable/cli/Command";
import { withJsonErrorHandling } from "../../../../shared/output/json-error-handling.ts";
import { legacyManagementApiRuntimeLayer } from "../../../shared/legacy-management-api-runtime.layer.ts";
import { withLegacyCommandInstrumentation } from "../../../telemetry/legacy-command-instrumentation.ts";
import { legacyWorkersDelete } from "./delete.handler.ts";

// No local `--yes`: it is a root persistent flag every other confirming command
// reads through `legacyResolveYes`, so redeclaring it here would shadow the
// global, list `--yes` twice in `--help`, and quietly ignore `SUPABASE_YES`.
const config = {
name: Argument.string("name").pipe(Argument.withDescription("Worker to delete.")),
projectRef: Flag.string("project-ref").pipe(
Flag.withDescription("Project ref of the Supabase project."),
Flag.optional,
),
} as const;

export type LegacyWorkersDeleteFlags = CliCommand.Command.Config.Infer<typeof config>;

export const legacyWorkersDeleteCommand = Command.make("delete", config).pipe(
Command.withDescription(
"Delete a worker from the linked Supabase project. Irreversible; its local directory and supabase/config.toml entry are kept.",
),
Command.withShortDescription("Delete a worker from Supabase"),
Command.withExamples([
{
command: "supabase workers delete api",
description: "Delete a worker, confirming by typing its name",
},
{
command: "supabase workers delete api --yes",
description: "Skip the confirmation prompt (scripts and CI)",
},
]),
Command.withHandler((flags) =>
legacyWorkersDelete(flags).pipe(
withLegacyCommandInstrumentation({ flags }),
withJsonErrorHandling,
),
),
Command.provide(legacyManagementApiRuntimeLayer(["workers", "delete"])),
);
Loading
Loading