From b4ce50a69007d6be582510c03843b86896ad9b46 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 20 Jul 2026 05:03:59 +0000 Subject: [PATCH 01/10] Update dependencies from https://github.com/dotnet/arcade build 20260716.5 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26366.5 --- eng/Version.Details.xml | 8 +++---- eng/common/core-templates/job/onelocbuild.yml | 21 ++++++++++++++++++- eng/common/tools.ps1 | 2 +- eng/common/tools.sh | 2 +- global.json | 4 ++-- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6de76751a..31477b0d5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - efce34e9f9f25af27e2b471fbbf8c21f1ac2e318 + b1448f6afdd8d543e6452c293ce99c68c745b200 - + https://github.com/dotnet/arcade - efce34e9f9f25af27e2b471fbbf8c21f1ac2e318 + b1448f6afdd8d543e6452c293ce99c68c745b200 diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index edefa789d..79386ab08 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -8,6 +8,12 @@ parameters: CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex GithubPat: $(BotAccount-dotnet-bot-repo-PAT) + # Service connection for WIF-based Entra authentication to ceapex feeds (replaces CeapexPat). + # When set, dnceng/internal builds acquire a federated Entra token instead of using a PAT. + # All other projects (e.g. DevDiv, public), where this dnceng-scoped service connection does not + # exist, and any pipeline that sets this to '' fall back to PAT-based auth via the CeapexPat parameter. + CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' + SourcesDirectory: $(System.DefaultWorkingDirectory) CreatePr: true AutoCompletePr: false @@ -73,6 +79,16 @@ jobs: displayName: Generate LocProject.json condition: ${{ parameters.condition }} + # Acquire an Entra token for ceapex feed access via WIF (dnceng/internal only). + # All other projects use PAT-based auth, since the ceapex service connection is scoped to dnceng/internal. + - ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + - template: /eng/common/core-templates/steps/get-federated-access-token.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + federatedServiceConnection: ${{ parameters.CeapexServiceConnection }} + outputVariableName: 'CeapexEntraToken' + condition: ${{ parameters.condition }} + - task: OneLocBuild@2 displayName: OneLocBuild env: @@ -89,7 +105,10 @@ jobs: ${{ if eq(parameters.RepoType, 'gitHub') }}: isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth - patVariable: ${{ parameters.CeapexPat }} + ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + patVariable: $(CeapexEntraToken) + ${{ if or(eq(parameters.CeapexServiceConnection, ''), ne(variables['System.TeamProject'], 'internal')) }}: + patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} gitHubPatVariable: "${{ parameters.GithubPat }}" diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index a06513a59..d89aa4878 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -727,7 +727,7 @@ function InitializeToolset() { '' | Set-Content $proj - MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile + MSBuild-Core $proj $bl /t:__WriteToolsetLocation /clp:ErrorsOnly`;NoSummary /p:__ToolsetLocationOutputFile=$toolsetLocationFile /p:RestoreIgnoreFailedSources=true $path = Get-Content $toolsetLocationFile -Encoding UTF8 -TotalCount 1 if (!(Test-Path $path)) { diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 01b09b657..c412703d1 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -410,7 +410,7 @@ function InitializeToolset { fi echo '' > "$proj" - MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" + MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file" /p:RestoreIgnoreFailedSources=true local toolset_build_proj=`cat "$toolset_location_file"` diff --git a/global.json b/global.json index 6fcdaf863..8d880a726 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26301.4", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26301.4" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26366.5", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26366.5" } } From 291f0379d384076d1454b9a0e5cda22bc8029cd0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 27 Jul 2026 05:03:41 +0000 Subject: [PATCH 02/10] Update dependencies from https://github.com/dotnet/arcade build 20260722.8 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26372.8 --- eng/Version.Details.xml | 8 ++++---- global.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 31477b0d5..eac2ac27c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - b1448f6afdd8d543e6452c293ce99c68c745b200 + 16960d68c1325deaabd35f46313462b7c1070545 - + https://github.com/dotnet/arcade - b1448f6afdd8d543e6452c293ce99c68c745b200 + 16960d68c1325deaabd35f46313462b7c1070545 diff --git a/global.json b/global.json index 8d880a726..36f5ae7cb 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26366.5", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26366.5" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26372.8", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26372.8" } } From 6e5e0b3c83d24ddf9908d1c88e26f809eed2bdb0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 3 Aug 2026 05:02:48 +0000 Subject: [PATCH 03/10] Update dependencies from https://github.com/dotnet/arcade build 20260729.3 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26379.3 --- eng/Version.Details.xml | 8 ++++---- eng/common/core-templates/steps/publish-logs.yml | 1 - global.json | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index eac2ac27c..3c8739916 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - 16960d68c1325deaabd35f46313462b7c1070545 + 2e2298e9cdec79ef907be5246d725c97661a946a - + https://github.com/dotnet/arcade - 16960d68c1325deaabd35f46313462b7c1070545 + 2e2298e9cdec79ef907be5246d725c97661a946a diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml index 0623ac6e1..917827999 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -30,7 +30,6 @@ steps: -TokensFilePath '$(System.DefaultWorkingDirectory)/eng/BinlogSecretsRedactionFile.txt' '$(publishing-dnceng-devdiv-code-r-build-re)' '$(MaestroAccessToken)' - '$(dn-bot-all-orgs-artifact-feeds-rw)' '$(akams-client-id)' '$(microsoft-symbol-server-pat)' '$(symweb-symbol-server-pat)' diff --git a/global.json b/global.json index 36f5ae7cb..a2be9fa97 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26372.8", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26372.8" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26379.3", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26379.3" } } From ead6483ae93ee320d39a37c0fafce7febdb5a752 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 10 Aug 2026 05:03:28 +0000 Subject: [PATCH 04/10] Update dependencies from https://github.com/dotnet/arcade build 20260806.11 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26406.11 --- eng/Version.Details.xml | 8 +- eng/common/Get-GitHubAppToken.ps1 | 154 ++++++++++++++++++ eng/common/core-templates/job/onelocbuild.yml | 28 +++- .../job/publish-build-assets.yml | 2 - .../core-templates/jobs/codeql-build.yml | 1 - .../post-build/common-variables.yml | 2 - .../steps/get-github-app-token.yml | 79 +++++++++ .../core-templates/steps/publish-logs.yml | 2 - .../steps/get-github-app-token.yml | 7 + .../templates/steps/get-github-app-token.yml | 7 + global.json | 4 +- 11 files changed, 280 insertions(+), 14 deletions(-) create mode 100644 eng/common/Get-GitHubAppToken.ps1 create mode 100644 eng/common/core-templates/steps/get-github-app-token.yml create mode 100644 eng/common/templates-official/steps/get-github-app-token.yml create mode 100644 eng/common/templates/steps/get-github-app-token.yml diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3c8739916..25b5df468 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - 2e2298e9cdec79ef907be5246d725c97661a946a + f3bffca1f93573c88a7f9b79fac258dff76f6215 - + https://github.com/dotnet/arcade - 2e2298e9cdec79ef907be5246d725c97661a946a + f3bffca1f93573c88a7f9b79fac258dff76f6215 diff --git a/eng/common/Get-GitHubAppToken.ps1 b/eng/common/Get-GitHubAppToken.ps1 new file mode 100644 index 000000000..6b5899d7a --- /dev/null +++ b/eng/common/Get-GitHubAppToken.ps1 @@ -0,0 +1,154 @@ +# Mints a short-lived GitHub App installation access token by signing a JWT +# with a private key stored in Azure Key Vault (RSA, RS256). The signed JWT is +# exchanged with the GitHub API for a token scoped to a single installation. +# +# Requirements: +# - A GitHub App whose private key has been uploaded into Key Vault as an RSA +# key (the PEM converted to a Key Vault *key*, NOT stored as a secret). +# - The caller (the federated Azure service connection used to run this script) +# must have the `Key Vault Crypto User` role (or at minimum the `Sign` +# action) on that key. +# - The App must be installed on the target organization/account +# (`InstallationOwner`) with the permissions/repositories it needs. +# +# Installation tokens (ghs_*) are exempt from the enterprise classic-PAT +# lifetime policy, which is why this replaces the long-lived PAT. + +[CmdletBinding()] +param( + # Name of the Key Vault that holds the GitHub App's RSA signing key. + [Parameter(Mandatory = $true)] + [string] $KeyVaultName, + + # Name of the RSA key inside the Key Vault (the App's private key). + [Parameter(Mandatory = $true)] + [string] $KeyName, + + # The GitHub App's Client ID (the value to put in the `iss` JWT claim). + [Parameter(Mandatory = $true)] + [string] $AppClientId, + + # Login of the organization or user account whose installation we should + # mint the token for (e.g. `dotnet`, `microsoft`). + [Parameter(Mandatory = $true)] + [string] $InstallationOwner, + + # Optional Azure DevOps pipeline variable name to set with the installation + # token (marked as a secret). When not specified, the token is written to + # stdout instead. + [Parameter(Mandatory = $false)] + [string] $OutputVariableName +) + +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +. $PSScriptRoot\pipeline-logging-functions.ps1 + +function ConvertTo-Base64Url([byte[]] $bytes) { + return [Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_') +} + +# Build JWT header and payload. Use [ordered] hashtables so JSON +# serialization is deterministic. +$jwtHeader = [ordered]@{ + alg = 'RS256' + typ = 'JWT' +} +$now = [System.DateTimeOffset]::UtcNow +$jwtPayload = [ordered]@{ + iat = $now.AddMinutes(-1).ToUnixTimeSeconds() + exp = $now.AddMinutes(5).ToUnixTimeSeconds() + iss = $AppClientId +} + +$headerEncoded = ConvertTo-Base64Url ([System.Text.Encoding]::UTF8.GetBytes(($jwtHeader | ConvertTo-Json -Compress))) +$payloadEncoded = ConvertTo-Base64Url ([System.Text.Encoding]::UTF8.GetBytes(($jwtPayload | ConvertTo-Json -Compress))) +$signingInput = "$headerEncoded.$payloadEncoded" + +# Key Vault `sign` expects the *digest* (base64), not the raw bytes. +$sha256 = [System.Security.Cryptography.SHA256]::Create() +$digestBytes = $sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($signingInput)) +$digestBase64 = [Convert]::ToBase64String($digestBytes) + +Write-Host "Signing JWT with key '$KeyName' in vault '$KeyVaultName'..." +$previousNativeCommandErrorPreference = $PSNativeCommandUseErrorActionPreference +try { + # Azure CLI can emit non-fatal Python warnings to stderr even when signing succeeds. + # Use the exit code to determine success for this invocation. + $PSNativeCommandUseErrorActionPreference = $false + $signatureBase64 = az keyvault key sign ` + --vault-name $KeyVaultName ` + --name $KeyName ` + --algorithm RS256 ` + --digest $digestBase64 ` + --query signature ` + --output tsv ` + --only-show-errors + $signExitCode = $LASTEXITCODE +} +catch { + Write-PipelineTelemetryError -Category 'Build' -Message "Failed to sign the JWT via Key Vault (key '$KeyName', vault '$KeyVaultName'): $_. Verify the service connection identity has the 'Key Vault Crypto User' role (Sign action) on the key." + exit 1 +} +finally { + $PSNativeCommandUseErrorActionPreference = $previousNativeCommandErrorPreference +} +if ($signExitCode -ne 0 -or [string]::IsNullOrWhiteSpace($signatureBase64)) { + Write-PipelineTelemetryError -Category 'Build' -Message "'az keyvault key sign' exited with code $signExitCode for key '$KeyName' in vault '$KeyVaultName'. Verify the service connection identity has the 'Key Vault Crypto User' role (Sign action) on the key." + exit 1 +} +$signatureUrl = $signatureBase64.Trim().TrimEnd('=').Replace('+', '-').Replace('/', '_') +$jwt = "$signingInput.$signatureUrl" + +$headers = @{ + Authorization = "Bearer $jwt" + 'X-GitHub-Api-Version' = '2022-11-28' + Accept = 'application/vnd.github+json' + 'User-Agent' = 'dotnet-arcade-onelocbuild' +} + +Write-Host "Looking up installation for '$InstallationOwner'..." +try { + $installations = @() + $page = 1 + do { + $pageInstallations = @(Invoke-RestMethod ` + -Uri "https://api.github.com/app/installations?per_page=100&page=$page" ` + -Headers $headers ` + -Method Get) + $installations += $pageInstallations + $page++ + } while ($pageInstallations.Count -eq 100) +} +catch { + Write-PipelineTelemetryError -Category 'Build' -Message "Failed to list GitHub App installations: $_. The signed JWT may be invalid or the App's Client ID ('$AppClientId') may be incorrect." + exit 1 +} +$installation = $installations | Where-Object { $_.account.login -ieq $InstallationOwner } | Select-Object -First 1 +if (-not $installation) { + $found = ($installations | ForEach-Object { $_.account.login }) -join ', ' + Write-PipelineTelemetryError -Category 'Build' -Message "No installation found for '$InstallationOwner'. App is installed on: $found" + exit 1 +} + +try { + $tokenResponse = Invoke-RestMethod ` + -Uri "https://api.github.com/app/installations/$($installation.id)/access_tokens" ` + -Headers $headers ` + -Method Post ` + -ContentType 'application/json' +} +catch { + Write-PipelineTelemetryError -Category 'Build' -Message "Failed to mint an installation access token for '$InstallationOwner' (installation $($installation.id)): $_" + exit 1 +} + +Write-Host "Got installation token for '$InstallationOwner' (expires $($tokenResponse.expires_at))." +if ($OutputVariableName) { + Write-Host "Setting pipeline variable '$OutputVariableName'." + Write-Host "##vso[task.setvariable variable=$OutputVariableName;issecret=true]$($tokenResponse.token)" +} +else { + Write-Host $tokenResponse.token -ForegroundColor Green +} diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index 79386ab08..d76ed063f 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -14,6 +14,15 @@ parameters: # exist, and any pipeline that sets this to '' fall back to PAT-based auth via the CeapexPat parameter. CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' + # GitHub App authentication for the OneLoc check-in PR (dnceng/internal only). + # The infrastructure identifiers are centralized here and the App path is enabled by default. + # DevDiv requires its own project-scoped service connection before this path can be enabled there. + UseGitHubAppAuthentication: true + GitHubAppServiceConnection: 'dnceng-oneloc-githubapp' + GitHubAppClientId: 'Iv23lijBU8x3gc9lDOc9' + GitHubAppKeyVaultName: 'EngKeyVault' + GitHubAppKeyName: 'oneloc-localization-app-key' + SourcesDirectory: $(System.DefaultWorkingDirectory) CreatePr: true AutoCompletePr: false @@ -89,6 +98,20 @@ jobs: outputVariableName: 'CeapexEntraToken' condition: ${{ parameters.condition }} + # Mint a short-lived GitHub App installation token for the loc check-in PR (dnceng/internal only). + # All other projects fall back to PAT-based auth, since the app service connection is scoped to dnceng/internal. + - ${{ if and(eq(parameters.RepoType, 'gitHub'), eq(parameters.UseGitHubAppAuthentication, true), eq(variables['System.TeamProject'], 'internal')) }}: + - template: /eng/common/core-templates/steps/get-github-app-token.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + azureSubscription: ${{ parameters.GitHubAppServiceConnection }} + keyVaultName: ${{ parameters.GitHubAppKeyVaultName }} + keyName: ${{ parameters.GitHubAppKeyName }} + appClientId: ${{ parameters.GitHubAppClientId }} + installationOwner: ${{ parameters.GitHubOrg }} + outputVariableName: 'GitHubAppInstallationToken' + condition: ${{ parameters.condition }} + - task: OneLocBuild@2 displayName: OneLocBuild env: @@ -111,7 +134,10 @@ jobs: patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} - gitHubPatVariable: "${{ parameters.GithubPat }}" + ${{ if and(eq(parameters.UseGitHubAppAuthentication, true), eq(variables['System.TeamProject'], 'internal')) }}: + gitHubPatVariable: "$(GitHubAppInstallationToken)" + ${{ if or(eq(parameters.UseGitHubAppAuthentication, false), ne(variables['System.TeamProject'], 'internal')) }}: + gitHubPatVariable: "${{ parameters.GithubPat }}" ${{ if ne(parameters.MirrorRepo, '') }}: isMirrorRepoSelected: true gitHubOrganization: ${{ parameters.GitHubOrg }} diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index 3cb20fb50..5a0343f97 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -52,8 +52,6 @@ jobs: parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: Publish-Build-Assets - - group: AzureDevOps-Artifact-Feeds-Pats - name: runCodesignValidationInjection value: false # unconditional - needed for logs publishing (redactor tool version) diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml index 4571a7864..87c2c4c20 100644 --- a/eng/common/core-templates/jobs/codeql-build.yml +++ b/eng/common/core-templates/jobs/codeql-build.yml @@ -19,7 +19,6 @@ jobs: enableTelemetry: true variables: - - group: Publish-Build-Assets # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in # sync with the packages.config file. - name: DefaultGuardianVersion diff --git a/eng/common/core-templates/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml index d5627a994..3413a9a57 100644 --- a/eng/common/core-templates/post-build/common-variables.yml +++ b/eng/common/core-templates/post-build/common-variables.yml @@ -1,6 +1,4 @@ variables: - - group: Publish-Build-Assets - # Whether the build is internal or not - name: IsInternalBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} diff --git a/eng/common/core-templates/steps/get-github-app-token.yml b/eng/common/core-templates/steps/get-github-app-token.yml new file mode 100644 index 000000000..6d42a48d3 --- /dev/null +++ b/eng/common/core-templates/steps/get-github-app-token.yml @@ -0,0 +1,79 @@ +# Mints a short-lived GitHub App installation access token by signing a JWT +# with a private key stored in Azure Key Vault (RSA, RS256). The JWT is +# exchanged with the GitHub API for a token scoped to a single installation. +# +# Requirements (per GitHub App you want to authenticate as): +# - A GitHub App with its private key uploaded into Key Vault as an RSA key +# (PEM converted to a key, NOT stored as a secret). +# - The Azure service connection passed via `azureSubscription` must be +# granted the `Key Vault Crypto User` role (or at minimum `Sign` action) +# on that key. +# - The App must be installed on the target organization/account +# (`installationOwner`) with the permissions/repositories you need. +# +# Output: a secret pipeline variable named ${{ parameters.outputVariableName }} +# containing the installation access token. Token lifetime is ~1 hour and is +# automatically scrubbed from logs. Installation tokens are exempt from the +# enterprise classic-PAT lifetime policy. + +parameters: +# Azure DevOps service connection (federated) that can call +# `az keyvault key sign` on the App's signing key. +- name: azureSubscription + type: string + +# Name of the Key Vault that holds the GitHub App's RSA signing key. +- name: keyVaultName + type: string + +# Name of the RSA key inside the Key Vault (the App's private key). +- name: keyName + type: string + +# The GitHub App's Client ID (the value to put in the `iss` JWT claim). +# Prefer this over the numeric App ID; GitHub accepts either, but Client ID +# is the documented form going forward. +- name: appClientId + type: string + +# Login of the organization or user account whose installation we should +# mint the token for (e.g. `dotnet`, `microsoft`). +- name: installationOwner + type: string + +# Name of the pipeline variable that will receive the installation token. +- name: outputVariableName + type: string + +- name: is1ESPipeline + type: boolean + +- name: stepName + type: string + default: getGitHubAppInstallationToken + +- name: condition + type: string + default: '' + +- name: displayName + type: string + default: Get GitHub App installation token + +steps: +- task: AzureCLI@2 + displayName: ${{ parameters.displayName }} + name: ${{ parameters.stepName }} + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} + inputs: + azureSubscription: ${{ parameters.azureSubscription }} + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + & "$(System.DefaultWorkingDirectory)/eng/common/Get-GitHubAppToken.ps1" ` + -KeyVaultName '${{ parameters.keyVaultName }}' ` + -KeyName '${{ parameters.keyName }}' ` + -AppClientId '${{ parameters.appClientId }}' ` + -InstallationOwner '${{ parameters.installationOwner }}' ` + -OutputVariableName '${{ parameters.outputVariableName }}' diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml index 917827999..f460b24eb 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -28,9 +28,7 @@ steps: arguments: -InputPath '$(System.DefaultWorkingDirectory)/PostBuildLogs' -BinlogToolVersion ${{parameters.BinlogToolVersion}} -TokensFilePath '$(System.DefaultWorkingDirectory)/eng/BinlogSecretsRedactionFile.txt' - '$(publishing-dnceng-devdiv-code-r-build-re)' '$(MaestroAccessToken)' - '$(akams-client-id)' '$(microsoft-symbol-server-pat)' '$(symweb-symbol-server-pat)' '$(dn-bot-all-orgs-build-rw-code-rw)' diff --git a/eng/common/templates-official/steps/get-github-app-token.yml b/eng/common/templates-official/steps/get-github-app-token.yml new file mode 100644 index 000000000..c89f3641a --- /dev/null +++ b/eng/common/templates-official/steps/get-github-app-token.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/get-github-app-token.yml + parameters: + is1ESPipeline: true + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates/steps/get-github-app-token.yml b/eng/common/templates/steps/get-github-app-token.yml new file mode 100644 index 000000000..79e182c64 --- /dev/null +++ b/eng/common/templates/steps/get-github-app-token.yml @@ -0,0 +1,7 @@ +steps: +- template: /eng/common/core-templates/steps/get-github-app-token.yml + parameters: + is1ESPipeline: false + + ${{ each parameter in parameters }}: + ${{ parameter.key }}: ${{ parameter.value }} diff --git a/global.json b/global.json index a2be9fa97..6b2a70920 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26379.3", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26379.3" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26406.11", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26406.11" } } From ef90ab1c8d1fcf0a4d400dba81fcff50ec2a9925 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 17 Aug 2026 05:03:17 +0000 Subject: [PATCH 05/10] Update dependencies from https://github.com/dotnet/arcade build 20260811.5 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26411.5 --- eng/Version.Details.xml | 8 ++++---- eng/common/Get-GitHubAppToken.ps1 | 18 ++++++++++++++---- global.json | 4 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 25b5df468..980041c67 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - f3bffca1f93573c88a7f9b79fac258dff76f6215 + 43f11677d894d27b41fce39c496836c8207f3b8d - + https://github.com/dotnet/arcade - f3bffca1f93573c88a7f9b79fac258dff76f6215 + 43f11677d894d27b41fce39c496836c8207f3b8d diff --git a/eng/common/Get-GitHubAppToken.ps1 b/eng/common/Get-GitHubAppToken.ps1 index 6b5899d7a..9c7e3dcd6 100644 --- a/eng/common/Get-GitHubAppToken.ps1 +++ b/eng/common/Get-GitHubAppToken.ps1 @@ -113,10 +113,13 @@ try { $installations = @() $page = 1 do { - $pageInstallations = @(Invoke-RestMethod ` + # Assign the response before wrapping it in @(). PowerShell otherwise + # preserves a top-level JSON array as one nested pipeline object. + $pageResponse = Invoke-RestMethod ` -Uri "https://api.github.com/app/installations?per_page=100&page=$page" ` -Headers $headers ` - -Method Get) + -Method Get + $pageInstallations = @($pageResponse) $installations += $pageInstallations $page++ } while ($pageInstallations.Count -eq 100) @@ -125,12 +128,19 @@ catch { Write-PipelineTelemetryError -Category 'Build' -Message "Failed to list GitHub App installations: $_. The signed JWT may be invalid or the App's Client ID ('$AppClientId') may be incorrect." exit 1 } -$installation = $installations | Where-Object { $_.account.login -ieq $InstallationOwner } | Select-Object -First 1 -if (-not $installation) { +$matchingInstallations = @($installations | Where-Object { $_.account.login -ieq $InstallationOwner }) +if ($matchingInstallations.Count -eq 0) { $found = ($installations | ForEach-Object { $_.account.login }) -join ', ' Write-PipelineTelemetryError -Category 'Build' -Message "No installation found for '$InstallationOwner'. App is installed on: $found" exit 1 } +if ($matchingInstallations.Count -ne 1) { + $matchingIds = ($matchingInstallations | ForEach-Object { $_.id }) -join ', ' + Write-PipelineTelemetryError -Category 'Build' -Message "Found multiple installations for '$InstallationOwner': $matchingIds" + exit 1 +} +$installation = $matchingInstallations[0] +Write-Host "Using installation $($installation.id) for '$($installation.account.login)'." try { $tokenResponse = Invoke-RestMethod ` diff --git a/global.json b/global.json index 6b2a70920..269072d4a 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26406.11", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26406.11" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26411.5", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26411.5" } } From 8b5bf87d0c068d8a0c1939c56d637f83beee9de1 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 24 Aug 2026 05:04:04 +0000 Subject: [PATCH 06/10] Update dependencies from https://github.com/dotnet/arcade build 20260823.5 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26423.5 --- eng/Version.Details.xml | 8 +++---- eng/common/core-templates/job/onelocbuild.yml | 22 +++++++++++-------- eng/common/sdl/packages.config | 2 +- global.json | 4 ++-- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 980041c67..7aa395895 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - 43f11677d894d27b41fce39c496836c8207f3b8d + d9d97de241d6e2bc5cce12d9e7f54e8d19ca67dc - + https://github.com/dotnet/arcade - 43f11677d894d27b41fce39c496836c8207f3b8d + d9d97de241d6e2bc5cce12d9e7f54e8d19ca67dc diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index d76ed063f..0dd3c8dd2 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -14,10 +14,11 @@ parameters: # exist, and any pipeline that sets this to '' fall back to PAT-based auth via the CeapexPat parameter. CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' - # GitHub App authentication for the OneLoc check-in PR (dnceng/internal only). - # The infrastructure identifiers are centralized here and the App path is enabled by default. - # DevDiv requires its own project-scoped service connection before this path can be enabled there. + # GitHub App authentication for the OneLoc check-in PR. + # dnceng/internal and DevDiv/DevDiv are enabled by default with their project-scoped service + # connections. Other projects must explicitly opt in after provisioning equivalent infrastructure. UseGitHubAppAuthentication: true + UseGitHubAppAuthenticationInOtherProjects: false GitHubAppServiceConnection: 'dnceng-oneloc-githubapp' GitHubAppClientId: 'Iv23lijBU8x3gc9lDOc9' GitHubAppKeyVaultName: 'EngKeyVault' @@ -98,13 +99,16 @@ jobs: outputVariableName: 'CeapexEntraToken' condition: ${{ parameters.condition }} - # Mint a short-lived GitHub App installation token for the loc check-in PR (dnceng/internal only). - # All other projects fall back to PAT-based auth, since the app service connection is scoped to dnceng/internal. - - ${{ if and(eq(parameters.RepoType, 'gitHub'), eq(parameters.UseGitHubAppAuthentication, true), eq(variables['System.TeamProject'], 'internal')) }}: + # Mint a short-lived GitHub App installation token for the loc check-in PR. Use the connection + # provisioned in each supported project; other projects must explicitly opt in and override it. + - ${{ if and(eq(parameters.RepoType, 'gitHub'), eq(parameters.UseGitHubAppAuthentication, true), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'), eq(parameters.UseGitHubAppAuthenticationInOtherProjects, true))) }}: - template: /eng/common/core-templates/steps/get-github-app-token.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} - azureSubscription: ${{ parameters.GitHubAppServiceConnection }} + ${{ if and(eq(variables['System.TeamProject'], 'DevDiv'), eq(parameters.GitHubAppServiceConnection, 'dnceng-oneloc-githubapp')) }}: + azureSubscription: 'devdiv-oneloc-githubapp' + ${{ else }}: + azureSubscription: ${{ parameters.GitHubAppServiceConnection }} keyVaultName: ${{ parameters.GitHubAppKeyVaultName }} keyName: ${{ parameters.GitHubAppKeyName }} appClientId: ${{ parameters.GitHubAppClientId }} @@ -134,9 +138,9 @@ jobs: patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} - ${{ if and(eq(parameters.UseGitHubAppAuthentication, true), eq(variables['System.TeamProject'], 'internal')) }}: + ${{ if and(eq(parameters.UseGitHubAppAuthentication, true), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'), eq(parameters.UseGitHubAppAuthenticationInOtherProjects, true))) }}: gitHubPatVariable: "$(GitHubAppInstallationToken)" - ${{ if or(eq(parameters.UseGitHubAppAuthentication, false), ne(variables['System.TeamProject'], 'internal')) }}: + ${{ else }}: gitHubPatVariable: "${{ parameters.GithubPat }}" ${{ if ne(parameters.MirrorRepo, '') }}: isMirrorRepoSelected: true diff --git a/eng/common/sdl/packages.config b/eng/common/sdl/packages.config index 4585cfd6b..e5f543ea6 100644 --- a/eng/common/sdl/packages.config +++ b/eng/common/sdl/packages.config @@ -1,4 +1,4 @@ - + diff --git a/global.json b/global.json index 269072d4a..4aef3f5a6 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26411.5", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26411.5" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26423.5", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26423.5" } } From ceef80de6e4c2cb5f1495928fe43a7fbe2ca4a1e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 31 Aug 2026 05:03:19 +0000 Subject: [PATCH 07/10] Update dependencies from https://github.com/dotnet/arcade build 20260829.3 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26429.3 --- eng/Version.Details.xml | 8 ++++---- eng/common/core-templates/job/onelocbuild.yml | 14 ++++++-------- global.json | 4 ++-- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7aa395895..f3be0f01c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - d9d97de241d6e2bc5cce12d9e7f54e8d19ca67dc + df7cbf719bdc6a2e6dfc229542a53bf28a8d5180 - + https://github.com/dotnet/arcade - d9d97de241d6e2bc5cce12d9e7f54e8d19ca67dc + df7cbf719bdc6a2e6dfc229542a53bf28a8d5180 diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index 0dd3c8dd2..932fcef64 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -9,9 +9,8 @@ parameters: GithubPat: $(BotAccount-dotnet-bot-repo-PAT) # Service connection for WIF-based Entra authentication to ceapex feeds (replaces CeapexPat). - # When set, dnceng/internal builds acquire a federated Entra token instead of using a PAT. - # All other projects (e.g. DevDiv, public), where this dnceng-scoped service connection does not - # exist, and any pipeline that sets this to '' fall back to PAT-based auth via the CeapexPat parameter. + # dnceng/internal and DevDiv/DevDiv have same-named, project-scoped connections. Other projects, + # and any pipeline that sets this to '', fall back to PAT-based auth via the CeapexPat parameter. CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' # GitHub App authentication for the OneLoc check-in PR. @@ -89,9 +88,8 @@ jobs: displayName: Generate LocProject.json condition: ${{ parameters.condition }} - # Acquire an Entra token for ceapex feed access via WIF (dnceng/internal only). - # All other projects use PAT-based auth, since the ceapex service connection is scoped to dnceng/internal. - - ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + # Acquire an Entra token for ceapex feed access in the supported internal and DevDiv projects. + - ${{ if and(ne(parameters.CeapexServiceConnection, ''), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'))) }}: - template: /eng/common/core-templates/steps/get-federated-access-token.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} @@ -132,9 +130,9 @@ jobs: ${{ if eq(parameters.RepoType, 'gitHub') }}: isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth - ${{ if and(ne(parameters.CeapexServiceConnection, ''), eq(variables['System.TeamProject'], 'internal')) }}: + ${{ if and(ne(parameters.CeapexServiceConnection, ''), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'))) }}: patVariable: $(CeapexEntraToken) - ${{ if or(eq(parameters.CeapexServiceConnection, ''), ne(variables['System.TeamProject'], 'internal')) }}: + ${{ if or(eq(parameters.CeapexServiceConnection, ''), and(ne(variables['System.TeamProject'], 'internal'), ne(variables['System.TeamProject'], 'DevDiv'))) }}: patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} diff --git a/global.json b/global.json index 4aef3f5a6..35e0b0621 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26423.5", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26423.5" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26429.3", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26429.3" } } From 55eeb233abbd2e3ad54ec386a4bd826ee56b4cf6 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 7 Sep 2026 05:03:00 +0000 Subject: [PATCH 08/10] Update dependencies from https://github.com/dotnet/arcade build 20260831.8 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26431.8 --- eng/Version.Details.xml | 8 ++++---- eng/common/Get-GitHubAppToken.ps1 | 13 +++++++------ global.json | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index f3be0f01c..7186e2ba8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - df7cbf719bdc6a2e6dfc229542a53bf28a8d5180 + ee364d8268f86d6a2ab859f6cc82ca6f9d20b31c - + https://github.com/dotnet/arcade - df7cbf719bdc6a2e6dfc229542a53bf28a8d5180 + ee364d8268f86d6a2ab859f6cc82ca6f9d20b31c diff --git a/eng/common/Get-GitHubAppToken.ps1 b/eng/common/Get-GitHubAppToken.ps1 index 9c7e3dcd6..ea776bd6b 100644 --- a/eng/common/Get-GitHubAppToken.ps1 +++ b/eng/common/Get-GitHubAppToken.ps1 @@ -110,19 +110,20 @@ $headers = @{ Write-Host "Looking up installation for '$InstallationOwner'..." try { - $installations = @() + $installations = [System.Collections.Generic.List[object]]::new() $page = 1 do { - # Assign the response before wrapping it in @(). PowerShell otherwise - # preserves a top-level JSON array as one nested pipeline object. $pageResponse = Invoke-RestMethod ` -Uri "https://api.github.com/app/installations?per_page=100&page=$page" ` -Headers $headers ` -Method Get - $pageInstallations = @($pageResponse) - $installations += $pageInstallations + $pageInstallationCount = 0 + foreach ($installation in $pageResponse) { + $installations.Add($installation) + $pageInstallationCount++ + } $page++ - } while ($pageInstallations.Count -eq 100) + } while ($pageInstallationCount -eq 100) } catch { Write-PipelineTelemetryError -Category 'Build' -Message "Failed to list GitHub App installations: $_. The signed JWT may be invalid or the App's Client ID ('$AppClientId') may be incorrect." diff --git a/global.json b/global.json index 35e0b0621..c54686d05 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26429.3", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26429.3" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26431.8", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26431.8" } } From 6a9e5d98adf89a9cee07631eb3af060b2ae07b6a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 14 Sep 2026 05:04:03 +0000 Subject: [PATCH 09/10] Update dependencies from https://github.com/dotnet/arcade build 20260908.10 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26458.10 --- eng/Version.Details.xml | 8 ++-- eng/common/core-templates/job/onelocbuild.yml | 46 +++++++------------ global.json | 4 +- 3 files changed, 22 insertions(+), 36 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7186e2ba8..d920d5c81 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - ee364d8268f86d6a2ab859f6cc82ca6f9d20b31c + c11157d174c111c4ab316dc60ff53311e410ef97 - + https://github.com/dotnet/arcade - ee364d8268f86d6a2ab859f6cc82ca6f9d20b31c + c11157d174c111c4ab316dc60ff53311e410ef97 diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index 932fcef64..ea590495f 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -5,19 +5,10 @@ parameters: # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool pool: '' - CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex - GithubPat: $(BotAccount-dotnet-bot-repo-PAT) - - # Service connection for WIF-based Entra authentication to ceapex feeds (replaces CeapexPat). - # dnceng/internal and DevDiv/DevDiv have same-named, project-scoped connections. Other projects, - # and any pipeline that sets this to '', fall back to PAT-based auth via the CeapexPat parameter. + # Project-scoped WIF service connection for Ceapex feed authentication. CeapexServiceConnection: 'dnceng-onelocbuild-ceapex' # GitHub App authentication for the OneLoc check-in PR. - # dnceng/internal and DevDiv/DevDiv are enabled by default with their project-scoped service - # connections. Other projects must explicitly opt in after provisioning equivalent infrastructure. - UseGitHubAppAuthentication: true - UseGitHubAppAuthenticationInOtherProjects: false GitHubAppServiceConnection: 'dnceng-oneloc-githubapp' GitHubAppClientId: 'Iv23lijBU8x3gc9lDOc9' GitHubAppKeyVaultName: 'EngKeyVault' @@ -48,7 +39,6 @@ jobs: displayName: OneLocBuild${{ parameters.JobNameSuffix }} variables: - - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat - name: _GenerateLocProjectArguments value: -SourcesDirectory ${{ parameters.SourcesDirectory }} -LanguageSet "${{ parameters.LanguageSet }}" @@ -79,6 +69,10 @@ jobs: steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error + - ${{ if notIn(variables['System.TeamProject'], 'internal', 'DevDiv') }}: + - 'OneLocBuild is supported only in dnceng/internal and DevDiv/DevDiv.': error + - ${{ if eq(parameters.CeapexServiceConnection, '') }}: + - 'CeapexServiceConnection must identify a WIF service connection.': error - ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}: - task: Powershell@2 @@ -88,18 +82,16 @@ jobs: displayName: Generate LocProject.json condition: ${{ parameters.condition }} - # Acquire an Entra token for ceapex feed access in the supported internal and DevDiv projects. - - ${{ if and(ne(parameters.CeapexServiceConnection, ''), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'))) }}: - - template: /eng/common/core-templates/steps/get-federated-access-token.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} - federatedServiceConnection: ${{ parameters.CeapexServiceConnection }} - outputVariableName: 'CeapexEntraToken' - condition: ${{ parameters.condition }} + # Acquire a short-lived Entra token for Ceapex feed access. + - template: /eng/common/core-templates/steps/get-federated-access-token.yml + parameters: + is1ESPipeline: ${{ parameters.is1ESPipeline }} + federatedServiceConnection: ${{ parameters.CeapexServiceConnection }} + outputVariableName: 'CeapexEntraToken' + condition: ${{ parameters.condition }} - # Mint a short-lived GitHub App installation token for the loc check-in PR. Use the connection - # provisioned in each supported project; other projects must explicitly opt in and override it. - - ${{ if and(eq(parameters.RepoType, 'gitHub'), eq(parameters.UseGitHubAppAuthentication, true), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'), eq(parameters.UseGitHubAppAuthenticationInOtherProjects, true))) }}: + # Mint a short-lived GitHub App installation token for the loc check-in PR. + - ${{ if eq(parameters.RepoType, 'gitHub') }}: - template: /eng/common/core-templates/steps/get-github-app-token.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} @@ -130,16 +122,10 @@ jobs: ${{ if eq(parameters.RepoType, 'gitHub') }}: isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth - ${{ if and(ne(parameters.CeapexServiceConnection, ''), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'))) }}: - patVariable: $(CeapexEntraToken) - ${{ if or(eq(parameters.CeapexServiceConnection, ''), and(ne(variables['System.TeamProject'], 'internal'), ne(variables['System.TeamProject'], 'DevDiv'))) }}: - patVariable: ${{ parameters.CeapexPat }} + patVariable: $(CeapexEntraToken) ${{ if eq(parameters.RepoType, 'gitHub') }}: repoType: ${{ parameters.RepoType }} - ${{ if and(eq(parameters.UseGitHubAppAuthentication, true), or(eq(variables['System.TeamProject'], 'internal'), eq(variables['System.TeamProject'], 'DevDiv'), eq(parameters.UseGitHubAppAuthenticationInOtherProjects, true))) }}: - gitHubPatVariable: "$(GitHubAppInstallationToken)" - ${{ else }}: - gitHubPatVariable: "${{ parameters.GithubPat }}" + gitHubPatVariable: "$(GitHubAppInstallationToken)" ${{ if ne(parameters.MirrorRepo, '') }}: isMirrorRepoSelected: true gitHubOrganization: ${{ parameters.GitHubOrg }} diff --git a/global.json b/global.json index c54686d05..7cc16d73d 100644 --- a/global.json +++ b/global.json @@ -3,7 +3,7 @@ "dotnet": "9.0.116" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26431.8", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26431.8" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26458.10", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26458.10" } } From e901c46dcadac7e4003d29e3f38ac0b418148f70 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 21 Sep 2026 05:04:52 +0000 Subject: [PATCH 10/10] Update dependencies from https://github.com/dotnet/arcade build 20260918.4 On relative base path root Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 9.0.0-beta.26301.4 -> To Version 9.0.0-beta.26468.4 --- eng/Version.Details.xml | 8 ++-- eng/common/core-templates/job/job.yml | 3 +- .../core-templates/steps/send-to-helix.yml | 46 +++++++++++++++++-- global.json | 6 +-- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d920d5c81..bb9d22e0f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,13 +3,13 @@ - + https://github.com/dotnet/arcade - c11157d174c111c4ab316dc60ff53311e410ef97 + d23725174e27de790e188bbce48fc190c569da5b - + https://github.com/dotnet/arcade - c11157d174c111c4ab316dc60ff53311e410ef97 + d23725174e27de790e188bbce48fc190c569da5b diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml index 8da43d3b5..b0020eb39 100644 --- a/eng/common/core-templates/job/job.yml +++ b/eng/common/core-templates/job/job.yml @@ -112,7 +112,8 @@ jobs: - name: ${{ pair.key }} value: ${{ pair.value }} - # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds + # DotNet-HelixApi-Access provides 'HelixApiAccessToken' for internal builds. + # Entra-enabled Helix templates do not forward this value to their processes. - ${{ if and(eq(parameters.enableTelemetry, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - group: DotNet-HelixApi-Access diff --git a/eng/common/core-templates/steps/send-to-helix.yml b/eng/common/core-templates/steps/send-to-helix.yml index 68fa739c4..49e59b13f 100644 --- a/eng/common/core-templates/steps/send-to-helix.yml +++ b/eng/common/core-templates/steps/send-to-helix.yml @@ -4,7 +4,9 @@ parameters: HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues - HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixAccessToken: '' # optional -- legacy access token; not forwarded when HelixUseEntraAuthentication is true + HelixUseEntraAuthentication: false # optional -- use refreshable Entra authentication instead of a PAT or anonymous access + HelixAzureSubscription: '' # required when HelixUseEntraAuthentication is true -- Azure service connection ID authorized for Helix HelixProjectPath: 'eng/common/helixpublish.proj' # optional -- path to the project file to build relative to BUILD_SOURCESDIRECTORY HelixProjectArguments: '' # optional -- arguments passed to the build command HelixConfiguration: '' # optional -- additional property attached to a job @@ -31,7 +33,31 @@ parameters: continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false steps: - - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' + - ${{ if and(eq(parameters.HelixUseEntraAuthentication, true), eq(parameters.HelixAzureSubscription, '')) }}: + - pwsh: throw "HelixAzureSubscription must be set when HelixUseEntraAuthentication is true." + displayName: Validate Helix Entra authentication + condition: ${{ parameters.condition }} + + - ${{ if eq(parameters.HelixUseEntraAuthentication, true) }}: + - task: AzureCLI@2 + displayName: Read Helix Entra service connection + inputs: + azureSubscription: ${{ parameters.HelixAzureSubscription }} + addSpnToEnvironment: true + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + if ([string]::IsNullOrWhiteSpace($env:servicePrincipalId) -or [string]::IsNullOrWhiteSpace($env:tenantId)) { + throw "The Helix Azure service connection did not provide a service principal or tenant ID." + } + + # The SDK uses these values with System.AccessToken and System.OidcRequestUri + # to construct AzurePipelinesCredential in the subsequent MSBuild process. + Write-Host "##vso[task.setvariable variable=HelixEntraClientId]$env:servicePrincipalId" + Write-Host "##vso[task.setvariable variable=HelixEntraTenantId]$env:tenantId" + condition: ${{ parameters.condition }} + + - powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 $env:BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false /p:HelixUseEntraAuthentication=${{ parameters.HelixUseEntraAuthentication }} ${{ parameters.HelixProjectArguments }} /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"' displayName: ${{ parameters.DisplayNamePrefix }} (Windows) env: BuildConfig: $(_BuildConfig) @@ -40,7 +66,12 @@ steps: HelixBuild: ${{ parameters.HelixBuild }} HelixConfiguration: ${{ parameters.HelixConfiguration }} HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} + ${{ if eq(parameters.HelixUseEntraAuthentication, false) }}: + HelixAccessToken: ${{ parameters.HelixAccessToken }} + ${{ if eq(parameters.HelixUseEntraAuthentication, true) }}: + AZURESUBSCRIPTION_CLIENT_ID: $(HelixEntraClientId) + AZURESUBSCRIPTION_TENANT_ID: $(HelixEntraTenantId) + AZURESUBSCRIPTION_SERVICE_CONNECTION_ID: ${{ parameters.HelixAzureSubscription }} HelixPreCommands: ${{ parameters.HelixPreCommands }} HelixPostCommands: ${{ parameters.HelixPostCommands }} WorkItemDirectory: ${{ parameters.WorkItemDirectory }} @@ -61,7 +92,7 @@ steps: SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/${{ parameters.HelixProjectPath }} /restore /p:TreatWarningsAsErrors=false /p:HelixUseEntraAuthentication=${{ parameters.HelixUseEntraAuthentication }} ${{ parameters.HelixProjectArguments }} /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog displayName: ${{ parameters.DisplayNamePrefix }} (Unix) env: BuildConfig: $(_BuildConfig) @@ -70,7 +101,12 @@ steps: HelixBuild: ${{ parameters.HelixBuild }} HelixConfiguration: ${{ parameters.HelixConfiguration }} HelixTargetQueues: ${{ parameters.HelixTargetQueues }} - HelixAccessToken: ${{ parameters.HelixAccessToken }} + ${{ if eq(parameters.HelixUseEntraAuthentication, false) }}: + HelixAccessToken: ${{ parameters.HelixAccessToken }} + ${{ if eq(parameters.HelixUseEntraAuthentication, true) }}: + AZURESUBSCRIPTION_CLIENT_ID: $(HelixEntraClientId) + AZURESUBSCRIPTION_TENANT_ID: $(HelixEntraTenantId) + AZURESUBSCRIPTION_SERVICE_CONNECTION_ID: ${{ parameters.HelixAzureSubscription }} HelixPreCommands: ${{ parameters.HelixPreCommands }} HelixPostCommands: ${{ parameters.HelixPostCommands }} WorkItemDirectory: ${{ parameters.WorkItemDirectory }} diff --git a/global.json b/global.json index 7cc16d73d..17835ede2 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "tools": { - "dotnet": "9.0.116" + "dotnet": "9.0.121" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26458.10", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26458.10" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26468.4", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26468.4" } }