diff --git a/build-tools/automation/yaml-templates/apk-instrumentation.yaml b/build-tools/automation/yaml-templates/apk-instrumentation.yaml
index 0cb374a7b1e..e90c8f52b49 100644
--- a/build-tools/automation/yaml-templates/apk-instrumentation.yaml
+++ b/build-tools/automation/yaml-templates/apk-instrumentation.yaml
@@ -29,8 +29,6 @@ steps:
$env:PATH = "${DOTNET_ROOT};$env:PATH"
$dotnetPath = "${DOTNET_ROOT}\dotnet.exe"
}
- # Workaround for https://github.com/dotnet/sdk/pull/55581
- $env:DOTNET_HOST_PATH = $dotnetPath
& $dotnetPath test $projectFile -bl:${{ parameters.xaSourcePath }}/bin/Test${{ parameters.configuration }}/run-${{ parameters.testName }}.binlog -c ${{ parameters.configuration }} --results-directory $resultsDir --report-trx --report-trx-filename ${{ parameters.testName }}.trx --output Detailed ${{ parameters.extraBuildArgs }}
Pop-Location
displayName: run ${{ parameters.testName }}
@@ -59,13 +57,20 @@ steps:
continueOnError: true
timeoutInMinutes: 3
-- script: >
- DEST="$(Build.StagingDirectory)/Test${{ parameters.configuration }}/${{ parameters.artifactFolder }}/" &&
- mkdir -p "$DEST" &&
- cp "${{ parameters.artifactSource }}" "$DEST" ||
- echo "copy apk/aab failed" # We don't need to report the error
- displayName: copy apk/aab
- condition: ne(variables['Agent.JobStatus'], 'Succeeded')
+- script: |
+ DEST="$(Build.StagingDirectory)/Test${{ parameters.configuration }}/${{ parameters.artifactFolder }}/"
+ INTERMEDIATE_DIR="$(dirname "${{ parameters.project }}")/obj/${{ parameters.configuration }}/$(DotNetTargetFramework)-android/android/bin"
+ mkdir -p "$DEST"
+ cp "${{ parameters.artifactSource }}" "$DEST" || echo "copy apk/aab failed"
+ cp "$INTERMEDIATE_DIR/packaged_resources" "$DEST/packaged_resources.zip" || echo "copy packaged_resources failed"
+ cp "$INTERMEDIATE_DIR/base.zip" "$DEST" || echo "copy base.zip failed"
+ for AAB in "$INTERMEDIATE_DIR"/*.aab; do
+ if [ -f "$AAB" ]; then
+ cp "$AAB" "$DEST"
+ fi
+ done
+ displayName: copy package intermediates
+ condition: ${{ parameters.condition }}
continueOnError: true
# Always capture full device logcat so we can diagnose native library load
diff --git a/build-tools/automation/yaml-templates/stage-package-tests.yaml b/build-tools/automation/yaml-templates/stage-package-tests.yaml
index 7cbed90d579..d4a684b183c 100644
--- a/build-tools/automation/yaml-templates/stage-package-tests.yaml
+++ b/build-tools/automation/yaml-templates/stage-package-tests.yaml
@@ -178,15 +178,6 @@ stages:
artifactSource: bin/Test$(XA.Build.Configuration)/$(DotNetTargetFramework)-android/Mono.Android.NET_Tests-Signed.aab
artifactFolder: $(DotNetTargetFramework)-NativeAOT
- - template: /build-tools/automation/yaml-templates/apk-instrumentation.yaml
- parameters:
- configuration: $(XA.Build.Configuration)
- testName: Mono.Android.NET_Tests-NativeAOTTrimmable
- project: tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj
- extraBuildArgs: -p:TestsFlavor=NativeAOTTrimmable -p:PublishAot=true -p:_AndroidTypeMapImplementation=trimmable
- artifactSource: bin/Test$(XA.Build.Configuration)/$(DotNetTargetFramework)-android/Mono.Android.NET_Tests-Signed.aab
- artifactFolder: $(DotNetTargetFramework)-NativeAOTTrimmable
-
- template: /build-tools/automation/yaml-templates/apk-instrumentation.yaml
parameters:
configuration: $(XA.Build.Configuration)
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index edd1abeaae2..03194327f93 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,20 +1,20 @@
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
https://github.com/dotnet/dotnet
@@ -36,21 +36,21 @@
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
-
+
https://github.com/dotnet/dotnet
- 5da2de22f7c6e2ebe7ed4c16c614b00183145d3c
+ 7cdb217445905f3342bbb0266a4497b9a014389a
-
+
https://github.com/microsoft/testfx
- e492730d840fc5864eff04230dd993041cf6189a
+ 26dda6f3c287c9f8a012c2727870d33a0d88e0cb
diff --git a/eng/Versions.props b/eng/Versions.props
index f266a7321ef..28aa2a199a6 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -1,21 +1,21 @@
- 11.0.100-rc.1.26401.101
+ 11.0.100-rc.1.26411.119
$(MicrosoftNETSdkPackageVersion)
- 11.0.0-rc.1.26401.101
- 11.0.0-rc.1.26401.101
+ 11.0.0-rc.1.26411.119
+ 11.0.0-rc.1.26411.119
7.0.0-beta.22103.1
11.0.0-beta.26060.102
- 11.0.0-beta.26401.101
+ 11.0.0-beta.26411.119
11.0.100-preview.4.26215.121
11.0.100-preview.4.26215.121
$(MicrosoftNETWorkloadMonoToolChainCurrentManifest110100preview4PackageVersion)
$(MicrosoftNETWorkloadEmscriptenCurrentManifest110100preview4PackageVersion)
- 11.0.100-rc.1.26401.101
- 0.11.5-preview.26401.101
- 4.4.0-preview.26402.3
+ 11.0.100-rc.1.26411.119
+ 0.11.5-preview.26411.119
+ 4.4.0-preview.26409.6
10.0.10
11.0.0-preview.1.26104.118
diff --git a/eng/common/Get-GitHubAppToken.ps1 b/eng/common/Get-GitHubAppToken.ps1
new file mode 100644
index 00000000000..6b5899d7a29
--- /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/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1
index b3bddff355e..b7a3769364d 100644
--- a/eng/common/SetupNugetSources.ps1
+++ b/eng/common/SetupNugetSources.ps1
@@ -11,7 +11,7 @@
# condition: eq(variables['Agent.OS'], 'Windows_NT')
# inputs:
# filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
-# arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token
+# arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config
# env:
# Token: $(InternalFeedToken)
#
@@ -29,12 +29,14 @@
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)][string]$ConfigFile,
- $Password
+ # Keep the legacy name as an alias while callers migrate secrets to the Token environment variable.
+ [Alias("Password")]$Credential
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version 2.0
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$feedCredential = if ($env:Token) { $env:Token } else { $Credential }
# This script only consumes helper functions from tools.ps1 to configure NuGet feeds.
# Skip importing configure-toolset.ps1 so that repo-specific toolset setup (e.g. acquiring
@@ -44,14 +46,14 @@ $disableConfigureToolsetImport = $true
. $PSScriptRoot\tools.ps1
# Adds or enables the package source with the given name
-function AddOrEnablePackageSource($sources, $disabledPackageSources, $SourceName, $SourceEndPoint, $creds, $Username, $pwd) {
- if ($disabledPackageSources -eq $null -or -not (EnableInternalPackageSource -DisabledPackageSources $disabledPackageSources -Creds $creds -PackageSourceName $SourceName)) {
- AddPackageSource -Sources $sources -SourceName $SourceName -SourceEndPoint $SourceEndPoint -Creds $creds -Username $userName -pwd $Password
+function AddOrEnablePackageSource($sources, $disabledPackageSources, $SourceName, $SourceEndPoint, $creds, $Username, $credential) {
+ if ($disabledPackageSources -eq $null -or -not (EnableInternalPackageSource -DisabledPackageSources $disabledPackageSources -Creds $creds -PackageSourceName $SourceName -Credential $credential)) {
+ AddPackageSource -Sources $sources -SourceName $SourceName -SourceEndPoint $SourceEndPoint -Creds $creds -Username $Username -credential $credential
}
}
# Add source entry to PackageSources
-function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Username, $pwd) {
+function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Username, $credential) {
$packageSource = $sources.SelectSingleNode("add[@key='$SourceName']")
if ($packageSource -eq $null)
@@ -67,13 +69,13 @@ function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Usern
Write-Host "Package source $SourceName already present and enabled."
}
- AddCredential -Creds $creds -Source $SourceName -Username $Username -pwd $pwd
+ AddCredential -Creds $creds -Source $SourceName -Username $Username -credential $credential
}
# Add a credential node for the specified source
-function AddCredential($creds, $source, $username, $pwd) {
+function AddCredential($creds, $source, $username, $credential) {
# If no cred supplied, don't do anything.
- if (!$pwd) {
+ if (!$credential) {
return;
}
@@ -108,19 +110,19 @@ function AddCredential($creds, $source, $username, $pwd) {
$sourceElement.AppendChild($passwordElement) | Out-Null
}
- $passwordElement.SetAttribute("value", $pwd)
+ $passwordElement.SetAttribute("value", $credential)
}
# Enable all darc-int package sources.
-function EnableMaestroInternalPackageSources($DisabledPackageSources, $Creds) {
+function EnableMaestroInternalPackageSources($DisabledPackageSources, $Creds, $Credential) {
$maestroInternalSources = $DisabledPackageSources.SelectNodes("add[contains(@key,'darc-int')]")
ForEach ($DisabledPackageSource in $maestroInternalSources) {
- EnableInternalPackageSource -DisabledPackageSources $DisabledPackageSources -Creds $Creds -PackageSourceName $DisabledPackageSource.key
+ EnableInternalPackageSource -DisabledPackageSources $DisabledPackageSources -Creds $Creds -PackageSourceName $DisabledPackageSource.key -Credential $Credential
}
}
# Enables an internal package source by name, if found. Returns true if the package source was found and enabled, false otherwise.
-function EnableInternalPackageSource($DisabledPackageSources, $Creds, $PackageSourceName) {
+function EnableInternalPackageSource($DisabledPackageSources, $Creds, $PackageSourceName, $Credential) {
$DisabledPackageSource = $DisabledPackageSources.SelectSingleNode("add[@key='$PackageSourceName']")
if ($DisabledPackageSource) {
Write-Host "Enabling internal source '$($DisabledPackageSource.key)'."
@@ -128,7 +130,7 @@ function EnableInternalPackageSource($DisabledPackageSources, $Creds, $PackageSo
# Due to https://github.com/NuGet/Home/issues/10291, we must actually remove the disabled entries
$DisabledPackageSources.RemoveChild($DisabledPackageSource)
- AddCredential -Creds $creds -Source $DisabledPackageSource.Key -Username $userName -pwd $Password
+ AddCredential -Creds $creds -Source $DisabledPackageSource.Key -Username $userName -credential $credential
return $true
}
return $false
@@ -153,7 +155,7 @@ if ($sources -eq $null) {
$creds = $null
$feedSuffix = "v3/index.json"
-if ($Password) {
+if ($feedCredential) {
$feedSuffix = "v2"
# Looks for a node. Create it if none is found.
$creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials")
@@ -169,7 +171,7 @@ $userName = "dn-bot"
$disabledSources = $doc.DocumentElement.SelectSingleNode("disabledPackageSources")
if ($disabledSources -ne $null) {
Write-Host "Checking for any darc-int disabled package sources in the disabledPackageSources node"
- EnableMaestroInternalPackageSources -DisabledPackageSources $disabledSources -Creds $creds
+ EnableMaestroInternalPackageSources -DisabledPackageSources $disabledSources -Creds $creds -Credential $feedCredential
}
$dotnetVersions = @('5','6','7','8','9','10')
@@ -177,8 +179,8 @@ foreach ($dotnetVersion in $dotnetVersions) {
$feedPrefix = "dotnet" + $dotnetVersion;
$dotnetSource = $sources.SelectSingleNode("add[@key='$feedPrefix']")
if ($dotnetSource -ne $null) {
- AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "$feedPrefix-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal/nuget/$feedSuffix" -Creds $creds -Username $userName -pwd $Password
- AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "$feedPrefix-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal-transport/nuget/$feedSuffix" -Creds $creds -Username $userName -pwd $Password
+ AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "$feedPrefix-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal/nuget/$feedSuffix" -Creds $creds -Username $userName -credential $feedCredential
+ AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "$feedPrefix-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal-transport/nuget/$feedSuffix" -Creds $creds -Username $userName -credential $feedCredential
}
}
diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh
index 67e7e0942ca..c3ae8ac054f 100644
--- a/eng/common/SetupNugetSources.sh
+++ b/eng/common/SetupNugetSources.sh
@@ -24,7 +24,9 @@
# This logic is also abstracted into enable-internal-sources.yml.
ConfigFile=$1
-CredToken=$2
+# Prefer the environment variable so credentials do not appear in process arguments.
+# Retain the positional argument as a compatibility fallback for existing callers.
+CredToken=${Token:-$2}
NL='\n'
TB=' '
diff --git a/eng/common/build.ps1 b/eng/common/build.ps1
index dd84699f500..fee2f839919 100644
--- a/eng/common/build.ps1
+++ b/eng/common/build.ps1
@@ -8,6 +8,7 @@ Param(
[bool] $warnAsError = $true,
[string] $warnNotAsError = '',
[bool] $nodeReuse = $true,
+ [bool][Alias('mt')]$msbuildMultiThreaded = $false,
[switch] $buildCheck = $false,
[switch][Alias('r')]$restore,
[switch] $deployDeps,
@@ -79,6 +80,7 @@ function Print-Usage() {
Write-Host " -excludePrereleaseVS Set to exclude build engines in prerelease versions of Visual Studio"
Write-Host " -nativeToolsOnMachine Sets the native tools on machine environment variable (indicating that the script should use native tools on machine)"
Write-Host " -nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')"
+ Write-Host " -msbuildMultiThreaded Sets MSBuild's multi-threaded mode, i.e. the -mt switch ('1' or '0') (short: -mt)"
Write-Host " -buildCheck Sets /check msbuild parameter"
Write-Host " -fromVMR Set when building from within the VMR"
Write-Host " -disablePipelineSetResult Set to disable masking the actual exit code in the pipeline when the build fails"
@@ -175,9 +177,8 @@ try {
if (-not $excludeCIBinarylog) {
$binaryLog = $true
}
- # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED.
- # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on.
- if ($env:MSBUILD_NODEREUSE_ENABLED -ne "1") {
+ # Node reuse isn't used on CI unless it was explicitly requested via -nodeReuse.
+ if (-not $PSBoundParameters.ContainsKey('nodeReuse')) {
$nodeReuse = $false
}
}
diff --git a/eng/common/build.sh b/eng/common/build.sh
index e37edd6cff3..109d83ff73f 100644
--- a/eng/common/build.sh
+++ b/eng/common/build.sh
@@ -43,6 +43,7 @@ usage()
echo " --pipelinesLog Promote msbuild errors/warnings to Azure Pipelines timeline issues; defaults to on in CI (short: -pl)"
echo " --prepareMachine Prepare machine for CI run, clean up processes after build"
echo " --nodeReuse Sets nodereuse msbuild parameter ('true' or 'false')"
+ echo " --msbuildMultiThreaded Sets MSBuild's multi-threaded mode, i.e. the -mt switch ('true' or 'false') (short: --mt)"
echo " --warnAsError Sets warnaserror msbuild parameter ('true' or 'false')"
echo " --warnNotAsError Sets a semi-colon delimited list of warning codes that should not be treated as errors"
echo " --buildCheck Sets /check msbuild parameter"
@@ -84,7 +85,9 @@ clean=false
warn_as_error=true
warn_not_as_error=''
-node_reuse=true
+# Empty means "not specified"; tools.sh defaults these to on for local builds and off on CI.
+node_reuse=''
+msbuild_multi_threaded=''
build_check=false
binary_log=false
binary_log_name=''
@@ -199,6 +202,10 @@ while [[ $# -gt 0 ]]; do
node_reuse=$2
shift
;;
+ -msbuildmultithreaded|-mt)
+ msbuild_multi_threaded=$2
+ shift
+ ;;
-buildcheck)
build_check=true
;;
@@ -224,11 +231,6 @@ fi
if [[ "$ci" == true ]]; then
pipelines_log=true
- # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED.
- # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on.
- if [[ "${MSBUILD_NODEREUSE_ENABLED:-}" != "1" ]]; then
- node_reuse=false
- fi
if [[ "$exclude_ci_binary_log" == false ]]; then
binary_log=true
fi
diff --git a/eng/common/core-templates/job/helix-job-monitor.yml b/eng/common/core-templates/job/helix-job-monitor.yml
index 62fa1997117..a65b50d0a78 100644
--- a/eng/common/core-templates/job/helix-job-monitor.yml
+++ b/eng/common/core-templates/job/helix-job-monitor.yml
@@ -26,6 +26,11 @@ parameters:
type: string
default: ''
+# Whether failures in the monitor job should allow the pipeline to continue.
+- name: continueOnError
+ type: boolean
+ default: false
+
# NuGet package id of the Helix job monitor tool.
- name: toolPackageId
type: string
@@ -65,6 +70,12 @@ parameters:
type: boolean
default: true
+# When true, allow the monitor to succeed when this stage produces no Helix jobs in any attempt.
+# Forwarded as --allow-no-helix-jobs.
+- name: allowNoHelixJobs
+ type: boolean
+ default: false
+
# When true, test results are reported to Azure DevOps using the fully qualified test name
# (Namespace.Type.Method) as the stable automatedTestName and the visible title is qualified as
# well (--use-fully-qualified-test-name). Opt-in because it changes AzDO test identity and display;
@@ -97,6 +108,7 @@ jobs:
- job: HelixJobMonitor
displayName: Monitor Helix Jobs
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
+ continueOnError: ${{ parameters.continueOnError }}
${{ if ne(length(parameters.dependsOn), 0) }}:
dependsOn: ${{ parameters.dependsOn }}
${{ if ne(parameters.condition, '') }}:
@@ -189,6 +201,7 @@ jobs:
--helix-base-uri '${{ parameters.helixBaseUri }}'
--polling-interval-seconds '${{ parameters.pollingIntervalSeconds }}'
--fail-on-failed-tests '${{ parameters.failWorkItemsWithFailedTests }}'
+ --allow-no-helix-jobs '${{ parameters.allowNoHelixJobs }}'
--use-fully-qualified-test-name '${{ parameters.useFullyQualifiedTestName }}'
--max-wait-minutes "$((${{ parameters.timeoutInMinutes }} - 5))" # Set the tool's timeout slightly lower than the Azure DevOps job timeout to allow it to exit gracefully.
--stage-name '$(System.StageName)'
diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml
index 2816d2905a0..4f5653d73ac 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:
@@ -110,7 +133,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 4229288d3d3..330225ae093 100644
--- a/eng/common/core-templates/job/publish-build-assets.yml
+++ b/eng/common/core-templates/job/publish-build-assets.yml
@@ -58,8 +58,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/post-build/common-variables.yml b/eng/common/core-templates/post-build/common-variables.yml
index db298ae16ba..a3a8480e254 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/stages/renovate.yml b/eng/common/core-templates/stages/renovate.yml
index edab2818258..cfa9683794a 100644
--- a/eng/common/core-templates/stages/renovate.yml
+++ b/eng/common/core-templates/stages/renovate.yml
@@ -81,6 +81,8 @@ resources:
extends:
template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
parameters:
+ settings:
+ networkIsolationPolicy: Permissive
pool: ${{ parameters.pool }}
sdl:
sourceAnalysisPool: ${{ parameters.sdlPool }}
diff --git a/eng/common/core-templates/steps/enable-internal-sources.yml b/eng/common/core-templates/steps/enable-internal-sources.yml
index 51af9a01709..843cdff7821 100644
--- a/eng/common/core-templates/steps/enable-internal-sources.yml
+++ b/eng/common/core-templates/steps/enable-internal-sources.yml
@@ -19,7 +19,7 @@ steps:
displayName: Setup Internal Feeds
inputs:
filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
- arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token
+ arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config
env:
Token: ${{ parameters.legacyCredential }}
- task: Bash@3
@@ -28,7 +28,7 @@ steps:
inputs:
targetType: inline
script: |
- "$(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh" "$(System.DefaultWorkingDirectory)/NuGet.config" "$Token"
+ "$(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh" "$(System.DefaultWorkingDirectory)/NuGet.config"
env:
Token: ${{ parameters.legacyCredential }}
# If running on dnceng (internal project), just use the default behavior for NuGetAuthenticate.
@@ -58,13 +58,17 @@ steps:
displayName: Setup Internal Feeds
inputs:
filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
- arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token)
+ arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config
+ env:
+ Token: $(dnceng-artifacts-feeds-read-access-token)
- task: Bash@3
condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'))
displayName: Setup Internal Feeds
inputs:
filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh
- arguments: $(System.DefaultWorkingDirectory)/NuGet.config $(dnceng-artifacts-feeds-read-access-token)
+ arguments: $(System.DefaultWorkingDirectory)/NuGet.config
+ env:
+ Token: $(dnceng-artifacts-feeds-read-access-token)
# This is required in certain scenarios to install the ADO credential provider.
# It installed by default in some msbuild invocations (e.g. VS msbuild), but needs to be installed for others
# (e.g. dotnet msbuild).
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 00000000000..6d42a48d3c3
--- /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 c496f3d0dc7..2c1e0ab1162 100644
--- a/eng/common/core-templates/steps/publish-logs.yml
+++ b/eng/common/core-templates/steps/publish-logs.yml
@@ -30,8 +30,6 @@ steps:
-TokensFilePath '$(System.DefaultWorkingDirectory)/eng/BinlogSecretsRedactionFile.txt'
-runtimeSourceFeed https://ci.dot.net/internal
-runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)'
- '$(publishing-dnceng-devdiv-code-r-build-re)'
- '$(akams-client-id)'
'$(System.AccessToken)'
${{parameters.CustomSensitiveDataList}}
continueOnError: true
@@ -56,4 +54,3 @@ steps:
condition: always()
retryCountOnTaskFailure: 10 # for any files being locked
isProduction: false # logs are non-production artifacts
-
diff --git a/eng/common/msbuild.ps1 b/eng/common/msbuild.ps1
index 495d533a909..b6dfb570ea5 100644
--- a/eng/common/msbuild.ps1
+++ b/eng/common/msbuild.ps1
@@ -3,6 +3,7 @@ Param(
[string] $verbosity = 'minimal',
[bool] $warnAsError = $true,
[bool] $nodeReuse = $true,
+ [bool][Alias('mt')]$msbuildMultiThreaded = $false,
[switch] $ci,
[switch] $prepareMachine,
[switch] $excludePrereleaseVS,
@@ -13,12 +14,9 @@ Param(
. $PSScriptRoot\tools.ps1
try {
- if ($ci) {
- # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED.
- # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on.
- if ($env:MSBUILD_NODEREUSE_ENABLED -ne "1") {
- $nodeReuse = $false
- }
+ # Node reuse isn't used on CI unless it was explicitly requested via -nodeReuse.
+ if ($ci -and -not $PSBoundParameters.ContainsKey('nodeReuse')) {
+ $nodeReuse = $false
}
MSBuild @extraArgs
diff --git a/eng/common/msbuild.sh b/eng/common/msbuild.sh
index 333be3232fc..a40c101237b 100644
--- a/eng/common/msbuild.sh
+++ b/eng/common/msbuild.sh
@@ -14,7 +14,9 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
verbosity='minimal'
warn_as_error=true
-node_reuse=true
+# Empty means "not specified"; tools.sh defaults these to on for local builds and off on CI.
+node_reuse=''
+msbuild_multi_threaded=''
prepare_machine=false
extra_args=''
@@ -33,6 +35,10 @@ while (($# > 0)); do
node_reuse=$2
shift 2
;;
+ --msbuildmultithreaded|--mt)
+ msbuild_multi_threaded=$2
+ shift 2
+ ;;
--ci)
ci=true
shift 1
@@ -50,13 +56,5 @@ done
. "$scriptroot/tools.sh"
-if [[ "$ci" == true ]]; then
- # Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED.
- # Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on.
- if [[ "${MSBUILD_NODEREUSE_ENABLED:-}" != "1" ]]; then
- node_reuse=false
- fi
-fi
-
MSBuild $extra_args
ExitWithExitCode 0
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 00000000000..c89f3641a4d
--- /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 00000000000..79e182c6416
--- /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/eng/common/tools.ps1 b/eng/common/tools.ps1
index da07386ff1f..e84033dad90 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -31,11 +31,16 @@
# Set to true to reuse msbuild nodes. Recommended to not reuse on CI.
[bool]$nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { !$ci }
+# Set to true to build with MSBuild's multi-threaded mode (-mt). Opt-in for now, so off unless it was
+# explicitly requested. It's intended to become the default for local builds once it has proven out.
+[bool]$msbuildMultiThreaded = if (Test-Path variable:msbuildMultiThreaded) { $msbuildMultiThreaded } else { $false }
+
# Configures warning treatment in msbuild.
[bool]$warnAsError = if (Test-Path variable:warnAsError) { $warnAsError } else { $true }
# Specifies semi-colon delimited list of warning codes that should not be treated as errors.
-[string]$warnNotAsError = if (Test-Path variable:warnNotAsError) { $warnNotAsError } else { '' }
+# Defaults to NuGet Audit warning codes NU1901-NU1904.
+[string]$warnNotAsError = if ((Test-Path variable:warnNotAsError) -and $warnNotAsError) { $warnNotAsError } else { 'NU1901;NU1902;NU1903;NU1904' }
# Specifies which msbuild engine to use for build: 'vs', 'dotnet' or unspecified (determined based on presence of tools.vs in global.json).
[string]$msbuildEngine = if (Test-Path variable:msbuildEngine) { $msbuildEngine } else { $null }
@@ -808,8 +813,8 @@ function MSBuild() {
$cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci"
- # Add -mt flag for MSBuild multithreaded mode if enabled via environment variable
- if ($env:MSBUILD_MT_ENABLED -eq "1") {
+ # Build with MSBuild's multi-threaded mode.
+ if ($msbuildMultiThreaded) {
$cmdArgs += ' -mt'
}
diff --git a/eng/common/tools.sh b/eng/common/tools.sh
index 20f791c11de..4d14b100b06 100644
--- a/eng/common/tools.sh
+++ b/eng/common/tools.sh
@@ -1,5 +1,15 @@
#!/usr/bin/env bash
+# Normalizes the value of a boolean build argument. Accepts 1/0 in addition to true/false so that
+# the same value works with the PowerShell scripts, whose [bool] parameters only bind 1/0.
+function NormalizeBoolArg {
+ case "${1:-}" in
+ 1) echo true ;;
+ 0) echo false ;;
+ *) echo "${1:-}" ;;
+ esac
+}
+
# Initialize variables if they aren't already defined.
# CI mode - set to true on CI server for PR validation build or official build.
@@ -43,17 +53,25 @@ restore=${restore:-true}
verbosity=${verbosity:-'minimal'}
# Set to true to reuse msbuild nodes. Recommended to not reuse on CI.
+node_reuse=$(NormalizeBoolArg "${node_reuse:-}")
if [[ "$ci" == true ]]; then
node_reuse=${node_reuse:-false}
else
node_reuse=${node_reuse:-true}
fi
+# Set to true to build with MSBuild's multi-threaded mode (-mt). Opt-in for now, so off unless it was
+# explicitly requested. It's intended to become the default for local builds once it has proven out.
+msbuild_multi_threaded=$(NormalizeBoolArg "${msbuild_multi_threaded:-}")
+msbuild_multi_threaded=${msbuild_multi_threaded:-false}
+
# Configures warning treatment in msbuild.
+warn_as_error=$(NormalizeBoolArg "${warn_as_error:-}")
warn_as_error=${warn_as_error:-true}
# Specifies semi-colon delimited list of warning codes that should not be treated as errors.
-warn_not_as_error=${warn_not_as_error:-''}
+# Defaults to NuGet Audit warning codes NU1901-NU1904.
+warn_not_as_error="${warn_not_as_error:-NU1901;NU1902;NU1903;NU1904}"
# True to attempt using .NET Core already that meets requirements specified in global.json
# installed on the machine instead of downloading one.
@@ -587,9 +605,9 @@ function MSBuild {
}
}
- # Add -mt flag for MSBuild multithreaded mode if enabled via environment variable
+ # Build with MSBuild's multi-threaded mode.
local mt_switch=""
- if [[ "${MSBUILD_MT_ENABLED:-}" == "1" ]]; then
+ if [[ "$msbuild_multi_threaded" == true ]]; then
mt_switch="-mt"
fi
diff --git a/global.json b/global.json
index 2eb55a24266..44205817173 100644
--- a/global.json
+++ b/global.json
@@ -4,6 +4,6 @@
},
"msbuild-sdks": {
"Microsoft.Build.NoTargets": "3.7.134",
- "Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.26401.101"
+ "Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.26411.119"
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
index 3db85d3f68c..cfc00a72881 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
@@ -371,13 +371,6 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
/>
-
-
-
- $(NativeBinaryPrefix)$(TargetName).so
- PreserveNewest
-
-
@@ -399,7 +392,18 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
DependsOnTargets="$(_AndroidRunNativeCompileDependsOn)" />
+
+ <_AndroidNativeAotSharedLibraryName>lib$(TargetName).so
+ <_AndroidNativeAotSharedLibrary Condition=" '$(NativeOutputPath)' != '' ">$(NativeOutputPath)$(_AndroidNativeAotSharedLibraryName)
+ <_AndroidNativeAotSharedLibrary Condition=" '$(NativeOutputPath)' == '' ">$(OutputPath)$(RuntimeIdentifier)/native/$(_AndroidNativeAotSharedLibraryName)
+
+
+
+
+ $(_AndroidNativeAotSharedLibraryName)
+ PreserveNewest
+
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs
index acafc24fe8a..97f04f687c7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs
@@ -209,12 +209,12 @@ public String Say (String quote) {
aarEntry.Extract (aarStream);
aarStream.Seek (0, SeekOrigin.Begin);
- // Look for 2 .jar files under libs/
+ // Look for the Maven dependency, foo.jar, and the compiled AndroidJavaSource output under libs/
using var aar = ZipArchive.Open (aarStream);
int count = aar.Count (e =>
e.FullName.StartsWith ("libs/", StringComparison.OrdinalIgnoreCase) &&
e.FullName.EndsWith (".jar", StringComparison.OrdinalIgnoreCase));
- Assert.AreEqual (2, count, $"There should be 2 .jar files in the {aarPath} archive, but found {count}.");
+ Assert.AreEqual (3, count, $"There should be 3 .jar files in the {aarPath} archive, but found {count}.");
}
static IEnumerable