Add manage:delete-sandbox-workspaces command - #92
Conversation
Adds a new CLI command that deletes keboola.sandboxes workspaces in a project or organization. It pulls the workspace list from Connection, skips any workspace whose schema still has an active session in the Editor Service, then deletes the workspace configuration followed by the workspace itself for the remaining ones. Scoped by --project-id or --organization-id (mutually exclusive), filtered by a creation-date window, with --force gating real deletions and verbose per-workspace logging in dry-run as well. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new CLI maintenance command to identify and (optionally) delete keboola.sandboxes workspaces that have no active Editor Service session, scoped by project/organization and a creation-date window.
Changes:
- Introduces
manage:delete-sandbox-workspaceswith--project-id/--organization-id,--created-after/--created-before, and--force(dry-run default). - Implements per-project branching traversal, session-by-schema matching, and deletion order (configuration trash+purge → workspace) with summarized reporting.
- Registers the new command in the CLI application bootstrap.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Keboola/Console/Command/DeleteSandboxWorkspaces.php | New command implementation: discovery, filtering, session matching, deletion, and reporting. |
| cli.php | Registers the new command in the application. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } catch (StorageClientException $e) { | ||
| if (str_contains($e->getMessage(), 'not found')) { | ||
| $output->writeln(sprintf( | ||
| ' Configuration %s/%s already gone', | ||
| self::COMPONENT_ID, | ||
| $configurationId, | ||
| )); | ||
| $configDeleted = true; | ||
| } else { |
| (string) $workspaceId, | ||
| $createdStr, | ||
| )); | ||
| $projectSkippedComponent++; |
| $editorClient = new EditorServiceClient($editorUrl, $storageToken['token']); | ||
|
|
||
| // Index editor sessions by workspaceSchema for O(1) lookup against workspace credentials. | ||
| $sessionsBySchema = []; |
There was a problem hiding this comment.
hypoteticky muzes narazit na session, ktera WS nema, protoze se zrovna vytváí, ale nemyslím si, ze by to tady neco rozbilo
| } | ||
|
|
||
| if ($configurationId === '') { | ||
| $output->writeln(sprintf( |
There was a problem hiding this comment.
no jestli jsou pro komponentu keboola.sandboxes a současně ta konfigurace neexistuje, tak bych je smazal ne? co s nima.
|
|
||
| class DeleteSandboxWorkspaces extends Command | ||
| { | ||
| private const string COMPONENT_ID = 'keboola.sandboxes'; |
There was a problem hiding this comment.
a tak pojďmě přihodit ještě keboola.snowflake-transformation
There was a problem hiding this comment.
ono je asi ne zvážení jestli to nedát configurovatelný a s defaultem na keboola.sandboxes anebo chceš dělat ještě nějakej další command?
| null, | ||
| InputOption::VALUE_REQUIRED, | ||
| 'Only consider workspaces created at or after this date ' | ||
| . '(strtotime expression, e.g. "-30 days", "2026-01-01"). Default: "-30 days".', |
There was a problem hiding this comment.
to jsou takový divný defaulty - je to spíš naopak, ty měsíc starý asi jako mazat nechceš
- Make --component configurable (default keboola.sandboxes); empty value permitted so workspaces with no component can be targeted. - Enrich SKIP/DELETE log lines and the per-project candidates listing with component, configurationId, loginType and owner email (from creatorToken.description), falling back to "(none)" when absent. - Override the active-editor-session SKIP when the workspace points at a configurationId that no longer exists: GET the config, treat 404 as a stale session, log a NOTICE and proceed to delete the workspace.
The earlier SKIP for empty configurationId already returns, so the nested check inside the active-session branch was unreachable as false.
…ting Consolidates the outstanding workspace tooling into this branch, replacing PRs #92, #98 and #100. Adds three commands and documents them; no existing command is modified. manage:check-project-workspaces-state (read-only) Triage step for a known list of workspaces: reports whether each is still live and whether its configuration is live, trashed or gone, and suggests the follow-up command. Configuration state is resolved per branch, because branches hold independent copies under the same id and merging them misclassifies a config that is live in one branch and trashed in another. Also reports each configuration's most recent job from the Queue API, which is usually what decides whether it is still in use, and runs a sanity query for any job in the project first so that blank lastJob columns are not misread as "never used". manage:delete-project-workspaces-by-id List-driven deletion with layered guards: password-login only unless --any-login-type, optional expected-schema verification, and configuration deletion only behind --with-configuration and only when that configuration owns exactly the listed workspace. Deletes the workspace without touching the configuration by default. A purge refused with storage.components.cannotDeleteConfiguration is counted as failed rather than deleted, since in that case the configuration is still in the trash and its workspace and backend user still exist. manage:list-external-buckets (read-only) Stack-wide CSV audit of external buckets with created date, isReadOnly and whether KBC.description metadata is set. Drops its temporary token even when listing fails, and continues past projects it cannot reach. README gains entries for all three, and the "Which command should I use?" table now points at the by-id command as the preferred list-driven option over manage:mass-delete-project-workspaces, which needs an interactively pasted token per project and always purges the configuration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Closing as part of consolidating the workspace tooling into #106. Unlike #100, this one is not carried over — What that means concretely, so it is on the record rather than lost:
@odinuv — your review comments here were never answered, so for the record rather than to reopen the discussion:
The branch stays, so this is reversible if the session-aware sweep turns out to be worth having. |
Summary
manage:delete-sandbox-workspacesCLI command that cleans upkeboola.sandboxesworkspaces in a project (--project-id) or across an entire organization (--organization-id).connection.schema; workspaces with an active session are skipped. The rest are deleted in the order configuration → workspace (configuration deleted twice = trash + purge, matching existing cleanup commands).--created-after/--created-before, default-30 days→now) and gated by--force(dry-run by default). Verbose per-workspace logging always on, plus per-branch / per-project / final summaries with skip-reason breakdown.Test plan
php cli.php manage:delete-sandbox-workspaces --helpshows the new options--project-id) and inspect the candidate list and skip-reason counts--organization-id)--forceagainst a throwaway project and verify configs + workspaces disappear and active-session workspaces are untouched🤖 Generated with Claude Code