Skip to content

feat(clean): support closed PR cleanup#183

Merged
helizaga merged 3 commits into
coderabbitai:mainfrom
scarf005:feat/clean-closed-prs
Jun 11, 2026
Merged

feat(clean): support closed PR cleanup#183
helizaga merged 3 commits into
coderabbitai:mainfrom
scarf005:feat/clean-closed-prs

Conversation

@scarf005

@scarf005 scarf005 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Description

  • Add git gtr clean --closed for closed PR/MR worktree cleanup.
  • Treat --merged --closed as merged OR closed.
  • Update docs, help text, completions, and provider tests.

Motivation

Clean up worktrees for rejected/closed PRs as well as merged PRs.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code refactoring (no functional changes)
  • Other (please describe):

Testing

  • npm exec --yes bats -- tests/provider.bats tests/cmd_clean.bats tests/cmd_help.bats tests/completion.bats
  • ./scripts/generate-completions.sh --check
  • bash -n lib/provider.sh lib/commands/clean.sh lib/commands/help.sh lib/commands/doctor.sh scripts/generate-completions.sh completions/gtr.bash completions/_git-gtr completions/git-gtr.fish tests/provider.bats tests/cmd_clean.bats tests/cmd_help.bats
  • tmp_global=$(mktemp) && GIT_CONFIG_GLOBAL=$tmp_global npm exec --yes bats -- tests/; rc=$?; rm -f $tmp_global; exit $rc

Manual Testing Checklist

Tested on:

  • macOS
  • Linux (specify distro: Fedora Linux 44)
  • Windows (Git Bash)

Core functionality tested:

  • git gtr new <branch> - Create worktree
  • git gtr go <branch> - Navigate to worktree
  • git gtr editor <branch> - Open in editor (if applicable)
  • git gtr ai <branch> - Start AI tool (if applicable)
  • git gtr rm <branch> - Remove worktree
  • git gtr list - List worktrees
  • git gtr config - Configuration commands (if applicable)
  • Other commands affected by this change: git gtr clean --closed, git gtr clean --merged --closed --to main

Test Steps

  1. Run provider, clean, help, and completion BATS tests.
  2. Run the full BATS suite with an isolated global git config.
  3. Verify generated completions are current.
  4. Syntax-check touched Bash files.

Expected behavior: --closed removes worktrees with closed PRs/MRs; --merged --closed removes merged OR closed matches.

Actual behavior: Matches expected behavior in targeted and full-suite tests.

Breaking Changes

  • This PR introduces breaking changes
  • I have discussed this in an issue first
  • Migration guide is included in documentation

Checklist

