Skip to content

Commit 5760923

Browse files
authored
Add scripts for cloning/updating Azure DevOps repositories and creating build validation policies (#16)
1 parent 4973aae commit 5760923

2 files changed

Lines changed: 180 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Define the list of Azure DevOps project names
2+
$organization = "yourOrg"
3+
$destinationFolder = "/Users/user/$organization"
4+
$pat = ""
5+
$VerbosePreference = 'Continue'
6+
7+
# Function to get all projects in the organization
8+
function Get-AdoProjects {
9+
$uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0"
10+
$response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) }
11+
return $response.value
12+
}
13+
14+
# Function to get repositories for a given project
15+
function Get-AdoRepositories($project) {
16+
$uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0"
17+
$uri = $uri -replace " ", "%20"
18+
Write-Verbose $uri
19+
$response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) }
20+
return $response.value
21+
}
22+
23+
# Function to clone or update repositories
24+
function CloneOrUpdateRepo($repo, $projectFolder) {
25+
$repoName = $repo.name
26+
$repoUrl = $repo.remoteUrl
27+
$repoFolder = "$projectFolder/$repoName"
28+
29+
if (-not (Test-Path -Path $repoFolder)) {
30+
Write-Verbose "Cloning $($repo.name)"
31+
git clone $repoUrl $repoFolder
32+
} else {
33+
Write-Verbose "Pulling/Refreshing $($repo.name)"
34+
Set-Location -Path $repoFolder
35+
git checkout main
36+
git pull
37+
Set-Location -Path $projectFolder
38+
}
39+
}
40+
41+
# Main script
42+
Write-Verbose "Getting projects ..."
43+
$projects = Get-AdoProjects
44+
Write-Verbose "Found $($projects.Count) projects: $($projects.name)"
45+
foreach ($project in $projects) {
46+
$projectFolder = "$destinationFolder/$($project.name)"
47+
if (-not (Test-Path -Path $projectFolder)) {
48+
Write-Verbose "Creating folder $projectFolder"
49+
New-Item -ItemType Directory -Path $projectFolder
50+
}
51+
52+
Write-Verbose "Getting repos for $($project.name) ..."
53+
$repos = Get-AdoRepositories -project $project.name
54+
Write-Verbose "Found $($repos.Count) repos: $($repos.name)"
55+
# ask to proceed
56+
Read-Host "Press Enter to continue"
57+
foreach ($repo in $repos) {
58+
$response = Read-Host "Do you want to clone/update the repo $($repo.name)? (y/n)"
59+
if ($response -eq 'y') {
60+
CloneOrUpdateRepo -repo $repo -projectFolder $projectFolder
61+
} else {
62+
Write-Verbose "Skipping $($repo.name)"
63+
}
64+
}
65+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Define the list of Azure DevOps project names
2+
$organization = "org1"
3+
$pat = "<pat>"
4+
$projects = @(
5+
[PSCustomObject]@{
6+
name = "project1"
7+
}
8+
)
9+
$VerbosePreference = 'Continue'
10+
11+
# Log in to Azure DevOps using PAT
12+
$env:AZURE_DEVOPS_EXT_PAT = "$pat"
13+
14+
# Function to get all projects in the organization
15+
function Get-AdoProjects {
16+
$uri = "https://dev.azure.com/$organization/_apis/projects?api-version=6.0"
17+
$response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) }
18+
return $response.value
19+
}
20+
21+
# Function to get repositories for a given project
22+
function Get-AdoRepositories($project) {
23+
$uri = "https://dev.azure.com/$organization/$project/_apis/git/repositories?api-version=6.0"
24+
$uri = $uri -replace " ", "%20"
25+
$response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) }
26+
return $response.value
27+
}
28+
29+
# Function to get all Azure Pipelines
30+
function Get-AdoPipelines($project) {
31+
$uri = "https://dev.azure.com/$organization/$project/_apis/pipelines?api-version=6.0"
32+
$uri = $uri -replace " ", "%20"
33+
$response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) }
34+
return $response.value
35+
}
36+
37+
# Function to get all build policies
38+
function Get-AdoBuildPolicies($project) {
39+
$uri = "https://dev.azure.com/$organization/$project/_apis/policy/configurations?api-version=6.0"
40+
$uri = $uri -replace " ", "%20"
41+
$response = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")) }
42+
return $response.value
43+
}
44+
45+
function CreateBuildValidationPolicy($project, $repo, $buildDefinition) {
46+
# check matching policies
47+
$matchingPolicies = $buildPolicies | Where-Object { $_.settings.buildDefinitionId -eq $buildDefinition.id }
48+
if ($matchingPolicies) {
49+
Write-Verbose "Policy already exists for $($repo.name) using pipeline $($buildDefinition.name). Updating."
50+
az repos policy build update `
51+
--id $matchingPolicies.id `
52+
--blocking $false `
53+
--branch main `
54+
--build-definition-id $buildDefinition.id `
55+
--display-name $repo.name `
56+
--enabled $true `
57+
--manual-queue-only $false `
58+
--queue-on-source-update-only $false `
59+
--repository-id $repo.id `
60+
--valid-duration 0 `
61+
--project $project.name
62+
63+
# Build Validation Policy
64+
# --blocking $false - Policy Requirement: Optional
65+
# --manual-queue-only $false - Trigger: Manual
66+
# --valid-duration 0 - Build expiration: Immediately when main is updated
67+
} else {
68+
Write-Verbose "Creating build validation policy for $($repo.name) using pipeline $($buildDefinition.name)."
69+
az repos policy build create `
70+
--blocking $false `
71+
--branch main `
72+
--build-definition-id $buildDefinition.id `
73+
--display-name $repo.name `
74+
--enabled $true `
75+
--manual-queue-only $false `
76+
--queue-on-source-update-only $false `
77+
--repository-id $repo.id `
78+
--valid-duration 0 `
79+
--project $project.name
80+
}
81+
}
82+
83+
# Main script
84+
Write-Verbose "Getting projects ..."
85+
if ($projects.Count -eq 0) {
86+
Write-Verbose "Getting all projects ..."
87+
$projects = Get-AdoProjects
88+
} else {
89+
Write-Verbose "Using provided project(s): $($projects.name)"
90+
}
91+
Write-Verbose "Found $($projects.Count) project(s): $($projects.name)"
92+
foreach ($project in $projects) {
93+
Write-Verbose "Getting repos for $($project.name) ..."
94+
$repos = Get-AdoRepositories -project $project.name
95+
Write-Verbose "Found $($repos.Count) repos."
96+
$pipelines = Get-AdoPipelines -project $project.name
97+
Write-Verbose "Found $($pipelines.Count) pipelines."
98+
$buildPolicies = Get-AdoBuildPolicies -project $project.name
99+
Write-Verbose "Found $($buildPolicies.Count) build policies."
100+
# Check matching pipelines
101+
$checkedRepos = $repos | Where-Object { $_.name -in $pipelines.name }
102+
Write-Verbose "Found $($checkedRepos.Count) repos with matching pipelines."
103+
104+
Read-Host "Press Enter to continue"
105+
106+
foreach ($repo in $repos) {
107+
$buildDefinition = $pipelines | Where-Object { $_.name -eq "$($repo.name)" }
108+
# $response = Read-Host "Do you want to create build validation for repo $($repo.name) using pipeline $($buildDefinition.name)? (y/n)"
109+
# if ($response -eq 'y') {
110+
CreateBuildValidationPolicy -repo $repo -project $project -buildDefinition $buildDefinition
111+
# } else {
112+
# Write-Verbose "Skipping $($repo.name)"
113+
# }
114+
}
115+
}

0 commit comments

Comments
 (0)