Skip to content

Commit 66201e9

Browse files
dotnet-maestro[bot]matouskozakCopilot
authored
[main] Update dependencies from dotnet/arcade (#7713)
This pull request updates the following dependencies [marker]: <> (Begin:c692823c-b896-437f-4f57-08dc434cc8f6) ## From https://github.com/dotnet/arcade - **Subscription**: [c692823c-b896-437f-4f57-08dc434cc8f6](https://maestro.dot.net/subscriptions?search=c692823c-b896-437f-4f57-08dc434cc8f6) - **Build**: [20260919.3](https://dev.azure.com/dnceng/internal/_build/results?buildId=3081466) ([332877](https://maestro.dot.net/channel/2/github:dotnet:arcade/build/332877)) - **Date Produced**: September 19, 2026 7:28:49 PM UTC - **Commit**: [63c79a28ca6e086d59c5553e7ed69cacb1d52fbd](dotnet/arcade@63c79a2) - **Branch**: [main](https://github.com/dotnet/arcade/tree/main) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [11.0.0-beta.26456.1 to 12.0.0-beta.26469.3][2] - Microsoft.DotNet.Arcade.Sdk - Microsoft.DotNet.Build.Tasks.Feed - Microsoft.DotNet.Helix.Sdk - Microsoft.DotNet.SignTool - Microsoft.DotNet.XliffTasks - Microsoft.DotNet.XUnitExtensions [2]: dotnet/arcade@66b75e6...63c79a2 [DependencyUpdate]: <> (End) [marker]: <> (End:c692823c-b896-437f-4f57-08dc434cc8f6) --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: Matous Kozak <matouskozak@seznam.cz> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 2187401 commit 66201e9

17 files changed

Lines changed: 363 additions & 135 deletions

‎eng/Version.Details.xml‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,34 @@
77
</Dependency>
88
</ProductDependencies>
99
<ToolsetDependencies>
10-
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="11.0.0-beta.26456.1">
10+
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="12.0.0-beta.26469.3">
1111
<Uri>https://github.com/dotnet/arcade</Uri>
12-
<Sha>66b75e61d883abd9e3af86a811c3809a8d9142ca</Sha>
12+
<Sha>63c79a28ca6e086d59c5553e7ed69cacb1d52fbd</Sha>
1313
</Dependency>
14-
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="11.0.0-beta.26456.1">
14+
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="12.0.0-beta.26469.3">
1515
<Uri>https://github.com/dotnet/arcade</Uri>
16-
<Sha>66b75e61d883abd9e3af86a811c3809a8d9142ca</Sha>
16+
<Sha>63c79a28ca6e086d59c5553e7ed69cacb1d52fbd</Sha>
1717
</Dependency>
18-
<Dependency Name="Microsoft.DotNet.SignTool" Version="11.0.0-beta.26456.1">
18+
<Dependency Name="Microsoft.DotNet.SignTool" Version="12.0.0-beta.26469.3">
1919
<Uri>https://github.com/dotnet/arcade</Uri>
20-
<Sha>66b75e61d883abd9e3af86a811c3809a8d9142ca</Sha>
20+
<Sha>63c79a28ca6e086d59c5553e7ed69cacb1d52fbd</Sha>
2121
</Dependency>
22-
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="11.0.0-beta.26456.1">
22+
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="12.0.0-beta.26469.3">
2323
<Uri>https://github.com/dotnet/arcade</Uri>
24-
<Sha>66b75e61d883abd9e3af86a811c3809a8d9142ca</Sha>
24+
<Sha>63c79a28ca6e086d59c5553e7ed69cacb1d52fbd</Sha>
2525
</Dependency>
2626
<!-- Stay on package 8.0 until we stop testing for net6.0
2727
<Dependency Name="Microsoft.DotNet.RemoteExecutor" Version="9.0.0-beta.24212.4">
2828
<Uri>https://github.com/dotnet/arcade</Uri>
2929
<Sha>812d978c303174dc1aa305d7359e79053d7d4971</Sha>
3030
</Dependency> -->
31-
<Dependency Name="Microsoft.DotNet.XUnitExtensions" Version="11.0.0-beta.26456.1">
31+
<Dependency Name="Microsoft.DotNet.XUnitExtensions" Version="12.0.0-beta.26469.3">
3232
<Uri>https://github.com/dotnet/arcade</Uri>
33-
<Sha>66b75e61d883abd9e3af86a811c3809a8d9142ca</Sha>
33+
<Sha>63c79a28ca6e086d59c5553e7ed69cacb1d52fbd</Sha>
3434
</Dependency>
35-
<Dependency Name="Microsoft.DotNet.XliffTasks" Version="11.0.0-beta.26456.1">
35+
<Dependency Name="Microsoft.DotNet.XliffTasks" Version="12.0.0-beta.26469.3">
3636
<Uri>https://github.com/dotnet/arcade</Uri>
37-
<Sha>66b75e61d883abd9e3af86a811c3809a8d9142ca</Sha>
37+
<Sha>63c79a28ca6e086d59c5553e7ed69cacb1d52fbd</Sha>
3838
</Dependency>
3939
</ToolsetDependencies>
4040
</Dependencies>

‎eng/Versions.props‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
<MicrosoftDotNetBuildTasksTemplatingVersion>9.0.0-beta.24212.4</MicrosoftDotNetBuildTasksTemplatingVersion>
9999
<MicrosoftDotNetPlatformAbstractionsVersion>5.0.0-preview.5.20278.1</MicrosoftDotNetPlatformAbstractionsVersion>
100100
<MicrosoftDotNetRemoteExecutorVersion>8.0.0-beta.24525.2</MicrosoftDotNetRemoteExecutorVersion>
101-
<MicrosoftDotNetXUnitExtensionsVersion>11.0.0-beta.26456.1</MicrosoftDotNetXUnitExtensionsVersion>
101+
<MicrosoftDotNetXUnitExtensionsVersion>12.0.0-beta.26469.3</MicrosoftDotNetXUnitExtensionsVersion>
102102
<MicrosoftExtensionsDependencyModelVersion>9.0.4</MicrosoftExtensionsDependencyModelVersion>
103103
<MicrosoftMLOnnxTestModelsVersion>0.0.6-test</MicrosoftMLOnnxTestModelsVersion>
104104
<MicrosoftMLTensorFlowTestModelsVersion>0.0.13-test</MicrosoftMLTensorFlowTestModelsVersion>

‎eng/common/Get-GitHubAppToken.ps1‎

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
# Mints a short-lived GitHub App installation access token by signing a JWT
2-
# with a private key stored in Azure Key Vault (RSA, RS256). The signed JWT is
3-
# exchanged with the GitHub API for a token scoped to a single installation.
2+
# with an RSA private key (RS256). The signed JWT is exchanged with the GitHub
3+
# API for a token scoped to a single installation.
44
#
55
# Requirements:
6-
# - A GitHub App whose private key has been uploaded into Key Vault as an RSA
7-
# key (the PEM converted to a Key Vault *key*, NOT stored as a secret).
8-
# - The caller (the federated Azure service connection used to run this script)
9-
# must have the `Key Vault Crypto User` role (or at minimum the `Sign`
10-
# action) on that key.
6+
# - A GitHub App ID and PEM private key stored as Azure Key Vault secrets.
7+
# - The federated Azure service connection running this script must have
8+
# `Get` access to those two secrets.
119
# - The App must be installed on the target organization/account
1210
# (`InstallationOwner`) with the permissions/repositories it needs.
1311
#
@@ -16,17 +14,17 @@
1614

1715
[CmdletBinding()]
1816
param(
19-
# Name of the Key Vault that holds the GitHub App's RSA signing key.
17+
# Name of the Key Vault holding the GitHub App credentials.
2018
[Parameter(Mandatory = $true)]
2119
[string] $KeyVaultName,
2220

23-
# Name of the RSA key inside the Key Vault (the App's private key).
21+
# Secret Manager projection containing the GitHub App ID.
2422
[Parameter(Mandatory = $true)]
25-
[string] $KeyName,
23+
[string] $AppIdSecretName,
2624

27-
# The GitHub App's Client ID (the value to put in the `iss` JWT claim).
25+
# Secret Manager projection containing the PEM private key.
2826
[Parameter(Mandatory = $true)]
29-
[string] $AppClientId,
27+
[string] $AppPrivateKeySecretName,
3028

3129
# Login of the organization or user account whose installation we should
3230
# mint the token for (e.g. `dotnet`, `microsoft`).
@@ -39,16 +37,69 @@ param(
3937
[Parameter(Mandatory = $false)]
4038
[string] $OutputVariableName
4139
)
42-
4340
$ErrorActionPreference = 'Stop'
4441
$PSNativeCommandUseErrorActionPreference = $true
4542

4643
. $PSScriptRoot\pipeline-logging-functions.ps1
4744

45+
if ($KeyVaultName -notmatch '^[A-Za-z][A-Za-z0-9-]{1,22}[A-Za-z0-9]$' -or $KeyVaultName.Contains('--')) {
46+
Write-PipelineTelemetryError -Category 'Build' -Message "KeyVaultName '$KeyVaultName' is not a valid Azure Key Vault name."
47+
exit 1
48+
}
49+
4850
function ConvertTo-Base64Url([byte[]] $bytes) {
4951
return [Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_')
5052
}
5153

54+
$previousNativeCommandErrorPreference = $PSNativeCommandUseErrorActionPreference
55+
try {
56+
# Azure CLI can emit non-fatal Python warnings to stderr.
57+
$PSNativeCommandUseErrorActionPreference = $false
58+
$keyVaultAccessToken = az account get-access-token `
59+
--resource https://vault.azure.net `
60+
--query accessToken `
61+
--output tsv `
62+
--only-show-errors
63+
$tokenExitCode = $LASTEXITCODE
64+
}
65+
catch {
66+
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to acquire an Azure Key Vault access token: $_"
67+
exit 1
68+
}
69+
finally {
70+
$PSNativeCommandUseErrorActionPreference = $previousNativeCommandErrorPreference
71+
}
72+
if ($tokenExitCode -ne 0 -or [string]::IsNullOrWhiteSpace($keyVaultAccessToken)) {
73+
Write-PipelineTelemetryError -Category 'Build' -Message "'az account get-access-token' exited with code $tokenExitCode while acquiring an Azure Key Vault access token."
74+
exit 1
75+
}
76+
77+
function Get-KeyVaultSecret([string] $SecretName) {
78+
# Use the data-plane REST API because `az keyvault secret show` can fail
79+
# with Errno 22 on hosted Windows agents when reading these projections.
80+
$escapedSecretName = [Uri]::EscapeDataString($SecretName)
81+
$secretUri = "https://$KeyVaultName.vault.azure.net/secrets/$escapedSecretName`?api-version=7.4"
82+
try {
83+
$response = Invoke-RestMethod `
84+
-Uri $secretUri `
85+
-Headers @{ Authorization = "Bearer $keyVaultAccessToken" } `
86+
-Method Get
87+
}
88+
catch {
89+
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to read secret '$SecretName' from vault '$KeyVaultName': $_. Verify the secret exists and the service connection has 'Key Vault Secrets User' access to it."
90+
exit 1
91+
}
92+
if ([string]::IsNullOrWhiteSpace($response.value)) {
93+
Write-PipelineTelemetryError -Category 'Build' -Message "Secret '$SecretName' in vault '$KeyVaultName' is empty."
94+
exit 1
95+
}
96+
return [string] $response.value
97+
}
98+
99+
Write-Host "Reading GitHub App credentials from vault '$KeyVaultName'..."
100+
$appId = Get-KeyVaultSecret $AppIdSecretName
101+
$privateKey = Get-KeyVaultSecret $AppPrivateKeySecretName
102+
52103
# Build JWT header and payload. Use [ordered] hashtables so JSON
53104
# serialization is deterministic.
54105
$jwtHeader = [ordered]@{
@@ -59,46 +110,38 @@ $now = [System.DateTimeOffset]::UtcNow
59110
$jwtPayload = [ordered]@{
60111
iat = $now.AddMinutes(-1).ToUnixTimeSeconds()
61112
exp = $now.AddMinutes(5).ToUnixTimeSeconds()
62-
iss = $AppClientId
113+
iss = $appId
63114
}
64115

65116
$headerEncoded = ConvertTo-Base64Url ([System.Text.Encoding]::UTF8.GetBytes(($jwtHeader | ConvertTo-Json -Compress)))
66117
$payloadEncoded = ConvertTo-Base64Url ([System.Text.Encoding]::UTF8.GetBytes(($jwtPayload | ConvertTo-Json -Compress)))
67118
$signingInput = "$headerEncoded.$payloadEncoded"
68119

69-
# Key Vault `sign` expects the *digest* (base64), not the raw bytes.
70-
$sha256 = [System.Security.Cryptography.SHA256]::Create()
71-
$digestBytes = $sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($signingInput))
72-
$digestBase64 = [Convert]::ToBase64String($digestBytes)
120+
$sha256 = [System.Security.Cryptography.SHA256]::Create()
121+
try {
122+
$digestBytes = $sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($signingInput))
123+
}
124+
finally {
125+
$sha256.Dispose()
126+
}
73127

74-
Write-Host "Signing JWT with key '$KeyName' in vault '$KeyVaultName'..."
75-
$previousNativeCommandErrorPreference = $PSNativeCommandUseErrorActionPreference
128+
Write-Host 'Signing JWT with the GitHub App private key...'
129+
$rsa = [System.Security.Cryptography.RSA]::Create()
76130
try {
77-
# Azure CLI can emit non-fatal Python warnings to stderr even when signing succeeds.
78-
# Use the exit code to determine success for this invocation.
79-
$PSNativeCommandUseErrorActionPreference = $false
80-
$signatureBase64 = az keyvault key sign `
81-
--vault-name $KeyVaultName `
82-
--name $KeyName `
83-
--algorithm RS256 `
84-
--digest $digestBase64 `
85-
--query signature `
86-
--output tsv `
87-
--only-show-errors
88-
$signExitCode = $LASTEXITCODE
131+
$rsa.ImportFromPem($privateKey)
132+
$signatureBytes = $rsa.SignHash(
133+
$digestBytes,
134+
[System.Security.Cryptography.HashAlgorithmName]::SHA256,
135+
[System.Security.Cryptography.RSASignaturePadding]::Pkcs1)
136+
$signatureUrl = ConvertTo-Base64Url $signatureBytes
89137
}
90138
catch {
91-
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."
139+
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to sign the GitHub App JWT with the supplied private key: $_"
92140
exit 1
93141
}
94142
finally {
95-
$PSNativeCommandUseErrorActionPreference = $previousNativeCommandErrorPreference
96-
}
97-
if ($signExitCode -ne 0 -or [string]::IsNullOrWhiteSpace($signatureBase64)) {
98-
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."
99-
exit 1
143+
$rsa.Dispose()
100144
}
101-
$signatureUrl = $signatureBase64.Trim().TrimEnd('=').Replace('+', '-').Replace('/', '_')
102145
$jwt = "$signingInput.$signatureUrl"
103146

104147
$headers = @{
@@ -126,7 +169,7 @@ try {
126169
} while ($pageInstallationCount -eq 100)
127170
}
128171
catch {
129-
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."
172+
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to list GitHub App installations: $_. The signed JWT may be invalid or the App ID may be incorrect."
130173
exit 1
131174
}
132175
$matchingInstallations = @($installations | Where-Object { $_.account.login -ieq $InstallationOwner })

‎eng/common/build.ps1‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Param(
88
[bool] $warnAsError = $true,
99
[string] $warnNotAsError = '',
1010
[bool] $nodeReuse = $true,
11-
[bool][Alias('mt')]$msbuildMultiThreaded = $false,
11+
[bool][Alias('mt')]$msbuildMultiThreaded = $true,
1212
[switch] $buildCheck = $false,
1313
[switch][Alias('r')]$restore,
1414
[switch] $deployDeps,
@@ -181,6 +181,10 @@ try {
181181
if (-not $PSBoundParameters.ContainsKey('nodeReuse')) {
182182
$nodeReuse = $false
183183
}
184+
# MSBuild's multi-threaded mode isn't run on CI unless it was explicitly requested via -msbuildMultiThreaded.
185+
if (-not $PSBoundParameters.ContainsKey('msbuildMultiThreaded')) {
186+
$msbuildMultiThreaded = $false
187+
}
184188
}
185189

186190
if (-not [string]::IsNullOrEmpty($binaryLogName)) {

‎eng/common/build.sh‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ function Build {
254254
properties+=("/p:Projects=$projects")
255255
fi
256256

257-
local bl=""
257+
local bl=()
258258
if [[ "$binary_log" == true ]]; then
259259
local binary_log_path=""
260260
if [[ -z "$binary_log_name" ]]; then
@@ -266,16 +266,16 @@ function Build {
266266
fi
267267

268268
mkdir -p "$(dirname "$binary_log_path")"
269-
bl="/bl:\"$binary_log_path\""
269+
bl=("/bl:$binary_log_path")
270270
fi
271271

272272
local check=""
273273
if [[ "$build_check" == true ]]; then
274274
check="/check"
275275
fi
276276

277-
MSBuild $_InitializeToolset \
278-
$bl \
277+
MSBuild "$_InitializeToolset" \
278+
${bl[@]+"${bl[@]}"} \
279279
$check \
280280
/p:Configuration=$configuration \
281281
/p:RepoRoot="$repo_root" \
@@ -299,7 +299,7 @@ function Build {
299299

300300
if [[ "$clean" == true ]]; then
301301
if [ -d "$artifacts_dir" ]; then
302-
rm -rf $artifacts_dir
302+
rm -rf "$artifacts_dir"
303303
echo "Artifacts directory deleted."
304304
fi
305305
exit 0

‎eng/common/core-templates/job/helix-job-monitor.yml‎

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,23 @@ parameters:
5252
type: string
5353
default: https://helix.dot.net/
5454

55-
# Helix API access token forwarded to the tool via the HELIX_ACCESSTOKEN environment variable.
55+
# Helix API access token forwarded via HELIX_ACCESSTOKEN. Not forwarded when
56+
# useEntraAuthentication is true.
5657
- name: helixAccessToken
5758
type: string
5859
default: ''
5960

61+
# Use a refreshable Entra credential instead of a PAT or anonymous access.
62+
- name: useEntraAuthentication
63+
type: boolean
64+
default: false
65+
66+
# Azure service connection ID authorized for Helix. Required when
67+
# useEntraAuthentication is true.
68+
- name: azureSubscription
69+
type: string
70+
default: ''
71+
6072
# Polling interval in seconds (--polling-interval-seconds).
6173
- name: pollingIntervalSeconds
6274
type: number
@@ -141,6 +153,26 @@ jobs:
141153
- checkout: self
142154
fetchDepth: 1
143155

156+
- ${{ if and(eq(parameters.useEntraAuthentication, true), eq(parameters.azureSubscription, '')) }}:
157+
- pwsh: throw "azureSubscription must be set when useEntraAuthentication is true."
158+
displayName: Validate Helix Entra authentication
159+
160+
- ${{ if eq(parameters.useEntraAuthentication, true) }}:
161+
- task: AzureCLI@2
162+
displayName: Initialize Helix Entra authentication
163+
inputs:
164+
azureSubscription: ${{ parameters.azureSubscription }}
165+
addSpnToEnvironment: true
166+
scriptType: pscore
167+
scriptLocation: inlineScript
168+
inlineScript: |
169+
if ([string]::IsNullOrWhiteSpace($env:servicePrincipalId) -or [string]::IsNullOrWhiteSpace($env:tenantId)) {
170+
throw "The Helix Azure service connection did not provide a service principal or tenant ID."
171+
}
172+
173+
Write-Host "##vso[task.setvariable variable=HelixEntraClientId]$env:servicePrincipalId"
174+
Write-Host "##vso[task.setvariable variable=HelixEntraTenantId]$env:tenantId"
175+
144176
- ${{ if ne(parameters.toolNupkgArtifactName, '') }}:
145177
- task: DownloadPipelineArtifact@2
146178
displayName: Download Helix Job Monitor artifact
@@ -214,6 +246,7 @@ jobs:
214246
215247
toolArgs=(
216248
--helix-base-uri '${{ parameters.helixBaseUri }}'
249+
--use-entra-authentication '${{ parameters.useEntraAuthentication }}'
217250
--polling-interval-seconds '${{ parameters.pollingIntervalSeconds }}'
218251
--fail-on-failed-tests '${{ parameters.failWorkItemsWithFailedTests }}'
219252
--allow-no-helix-jobs '${{ parameters.allowNoHelixJobs }}'
@@ -275,4 +308,9 @@ jobs:
275308
displayName: Monitor Helix Jobs
276309
env:
277310
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
278-
HELIX_ACCESSTOKEN: ${{ parameters.helixAccessToken }}
311+
${{ if eq(parameters.useEntraAuthentication, false) }}:
312+
HELIX_ACCESSTOKEN: ${{ parameters.helixAccessToken }}
313+
${{ if eq(parameters.useEntraAuthentication, true) }}:
314+
AZURESUBSCRIPTION_CLIENT_ID: $(HelixEntraClientId)
315+
AZURESUBSCRIPTION_TENANT_ID: $(HelixEntraTenantId)
316+
AZURESUBSCRIPTION_SERVICE_CONNECTION_ID: ${{ parameters.azureSubscription }}

0 commit comments

Comments
 (0)