1+ # Prune stale local and remote branches for RustAPI.
2+ # Usage:
3+ # .\.github\scripts\prune_stale_branches.ps1 -DryRun
4+ # .\.github\scripts\prune_stale_branches.ps1
5+ # .\.github\scripts\prune_stale_branches.ps1 -DeleteRemote
6+
7+ param (
8+ [switch ]$DryRun ,
9+ [switch ]$DeleteRemote ,
10+ [int ]$StaleDays = 30
11+ )
12+
13+ $ErrorActionPreference = " Stop"
14+ $repoRoot = git - C $PSScriptRoot rev- parse -- show-toplevel
15+ Set-Location $repoRoot
16+
17+ $protected = @ (" main" , " master" , " gh-pages" , " Production-baseline" )
18+ $stalePatterns = @ (" ^copilot/" , " ^copilot-" , " ^sentinel-" , " ^secure-" )
19+
20+ function Test-StaleBranchName ([string ]$Name ) {
21+ foreach ($pattern in $stalePatterns ) {
22+ if ($Name -match $pattern ) { return $true }
23+ }
24+ return $false
25+ }
26+
27+ Write-Host " Scanning branches older than $StaleDays days..."
28+ $cutoff = (Get-Date ).AddDays(- $StaleDays )
29+
30+ $localBranches = git for - each- ref -- format= " %(refname:short)|%(committerdate:iso8601)" refs/ heads/ |
31+ ForEach-Object {
32+ $parts = $_ -split ' \|' , 2
33+ [PSCustomObject ]@ { Name = $parts [0 ]; Date = [datetime ]$parts [1 ] }
34+ }
35+
36+ $candidates = $localBranches |
37+ Where-Object { $protected -notcontains $_.Name } |
38+ Where-Object { $_.Date -lt $cutoff -or (Test-StaleBranchName $_.Name ) }
39+
40+ if (-not $candidates ) {
41+ Write-Host " No stale branches found."
42+ exit 0
43+ }
44+
45+ Write-Host " "
46+ Write-Host " Stale branch candidates:"
47+ $candidates | ForEach-Object { Write-Host " $ ( $_.Name ) (last commit: $ ( $_.Date.ToString (' yyyy-MM-dd' )) )" }
48+
49+ if ($DryRun ) {
50+ Write-Host " "
51+ Write-Host " Dry run - no branches deleted."
52+ exit 0
53+ }
54+
55+ foreach ($branch in $candidates ) {
56+ Write-Host " Deleting local branch: $ ( $branch.Name ) "
57+ git branch - D $branch.Name
58+ }
59+
60+ if ($DeleteRemote ) {
61+ if (-not (Get-Command gh - ErrorAction SilentlyContinue)) {
62+ Write-Error " gh CLI not found. Install GitHub CLI or omit -DeleteRemote."
63+ }
64+ $repo = gh repo view -- json nameWithOwner - q .nameWithOwner
65+ $remoteBranches = git for - each- ref -- format= " %(refname:short)" refs/ remotes/ origin/ |
66+ ForEach-Object { $_ -replace ' ^origin/' , ' ' } |
67+ Where-Object { $_ -ne " HEAD" -and $protected -notcontains $_ } |
68+ Where-Object { Test-StaleBranchName $_ }
69+
70+ foreach ($branch in $remoteBranches ) {
71+ Write-Host " Deleting remote branch: origin/$branch "
72+ gh api - X DELETE " repos/$repo /git/refs/heads/$branch "
73+ }
74+ }
75+
76+ Write-Host " "
77+ Write-Host " Done. Enable GitHub stale branch archiving:"
78+ Write-Host " Repository Settings - Branches - Add branch ruleset (archive after 30 days)"
0 commit comments