Before submitting this PR, please check:

  • I have read CONTRIBUTING.md
  • My code follows the project's style guidelines
  • I have performed manual testing on at least one platform
  • I have updated documentation (README.md, CLAUDE.md, etc.) if needed
  • My changes work on multiple platforms (or I've noted platform-specific behavior)
  • I have added/updated shell completions (if adding new commands or flags)
  • I have tested with both git gtr (production) and ./bin/gtr (development)
  • No new external dependencies are introduced (Bash + git only)
  • All existing functionality still works

Additional Context

--to <ref> applies to both --merged and --closed cleanup.


License Acknowledgment

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache License 2.0.

PR opened by gpt-5.5 high on pi

Summary by CodeRabbit

  • New Features

    • Added --closed to remove worktrees for closed PRs/MRs; --to now applies when filtering by merged or closed PRs/MRs.
  • Documentation

    • Updated README, help text, and configuration docs to document --closed, updated --to semantics, and provider-detection guidance.
  • Tests

    • Added/updated integration and provider tests covering closed-state behavior and --to validation.
  • Chores

    • Updated shell completions and doctor messaging to reflect merged/closed support.

Assisted-by: pi:gpt-5.5
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
@scarf005 scarf005 requested a review from NatoBoram as a code owner June 10, 2026 10:48
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 23b9e156-84e9-4fb2-b677-871961d4cec4

📥 Commits

Reviewing files that changed from the base of the PR and between c69bdfc and 2c94de6.

📒 Files selected for processing (2)
  • lib/provider.sh
  • tests/provider.bats
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/provider.sh

Walkthrough

Extends git gtr clean so it can prune worktrees whose PRs/MRs are closed as well as merged. Adds provider-level state checks, integrates them into the clean workflow, introduces --closed, updates completions/docs/help/doctor, and adds tests for closed-state handling.

Changes

Closed PR/MR cleanup feature

Layer / File(s) Summary
Provider-level PR/MR state detection
lib/provider.sh
Introduces check_branch_pr_state and _gitlab_mr_matches_tip to query GitHub (gh pr list) and GitLab (glab mr list) for PR/MR merged or closed states with optional base/target-ref and commit-SHA matching; adds check_branch_closed and refactors check_branch_merged.
Core clean command PR/MR state matching
lib/commands/clean.sh
Adds _clean_branch_matches_pr_state, introduces _clean_prs, updates worktree-iteration to consult _clean_should_skip and the new state matcher, extends cmd_clean parsing for --closed, broadens --to validation, and dispatches to _clean_prs.
Shell completion updates
completions/_git-gtr, completions/git-gtr.fish, completions/gtr.bash, scripts/generate-completions.sh
Updates Zsh, Fish, and Bash completions and the generation scripts to include --closed and adjust --to descriptions to "targeting" semantics.
Help text and documentation updates
lib/commands/help.sh, README.md, docs/configuration.md, lib/commands/doctor.sh
Revises help text, README examples, configuration docs, and doctor output to mention --closed and update --to wording and provider-detection notes.
Integration and unit tests
tests/provider.bats, tests/cmd_clean.bats, tests/cmd_help.bats
Adds tests for check_branch_closed on GitHub and GitLab, updates --to validation tests, adds integration-style clean tests for --closed and combined --merged --closed, and updates dirty-worktree behavior tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • NatoBoram

Poem

🐰 A hop, a scrub, a tidy trail,
Closed or merged — the runner's tale.
Branches pruned with gentle thump,
Garden neat, no roots to bump.
Hooray, the worktrees take a nap!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding support for the --closed option to the clean command for removing worktrees associated with closed PRs/MRs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
lib/commands/clean.sh (1)

186-188: ⚡ Quick win

Short-circuit local skip cases before hitting the provider.

_clean_branch_matches_pr_state runs before _clean_should_skip, so active, detached, or dirty worktrees still pay for gh/glab lookups even though they cannot be removed. Pushing the cheap local eligibility check ahead of the provider query would reduce unnecessary API traffic and auth/rate-limit churn in larger cleanup runs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/commands/clean.sh` around lines 186 - 188, The local eligibility check
`_clean_should_skip` is currently performed after the provider query
`_clean_branch_matches_pr_state`, causing unnecessary API calls; swap the order
so `_clean_should_skip "$dir" "$branch" "$force" "$active_worktree_path"` runs
first and returns early when true, and only then call
`_clean_branch_matches_pr_state "$provider" "$branch" "$target_ref"
"$branch_tip" "$merged_mode" "$closed_mode"` when local checks pass; ensure any
surrounding conditionals/returns are adjusted so the skip path behaves
identically (no provider call) and the original branch-matching logic still
executes when not skipped.
lib/provider.sh (1)

176-185: ⚡ Quick win

Verify the GitLab SHA guard against a single MR field.

The reused-branch-name guard is doing a raw substring search across the entire JSON payload. Any matching "sha" or "head_sha" anywhere in that response can satisfy the check, which makes this destructive path depend on an imprecise match. Please verify which exact field glab mr list --output json exposes for the source-head commit and compare that field structurally instead of grepping the whole blob.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/provider.sh` around lines 176 - 185, The current substring match against
mr_result using branch_tip is unsafe; update the check to parse the JSON
structurally (e.g. with jq) instead of grepping the whole blob: read mr_result,
select the MR object that matches the source branch (or MR iid) and extract its
explicit commit field (the exact field name returned by glab, e.g. .head_sha or
.sha—verify with glab mr list --output json), then compare that extracted value
to branch_tip and return 0/1 accordingly; replace the case block that inspects
compact_result with this jq-based extraction and a direct string comparison
against branch_tip (referencing variables branch_tip and mr_result and the
current case block for location).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@lib/commands/clean.sh`:
- Around line 186-188: The local eligibility check `_clean_should_skip` is
currently performed after the provider query `_clean_branch_matches_pr_state`,
causing unnecessary API calls; swap the order so `_clean_should_skip "$dir"
"$branch" "$force" "$active_worktree_path"` runs first and returns early when
true, and only then call `_clean_branch_matches_pr_state "$provider" "$branch"
"$target_ref" "$branch_tip" "$merged_mode" "$closed_mode"` when local checks
pass; ensure any surrounding conditionals/returns are adjusted so the skip path
behaves identically (no provider call) and the original branch-matching logic
still executes when not skipped.

In `@lib/provider.sh`:
- Around line 176-185: The current substring match against mr_result using
branch_tip is unsafe; update the check to parse the JSON structurally (e.g. with
jq) instead of grepping the whole blob: read mr_result, select the MR object
that matches the source branch (or MR iid) and extract its explicit commit field
(the exact field name returned by glab, e.g. .head_sha or .sha—verify with glab
mr list --output json), then compare that extracted value to branch_tip and
return 0/1 accordingly; replace the case block that inspects compact_result with
this jq-based extraction and a direct string comparison against branch_tip
(referencing variables branch_tip and mr_result and the current case block for
location).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4abc4c8f-101f-4138-870c-19901675002c

📥 Commits

Reviewing files that changed from the base of the PR and between 94dc064 and 9b798f3.

📒 Files selected for processing (13)
  • README.md
  • completions/_git-gtr
  • completions/git-gtr.fish
  • completions/gtr.bash
  • docs/configuration.md
  • lib/commands/clean.sh
  • lib/commands/doctor.sh
  • lib/commands/help.sh
  • lib/provider.sh
  • scripts/generate-completions.sh
  • tests/cmd_clean.bats
  • tests/cmd_help.bats
  • tests/provider.bats

Assisted-by: pi:gpt-5.5
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/provider.sh`:
- Around line 138-158: The no-jq fallback currently extracts only "sha" and
"diff_refs.head_sha" but misses a top-level "head_sha"; update the while-loop
parsing in provider.sh to also extract and compare a top-level "head_sha" (e.g.,
add a head_sha_field from "$object" similar to sha_field and test [
"$head_sha_field" = "$branch_tip" ]), checking it before inspecting diff_refs,
so objects exposing only "head_sha" are correctly matched; ensure you reference
the existing variables (object, sha_field, diff_refs, branch_tip) and return 0
on match to mirror the jq branch behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: fb6959cf-67f0-4006-a577-3eeebefdb6bb

📥 Commits

Reviewing files that changed from the base of the PR and between 9b798f3 and c69bdfc.

📒 Files selected for processing (4)
  • lib/commands/clean.sh
  • lib/provider.sh
  • tests/cmd_clean.bats
  • tests/provider.bats
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/commands/clean.sh

Comment thread lib/provider.sh
Assisted-by: pi:gpt-5.5
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
@helizaga helizaga merged commit 123ca57 into coderabbitai:main Jun 11, 2026
1 check passed
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.

2 participants