Skip to content

Commit 6a15cc3

Browse files
authored
Merge pull request #1326 from microsoftgraph/dev
main refresh
2 parents 90c3f40 + ea62bb7 commit 6a15cc3

File tree

10 files changed

+242
-39
lines changed

10 files changed

+242
-39
lines changed

.azure-pipelines/generation-pipeline.yml

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -805,26 +805,3 @@ stages:
805805
repoName: msgraph-beta-cli
806806
projectFile: src/msgraph-beta-cli.csproj
807807

808-
# - stage: stage_objc_v1
809-
# dependsOn:
810-
# - stage_build_and_publish_typewriter
811-
# - stage_v1_metadata
812-
# condition: |
813-
# and
814-
# (
815-
# eq(dependencies.stage_build_and_publish_typewriter.result, 'Succeeded'),
816-
# in(dependencies.stage_v1_metadata.result, 'Succeeded', 'Skipped')
817-
# )
818-
# jobs:
819-
# - job: objc_v1
820-
# steps:
821-
# - template: generation-templates/language-generation.yml
822-
# parameters:
823-
# language: 'ObjC'
824-
# version: ''
825-
# repoName: 'msgraph-sdk-objc-models'
826-
# branchName: $(v1Branch)
827-
# cleanMetadataFile: $(cleanMetadataFileV1)
828-
# cleanMetadataFolder: $(cleanMetadataFolderV1)
829-
# languageSpecificSteps:
830-
# - template: generation-templates/objc.yml

.azure-pipelines/generation-templates/language-generation-kiota.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,22 @@ steps:
102102
CommitMessagePrefix: ${{ parameters.commitMessagePrefix }}
103103
workingDirectory: ${{ parameters.repoName }}
104104

105+
- task: AzureKeyVault@2
106+
displayName: "Azure Key Vault: Get Secrets"
107+
inputs:
108+
azureSubscription: "Federated AKV Managed Identity Connection"
109+
KeyVaultName: akv-prod-eastus
110+
SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey"
111+
105112
- pwsh: '$(scriptsDirectory)/create-pull-request.ps1'
106-
displayName: 'Create Pull Request for the generated build'
113+
displayName: 'Create Pull Request for the generated build for ${{ parameters.repoName }}'
107114
env:
108-
Version: ${{ parameters.version }}
109115
BaseBranch: ${{ parameters.baseBranchName}}
110-
OverrideSkipCI: $(overrideSkipCI)
111-
GITHUB_TOKEN: $(GithubAuthToken)
112116
GeneratePullRequest: ${{ parameters.generatePullRequest}}
117+
GhAppId: $(microsoft-graph-devx-bot-appid)
118+
GhAppKey: $(microsoft-graph-devx-bot-privatekey)
119+
OverrideSkipCI: $(overrideSkipCI)
120+
RepoName: 'microsoftgraph/${{ parameters.repoName}}' # the assumption is that repo in the microsoftgraph org
121+
ScriptsDirectory: $(scriptsDirectory)
122+
Version: ${{ parameters.version }}
113123
workingDirectory: ${{ parameters.repoName }}

.azure-pipelines/generation-templates/language-generation.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,22 @@ steps:
8080
OverrideSkipCI: $(overrideSkipCI)
8181
workingDirectory: ${{ parameters.repoName }}
8282

83+
- task: AzureKeyVault@2
84+
displayName: "Azure Key Vault: Get Secrets"
85+
inputs:
86+
azureSubscription: "Federated AKV Managed Identity Connection"
87+
KeyVaultName: akv-prod-eastus
88+
SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey"
89+
8390
- pwsh: '$(scriptsDirectory)/create-pull-request.ps1'
84-
displayName: 'Create Pull Request for the generated build'
91+
displayName: 'Create Pull Request for the generated build for ${{ parameters.repoName }}'
8592
env:
86-
Version: ${{ parameters.version }}
8793
BaseBranch: ${{ parameters.baseBranchName}}
88-
OverrideSkipCI: $(overrideSkipCI)
89-
GITHUB_TOKEN: $(GithubAuthToken)
9094
GeneratePullRequest: ${{ parameters.generatePullRequest}}
95+
GhAppId: $(microsoft-graph-devx-bot-appid)
96+
GhAppKey: $(microsoft-graph-devx-bot-privatekey)
97+
OverrideSkipCI: $(overrideSkipCI)
98+
RepoName: 'microsoftgraph/${{ parameters.repoName}}' # the assumption is that repo in the microsoftgraph org
99+
ScriptsDirectory: $(scriptsDirectory)
100+
Version: ${{ parameters.version }}
91101
workingDirectory: ${{ parameters.repoName }}

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
with:
1717
submodules: recursive
1818
- name: Setup .NET
19-
uses: actions/setup-dotnet@v4.2.0
19+
uses: actions/setup-dotnet@v4.3.0
2020
with:
2121
dotnet-version: 8.0.x
2222
- name: Restore dependencies

