Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 62 additions & 96 deletions docs/wiki/Azure-Pipelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,123 +66,89 @@ $SubscriptionId = '<Value>'
$ARM_CLIENT_ID = '<Value>'
$ARM_CLIENT_SECRET = '<Value>'

# Create a new project
$Project = az devops project list --query "value[?name=='$ProjectName'].{name:name, id:id}" --organization "https://dev.azure.com/$Organization" | ConvertFrom-Json
if ($null -eq $Project) {
$Project = az devops project create --name $ProjectName --organization "https://dev.azure.com/$Organization" `
--query "{name:name, id:id}" | ConvertFrom-Json

$OrgParams = @{
Organization = $Organization
Project = $ProjectName
}

# Set the defaults for the local Azure Cli shell
az devops configure `
--defaults organization="https://dev.azure.com/$Organization" project="$ProjectName"
# Install the ADOPS PowerShell module
Install-Module -Name ADOPS -Scope CurrentUser -RequiredVersion '2.0.1' -Force

# Create a new repository from the AzOps Accelerator template repository
$Repo = az repos list --query "[?name=='$RepoName'].{name:name, id:id}" | ConvertFrom-Json
if ($null -eq $Repo) {
$Repo = az repos create --name $RepoName --query "{name:name, id:id}" | ConvertFrom-Json
# Connect to Azure DevOps (This will open a browser window for you to login)
Connect-ADOPS -Organization $Organization

# Create a new project and wait for it to be created
$Project = Get-ADOPSProject @OrgParams
if ($null -eq $Project) {
$Project = New-ADOPSProject -Name $ProjectName -Organization $Organization -Visibility Private -Wait
}
az repos import create `
--git-url "https://github.com/Azure/AzOps-Accelerator.git" --repository "$($Repo.name)"
$null = az repos update --repository $RepoName --default-branch 'main'

# Add a variable group for authenticating pipelines with Azure Resource Manager and record the id output
if ($ARM_CLIENT_SECRET) {
$VariableGroupId = az pipelines variable-group create `
--name 'credentials' `
--variables `
"ARM_TENANT_ID=$TenantId" "ARM_SUBSCRIPTION_ID=$SubscriptionId" "ARM_CLIENT_ID=$ARM_CLIENT_ID" `
--query 'id'
} else {
$VariableGroupId = az pipelines variable-group create `
--name 'credentials' `
--variables `
"ARM_TENANT_ID=$TenantId" "ARM_SUBSCRIPTION_ID=$SubscriptionId" "ARM_CLIENT_ID=$ARM_CLIENT_ID" "ARM_CLIENT_SECRET=$ARM_CLIENT_SECRET" `
--query 'id'
# Create a new repository from the AzOps Accelerator template repository
try {
$Repo = Get-ADOPSRepository @OrgParams -Repository $RepoName
}
catch {
$Repo = New-ADOPSRepository @OrgParams -Name $RepoName
}

$ConfigVariableGroupId = az pipelines variable-group create `
--name 'azops' `
--variables `
"AZOPS_MODULE_VERSION=" "AZOPS_CUSTOM_SORT_ORDER=false" `
--query 'id'
# Import the AzOps Accelerator template repository and wait for the import to complete
$null = Import-ADOPSRepository @OrgParams -RepositoryName $RepoName -GitSource 'https://github.com/Azure/AzOps-Accelerator.git' -Wait
$null = Set-ADOPSRepository -RepositoryId $repo.id -DefaultBranch 'main' @OrgParams

# Add a secret to the variable group just created using id from above if using service principal
# Add a variable group for authenticating pipelines with Azure Resource Manager and record the id output
$CredentialVariableGroup = @(
@{Name = 'ARM_TENANT_ID'; Value = $TenantId; IsSecret = $false }
@{Name = 'ARM_SUBSCRIPTION_ID'; Value = $SubscriptionId; IsSecret = $false }
@{Name = 'ARM_CLIENT_ID'; Value = $ARM_CLIENT_ID; IsSecret = $false }
)
if ($ARM_CLIENT_SECRET) {
az pipelines variable-group variable create `
--id $VariableGroupId --name 'ARM_CLIENT_SECRET' --secret true --value $ARM_CLIENT_SECRET
$CredentialVariableGroup += @{Name = 'ARM_CLIENT_SECRET'; Value = $ARM_CLIENT_SECRET; IsSecret = $true }
}
$null = New-ADOPSVariableGroup -VariableGroupName 'credentials' -VariableHashtable $CredentialVariableGroup @OrgParams

# Create three new pipelines from existing YAML manifests.
az pipelines create --skip-first-run true `
--name 'AzOps - Push' --branch main --repository "$RepoName" --repository-type tfsgit --yaml-path .pipelines/push.yml

az pipelines create --skip-first-run true `
--name 'AzOps - Pull' --branch main --repository "$RepoName" --repository-type tfsgit --yaml-path .pipelines/pull.yml
$ConfigVariableGroup = @(
@{Name = 'AZOPS_MODULE_VERSION'; Value = ''; IsSecret = $false }
@{Name = 'AZOPS_CUSTOM_SORT_ORDER'; Value = 'false'; IsSecret = $false }
)
$null = New-ADOPSVariableGroup -VariableGroupName 'azops' -VariableHashtable $ConfigVariableGroup @OrgParams

az pipelines create --skip-first-run true `
--name 'AzOps - Validate' --branch main --repository "$RepoName" --repository-type tfsgit --yaml-path .pipelines/validate.yml
# Create three new pipelines from existing YAML manifests.
$null = New-ADOPSPipeline -Name 'AzOps - Push' -YamlPath '.pipelines/push.yml' -Repository $RepoName @OrgParams
$null = New-ADOPSPipeline -Name 'AzOps - Pull' -YamlPath '.pipelines/pull.yml' -Repository $RepoName @OrgParams
$null = New-ADOPSPipeline -Name 'AzOps - Validate' -YamlPath '.pipelines/validate.yml' -Repository $RepoName @OrgParams

# Add build validation policy to validate pull requests
az repos policy build create --blocking true --branch main `
--build-definition-id (az pipelines show --name 'AzOps - Validate' --query 'id') `
--display-name 'Validate' --enabled true --queue-on-source-update-only false `
--repository-id (az repos list --query "[?name=='$RepoName'].id" -o tsv) `
--manual-queue-only false --valid-duration 0 --path-filter '/root/*'
$RepoId = Get-ADOPSRepository -Repository $RepoName @OrgParams | Select-Object -ExpandProperty Id
$PipelineId = Get-ADOPSPipeline -Name 'AzOps - Validate' @OrgParams | Select-Object -ExpandProperty Id
$BuildPolicyParam = @{
RepositoryId = $RepoId
Branch = 'main'
PipelineId = $PipelineId
Displayname = 'Validate'
filenamePatterns = '/root/*'
}
$null = New-ADOPSBuildPolicy @BuildPolicyParam @OrgParams

# Add branch policy to limit merge types to squash only
az repos policy merge-strategy create --blocking true --branch main `
--repository-id (az repos list --query "[?name=='$RepoName'].id" -o tsv) --enabled true `
--allow-no-fast-forward false --allow-rebase false --allow-rebase-merge false `
--allow-squash true
$null = New-ADOPSMergePolicy -RepositoryId $RepoId -Branch 'main' -allowSquash @OrgParams

# Add permissions for the Build Service account to the git repository
$AzureDevOpsGlobalAppId = '499b84ac-1321-427f-aa17-267ca6975798'
$AzureReposSecurityNamespaceId = '2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87'
$ProjectId = az devops project list --query "value[?name=='$ProjectName'].id" -o tsv
$RepoId = az repos list --query "[?name=='$RepoName'].id" -o tsv
$QueryStrings = "searchFilter=General&queryMembership=None&api-version=6.0&filtervalue=$ProjectName Build Service ($Organization)"
$Uri = "`"https://vssps.dev.azure.com/$Organization/_apis/identities?$QueryStrings`""
$Subject = az rest --method get --uri $Uri --resource $AzureDevOpsGlobalAppId -o json | ConvertFrom-Json
$Body = @{
token = "repov2/$ProjectId/$RepoId"
merge = $true
accessControlEntries = @(
@{
# Contribute: 4
# Force push: 8
# CreateBranch: 16
# Contribute to pull requests: 16384
# Bypass policies when completing pull requests: 32768
allow = 4 + 8 + 16 + 16384 + 32768
deny = 0
descriptor = $Subject.value.descriptor
}
)
} | ConvertTo-Json -Compress | ConvertTo-Json # Convert to json twice to properly escape characters for Python interpreter
$Uri = "`"https://dev.azure.com/$Organization/_apis/accesscontrolentries/${AzureReposSecurityNamespaceId}?api-version=6.0`""
az rest --method post --uri $Uri --body $Body --resource $AzureDevOpsGlobalAppId -o json
$ProjectId = Get-ADOPSProject @OrgParams | Select-Object -ExpandProperty Id
$BuildAccount = Get-ADOPSUser -Organization $Organization |
Where-Object displayName -eq "$ProjectName Build Service ($Organization)"
foreach ($permission in 'GenericContribute', 'ForcePush', 'CreateBranch', 'PullRequestContribute', 'PullRequestBypassPolicy') {
$null = Set-ADOPSGitPermission -ProjectId $ProjectId -RepositoryId $RepoId -Descriptor $BuildAccount.descriptor -Allow $permission
}

# Add pipeline permissions for all three pipelines to the credentials Variable Groups
$AzureDevOpsGlobalAppId = '499b84ac-1321-427f-aa17-267ca6975798'
$Pipelines = az pipelines list --query "[? contains(name,'AzOps')].{id:id,name:name}" | ConvertFrom-Json
$Body = @(
@{
resource = @{}
pipelines = @(
foreach ($pipeline in $Pipelines) {
@{
id = $pipeline.id
authorized = $true
}
}
)
$Uri = "https://dev.azure.com/$Organization/$ProjectName/_apis/distributedtask/variablegroups?api-version=7.1-preview.2"
$VariableGroups = (Invoke-ADOPSRestMethod -Uri $Uri -Method 'Get').value | Where-Object name -in 'credentials', 'azops'
foreach ($pipeline in 'AzOps - Push', 'AzOps - Pull', 'AzOps - Validate') {
$PipelineId = Get-ADOPSPipeline -Name $pipeline @OrgParams | Select-Object -ExpandProperty Id
foreach ($groupId in $VariableGroups.id) {
$null = Grant-ADOPSPipelinePermission -PipelineId $PipelineId -ResourceType 'VariableGroup' -ResourceId $groupId @OrgParams
}
) | ConvertTo-Json -Depth 5 -Compress | ConvertTo-Json # Convert to json twice to properly escape characters for Python interpreter
foreach($groupName in 'credentials','azops') {
$VariableGroup = az pipelines variable-group list --query "[?name=='$groupName'].{id:id,name:name}" | ConvertFrom-Json
$Uri = "`"https://dev.azure.com/$Organization/$ProjectName/_apis/pipelines/pipelinepermissions/variablegroup/$($VariableGroup.id)?api-version=6.1-preview.1`""
az rest --method patch --uri $Uri --body $Body --resource $AzureDevOpsGlobalAppId -o json
}
```

Expand Down