Skip to content

feat(tools): add tvc-deploy delete-deployment and prune subcommands#418

Merged
prasanna-anchorage merged 5 commits into
mainfrom
worktree-13589e0f
Jul 23, 2026
Merged

feat(tools): add tvc-deploy delete-deployment and prune subcommands#418
prasanna-anchorage merged 5 commits into
mainfrom
worktree-13589e0f

Conversation

@pepe-anchor

Copy link
Copy Markdown
Contributor

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-deploy helper 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 deployment
  • prune --app-id <id> --keep <N=2>: keep the live deployment plus the newest N, delete the rest

Both submit DeleteTvcDeploymentIntent via 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 logic
  • cargo clippy --all-targets -- -D warnings: clean
  • cargo fmt --check: clean
  • First live use planned as prune --app-id <dev app> --keep 2 --dry-run against a dev app before running it for real

Safety: the live deployment is never deleted (client-side guard plus Turnkey server-side refusal), --keep must be >= 1, and deployments with no matching create activity are treated as protected.

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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-deployment and prune CLI subcommands and wires them into the command dispatcher.
  • Implements deployment enumeration/parsing, retention selection, and Turnkey DeleteTvcDeploymentIntent submission (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.

Comment thread tools/tvc-deploy/src/invite.rs Outdated
Comment thread tools/tvc-deploy/src/invite.rs
Generated by /finish P3 iteration 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_map inserts timestamp_seconds(&activity.created_at), and timestamp_seconds falls back to 0 on missing/unparsable timestamps. That makes such deployments look extremely old and eligible for pruning, even though prune otherwise 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

  • prune shells out to tvc app status before resolving auth via --org. Since the tvc CLI 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

Comment thread tools/tvc-deploy/src/invite.rs Outdated
Generated by /finish P3 iteration 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment thread tools/tvc-deploy/src/invite.rs
Comment thread tools/tvc-deploy/src/invite.rs
Generated by /finish P3 iteration 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment thread tools/tvc-deploy/src/invite.rs
Comment thread tools/tvc-deploy/src/invite.rs
Comment thread tools/tvc-deploy/README.md
Generated by /finish P3 iteration 4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 prune safety guards, but they don’t mention the org-resolution constraint caused by shelling out to tvc app status (no --org flag). Since the tool can/should refuse to run when --org would 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_auth ignores --org, but prune can still be invoked with --org and this guard returns Ok(). That makes it easy for operators to think they’re pruning a different org than TVC_ORG_ID. Fail fast when --org is 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.",

@pepe-anchor
pepe-anchor marked this pull request as ready for review July 23, 2026 11:40

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@prasanna-anchorage
prasanna-anchorage merged commit c82eb0c into main Jul 23, 2026
10 checks passed
@prasanna-anchorage
prasanna-anchorage deleted the worktree-13589e0f branch July 23, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants