From 098707daf0b6b9293845aad790b97b5b92b7b91b Mon Sep 17 00:00:00 2001 From: Az-Tech Platform Date: Mon, 24 Mar 2025 19:15:14 +1000 Subject: [PATCH 1/5] Add Update-GitHubRepos script and refactor Create-PullRequests parameters --- PowerShell/Snippets/Clone-Repos.ps1 | 48 ++-- PowerShell/Snippets/CloneUpdate-Repos.ps1 | 65 ----- PowerShell/Snippets/Create-PullRequests.ps1 | 2 +- PowerShell/Update-AdoRepos.ps1 | 99 +++++++ ...GitHubRepos.ps1 => Update-GitHubRepos.ps1} | 14 +- PowerShell/Update-Repos.ps1 | 244 ++++++++++++++++++ 6 files changed, 374 insertions(+), 98 deletions(-) delete mode 100644 PowerShell/Snippets/CloneUpdate-Repos.ps1 create mode 100644 PowerShell/Update-AdoRepos.ps1 rename PowerShell/{Snippets/Get-GitHubRepos.ps1 => Update-GitHubRepos.ps1} (84%) create mode 100644 PowerShell/Update-Repos.ps1 diff --git a/PowerShell/Snippets/Clone-Repos.ps1 b/PowerShell/Snippets/Clone-Repos.ps1 index 0045530..ff16701 100644 --- a/PowerShell/Snippets/Clone-Repos.ps1 +++ b/PowerShell/Snippets/Clone-Repos.ps1 @@ -2,38 +2,36 @@ Param( [string]$destinationFolder = ".", [string]$org = "123", [array]$projects = ( - "Modules" -) + "Modules") -# Make sure you have the Azure CLI installed (az extension add --name azure-devops) and logged in via az login or az devops login -# If you face /_apis authentication issues make sure to login via az login --allow-no-subscriptions + # Make sure you have the Azure CLI installed (az extension add --name azure-devops) and logged in via az login or az devops login + # If you face /_apis authentication issues make sure to login via az login --allow-no-subscriptions -az devops configure --defaults organization=https://dev.azure.com/$org -# $projects = az devops project list --organization=https://dev.azure.com/$org | ConvertFrom-Json + az devops configure --defaults organization=https://dev.azure.com/$org + # $projects = az devops project list --organization=https://dev.azure.com/$org | ConvertFrom-Json -foreach ($project in $projects) { - $repos = az repos list --project $project | ConvertFrom-Json - foreach ($repo in $repos) { - Write-Output "Repository [$($repo.name)] in project [$($project)]" - If(!(test-path -PathType container $destinationFolder)) - { + foreach ($project in $projects) { + $repos = az repos list --project $project | ConvertFrom-Json + foreach ($repo in $repos) { + Write-Output "Repository [$($repo.name)] in project [$($project)]" + If (!(test-path -PathType container $destinationFolder)) { New-Item -ItemType Directory -Path $destinationFolder } - git clone $($repo.remoteUrl) $destinationFolder/$($project)/$($repo.name) + git clone $($repo.remoteUrl) $destinationFolder/$($project)/$($repo.name) + } } -} -# clone repos in github + # clone repos in github -$destinationFolder = "." + $destinationFolder = "." -$tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" -$org = 'Azure' + $tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" + $org = 'Azure' -foreach ($repo in $tfrepos) { - If (!(test-path -PathType container $destinationFolder/$($org)/$($repo))) { - New-Item -ItemType Directory -Path $destinationFolder/$($org)/$($repo) - } - Write-Output "https://github.com/$org/$repo.git into $destinationFolder/$($org)/$($repo)" - git clone "https://github.com/$org/$repo.git" $destinationFolder/$($org)/$($repo) -} + foreach ($repo in $tfrepos) { + If (!(test-path -PathType container $destinationFolder/$($org)/$($repo))) { + New-Item -ItemType Directory -Path $destinationFolder/$($org)/$($repo) + } + Write-Output "https://github.com/$org/$repo.git into $destinationFolder/$($org)/$($repo)" + git clone "https://github.com/$org/$repo.git" $destinationFolder/$($org)/$($repo) + } diff --git a/PowerShell/Snippets/CloneUpdate-Repos.ps1 b/PowerShell/Snippets/CloneUpdate-Repos.ps1 deleted file mode 100644 index 41689f4..0000000 --- a/PowerShell/Snippets/CloneUpdate-Repos.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -# Define the list of Azure DevOps project names -$organization = "yourOrg" -$destinationFolder = "/Users/user/$organization" -$pat = "" -$VerbosePreference = 'Continue' - -# Function to get all projects in the organization -function Get-AdoProjects { - $uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0" - $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } - return $response.value -} - -# Function to get repositories for a given project -function Get-AdoRepositories($project) { - $uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0" - $uri = $uri -replace " ", "%20" - Write-Verbose $uri - $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } - return $response.value -} - -# Function to clone or update repositories -function CloneOrUpdateRepo($repo, $projectFolder) { - $repoName = $repo.name - $repoUrl = $repo.remoteUrl - $repoFolder = "$projectFolder/$repoName" - - if (-not (Test-Path -Path $repoFolder)) { - Write-Verbose "Cloning $($repo.name)" - git clone $repoUrl $repoFolder - } else { - Write-Verbose "Pulling/Refreshing $($repo.name)" - Set-Location -Path $repoFolder - git checkout main - git pull - Set-Location -Path $projectFolder - } -} - -# Main script -Write-Verbose "Getting projects ..." -$projects = Get-AdoProjects -Write-Verbose "Found $($projects.Count) projects: $($projects.name)" -foreach ($project in $projects) { - $projectFolder = "$destinationFolder/$($project.name)" - if (-not (Test-Path -Path $projectFolder)) { - Write-Verbose "Creating folder $projectFolder" - New-Item -ItemType Directory -Path $projectFolder - } - - Write-Verbose "Getting repos for $($project.name) ..." - $repos = Get-AdoRepositories -project $project.name - Write-Verbose "Found $($repos.Count) repos: $($repos.name)" - # ask to proceed - Read-Host "Press Enter to continue" - foreach ($repo in $repos) { - $response = Read-Host "Do you want to clone/update the repo $($repo.name)? (y/n)" - if ($response -eq 'y') { - CloneOrUpdateRepo -repo $repo -projectFolder $projectFolder - } else { - Write-Verbose "Skipping $($repo.name)" - } - } -} diff --git a/PowerShell/Snippets/Create-PullRequests.ps1 b/PowerShell/Snippets/Create-PullRequests.ps1 index 30010e0..9645fa5 100644 --- a/PowerShell/Snippets/Create-PullRequests.ps1 +++ b/PowerShell/Snippets/Create-PullRequests.ps1 @@ -1,6 +1,6 @@ Param( [string]$org = "x00", - [string]$project = "ESLZ Modules", + [string]$project = "Modules", [string]$token = "token", [string]$branchName = "users/segraef/provider-upgrade" ) diff --git a/PowerShell/Update-AdoRepos.ps1 b/PowerShell/Update-AdoRepos.ps1 new file mode 100644 index 0000000..05ccead --- /dev/null +++ b/PowerShell/Update-AdoRepos.ps1 @@ -0,0 +1,99 @@ +function Update-AdoRepos { + + <# +.SYNOPSIS + Script to clone or update Azure DevOps repositories for all projects in an organization. + +.DESCRIPTION + This script clones or updates Azure DevOps repositories for all projects in a specified organization into a specified destination folder. + +.PARAMETER organization + The Azure DevOps organization name. + +.PARAMETER destinationFolder + The folder where the repositories will be cloned or updated. + +.PARAMETER pat + The personal access token for authentication. + +.INPUTS + None + +.OUTPUTS + None + +.NOTES + Version: 1.0 + Author: Sebastian Graef + Creation Date: 22-03-2025 + Purpose/Change: Initial script development + +.EXAMPLE + CloneUpdate-AdoRepos.ps1 -organization "yourOrg" -destinationFolder "C:\Repos" -pat "yourPAT" +#> + + param ( + [string]$organization, + [string]$destinationFolder, + [string]$pat + ) + + # Function to get all projects in the organization + function Get-AdoProjects { + $uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0" + $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } + return $response.value + } + + # Function to get repositories for a given project + function Get-AdoRepositories($project) { + $uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0" + $uri = $uri -replace " ", "%20" + Write-Output $uri + $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } + return $response.value + } + + # Function to clone or update repositories + function CloneOrUpdateRepo($repo, $projectFolder) { + $repoName = $repo.name + $repoUrl = $repo.remoteUrl + $repoFolder = "$projectFolder/$repoName" + + if (-not (Test-Path -Path $repoFolder)) { + Write-Output "Cloning $($repo.name)" + git clone $repoUrl $repoFolder + } else { + Write-Output "Pulling/Refreshing $($repo.name)" + Set-Location -Path $repoFolder + git checkout main + git pull + Set-Location -Path $projectFolder + } + } + + # Main script + Write-Output "Getting projects ..." + $projects = Get-AdoProjects + Write-Output "Found $($projects.Count) projects: $($projects.name)" + foreach ($project in $projects) { + $projectFolder = "$destinationFolder/$($project.name)" + if (-not (Test-Path -Path $projectFolder)) { + Write-Output "Creating folder $projectFolder" + New-Item -ItemType Directory -Path $projectFolder + } + + Write-Output "Getting repos for $($project.name) ..." + $repos = Get-AdoRepositories -project $project.name + Write-Output "Found $($repos.Count) repos: $($repos.name)" + Read-Host "Press Enter to continue" + foreach ($repo in $repos) { + $response = Read-Host "Do you want to clone/update the repo $($repo.name)? (y/n)" + if ($response -eq 'y') { + CloneOrUpdateRepo -repo $repo -projectFolder $projectFolder + } else { + Write-Output "Skipping $($repo.name)" + } + } + } +} diff --git a/PowerShell/Snippets/Get-GitHubRepos.ps1 b/PowerShell/Update-GitHubRepos.ps1 similarity index 84% rename from PowerShell/Snippets/Get-GitHubRepos.ps1 rename to PowerShell/Update-GitHubRepos.ps1 index 4a3c973..c6d1637 100644 --- a/PowerShell/Snippets/Get-GitHubRepos.ps1 +++ b/PowerShell/Update-GitHubRepos.ps1 @@ -1,4 +1,4 @@ -function Get-GitHubRepos { +function Update-GitHubRepos { <# .SYNOPSIS @@ -10,7 +10,7 @@ function Get-GitHubRepos { .PARAMETER destinationFolder The folder where the repositories will be cloned or updated. -.PARAMETER org +.PARAMETER organization The GitHub organization name. .PARAMETER repos @@ -29,7 +29,7 @@ function Get-GitHubRepos { Purpose/Change: Initial script development .EXAMPLE - Get-GitHubRepos -destinationFolder "Git/Folder1" -org "Azure" -repos @("repo1", "repo2") + Get-GitHubRepos -destinationFolder "Git/Folder1" -organization "Azure" -repos @("repo1", "repo2") .EXAMPLE $tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" @@ -44,7 +44,7 @@ function Get-GitHubRepos { [Parameter()] [string]$destinationFolder, [Parameter()] - [string]$org, + [string]$organization, [Parameter()] [string[]]$repos ) @@ -58,17 +58,17 @@ function Get-GitHubRepos { } foreach ($repo in $repos) { - $repoPath = Join-Path -Path $destinationFolder -ChildPath "$org/$repo" + $repoPath = Join-Path -Path $destinationFolder -ChildPath "$organization/$repo" If (!(Test-Path -Path $repoPath)) { New-Item -ItemType Directory -Path $repoPath -Force Set-Location -Path $repoPath Write-Output "Cloning repository $repo into $repoPath." - git clone "https://github.com/$org/$repo.git" + git clone "https://github.com/$organization/$repo.git" } else { Write-Output "Directory $repoPath already exists. Updating only." if ((Get-ChildItem -Path $repoPath).Count -eq 0) { Write-Output "Cloning repository $repo into $repoPath." - git clone "https://github.com/$org/$repo.git" + git clone "https://github.com/$organization/$repo.git" } else { Write-Output "Pulling latest changes for $repo." Set-Location -Path $repoPath diff --git a/PowerShell/Update-Repos.ps1 b/PowerShell/Update-Repos.ps1 new file mode 100644 index 0000000..b7131b3 --- /dev/null +++ b/PowerShell/Update-Repos.ps1 @@ -0,0 +1,244 @@ +<# + .SYNOPSIS + Clones or updates GitHub repositories for a specified organization. + + .DESCRIPTION + This script clones or updates GitHub repositories for a specified organization into a specified destination folder. + + .PARAMETER destinationFolder + The folder where the repositories will be cloned or updated. + + .PARAMETER organization + The GitHub organization name. + + .PARAMETER repos + The list of repositories to clone or update. + + .INPUTS + None + + .OUTPUTS + None + + .NOTES + Version: 1.0 + Author: Sebastian Graef + Creation Date: 22-03-2025 + Purpose/Change: Initial script development + + .EXAMPLE + Get-GitHubRepos -destinationFolder "Git/Folder1" -organization "Azure" -repos @("repo1", "repo2") + + .EXAMPLE + $tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" + Get-GitHubRepos -repos $tfrepos + #> + +function Update-GitHubRepos { + + [CmdletBinding(SupportsShouldProcess)] + param + ( + [Parameter()] + [string]$destinationFolder, + [Parameter()] + [string]$organization, + [Parameter()] + [string[]]$repos + ) + + Write-Output "Found $($repos.Count) repositories." + $confirmation = Read-Host "Do you want to proceed with processing these repositories? (y/n)" + if ($confirmation -ne 'y') { + return + } + + foreach ($repo in $repos) { + $repoPath = Join-Path -Path $destinationFolder -ChildPath "$organization/$repo" + If (!(Test-Path -Path $repoPath)) { + New-Item -ItemType Directory -Path $repoPath -Force + Set-Location -Path $repoPath + Write-Output "Cloning repository $repo into $repoPath." + git clone "https://github.com/$organization/$repo.git" + } else { + Write-Output "Directory $repoPath already exists. Updating only." + if ((Get-ChildItem -Path $repoPath).Count -eq 0) { + Write-Output "Cloning repository $repo into $repoPath." + git clone "https://github.com/$organization/$repo.git" + } else { + Write-Output "Pulling latest changes for $repo." + Set-Location -Path $repoPath + git checkout main + git pull + } + } + } +} + + +<# +.SYNOPSIS + Script to clone or update Azure DevOps repositories for all projects in an organization. + +.DESCRIPTION + This script clones or updates Azure DevOps repositories for all projects in a specified organization into a specified destination folder. + +.PARAMETER organization + The Azure DevOps organization name. + +.PARAMETER destinationFolder + The folder where the repositories will be cloned or updated. + +.PARAMETER pat + The personal access token for authentication. + +.INPUTS + None + +.OUTPUTS + None + +.NOTES + Version: 1.0 + Author: Sebastian Graef + Creation Date: 22-03-2025 + Purpose/Change: Initial script development + +.EXAMPLE + CloneUpdate-AdoRepos.ps1 -organization "yourOrg" -destinationFolder "C:\Repos" -pat "yourPAT" +#> + +function Update-AdoRepos { + + [CmdletBinding(SupportsShouldProcess)] + param + ( + [Parameter()] + [string]$organization, + [Parameter()] + [string]$destinationFolder, + [Parameter()] + [string]$pat + ) + + # Function to get all projects in the organization + function Get-AdoProjects { + $uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0" + $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } + return $response.value + } + + # Function to get repositories for a given project + function Get-AdoRepositories($project) { + $uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0" + $uri = $uri -replace " ", "%20" + Write-Output $uri + $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } + return $response.value + } + + # Function to clone or update repositories + function CloneOrUpdateRepo($repo, $projectFolder) { + $repoName = $repo.name + $repoUrl = $repo.remoteUrl + $repoFolder = "$projectFolder/$repoName" + + if (-not (Test-Path -Path $repoFolder)) { + Write-Output "Cloning $($repo.name)" + git clone $repoUrl $repoFolder + } else { + Write-Output "Pulling/Refreshing $($repo.name)" + Set-Location -Path $repoFolder + git checkout main + git pull + Set-Location -Path $projectFolder + } + } + + # Main script + Write-Output "Getting projects ..." + $projects = Get-AdoProjects + Write-Output "Found $($projects.Count) projects: $($projects.name)" + foreach ($project in $projects) { + $projectFolder = "$destinationFolder/$($project.name)" + if (-not (Test-Path -Path $projectFolder)) { + Write-Output "Creating folder $projectFolder" + New-Item -ItemType Directory -Path $projectFolder + } + + Write-Output "Getting repos for $($project.name) ..." + $repos = Get-AdoRepositories -project $project.name + Write-Output "Found $($repos.Count) repos: $($repos.name)" + Read-Host "Press Enter to continue" + foreach ($repo in $repos) { + $response = Read-Host "Do you want to clone/update the repo $($repo.name)? (y/n)" + if ($response -eq 'y') { + CloneOrUpdateRepo -repo $repo -projectFolder $projectFolder + } else { + Write-Output "Skipping $($repo.name)" + } + } + } +} + +<# +.SYNOPSIS + Script to clone or update repositories for a specified organization. + +.DESCRIPTION + This script clones or updates repositories for a specified organization into a specified destination folder. It supports both GitHub and Azure DevOps repositories. + +.PARAMETER destinationFolder + The folder where the repositories will be cloned or updated. + +.PARAMETER organization + The organization name (GitHub or Azure DevOps). + +.PARAMETER repos + The list of GitHub repositories to clone or update. + +.PARAMETER pat + The personal access token for Azure DevOps authentication. + +.INPUTS + None + +.OUTPUTS + None + +.NOTES + Version: 1.0 + Author: Sebastian Graef + Creation Date: 22-03-2025 + Purpose/Change: Initial script development + +.EXAMPLE + Update-Repos -destinationFolder "C:\Repos" -organization "yourOrg" -repos @("repo1", "repo2") + +.EXAMPLE + Update-Repos -destinationFolder "C:\Repos" -organization "yourOrg" -pat "yourPAT" +#> + +function Update-Repos { + + [CmdletBinding()] + param + ( + [Parameter()] + [string]$destinationFolder, + [Parameter()] + [string]$organization, + [Parameter()] + [string[]]$repos, + [Parameter()] + [string]$pat + ) + + if ($pat) { + Write-Output "- Updating Azure DevOps repositories" + Update-AdoRepos -organization $organization -destinationFolder $destinationFolder -pat $pat + } else { + Write-Output "- Updating GitHub repositories" + Update-GitHubRepos -destinationFolder $destinationFolder -organization $organization -repos $repos + } +} From 06034f693c7099a67c294275a2e28e2fb8cbed2b Mon Sep 17 00:00:00 2001 From: Az-Tech Platform Date: Mon, 24 Mar 2025 19:23:28 +1000 Subject: [PATCH 2/5] Refactor Update-AdoRepos and Update-GitHubRepos scripts to support ShouldProcess for safer execution --- PowerShell/Update-AdoRepos.ps1 | 37 ++++++--- PowerShell/Update-GitHubRepos.ps1 | 126 +++++++++++++++--------------- PowerShell/Update-Repos.ps1 | 54 ++++++++----- 3 files changed, 121 insertions(+), 96 deletions(-) diff --git a/PowerShell/Update-AdoRepos.ps1 b/PowerShell/Update-AdoRepos.ps1 index 05ccead..fc78cbb 100644 --- a/PowerShell/Update-AdoRepos.ps1 +++ b/PowerShell/Update-AdoRepos.ps1 @@ -1,6 +1,4 @@ -function Update-AdoRepos { - - <# +<# .SYNOPSIS Script to clone or update Azure DevOps repositories for all projects in an organization. @@ -32,9 +30,16 @@ function Update-AdoRepos { CloneUpdate-AdoRepos.ps1 -organization "yourOrg" -destinationFolder "C:\Repos" -pat "yourPAT" #> - param ( +function Update-AdoRepos { + + [CmdletBinding(SupportsShouldProcess)] + param + ( + [Parameter()] [string]$organization, + [Parameter()] [string]$destinationFolder, + [Parameter()] [string]$pat ) @@ -61,14 +66,18 @@ function Update-AdoRepos { $repoFolder = "$projectFolder/$repoName" if (-not (Test-Path -Path $repoFolder)) { - Write-Output "Cloning $($repo.name)" - git clone $repoUrl $repoFolder + if ($PSCmdlet.ShouldProcess("Cloning $($repo.name)")) { + Write-Output "Cloning $($repo.name)" + git clone $repoUrl $repoFolder + } } else { - Write-Output "Pulling/Refreshing $($repo.name)" - Set-Location -Path $repoFolder - git checkout main - git pull - Set-Location -Path $projectFolder + if ($PSCmdlet.ShouldProcess("Pulling/Refreshing $($repo.name)")) { + Write-Output "Pulling/Refreshing $($repo.name)" + Set-Location -Path $repoFolder + git checkout main + git pull + Set-Location -Path $projectFolder + } } } @@ -79,8 +88,10 @@ function Update-AdoRepos { foreach ($project in $projects) { $projectFolder = "$destinationFolder/$($project.name)" if (-not (Test-Path -Path $projectFolder)) { - Write-Output "Creating folder $projectFolder" - New-Item -ItemType Directory -Path $projectFolder + if ($PSCmdlet.ShouldProcess("Creating folder $projectFolder")) { + Write-Output "Creating folder $projectFolder" + New-Item -ItemType Directory -Path $projectFolder + } } Write-Output "Getting repos for $($project.name) ..." diff --git a/PowerShell/Update-GitHubRepos.ps1 b/PowerShell/Update-GitHubRepos.ps1 index c6d1637..c82c8c4 100644 --- a/PowerShell/Update-GitHubRepos.ps1 +++ b/PowerShell/Update-GitHubRepos.ps1 @@ -1,80 +1,82 @@ -function Update-GitHubRepos { - <# -.SYNOPSIS - Clones or updates GitHub repositories for a specified organization. + .SYNOPSIS + Clones or updates GitHub repositories for a specified organization. -.DESCRIPTION - This script clones or updates GitHub repositories for a specified organization into a specified destination folder. + .DESCRIPTION + This script clones or updates GitHub repositories for a specified organization into a specified destination folder. -.PARAMETER destinationFolder - The folder where the repositories will be cloned or updated. + .PARAMETER destinationFolder + The folder where the repositories will be cloned or updated. -.PARAMETER organization - The GitHub organization name. + .PARAMETER organization + The GitHub organization name. -.PARAMETER repos - The list of repositories to clone or update. + .PARAMETER repos + The list of repositories to clone or update. -.INPUTS - None + .INPUTS + None -.OUTPUTS - None + .OUTPUTS + None -.NOTES - Version: 1.0 - Author: Sebastian Graef - Creation Date: 22-03-2025 - Purpose/Change: Initial script development + .NOTES + Version: 1.0 + Author: Sebastian Graef + Creation Date: 22-03-2025 + Purpose/Change: Initial script development -.EXAMPLE - Get-GitHubRepos -destinationFolder "Git/Folder1" -organization "Azure" -repos @("repo1", "repo2") + .EXAMPLE + Get-GitHubRepos -destinationFolder "Git/Folder1" -organization "Azure" -repos @("repo1", "repo2") -.EXAMPLE - $tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" - Get-GitHubRepos -repos $tfrepos + .EXAMPLE + $tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" + Get-GitHubRepos -repos $tfrepos #> - #region Parameters - - [CmdletBinding()] - param - ( - [Parameter()] - [string]$destinationFolder, - [Parameter()] - [string]$organization, - [Parameter()] - [string[]]$repos - ) +function Update-GitHubRepos { - #endregion + [CmdletBinding(SupportsShouldProcess)] + param + ( + [Parameter()] + [string]$destinationFolder, + [Parameter()] + [string]$organization, + [Parameter()] + [string[]]$repos + ) - Write-Output "Found $($repos.Count) repositories." - $confirmation = Read-Host "Do you want to proceed with processing these repositories? (y/n)" - if ($confirmation -ne 'y') { - return - } + Write-Output "Found $($repos.Count) repositories." + $confirmation = Read-Host "Do you want to proceed with processing these repositories? (y/n)" + if ($confirmation -ne 'y') { + return + } - foreach ($repo in $repos) { - $repoPath = Join-Path -Path $destinationFolder -ChildPath "$organization/$repo" - If (!(Test-Path -Path $repoPath)) { - New-Item -ItemType Directory -Path $repoPath -Force - Set-Location -Path $repoPath - Write-Output "Cloning repository $repo into $repoPath." - git clone "https://github.com/$organization/$repo.git" - } else { - Write-Output "Directory $repoPath already exists. Updating only." - if ((Get-ChildItem -Path $repoPath).Count -eq 0) { - Write-Output "Cloning repository $repo into $repoPath." - git clone "https://github.com/$organization/$repo.git" - } else { - Write-Output "Pulling latest changes for $repo." - Set-Location -Path $repoPath - git checkout main - git pull - } + foreach ($repo in $repos) { + $repoPath = Join-Path -Path $destinationFolder -ChildPath "$organization/$repo" + If (!(Test-Path -Path $repoPath)) { + if ($PSCmdlet.ShouldProcess("Cloning repository $repo into $repoPath")) { + New-Item -ItemType Directory -Path $repoPath -Force + Set-Location -Path $repoPath + Write-Output "Cloning repository $repo into $repoPath." + git clone "https://github.com/$organization/$repo.git" + } + } else { + Write-Output "Directory $repoPath already exists. Updating only." + if ((Get-ChildItem -Path $repoPath).Count -eq 0) { + if ($PSCmdlet.ShouldProcess("Cloning repository $repo into $repoPath")) { + Write-Output "Cloning repository $repo into $repoPath." + git clone "https://github.com/$organization/$repo.git" + } + } else { + if ($PSCmdlet.ShouldProcess("Pulling latest changes for $repo")) { + Write-Output "Pulling latest changes for $repo." + Set-Location -Path $repoPath + git checkout main + git pull } + } } + } } diff --git a/PowerShell/Update-Repos.ps1 b/PowerShell/Update-Repos.ps1 index b7131b3..3f8d612 100644 --- a/PowerShell/Update-Repos.ps1 +++ b/PowerShell/Update-Repos.ps1 @@ -32,7 +32,7 @@ .EXAMPLE $tfrepos = gh repo list azure -L 5000 --json name --jq '.[].name' | Select-String -Pattern "terraform-azurerm-avm" Get-GitHubRepos -repos $tfrepos - #> +#> function Update-GitHubRepos { @@ -56,20 +56,26 @@ function Update-GitHubRepos { foreach ($repo in $repos) { $repoPath = Join-Path -Path $destinationFolder -ChildPath "$organization/$repo" If (!(Test-Path -Path $repoPath)) { - New-Item -ItemType Directory -Path $repoPath -Force - Set-Location -Path $repoPath - Write-Output "Cloning repository $repo into $repoPath." - git clone "https://github.com/$organization/$repo.git" + if ($PSCmdlet.ShouldProcess("Cloning repository $repo into $repoPath")) { + New-Item -ItemType Directory -Path $repoPath -Force + Set-Location -Path $repoPath + Write-Output "Cloning repository $repo into $repoPath." + git clone "https://github.com/$organization/$repo.git" + } } else { Write-Output "Directory $repoPath already exists. Updating only." if ((Get-ChildItem -Path $repoPath).Count -eq 0) { - Write-Output "Cloning repository $repo into $repoPath." - git clone "https://github.com/$organization/$repo.git" + if ($PSCmdlet.ShouldProcess("Cloning repository $repo into $repoPath")) { + Write-Output "Cloning repository $repo into $repoPath." + git clone "https://github.com/$organization/$repo.git" + } } else { - Write-Output "Pulling latest changes for $repo." - Set-Location -Path $repoPath - git checkout main - git pull + if ($PSCmdlet.ShouldProcess("Pulling latest changes for $repo")) { + Write-Output "Pulling latest changes for $repo." + Set-Location -Path $repoPath + git checkout main + git pull + } } } } @@ -144,14 +150,18 @@ function Update-AdoRepos { $repoFolder = "$projectFolder/$repoName" if (-not (Test-Path -Path $repoFolder)) { - Write-Output "Cloning $($repo.name)" - git clone $repoUrl $repoFolder + if ($PSCmdlet.ShouldProcess("Cloning $($repo.name)")) { + Write-Output "Cloning $($repo.name)" + git clone $repoUrl $repoFolder + } } else { - Write-Output "Pulling/Refreshing $($repo.name)" - Set-Location -Path $repoFolder - git checkout main - git pull - Set-Location -Path $projectFolder + if ($PSCmdlet.ShouldProcess("Pulling/Refreshing $($repo.name)")) { + Write-Output "Pulling/Refreshing $($repo.name)" + Set-Location -Path $repoFolder + git checkout main + git pull + Set-Location -Path $projectFolder + } } } @@ -162,8 +172,10 @@ function Update-AdoRepos { foreach ($project in $projects) { $projectFolder = "$destinationFolder/$($project.name)" if (-not (Test-Path -Path $projectFolder)) { - Write-Output "Creating folder $projectFolder" - New-Item -ItemType Directory -Path $projectFolder + if ($PSCmdlet.ShouldProcess("Creating folder $projectFolder")) { + Write-Output "Creating folder $projectFolder" + New-Item -ItemType Directory -Path $projectFolder + } } Write-Output "Getting repos for $($project.name) ..." @@ -221,7 +233,7 @@ function Update-AdoRepos { function Update-Repos { - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( [Parameter()] From dd09c45d1f66274f3cc1549b1a821a5c3f0c77cf Mon Sep 17 00:00:00 2001 From: Az-Tech Platform Date: Mon, 24 Mar 2025 19:31:03 +1000 Subject: [PATCH 3/5] Refactor Create-PullRequests and Update-AdoRepos scripts to improve parameter handling and output methods --- PowerShell/Snippets/Create-PullRequests.ps1 | 8 +++----- PowerShell/Update-AdoRepos.ps1 | 8 ++++---- PowerShell/Update-Repos.ps1 | 8 ++++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/PowerShell/Snippets/Create-PullRequests.ps1 b/PowerShell/Snippets/Create-PullRequests.ps1 index 9645fa5..3f856c0 100644 --- a/PowerShell/Snippets/Create-PullRequests.ps1 +++ b/PowerShell/Snippets/Create-PullRequests.ps1 @@ -7,15 +7,13 @@ Param( az extension add --name azure-devops -echo $token | az devops login --organization https://dev.azure.com/$org +Write-Output $token | az devops login --organization https://dev.azure.com/$org az devops configure --defaults organization=https://dev.azure.com/$org project=$project $repos = az repos list | ConvertFrom-Json -$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token))) - # Create Pull Request on all repos foreach($repo in $repos){ - Write-Host $repo.name - # az repos pr create --repository $repo.name --source-branch $branchName --open --output table + Write-Output $repo.name + az repos pr create --repository $repo.name --source-branch $branchName --open --output table } diff --git a/PowerShell/Update-AdoRepos.ps1 b/PowerShell/Update-AdoRepos.ps1 index fc78cbb..aa95d1c 100644 --- a/PowerShell/Update-AdoRepos.ps1 +++ b/PowerShell/Update-AdoRepos.ps1 @@ -44,14 +44,14 @@ function Update-AdoRepos { ) # Function to get all projects in the organization - function Get-AdoProjects { + function Get-AdoProjects($organization,$pat) { $uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0" $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } return $response.value } # Function to get repositories for a given project - function Get-AdoRepositories($project) { + function Get-AdoRepositories($organization,$pat,$project) { $uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0" $uri = $uri -replace " ", "%20" Write-Output $uri @@ -83,7 +83,7 @@ function Update-AdoRepos { # Main script Write-Output "Getting projects ..." - $projects = Get-AdoProjects + $projects = Get-AdoProjects -organization $organization -pat $pat Write-Output "Found $($projects.Count) projects: $($projects.name)" foreach ($project in $projects) { $projectFolder = "$destinationFolder/$($project.name)" @@ -95,7 +95,7 @@ function Update-AdoRepos { } Write-Output "Getting repos for $($project.name) ..." - $repos = Get-AdoRepositories -project $project.name + $repos = Get-AdoRepositories -organization $organization -pat $pat -project $project.name Write-Output "Found $($repos.Count) repos: $($repos.name)" Read-Host "Press Enter to continue" foreach ($repo in $repos) { diff --git a/PowerShell/Update-Repos.ps1 b/PowerShell/Update-Repos.ps1 index 3f8d612..2674489 100644 --- a/PowerShell/Update-Repos.ps1 +++ b/PowerShell/Update-Repos.ps1 @@ -128,14 +128,14 @@ function Update-AdoRepos { ) # Function to get all projects in the organization - function Get-AdoProjects { + function Get-AdoProjects($organization,$pat) { $uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0" $response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) } return $response.value } # Function to get repositories for a given project - function Get-AdoRepositories($project) { + function Get-AdoRepositories($organization,$pat,$project) { $uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0" $uri = $uri -replace " ", "%20" Write-Output $uri @@ -167,7 +167,7 @@ function Update-AdoRepos { # Main script Write-Output "Getting projects ..." - $projects = Get-AdoProjects + $projects = Get-AdoProjects -organization $organization -pat $pat Write-Output "Found $($projects.Count) projects: $($projects.name)" foreach ($project in $projects) { $projectFolder = "$destinationFolder/$($project.name)" @@ -179,7 +179,7 @@ function Update-AdoRepos { } Write-Output "Getting repos for $($project.name) ..." - $repos = Get-AdoRepositories -project $project.name + $repos = Get-AdoRepositories -organization $organization -pat $pat -project $project.name Write-Output "Found $($repos.Count) repos: $($repos.name)" Read-Host "Press Enter to continue" foreach ($repo in $repos) { From 06acff3b23c2be7043fa74c12e8537a5026daba0 Mon Sep 17 00:00:00 2001 From: Az-Tech Platform Date: Mon, 24 Mar 2025 19:37:13 +1000 Subject: [PATCH 4/5] Refactor Create-PullRequests script to use CmdletBinding and support ShouldProcess for safer execution --- PowerShell/Snippets/Create-PullRequests.ps1 | 37 ++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/PowerShell/Snippets/Create-PullRequests.ps1 b/PowerShell/Snippets/Create-PullRequests.ps1 index 3f856c0..9bd7a6d 100644 --- a/PowerShell/Snippets/Create-PullRequests.ps1 +++ b/PowerShell/Snippets/Create-PullRequests.ps1 @@ -1,19 +1,26 @@ -Param( - [string]$org = "x00", - [string]$project = "Modules", - [string]$token = "token", - [string]$branchName = "users/segraef/provider-upgrade" -) +function Create-PullRequests { -az extension add --name azure-devops + [CmdletBinding(SupportsShouldProcess)] + Param( + [Parameter()] + [string]$org = "x00", + [Parameter()] + [string]$project = "Modules", + [Parameter()] + [string]$token = "token", + [Parameter()] + [string]$branchName = "users/segraef/provider-upgrade" + ) -Write-Output $token | az devops login --organization https://dev.azure.com/$org -az devops configure --defaults organization=https://dev.azure.com/$org project=$project -$repos = az repos list | ConvertFrom-Json + az extension add --name azure-devops -# Create Pull Request on all repos -foreach($repo in $repos){ - Write-Output $repo.name - az repos pr create --repository $repo.name --source-branch $branchName --open --output table -} + Write-Output $token | az devops login --organization https://dev.azure.com/$org + az devops configure --defaults organization=https://dev.azure.com/$org project=$project + $repos = az repos list | ConvertFrom-Json + # Create Pull Request on all repos + foreach ($repo in $repos) { + Write-Output $repo.name + az repos pr create --repository $repo.name --source-branch $branchName --open --output table + } +} From c3548aa80f82b0213dfab336fee18d1df57e9090 Mon Sep 17 00:00:00 2001 From: Az-Tech Platform Date: Mon, 24 Mar 2025 19:40:36 +1000 Subject: [PATCH 5/5] Replace Create-PullRequests script with Add-PullRequests script for improved functionality --- .../{Create-PullRequests.ps1 => Add-PullRequests.ps1} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename PowerShell/Snippets/{Create-PullRequests.ps1 => Add-PullRequests.ps1} (91%) diff --git a/PowerShell/Snippets/Create-PullRequests.ps1 b/PowerShell/Snippets/Add-PullRequests.ps1 similarity index 91% rename from PowerShell/Snippets/Create-PullRequests.ps1 rename to PowerShell/Snippets/Add-PullRequests.ps1 index 9bd7a6d..17abe5f 100644 --- a/PowerShell/Snippets/Create-PullRequests.ps1 +++ b/PowerShell/Snippets/Add-PullRequests.ps1 @@ -1,6 +1,6 @@ -function Create-PullRequests { +function Add-PullRequests { - [CmdletBinding(SupportsShouldProcess)] + [CmdletBinding()] Param( [Parameter()] [string]$org = "x00",