[#23] Added '--cleanup-stale' option to prune stale remote branches.#337
Conversation
📝 WalkthroughWalkthroughAdds optional stale remote branch cleanup to ChangesStale Remote Branch Cleanup
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #337 +/- ##
==========================================
+ Coverage 96.91% 97.00% +0.09%
==========================================
Files 6 6
Lines 421 501 +80
==========================================
+ Hits 408 486 +78
- Misses 13 15 +2 ☔ View full report in Codecov by Harness. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@README.md`:
- Line 177: The fenced code block containing the git-artifact command is missing
a language identifier on the opening fence, which triggers markdown linting
error MD040. To fix this, add bash as the language specifier to the opening
triple backticks of the code block that starts with the ./git-artifact
git@github.com:yourorg/your-repo-destination.git command. Change the opening
fence from triple backticks with no language to triple backticks followed by
bash.
In `@src/Commands/ArtifactCommand.php`:
- Around line 368-373: The code in the ArtifactCommand class fails to handle the
case when getRemoteDefaultBranch() returns NULL before proceeding with branch
cleanup. Currently, if the remote default branch cannot be resolved, the cleanup
continues without adding the default branch to the protected branches list,
risking deletion of the actual default branch. Add a check after calling
getRemoteDefaultBranch() that throws an exception or halts execution if the
method returns NULL, ensuring cleanup only proceeds when the default branch can
be safely protected.
In `@tests/Traits/GitTrait.php`:
- Around line 359-369: The finally block is unsetting GIT_AUTHOR_DATE and
GIT_COMMITTER_DATE environment variables without preserving their original
values, which causes test state leakage. Before setting these environment
variables (before the lines where putenv is called with the date values),
capture and store the original values of GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
using getenv(). Then in the finally block, restore these original values by
calling putenv with the stored values instead of calling putenv with only the
variable names (which unsets them). Use conditional logic to handle cases where
the variables were not previously set.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 1f07092e-37fd-442c-b49c-def9ca5e8d98
📒 Files selected for processing (7)
README.mdsrc/Commands/ArtifactCommand.phpsrc/Git/ArtifactGitRepository.phptests/Functional/CleanupStaleBranchesTest.phptests/Traits/GitTrait.phptests/Unit/ArtifactCommandTest.phptests/Unit/ArtifactGitRepositoryTest.php
Also specified the README example fence language and restored prior GIT_*_DATE values in the test commit helper.
Closes #23
Summary
Adds an opt-in
--cleanup-staleflag to theartifactcommand that prunes stale branches from the destination repository after a successful push. A companion--cleanup-patternglob (required) identifies which branches were created by the deployment workflow, and--cleanup-age(default 7 days) sets the staleness threshold. Cleanup is host-agnostic - it uses standardgit push --delete, so it works with GitHub, GitLab, Bitbucket, and any other remote. The just-pushed branch and the remote's default branch are always protected, and cleanup fails closed: if the remote default branch cannot be resolved, pruning is skipped entirely rather than risk deleting it. Any fetch or delete failure is logged as a warning and never aborts the deployment.Changes
New CLI options (
src/Commands/ArtifactCommand.php):--cleanup-stale- boolean gate that enables the feature; off by default so existing workflows are unaffected.--cleanup-pattern- required when--cleanup-staleis set; a shell glob identifying the deployment branches (e.g.deployment/*).--cleanup-age- positive integer number of days; branches older than this are eligible for deletion (default: 7).RuntimeExceptionbefore any Git work begins.--dry-runis respected: stale branches are listed but not deleted.Repository layer (
src/Git/ArtifactGitRepository.php):getRemoteBranchesInfo(string $remote): array<string, int>- shallow-fetches the remote (--depth=1) then readsrefs/remotes/<remote>viafor-each-refto return branch-name-to-Unix-timestamp pairs.getRemoteDefaultBranch(string $remote): ?string- resolves the remote's symbolic HEAD vials-remote --symref; returnsnullon any failure.deleteRemoteBranch(string $remote, string $branch): static- runsgit push <remote> --delete <branch>.static filterStaleBranches(...)- pure filtering logic: applies the glob, the age cutoff, and the protected-branch list, returning a sorted result. Static for easy unit-testing without a real repository.Tests:
tests/Functional/CleanupStaleBranchesTest.php- seven functional scenarios: basic prune, dry-run passthrough, default-and-just-pushed branch protection, no-stale-branches no-op, unknown-remote returns null, missing-pattern validation, and invalid-age validation (data provider).tests/Unit/ArtifactCommandTest.php- unit coverage for the three error-recovery paths incleanupStaleBranches(): list failure, per-branch delete failure, and the fail-closed skip when the default branch is unknown.tests/Unit/ArtifactGitRepositoryTest.php- eleven data-provider cases forfilterStaleBranches()covering empty input, glob non-match, staleness boundary, protected exclusion, future timestamps, sorted output, numeric branch names, and wildcard-with-protected.tests/Traits/GitTrait.php- new test helpers:gitCommitFileWithDate()(which now preserves and restores any pre-existingGIT_AUTHOR_DATE/GIT_COMMITTER_DATE),gitCreateBranchWithCommitDate(),gitGetBranchList(),gitAssertBranchesExist(),gitAssertBranchesNotExist().Documentation (
README.md):--cleanup-age,--cleanup-pattern, and--cleanup-stale.Before / After