diff --git a/.azure-pipelines/generation-pipeline.yml b/.azure-pipelines/generation-pipeline.yml
index 9857e7b82..0ec8a4b0f 100644
--- a/.azure-pipelines/generation-pipeline.yml
+++ b/.azure-pipelines/generation-pipeline.yml
@@ -805,26 +805,3 @@ stages:
repoName: msgraph-beta-cli
projectFile: src/msgraph-beta-cli.csproj
-# - stage: stage_objc_v1
-# dependsOn:
-# - stage_build_and_publish_typewriter
-# - stage_v1_metadata
-# condition: |
-# and
-# (
-# eq(dependencies.stage_build_and_publish_typewriter.result, 'Succeeded'),
-# in(dependencies.stage_v1_metadata.result, 'Succeeded', 'Skipped')
-# )
-# jobs:
-# - job: objc_v1
-# steps:
-# - template: generation-templates/language-generation.yml
-# parameters:
-# language: 'ObjC'
-# version: ''
-# repoName: 'msgraph-sdk-objc-models'
-# branchName: $(v1Branch)
-# cleanMetadataFile: $(cleanMetadataFileV1)
-# cleanMetadataFolder: $(cleanMetadataFolderV1)
-# languageSpecificSteps:
-# - template: generation-templates/objc.yml
diff --git a/.azure-pipelines/generation-templates/language-generation-kiota.yml b/.azure-pipelines/generation-templates/language-generation-kiota.yml
index ed89366e5..23af8f8e9 100644
--- a/.azure-pipelines/generation-templates/language-generation-kiota.yml
+++ b/.azure-pipelines/generation-templates/language-generation-kiota.yml
@@ -102,12 +102,22 @@ steps:
CommitMessagePrefix: ${{ parameters.commitMessagePrefix }}
workingDirectory: ${{ parameters.repoName }}
+- task: AzureKeyVault@2
+ displayName: "Azure Key Vault: Get Secrets"
+ inputs:
+ azureSubscription: "Federated AKV Managed Identity Connection"
+ KeyVaultName: akv-prod-eastus
+ SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey"
+
- pwsh: '$(scriptsDirectory)/create-pull-request.ps1'
- displayName: 'Create Pull Request for the generated build'
+ displayName: 'Create Pull Request for the generated build for ${{ parameters.repoName }}'
env:
- Version: ${{ parameters.version }}
BaseBranch: ${{ parameters.baseBranchName}}
- OverrideSkipCI: $(overrideSkipCI)
- GITHUB_TOKEN: $(GithubAuthToken)
GeneratePullRequest: ${{ parameters.generatePullRequest}}
+ GhAppId: $(microsoft-graph-devx-bot-appid)
+ GhAppKey: $(microsoft-graph-devx-bot-privatekey)
+ OverrideSkipCI: $(overrideSkipCI)
+ RepoName: 'microsoftgraph/${{ parameters.repoName}}' # the assumption is that repo in the microsoftgraph org
+ ScriptsDirectory: $(scriptsDirectory)
+ Version: ${{ parameters.version }}
workingDirectory: ${{ parameters.repoName }}
diff --git a/.azure-pipelines/generation-templates/language-generation.yml b/.azure-pipelines/generation-templates/language-generation.yml
index b184420f2..0d7aa4757 100644
--- a/.azure-pipelines/generation-templates/language-generation.yml
+++ b/.azure-pipelines/generation-templates/language-generation.yml
@@ -80,12 +80,22 @@ steps:
OverrideSkipCI: $(overrideSkipCI)
workingDirectory: ${{ parameters.repoName }}
+- task: AzureKeyVault@2
+ displayName: "Azure Key Vault: Get Secrets"
+ inputs:
+ azureSubscription: "Federated AKV Managed Identity Connection"
+ KeyVaultName: akv-prod-eastus
+ SecretsFilter: "microsoft-graph-devx-bot-appid,microsoft-graph-devx-bot-privatekey"
+
- pwsh: '$(scriptsDirectory)/create-pull-request.ps1'
- displayName: 'Create Pull Request for the generated build'
+ displayName: 'Create Pull Request for the generated build for ${{ parameters.repoName }}'
env:
- Version: ${{ parameters.version }}
BaseBranch: ${{ parameters.baseBranchName}}
- OverrideSkipCI: $(overrideSkipCI)
- GITHUB_TOKEN: $(GithubAuthToken)
GeneratePullRequest: ${{ parameters.generatePullRequest}}
+ GhAppId: $(microsoft-graph-devx-bot-appid)
+ GhAppKey: $(microsoft-graph-devx-bot-privatekey)
+ OverrideSkipCI: $(overrideSkipCI)
+ RepoName: 'microsoftgraph/${{ parameters.repoName}}' # the assumption is that repo in the microsoftgraph org
+ ScriptsDirectory: $(scriptsDirectory)
+ Version: ${{ parameters.version }}
workingDirectory: ${{ parameters.repoName }}
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index b2b2f7bcb..224d4f7d3 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -16,7 +16,7 @@ jobs:
with:
submodules: recursive
- name: Setup .NET
- uses: actions/setup-dotnet@v4.2.0
+ uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: 8.0.x
- name: Restore dependencies
diff --git a/GraphODataTemplateWriter.Test/GraphODataTemplateWriter.Test.csproj b/GraphODataTemplateWriter.Test/GraphODataTemplateWriter.Test.csproj
index 5ab1c034e..bd65ad134 100644
--- a/GraphODataTemplateWriter.Test/GraphODataTemplateWriter.Test.csproj
+++ b/GraphODataTemplateWriter.Test/GraphODataTemplateWriter.Test.csproj
@@ -16,7 +16,7 @@
-
+
3.7.1
diff --git a/scripts/Generate-Github-Token.ps1 b/scripts/Generate-Github-Token.ps1
new file mode 100644
index 000000000..0b1c04160
--- /dev/null
+++ b/scripts/Generate-Github-Token.ps1
@@ -0,0 +1,201 @@
+[CmdletBinding()]
+param (
+ [Parameter(Mandatory = $true)]
+ [string]
+ $AppClientId,
+ [Parameter(Mandatory = $true)]
+ [string]
+ $AppPrivateKeyContents,
+ [Parameter(Mandatory = $true)]
+ [ValidatePattern('^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$', ErrorMessage = "Repository must be in the format 'owner/repo' (e.g. 'octocat/hello-world')")]
+ [string]
+ $Repository
+)
+
+$ErrorActionPreference = "Stop"
+
+function Generate-AppToken {
+ param (
+ [string]
+ $ClientId,
+ [string]
+ $PrivateKeyContents
+ )
+
+ $header = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
+ alg = "RS256"
+ typ = "JWT"
+ }))).TrimEnd('=').Replace('+', '-').Replace('/', '_');
+
+ $payload = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
+ iat = [System.DateTimeOffset]::UtcNow.AddSeconds(-10).ToUnixTimeSeconds()
+ exp = [System.DateTimeOffset]::UtcNow.AddMinutes(1).ToUnixTimeSeconds()
+ iss = $ClientId
+ }))).TrimEnd('=').Replace('+', '-').Replace('/', '_');
+
+ $rsa = [System.Security.Cryptography.RSA]::Create()
+ $rsa.ImportFromPem($PrivateKeyContents)
+
+ $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('/', '_')
+ $jwt = "$header.$payload.$signature"
+
+ return $jwt
+}
+
+function Generate-InstallationToken {
+ param (
+ [string]
+ $AppToken,
+ [string]
+ $InstallationId,
+ [string]
+ $Repository
+ )
+
+ $uri = "https://api.github.com/app/installations/$InstallationId/access_tokens"
+ $headers = @{
+ Authorization = "Bearer $AppToken"
+ Accept = "application/vnd.github+json"
+ "X-GitHub-Api-Version" = "2022-11-28"
+ }
+
+ $body = @{
+ repositories = @($Repository)
+ }
+
+ $response = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body (ConvertTo-Json -InputObject $body -Compress -Depth 10)
+
+ return $response.token
+}
+
+
+function Get-OrganizationInstallationId {
+ param (
+ [string]
+ $AppToken,
+ [string]
+ $Organization
+ )
+
+ $uri = "https://api.github.com/orgs/$Organization/installation"
+ $headers = @{
+ Authorization = "Bearer $AppToken"
+ Accept = "application/vnd.github+json"
+ "X-GitHub-Api-Version" = "2022-11-28"
+ }
+
+ try {
+ $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
+
+ return $response.id
+ }
+ catch [Microsoft.PowerShell.Commands.HttpResponseException] {
+ if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::UnprocessableContent -or $_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
+ return $null
+ }
+
+ throw
+ }
+}
+
+function Get-RepositoryInstallationId {
+ param (
+ [string]
+ $AppToken,
+ [string]
+ $Repository
+ )
+
+ $uri = "https://api.github.com/repos/$Repository/installation"
+ $headers = @{
+ Authorization = "Bearer $AppToken"
+ Accept = "application/vnd.github+json"
+ "X-GitHub-Api-Version" = "2022-11-28"
+ }
+
+ try {
+ $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
+
+ return $response.id
+ }
+ catch [Microsoft.PowerShell.Commands.HttpResponseException] {
+ if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::UnprocessableContent -or $_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
+ return $null
+ }
+
+ throw
+ }
+}
+
+function Get-UserInstallationId {
+ param (
+ [string]
+ $AppToken,
+ [string]
+ $Username
+ )
+
+ $uri = "https://api.github.com/users/$Username/installation"
+ $headers = @{
+ Authorization = "Bearer $AppToken"
+ Accept = "application/vnd.github+json"
+ "X-GitHub-Api-Version" = "2022-11-28"
+ }
+
+ try {
+ $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
+
+ return $response.id
+ }
+ catch [Microsoft.PowerShell.Commands.HttpResponseException] {
+ if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::UnprocessableContent -or $_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotFound) {
+ return $null
+ }
+
+ throw
+ }
+}
+
+function Get-InstallationId {
+ param (
+ [string]
+ $AppToken,
+ [string]
+ $Owner,
+ [string]
+ $Repo
+ )
+
+ $orgInstallationId = Get-OrganizationInstallationId -AppToken $AppToken -Organization $Owner
+
+ if ($null -eq $orgInstallationId) {
+ $repoInstallationId = Get-RepositoryInstallationId -AppToken $AppToken -Repository "$Owner/$Repo"
+ }
+ else {
+ return $orgInstallationId
+ }
+
+ if ($null -eq $repoInstallationId) {
+ $userInstallationId = Get-UserInstallationId -AppToken $AppToken -Username $Owner
+ }
+ else {
+ return $repoInstallationId
+ }
+
+ if ($null -eq $userInstallationId) {
+ throw "Installation not found for repository '$Repo'"
+ }
+ else {
+ return $userInstallationId
+ }
+}
+
+$owner, $repo = $Repository -split '/'
+
+$AppToken = Generate-AppToken -ClientId $AppClientId -PrivateKeyContents $AppPrivateKeyContents
+
+$InstallationId = Get-InstallationId -AppToken $AppToken -Owner $owner -Repo $repo
+
+$InstallationToken = Generate-InstallationToken -AppToken $AppToken -InstallationId $InstallationId -Repository $repo
+
+Write-Output $InstallationToken
\ No newline at end of file
diff --git a/scripts/create-pull-request.ps1 b/scripts/create-pull-request.ps1
index e8af62fbc..3478a084a 100644
--- a/scripts/create-pull-request.ps1
+++ b/scripts/create-pull-request.ps1
@@ -11,7 +11,7 @@ if (($env:GeneratePullRequest -eq $False)) { # Skip CI if manually running this
$version = $env:Version
$title = "Generated $version models and request builders"
-$body = "This pull request was automatically created by Azure Pipelines. **Important** Check for unexpected deletions or changes in this PR."
+$body = ":bangbang:**_Important_**:bangbang:
Check for unexpected deletions or changes in this PR and ensure relevant CI checks are passing.
**Note:** This pull request was automatically created by Azure pipelines."
$baseBranchParameter = ""
if (![string]::IsNullOrEmpty($env:BaseBranch))
@@ -19,7 +19,12 @@ if (![string]::IsNullOrEmpty($env:BaseBranch))
$baseBranchParameter = "-B $env:BaseBranch" # optionally pass the base branch if provided as the PR will target the default branch otherwise
}
- # No need to specify reviewers as code owners should be added automatically.
+# The installed application is required to have the following permissions: read/write on pull requests/
+$tokenGenerationScript = "$env:ScriptsDirectory\Generate-Github-Token.ps1"
+$env:GITHUB_TOKEN = & $tokenGenerationScript -AppClientId $env:GhAppId -AppPrivateKeyContents $env:GhAppKey -Repository $env:RepoName
+Write-Host "Fetched Github Token for PR generation and set as environment variable." -ForegroundColor Green
+
+# No need to specify reviewers as code owners should be added automatically.
Invoke-Expression "gh auth login" # login to GitHub
Invoke-Expression "gh pr create -t ""$title"" -b ""$body"" $baseBranchParameter | Write-Host"
diff --git a/src/GraphODataTemplateWriter/GraphODataTemplateWriter.csproj b/src/GraphODataTemplateWriter/GraphODataTemplateWriter.csproj
index b7f7e684c..7d1e23bab 100644
--- a/src/GraphODataTemplateWriter/GraphODataTemplateWriter.csproj
+++ b/src/GraphODataTemplateWriter/GraphODataTemplateWriter.csproj
@@ -36,7 +36,7 @@
-
+
3.0.0
diff --git a/submodules/vipr b/submodules/vipr
index 6c62ff0ea..834d1a8af 160000
--- a/submodules/vipr
+++ b/submodules/vipr
@@ -1 +1 @@
-Subproject commit 6c62ff0ea3147062bb12888ee7dded395e867c69
+Subproject commit 834d1a8af3375f5ef98990e47c26a369666e87f5
diff --git a/test/Typewriter.Test/Typewriter.Test.csproj b/test/Typewriter.Test/Typewriter.Test.csproj
index ce7f26e29..e125ea93f 100644
--- a/test/Typewriter.Test/Typewriter.Test.csproj
+++ b/test/Typewriter.Test/Typewriter.Test.csproj
@@ -37,9 +37,9 @@
-
+
- 4.2.2
+ 4.3.2
4.6.0