param ( [string]$repofile, [string]$repolist, [string]$action, [string]$token, [string]$owner, [string]$outputfile, [string]$collaborator, [string]$collab_permission, [switch]$help, [int]$maxrepos = 1000 ) function Show-Help { @" This script allows you to pass a GitHub CLI command as an argument and a list of repositories or a file containing repository names to execute the 'gh' CLI command in batch. Supported Actions: - gh repo edit --visibility private: Edit the visibility of repositories. - gh repo delete: Delete repositories. - add-collaborator: Add a collaborator to repositories. - list-collaborators: List the collaborators for repositories and show their permissions you can check yours own too. - gh secret set <name> -b <value>: Set a secret for repositories. - gh secret list: List secrets for repositories. Parameters: - repofile: Path to a file containing a list of repositories (one per line). - repolist: A comma-separated list of repositories. - action: The 'gh' CLI command to execute. - token: (Optional) GitHub token for authentication. - owner: The GitHub username whose repositories will be listed. - outputfile: The file to output the list of repositories. If not specified, the repository list will be output to the console. - collaborator: The GitHub username of the collaborator to add to the repositories. - collab_permission: The permission level to assign to the collaborator (e.g., 'read', 'triage', 'write', 'maintain', 'admin'). Examples: - .\batchrepoaction.ps1 -repofile repofile.txt -action "gh repo view" - .\batchrepoaction.ps1 -repolist "user/repo1,user/repo2" -action "gh repo view" - .\batchrepoaction.ps1 -repolist "user/repo1,user/repo2" -action "gh repo view" -token "yourtoken" - .\batchrepoaction.ps1 -owner "your_github_username" -action "gh repo list" -outputfile repofile.txt - .\batchrepoaction.ps1 -owner "your_github_username" -action "gh repo list" - .\batchrepoaction.ps1 -repolist "user/repo1,user/repo2" -action "add-collaborator" -collaborator "collaborator_username" -collab_permission "write" - .\batchrepoaction.ps1 -repolist "user/repo1,user/repo2" -action "list-collaborators" - .\batchrepoaction.ps1 -repolist "user/repo1,user/repo2" -action "gh secret set mysecret -b 'valueofsecret'" - .\batchrepoaction.ps1 -repolist "user/repo1,user/repo2" -action "gh secret list" "@ } function Get-Repos { param ( [string]$repofile, [string]$repolist ) $repos = @() if ($repofile) { if (Test-Path $repofile) { $repos += Get-Content $repofile } else { Write-Error "File not found: $repofile" exit 1 } } if ($repolist) { $repos += $repolist -split "," } return $repos } function Invoke-Action { param ( [string]$repo, [string]$action, [string]$token, [string]$collaborator, [string]$collab_permission ) if ($token) { gh auth login --with-token $token } if ($action -eq "add-collaborator") { if (-not $collaborator) { Write-Error "Collaborator parameter is required for adding a collaborator." exit 1 } if (-not $collab_permission) { Write-Error "Collaborator permission parameter is required for adding a collaborator." exit 1 } $command = @" gh api --method PUT -H "Accept: application/vnd.github+json" /repos/$repo/collaborators/$collaborator -f permission=$collab_permission "@ } elseif ($action -eq "delete-collaborator") { if (-not $collaborator) { Write-Error "Collaborator parameter is required for deleting a collaborator." exit 1 } $command = @" gh api --method DELETE -H "Accept: application/vnd.github+json" /repos/$repo/collaborators/$collaborator "@ } elseif ($action -eq "list-collaborators") { $command = "gh api /repos/$repo/collaborators --jq '.[] | {login: .login, permission: .permissions}'" } elseif ($action -match "gh secret set (\S+) -b '?([^']+)'?") { $secret_name = $matches[1] $secret_value = $matches[2] Write-Output "secret, value: $secret_name, $secret_value" | ft -AutoSize $command = "gh secret set $secret_name -b '$secret_value' -R $repo" } elseif ($action -eq "gh secret list") { $command = "gh secret list -R $repo" } else { $command = "$action $repo" } Write-Host "Executing: $command" Write-Output "action, repo, token, collaborator, collab_permission: $action, $repo, $token, $collaborator, $collab_permission" | ft -AutoSize $result = Invoke-Expression "$command 2>&1" if ($LASTEXITCODE -ne 0) { Write-Error "Failed to execute command: $command" Write-Error "Error: $result" return } elseif ($action -eq "gh secret list" -and (-not $result -or $result.Trim() -eq "")) { Write-Host "No secrets found for repository: $repo" } else { Write-Host "Command executed successfully: $command" Write-Host $result return } } function Get-ReposList { param ( [string]$owner, [string]$outputfile ) $command = "gh repo list $owner -L $maxrepos --json owner,name,visibility,description" Write-Host "Executing: $command" $result = Invoke-Expression $command | ConvertFrom-Json if ($LASTEXITCODE -ne 0) { Write-Error "Failed to execute command: $command" } else { Write-Host "Command executed successfully: $command" if ($outputfile) { $repoList = $result | ForEach-Object { "$($_.owner.login)/$($_.name)" } $repoList | Out-File -FilePath $outputfile -Encoding utf8 Write-Host "Repository list saved to $outputfile" } else { Write-Host "Repository list:" $table = @() foreach ($repo in $result) { $table += [PSCustomObject]@{ Name = $repo.name Visibility = $repo.visibility Description = $repo.description } } $table | Format-Table -AutoSize } } } # Main script # Set output encoding to UTF-8 as repo names/desc could contain emojis [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 if ($help) { Show-Help exit 0 } # Check GitHub CLI authentication status $authStatus = Invoke-Expression "gh auth status --active 2>&1" $loggedInUser = $authStatus | Select-String -Pattern "Logged in to github.com account (\w+)" | ForEach-Object { if ($_ -match "Logged in to github.com account (\w+)") { $matches[1] } } if ($loggedInUser) { Write-Host "GitHub CLI authentication successful. Logged in as: $loggedInUser" if (-not $owner) { $owner = $loggedInUser } } else { Write-Host "GitHub CLI authentication failed. Please log in using 'gh auth login'." return } if (-not $action) { Write-Error "Action parameter is required." exit 1 } if ($action -eq "gh repo list" -and $owner) { Get-ReposList -owner $owner -outputfile $outputfile exit 0 } $repos = Get-Repos -repofile $repofile -repolist $repolist if ($repos.Count -eq 0) { Write-Error "No repositories specified." exit 1 } foreach ($repo in $repos) { Invoke-Action -repo $repo -action $action -token $token -collaborator $collaborator -collab_permission $collab_permission }