feat(tools): add tvc-deploy delete-deployment and prune subcommands#418
Conversation
Old TVC deployments for parser_app accumulate with every deploy and were never cleaned up, so the app's deployment list grew without bound. prune keeps the live deployment plus the newest --keep (default 2) and deletes the rest; delete-deployment is the one-shot primitive. Both submit DeleteTvcDeploymentIntent directly through the turnkey_client SDK and surface the approve-activity follow-up on consensus, matching the existing invite/policy flows. Deletion carries no manifest, so unlike deploy it doesn't shell out to tvc; prune only reads tvc app status to enumerate. Retention orders deployments by the created_at of their create activity (newest first). The live deployment is never deleted (client guard plus Turnkey's own server-side refusal), --keep must be >= 1, and deployments with no matching create activity are protected rather than risked. Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds deployment cleanup capabilities to the tvc-deploy operator tool so old parser_app TVC deployments can be removed safely without manual Turnkey API work.
Changes:
- Adds
delete-deploymentandpruneCLI subcommands and wires them into the command dispatcher. - Implements deployment enumeration/parsing, retention selection, and Turnkey
DeleteTvcDeploymentIntentsubmission (with consensus/approve follow-up). - Documents the new cleanup workflows and guardrails in the tool README.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tools/tvc-deploy/src/main.rs | Registers new delete-deployment and prune subcommands and routes execution. |
| tools/tvc-deploy/src/invite.rs | Implements delete/prune logic, tvc app status parsing, retention selection, and unit tests. |
| tools/tvc-deploy/README.md | Documents new cleanup subcommands, usage examples, and safety/consensus behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Generated by /finish P3 iteration 1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
tools/tvc-deploy/src/invite.rs:1398
deployment_created_at_mapinsertstimestamp_seconds(&activity.created_at), andtimestamp_secondsfalls back to0on missing/unparsable timestamps. That makes such deployments look extremely old and eligible for pruning, even thoughpruneotherwise treats deployments with no matching create activity as protected/undateable.
}
deployments
}
/// A deployment paired with the `created_at` of its `create_tvc_deployment`
/// activity, the ordering signal for retention ("newest N").
tools/tvc-deploy/src/invite.rs:1471
pruneshells out totvc app statusbefore resolving auth via--org. Since thetvcCLI uses env vars or the config file's active org (and has no--org), the enumerated deployments can come from a different org than the subsequent deletions, leading to a misleading plan and potentially unintended deletes.
Ok(map)
}
/// Submit a single `DeleteTvcDeploymentIntent`, reporting the activity id (or the
Generated by /finish P3 iteration 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Generated by /finish P3 iteration 3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Generated by /finish P3 iteration 4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
tools/tvc-deploy/src/invite.rs:1603
- In the prune plan output, undateable deployments are always printed without the
(live)marker. If the live deployment is undateable (no matching create activity), the plan becomes ambiguous even though this is the deployment the tool most needs to clearly protect.
}
sort_newest_first(&mut dated);
tools/tvc-deploy/README.md:209
- The docs list several
prunesafety guards, but they don’t mention the org-resolution constraint caused by shelling out totvc app status(no--orgflag). Since the tool can/should refuse to run when--orgwould not match the org used for status enumeration, documenting this here avoids surprising operators.
- `--keep` must be `>= 1`.
- A deployment with no matching `create_tvc_deployment` activity (so it can't be
dated) is protected and flagged, not deleted.
tools/tvc-deploy/src/invite.rs:413
- When env-var auth is active,
resolve_authignores--org, butprunecan still be invoked with--organd this guard returns Ok(). That makes it easy for operators to think they’re pruning a different org thanTVC_ORG_ID. Fail fast when--orgis provided under env-var auth to avoid silently targeting the env org.
"--org {given:?} was given, but env-var auth ({ENV_ORG_ID}/{ENV_API_KEY_PUBLIC}/\
{ENV_API_KEY_PRIVATE}) is active and always wins over --org; `tvc app status` \
(used by `prune` to enumerate deployments) has no --org flag either and always \
uses the env vars, so enumeration and deletion would silently target {ENV_ORG_ID} \
instead of --org's org. Unset the env vars to use --org, or omit --org.",
shahan-khatchadourian-anchorage
left a comment
There was a problem hiding this comment.
Reviewed the current head (1548cea7) after the Copilot review cycle. Spot-checked the fixes that landed — the org-mismatch guard against resolve_auth's actual precedence, the --keep off-by-one now correctly excluding live from the budget, and the undateable-deployment handling — and they hold up. Selection/parsing logic is pure and well covered by unit tests, plus there's a hard guard against ever deleting the live deployment as a backstop. README is clear on the safety guards. CI's green.
No blocking feedback — good to merge.
Why am I making this PR?
Old TVC deployments for parser_app pile up with every deploy and nobody's been cleaning them up. This adds cleanup subcommands to the standalone
tvc-deployhelper so we can prune them without hand-rolling Turnkey API calls each time.What am I changing?
Adds two subcommands to
tvc-deploy:delete-deployment --deploy-id <id>: delete a single deploymentprune --app-id <id> --keep <N=2>: keep the live deployment plus the newest N, delete the restBoth submit
DeleteTvcDeploymentIntentvia the turnkey_client 0.10 SDK and surface the approve-activity follow-up on consensus, matching the existing invite/policy flows in this tool.What is the Linear ticket?
PRS-582
What are the rollback steps?
Purely additive subcommands, no feature flag, no migration, and nothing else in the codebase calls into this new code. Rollback is just reverting the commit, there's no runtime state to unwind.
Is this change backwards compatible?
Yes. Only adds new CLI subcommands to
tvc-deploy; no existing behavior, flags, or defaults change.Does this require cross-team/service coordination?
No. This is a standalone operator tool, no other team needs to deploy or configure anything.
How do I know it works as designed? Which tests exercise this code?
cargo test -p tvc-deploy: 50 passed, including 9 new unit tests covering the status parser and retention selection logiccargo clippy --all-targets -- -D warnings: cleancargo fmt --check: cleanprune --app-id <dev app> --keep 2 --dry-runagainst a dev app before running it for realSafety: the live deployment is never deleted (client-side guard plus Turnkey server-side refusal),
--keepmust be >= 1, and deployments with no matching create activity are treated as protected.