Skip to content

Commit 774f530

Browse files
authored
{CI} Pipeline to auto sync resourceManagement.yml according to ADO Wiki Page - Service Contact List (Azure#30012)
1 parent f567049 commit 774f530

File tree

2 files changed

+238
-0
lines changed

2 files changed

+238
-0
lines changed

.azure-pipelines/sync-alias.yml

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Azure CLI Sync Alias
2+
3+
schedules:
4+
- cron: "50 15 * * *"
5+
displayName: 11:50 PM (UTC + 8:00) China Daily Run
6+
branches:
7+
include:
8+
- dev
9+
10+
# The 'resources' and 'uses' below are used to resolve the error 'Repository associated with wiki ID <WikiId> does not exist or you do not have permissions for the operation you are attempting.'
11+
resources:
12+
repositories:
13+
- repository: ServiceContactList
14+
type: git
15+
name: internal.wiki
16+
17+
jobs:
18+
- job: UpdateYaml
19+
displayName: Update resourceManagement.yml
20+
pool: pool-windows-2019
21+
uses:
22+
repositories:
23+
- ServiceContactList
24+
25+
steps:
26+
- task: UseDotNet@2
27+
displayName: Install .NET 8 SDK
28+
inputs:
29+
packageType: sdk
30+
version: 8.0.x
31+
32+
- pwsh: |
33+
dotnet --version
34+
dotnet new tool-manifest --force
35+
dotnet tool install powershell --version 7.4.*
36+
displayName: Install PowerShell 7.4.x
37+
38+
- pwsh: |
39+
dotnet tool run pwsh -NoLogo -NoProfile -NonInteractive -File ./tools/Github/ParseServiceContactsList.ps1 -AccessToken $env:SYSTEM_ACCESSTOKEN
40+
env:
41+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
42+
displayName: Update resourceManagement.yml file locally
43+
44+
- pwsh: |
45+
$hasChanges = git diff --name-only .github/policies
46+
if ($null -eq $hasChanges) {
47+
Write-Host "The wiki has no changes."
48+
Write-Host "##vso[task.setvariable variable=ChangesDetected]false"
49+
} else {
50+
Write-Host "There are changes in the repository."
51+
Write-Host "##vso[task.setvariable variable=ChangesDetected]true"
52+
}
53+
displayName: Check if Wiki table has any changes
54+
55+
- task: AzurePowerShell@5
56+
inputs:
57+
pwsh: true
58+
azureSubscription: '$(AZURE_SDK_INFRA_SUB_CONNECTED_SERVICE)'
59+
ScriptType: 'InlineScript'
60+
Inline: |
61+
$GithubToken = Get-AzKeyVaultSecret -VaultName $(GithubPATKeyVaultName) -Name $(GithubPATKeyVaultAccount) -AsPlainText
62+
Write-Host "##vso[task.setvariable variable=GithubToken;issecret=true]$GithubToken"
63+
azurePowerShellVersion: 'LatestVersion'
64+
displayName: Get Github PAT from Key Vault
65+
66+
- pwsh: |
67+
git config --global user.email "[email protected]"
68+
git config --global user.name "Azure CLI Team"
69+
git checkout -b "sync_alias_$env:Build_BuildId"
70+
71+
git add .github/policies
72+
git commit -m "Sync resourceManagement.yml"
73+
74+
git remote set-url origin https://azclibot:$(GithubToken)@github.com/Azure/azure-cli.git;
75+
git push origin "sync_alias_$env:Build_BuildId" --force
76+
displayName: Git commit and push
77+
condition: and(succeeded(), eq(variables['ChangesDetected'], 'true'))
78+
79+
- pwsh: |
80+
$Title = "{CI} Sync resourceManagement.yml according To ADO Wiki Page - Service Contact List"
81+
$HeadBranch = "sync_alias_$env:Build_BuildId"
82+
$BaseBranch = "dev"
83+
$Description = "This PR synchronizes the task: 'Triage issues to the service team' part of resourceManagement.yml from table of Service Contact List in ADO wiki page"
84+
85+
$Headers = @{"Accept" = "application/vnd.github+json"; "Authorization" = "Bearer $(GithubToken)" }
86+
$RequestBody = @{"title" = $Title; "body" = $Description; "head" = $HeadBranch; "base" = $BaseBranch;}
87+
$Uri = "https://api.github.com/repos/Azure/azure-cli/pulls"
88+
89+
Invoke-WebRequest -Uri $Uri -Method POST -Headers $Headers -Body ($RequestBody | ConvertTo-Json)
90+
91+
displayName: Create PR to dev branch
92+
condition: and(succeeded(), eq(variables['ChangesDetected'], 'true'))
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# ----------------------------------------------------------------------------------
2+
#
3+
# Copyright Microsoft Corporation
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
# ----------------------------------------------------------------------------------
14+
15+
<#
16+
.SYNOPSIS
17+
Sync ADO Wiki Service Contact List to resourceManagement.yml.
18+
19+
#>
20+
param(
21+
[Parameter(Mandatory = $true)]
22+
[string] $AccessToken
23+
)
24+
25+
function InitializeRequiredPackages {
26+
[CmdletBinding()]
27+
param ()
28+
29+
$packagesDirectoryName = "JsonYamlPackages"
30+
$packagesDirectory = Join-Path -Path . -ChildPath $packagesDirectoryName
31+
if (Test-Path -LiteralPath $packagesDirectory) {
32+
Remove-Item -LiteralPath $packagesDirectory -Recurse -Force
33+
}
34+
35+
New-Item -Path . -Name $packagesDirectoryName -ItemType Directory -Force
36+
37+
$requiredPackages = @(
38+
@{ PackageName = "Newtonsoft.Json"; PackageVersion = "13.0.2"; DllName = "Newtonsoft.Json.dll" },
39+
@{ PackageName = "YamlDotNet"; PackageVersion = "13.2.0"; DllName = "YamlDotNet.dll" }
40+
)
41+
42+
$requiredPackages | ForEach-Object {
43+
$packageName = $_["PackageName"]
44+
$packageVersion = $_["PackageVersion"]
45+
$packageDll = $_["DllName"]
46+
Install-Package -Name $packageName -RequiredVersion $packageVersion -Source "https://www.nuget.org/api/v2" -Destination $packagesDirectory -SkipDependencies -ExcludeVersion -Force
47+
Add-Type -LiteralPath (Join-Path -Path $packagesDirectory -ChildPath $packageName | Join-Path -ChildPath "lib" | Join-Path -ChildPath "net6.0" | Join-Path -ChildPath $packageDll) -ErrorAction SilentlyContinue
48+
}
49+
}
50+
51+
# get wiki content
52+
$username = ""
53+
$password = $AccessToken
54+
$pair = "{0}:{1}" -f ($username, $password)
55+
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
56+
$token = [System.Convert]::ToBase64String($bytes)
57+
$headers = @{
58+
Authorization = "Basic {0}" -f ($token)
59+
}
60+
61+
$response = Invoke-RestMethod 'https://dev.azure.com/azclitools/internal/_apis/wiki/wikis/internal.wiki/pages?path=/Service%20Contact%20List&includeContent=true' -Headers $headers -ErrorAction Stop
62+
$contactsList = ($response.content -split "\n") | Where-Object { $_ -like '|*' } | Select-Object -Skip 2
63+
64+
if ($null -ne $contactsList) {
65+
$idxServiceTeamLabel = 2
66+
$idxCLINotifyGithubHandler = 5
67+
$serviceContacts = [System.Collections.Generic.SortedList[System.String, PSCustomObject]]::new()
68+
69+
foreach ($contacts in $contactsList) {
70+
$items = $contacts -split "\|"
71+
$colServiceTeamLabel = $items[$idxServiceTeamLabel]
72+
if (![string]::IsNullOrWhiteSpace($colServiceTeamLabel)) {
73+
$serviceTeamLabel = $colServiceTeamLabel.Trim()
74+
$colCLINotifyGithubHandler = $items[$idxCLINotifyGithubHandler]
75+
76+
if (![string]::IsNullOrWhiteSpace($colCLINotifyGithubHandler)) {
77+
$CLINotifyGithubHandler = $colCLINotifyGithubHandler.Trim()
78+
[array]$mentionees = $CLINotifyGithubHandler.Split(",", [StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
79+
$_.Trim()
80+
}
81+
82+
$serviceContacts.Add($serviceTeamLabel, [PSCustomObject]@{
83+
if = @(
84+
[PSCustomObject]@{
85+
or = @(
86+
[PSCustomObject]@{
87+
labelAdded = [PSCustomObject]@{
88+
label = 'Service Attention'
89+
}
90+
},
91+
[PSCustomObject]@{
92+
labelAdded = [PSCustomObject]@{
93+
label = $serviceTeamLabel
94+
}
95+
}
96+
)
97+
},
98+
[PSCustomObject]@{
99+
hasLabel = [PSCustomObject]@{
100+
label = 'Service Attention'
101+
}
102+
},
103+
[PSCustomObject]@{
104+
hasLabel = [PSCustomObject]@{
105+
label = $serviceTeamLabel
106+
}
107+
}
108+
)
109+
then = @(
110+
[PSCustomObject]@{
111+
mentionUsers = [PSCustomObject]@{
112+
mentionees = $mentionees
113+
replyTemplate = 'Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc ${mentionees}.'
114+
assignMentionees = 'False'
115+
}
116+
}
117+
)
118+
})
119+
}
120+
}
121+
}
122+
}
123+
124+
# Update yaml file
125+
InitializeRequiredPackages
126+
127+
$yamlConfigPath = $PSScriptRoot | Split-Path | Split-Path | Join-Path -ChildPath ".github" | Join-Path -ChildPath "policies" | Join-Path -ChildPath "resourceManagement.yml"
128+
$yamlContent = Get-Content -Path $yamlConfigPath -Raw
129+
$yamlDeserializer = [YamlDotNet.Serialization.DeserializerBuilder]::new().Build()
130+
$yamlObjectGraph = $yamlDeserializer.Deserialize($yamlContent)
131+
$jsonSerializer = [YamlDotNet.Serialization.SerializerBuilder]::new().JsonCompatible().Build()
132+
$jsonObjectGraph = $jsonSerializer.Serialize($yamlObjectGraph) | ConvertFrom-Json
133+
134+
$serviceContactsTask = $jsonObjectGraph.configuration.resourceManagementConfiguration.eventResponderTasks | Where-Object { $_.description -eq "Triage issues to the service team" }
135+
if ($null -ne $serviceContactsTask) {
136+
$serviceContactsTask.then = $serviceContacts.Values
137+
}
138+
139+
$updatedJsonContent = $jsonObjectGraph | ConvertTo-Json -Depth 64
140+
$updatedJsonObjectGraph = [Newtonsoft.Json.JsonConvert]::DeserializeObject[System.Dynamic.ExpandoObject]($updatedJsonContent)
141+
$yamlSerializer = [YamlDotNet.Serialization.SerializerBuilder]::new().Build()
142+
$updatedYamlContent = $yamlSerializer.Serialize($updatedJsonObjectGraph)
143+
$updatedYamlContent | Out-File -FilePath $yamlConfigPath -NoNewline -Force
144+
145+
# Remove trailing space on each line
146+
(Get-Content -Path $yamlConfigPath) | ForEach-Object { $_.TrimEnd() } | Set-Content -Path $yamlConfigPath

0 commit comments

Comments
 (0)