GraphODataTemplateWriter.Test/GraphODataTemplateWriter.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</Content>
1717
</ItemGroup>
1818
<ItemGroup>
19-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
19+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
2020
<PackageReference Include="MSTest.TestAdapter">
2121
<Version>3.7.1</Version>
2222
</PackageReference>

scripts/Generate-Github-Token.ps1

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
[CmdletBinding()]
2+
param (
3+
[Parameter(Mandatory = $true)]
4+
[string]
5+
$AppClientId,
6+
[Parameter(Mandatory = $true)]
7+
[string]
8+
$AppPrivateKeyContents,
9+
[Parameter(Mandatory = $true)]
10+
[ValidatePattern('^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$', ErrorMessage = "Repository must be in the format 'owner/repo' (e.g. 'octocat/hello-world')")]
11+
[string]
12+
$Repository
13+
)
14+
15+
$ErrorActionPreference = "Stop"
16+
17+
function Generate-AppToken {
18+
param (
19+
[string]
20+
$ClientId,
21+
[string]
22+
$PrivateKeyContents
23+
)
24+
25+
$header = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
26+
alg = "RS256"
27+
typ = "JWT"
28+
}))).TrimEnd('=').Replace('+', '-').Replace('/', '_');
29+
30+
$payload = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
31+
iat = [System.DateTimeOffset]::UtcNow.AddSeconds(-10).ToUnixTimeSeconds()
32+
exp = [System.DateTimeOffset]::UtcNow.AddMinutes(1).ToUnixTimeSeconds()
33+
iss = $ClientId
34+
}))).TrimEnd('=').Replace('+', '-').Replace('/', '_');
35+
36+
$rsa = [System.Security.Cryptography.RSA]::Create()
37+
$rsa.ImportFromPem($PrivateKeyContents)
38+
39+
$signature = [Convert]::ToBase64String($rsa.SignData([System.Text.Encoding]::UTF8.GetBytes("$header.$payload"), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)).TrimEnd('=').Replace('+', '-').Replace('/', '_')
40+
$jwt = "$header.$payload.$signature"
41+
42+
return $jwt
43+
}
44+
45+
function Generate-InstallationToken {
46+
param (
47+
[string]
48+
$AppToken,
49+
[string]
50+
$InstallationId,
51+
[string]
52+
$Repository
53+
)
54+
55+
$uri = "https://api.github.com/app/installations/$InstallationId/access_tokens"
56+
$headers = @{
57+
Authorization = "Bearer $AppToken"
58+
Accept = "application/vnd.github+json"
59+
"X-GitHub-Api-Version" = "2022-11-28"
60+
}
61+
62+
$body = @{
63+
repositories = @($Repository)
64+
}
65+
66+
$response = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body (ConvertTo-Json -InputObject $body -Compress -Depth 10)
67+
68+
return $response.token
69+
}
70+
71+
72+
function Get-OrganizationInstallationId {
73+
param (
74+
[string]
75+
$AppToken,
76+
[string]
77+
$Organization
78+
)
79+
80+
$uri = "https://api.github.com/orgs/$Organization/installation"
81+
$headers = @{
82+
Authorization = "Bearer $AppToken"
83+
Accept = "application/vnd.github+json"
84+
"X-GitHub-Api-Version" = "2022-11-28"
85+
}
86+
87+
try {
88+
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
89+
90+
return $response.id
91+
}
92+
catch [Microsoft.PowerShell.Commands.HttpResponseException] {
93+
if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::UnprocessableContent -or $_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
94+
return $null
95+
}
96+
97+
throw
98+
}
99+
}
100+
101+
function Get-RepositoryInstallationId {
102+
param (
103+
[string]
104+
$AppToken,
105+
[string]
106+
$Repository
107+
)
108+
109+
$uri = "https://api.github.com/repos/$Repository/installation"
110+
$headers = @{
111+
Authorization = "Bearer $AppToken"
112+
Accept = "application/vnd.github+json"
113+
"X-GitHub-Api-Version" = "2022-11-28"
114+
}
115+
116+
try {
117+
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
118+
119+
return $response.id
120+
}
121+
catch [Microsoft.PowerShell.Commands.HttpResponseException] {
122+
if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::UnprocessableContent -or $_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
123+
return $null
124+
}
125+
126+
throw
127+
}
128+
}
129+
130+
function Get-UserInstallationId {
131+
param (
132+
[string]
133+
$AppToken,
134+
[string]
135+
$Username
136+
)
137+
138+
$uri = "https://api.github.com/users/$Username/installation"
139+
$headers = @{
140+
Authorization = "Bearer $AppToken"
141+
Accept = "application/vnd.github+json"
142+
"X-GitHub-Api-Version" = "2022-11-28"
143+
}
144+
145+
try {
146+
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
147+
148+
return $response.id
149+
}
150+
catch [Microsoft.PowerShell.Commands.HttpResponseException] {
151+
if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::UnprocessableContent -or $_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
152+
return $null
153+
}
154+
155+
throw
156+
}
157+
}
158+
159+
function Get-InstallationId {
160+
param (
161+
[string]
162+
$AppToken,
163+
[string]
164+
$Owner,
165+
[string]
166+
$Repo
167+
)
168+
169+
$orgInstallationId = Get-OrganizationInstallationId -AppToken $AppToken -Organization $Owner
170+
171+
if ($null -eq $orgInstallationId) {
172+
$repoInstallationId = Get-RepositoryInstallationId -AppToken $AppToken -Repository "$Owner/$Repo"
173+
}
174+
else {
175+
return $orgInstallationId
176+
}
177+
178+
if ($null -eq $repoInstallationId) {
179+
$userInstallationId = Get-UserInstallationId -AppToken $AppToken -Username $Owner
180+
}
181+
else {
182+
return $repoInstallationId
183+
}
184+
185+
if ($null -eq $userInstallationId) {
186+
throw "Installation not found for repository '$Repo'"
187+
}
188+
else {
189+
return $userInstallationId
190+
}
191+
}
192+
193+
$owner, $repo = $Repository -split '/'
194+
195+
$AppToken = Generate-AppToken -ClientId $AppClientId -PrivateKeyContents $AppPrivateKeyContents
196+
197+
$InstallationId = Get-InstallationId -AppToken $AppToken -Owner $owner -Repo $repo
198+
199+
$InstallationToken = Generate-InstallationToken -AppToken $AppToken -InstallationId $InstallationId -Repository $repo
200+
201+
Write-Output $InstallationToken

scripts/create-pull-request.ps1

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@ if (($env:GeneratePullRequest -eq $False)) { # Skip CI if manually running this
1111

1212
$version = $env:Version
1313
$title = "Generated $version models and request builders"
14-
$body = "This pull request was automatically created by Azure Pipelines. **Important** Check for unexpected deletions or changes in this PR."
14+
$body = ":bangbang:**_Important_**:bangbang: <br> Check for unexpected deletions or changes in this PR and ensure relevant CI checks are passing. <br><br> **Note:** This pull request was automatically created by Azure pipelines."
1515
$baseBranchParameter = ""
1616

1717
if (![string]::IsNullOrEmpty($env:BaseBranch))
1818
{
1919
$baseBranchParameter = "-B $env:BaseBranch" # optionally pass the base branch if provided as the PR will target the default branch otherwise
2020
}
2121

22-
# No need to specify reviewers as code owners should be added automatically.
22+
# The installed application is required to have the following permissions: read/write on pull requests/
23+
$tokenGenerationScript = "$env:ScriptsDirectory\Generate-Github-Token.ps1"
24+
$env:GITHUB_TOKEN = & $tokenGenerationScript -AppClientId $env:GhAppId -AppPrivateKeyContents $env:GhAppKey -Repository $env:RepoName
25+
Write-Host "Fetched Github Token for PR generation and set as environment variable." -ForegroundColor Green
26+
27+
# No need to specify reviewers as code owners should be added automatically.
2328
Invoke-Expression "gh auth login" # login to GitHub
2429
Invoke-Expression "gh pr create -t ""$title"" -b ""$body"" $baseBranchParameter | Write-Host"
2530

src/GraphODataTemplateWriter/GraphODataTemplateWriter.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
</ItemGroup>
3737
<ItemGroup>
3838
<PackageReference Include="Inflector.NetStandard" Version="1.2.2" />
39-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
39+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
4040
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
4141
<PackageReference Include="Mono.TextTemplating">
4242
<Version>3.0.0</Version>

submodules/vipr

test/Typewriter.Test/Typewriter.Test.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
<ProjectReference Include="..\..\Templates\Templates.csproj" />
3838
</ItemGroup>
3939
<ItemGroup>
40-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
40+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
4141
<PackageReference Include="NUnit">
42-
<Version>4.2.2</Version>
42+
<Version>4.3.2</Version>
4343
</PackageReference>
4444
<PackageReference Include="NUnit3TestAdapter">
4545
<Version>4.6.0</Version>

0 commit comments

Comments
 (0)