diff --git a/build-tools/automation/azure-pipelines-internal.yaml b/build-tools/automation/azure-pipelines-internal.yaml
index 0a5ee0a5f7e..232b42f8dad 100644
--- a/build-tools/automation/azure-pipelines-internal.yaml
+++ b/build-tools/automation/azure-pipelines-internal.yaml
@@ -10,10 +10,9 @@
# branch policies for main, release/*, and feature/*. Azure Repos does not
# support YAML `pr` triggers.
#
-# Signing is intentionally NOT enabled yet. We will eventually release &
-# sign from here; when we do, convert this to `extends` the 1ES
-# `MicroBuild.1ES.Official.yml` template and flip the `use1ESTemplate`
-# parameters below to `true` (see azure-pipelines.yaml for reference).
+# Signing uses the in-repo Arcade templates and adapter under
+# build-tools/automation/dnceng. Do not add a Xamarin.yaml-templates
+# repository resource: dnceng/internal cannot access that repository.
name: $(Build.SourceBranchName)-$(Build.SourceVersion)-$(Rev:r)
@@ -46,6 +45,22 @@ resources:
# Global variables
variables:
- template: /build-tools/automation/yaml-templates/variables.yaml@self
+- name: _TeamName
+ value: Maui
+- ${{ if and(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ne(variables['Build.Reason'], 'PullRequest')) }}:
+ - name: _SignType
+ value: real
+- ${{ else }}:
+ - name: _SignType
+ value: test
+- name: _BuildConfig
+ value: Release
+- name: _BuildOfficialId
+ value: $[ format('{0}.{1}', format('{0:yyyyMMdd}', pipeline.startTime), counter(format('{0:yyyyMMdd}', pipeline.startTime), 1)) ]
+- name: DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE
+ value: 'true'
+- name: DOTNET_SDK_VULNERABILITY_CHECK_DISABLE
+ value: 'true'
# Override for internal pipeline
- name: DefaultJavaSdkMajorVersion
value: 21
@@ -270,6 +285,329 @@ stages:
- template: /build-tools/automation/yaml-templates/fail-on-issue.yaml
+# Signing and Visual Studio workload insertion artifacts
+- stage: dotnet_prepare_release
+ displayName: Prepare .NET Release
+ dependsOn:
+ - mac_build
+ - linux_build
+ condition: and(
+ succeeded(),
+ ne(variables['Build.Reason'], 'PullRequest'),
+ ne(variables['Build.Reason'], 'Schedule')
+ )
+ jobs:
+ - template: /eng/common/templates/jobs/jobs.yml@self
+ parameters:
+ runAsPublic: false
+ enableMicrobuild: true
+ microbuildUseESRP: ${{ and(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), ne(variables['Build.Reason'], 'PullRequest')) }}
+ jobs:
+ - job: prepare_release
+ displayName: Sign NuGets and workload MSIs
+ timeoutInMinutes: 240
+ pool:
+ name: $(NetCoreInternalPoolName)
+ demands:
+ - ImageOverride -equals $(WindowsPoolImageNetCoreInternal)
+ workspace:
+ clean: all
+ steps:
+ - checkout: self
+ clean: true
+ fetchDepth: 1
+ fetchTags: false
+ path: s/android
+
+ - checkout: android-tools
+ path: s/android-tools
+
+ - task: DownloadPipelineArtifact@2
+ displayName: Download unsigned macOS and Windows packages
+ inputs:
+ artifactName: $(NuGetArtifactName)
+ downloadPath: $(Build.StagingDirectory)\unsigned\mac-win
+
+ - task: DownloadPipelineArtifact@2
+ displayName: Download unsigned Linux packages
+ inputs:
+ artifactName: $(LinuxNuGetArtifactName)
+ downloadPath: $(Build.StagingDirectory)\unsigned\linux
+
+ - task: UseDotNet@2
+ displayName: Install .NET 8 SDK for SwixBuild
+ inputs:
+ version: 8.0.x
+
+ - task: UseDotNet@2
+ displayName: Install .NET SDK for Arcade signing
+ inputs:
+ version: $(DotNetSdkVersion).x
+ includePreviewVersions: true
+
+ - pwsh: |
+ $unsigned = "$(Build.StagingDirectory)\unsigned"
+ $artifacts = "$(Build.SourcesDirectory)\android\artifacts"
+ $shipping = Join-Path $artifacts "packages\Release\Shipping"
+ $logs = Join-Path $artifacts "log\Release"
+ $signingLogs = "$(Build.StagingDirectory)\signing-logs"
+
+ Remove-Item $artifacts -Recurse -Force -ErrorAction Ignore
+ New-Item $shipping -ItemType Directory -Force | Out-Null
+ New-Item $logs -ItemType Directory -Force | Out-Null
+ New-Item $signingLogs -ItemType Directory -Force | Out-Null
+
+ $packages = @(Get-ChildItem $unsigned -Filter "*.nupkg" -File -Recurse)
+ if ($packages.Count -eq 0) {
+ throw "The build did not publish any NuGet packages."
+ }
+ Copy-Item $packages.FullName $shipping
+
+ $workloadProps = Get-ChildItem $unsigned -Filter "vs-workload.props" -File -Recurse | Select-Object -First 1
+ if (-not $workloadProps) {
+ throw "The build did not publish vs-workload.props."
+ }
+ Copy-Item $workloadProps.FullName $shipping
+
+ $signList = Get-ChildItem $unsigned -Filter "SignList.xml" -File -Recurse | Select-Object -First 1
+ if (-not $signList) {
+ throw "The build did not publish SignList.xml."
+ }
+
+ [xml] $arcadeSignList = Get-Content $signList.FullName
+ $packageEntries = foreach ($package in $packages) {
+ $archive = [IO.Compression.ZipFile]::OpenRead($package.FullName)
+ try {
+ foreach ($entry in $archive.Entries) {
+ [pscustomobject]@{
+ FullName = $entry.FullName.Replace("\", "/")
+ Name = $entry.Name
+ }
+ }
+ } finally {
+ $archive.Dispose()
+ }
+ }
+
+ foreach ($item in @($arcadeSignList.SelectNodes("/Project/ItemGroup/*[@Include]"))) {
+ $include = $item.GetAttribute("Include").Replace("\", "/")
+ if ($include.Contains("*") -or $include.Contains("?")) {
+ $matchedEntries = if ($include.Contains("/")) {
+ @($packageEntries | Where-Object { $_.FullName -like $include -or $_.FullName -like "*/$include" })
+ } else {
+ @($packageEntries | Where-Object { $_.Name -like $include })
+ }
+ $names = @($matchedEntries.Name | Where-Object { $_ } | Sort-Object -Unique)
+ if ($names.Count -eq 0) {
+ throw "Signing pattern '$include' did not match any package entries."
+ }
+ foreach ($name in $names) {
+ $expandedItem = $item.Clone()
+ $escapedName = $name.Replace("%", "%25").Replace(";", "%3B")
+ $expandedItem.SetAttribute("Include", $escapedName)
+ [void] $item.ParentNode.InsertBefore($expandedItem, $item)
+ }
+ [void] $item.ParentNode.RemoveChild($item)
+ } else {
+ if ($item.LocalName -eq "MacDeveloperSign" -or $item.LocalName -eq "MacDeveloperSignHarden") {
+ $include = [IO.Path]::GetFileName($include)
+ }
+ $include = $include.Replace("%", "%25").Replace(";", "%3B")
+ $item.SetAttribute("Include", $include)
+ }
+ }
+
+ $skipNames = @($arcadeSignList.SelectNodes("/Project/ItemGroup/Skip") | ForEach-Object Include)
+ foreach ($item in @($arcadeSignList.SelectNodes("/Project/ItemGroup/MacDeveloperSign | /Project/ItemGroup/MacDeveloperSignHarden"))) {
+ if ($item.GetAttribute("Include") -in $skipNames) {
+ [void] $item.ParentNode.RemoveChild($item)
+ }
+ }
+
+ $certificatesByName = @{}
+ foreach ($item in $arcadeSignList.SelectNodes("/Project/ItemGroup/ThirdParty | /Project/ItemGroup/ThirdPartyScript | /Project/ItemGroup/MacDeveloperSign | /Project/ItemGroup/MacDeveloperSignHarden")) {
+ $name = $item.GetAttribute("Include")
+ $certificateGroup = $item.LocalName
+ if ($certificatesByName.ContainsKey($name) -and $certificatesByName[$name] -ne $certificateGroup) {
+ throw "Signing entry '$name' is assigned to both '$($certificatesByName[$name])' and '$certificateGroup'."
+ }
+ $certificatesByName[$name] = $certificateGroup
+ }
+
+ $arcadeSignListPath = "$(Build.StagingDirectory)\ArcadeSignList.xml"
+ $arcadeSignList.Save($arcadeSignListPath)
+ Write-Host "##vso[task.setvariable variable=AndroidSignList]$arcadeSignListPath"
+
+ $signVerify = Get-ChildItem $unsigned -Filter "SignVerifyIgnore.txt" -File -Recurse | Select-Object -First 1
+ if (-not $signVerify) {
+ throw "The build did not publish SignVerifyIgnore.txt."
+ }
+ Copy-Item $signVerify.FullName "$(Build.StagingDirectory)\SignVerifyIgnore.txt"
+
+ $inputNames = $packages.Name | Sort-Object -Unique
+ $inputNames | ConvertTo-Json | Set-Content "$(Build.StagingDirectory)\unsigned-package-names.json"
+
+ $shortHash = "$(Build.SourceVersion)".Substring(0, 7)
+ Write-Host "##vso[task.setvariable variable=BUILD_SOURCEVERSIONSHORT]$shortHash"
+ displayName: Normalize unsigned artifacts for Arcade
+
+ - pwsh: |
+ $adapter = "$(Agent.TempDirectory)\android-arcade"
+ Remove-Item $adapter -Recurse -Force -ErrorAction Ignore
+ Copy-Item "$(Build.SourcesDirectory)\android\build-tools\automation\dnceng\arcade" $adapter -Recurse
+ Copy-Item "$(Build.SourcesDirectory)\android\eng\common" "$adapter\eng\common" -Recurse
+
+ $globalJson = Get-Content "$(Build.SourcesDirectory)\android\global.json" -Raw | ConvertFrom-Json -AsHashtable
+ $globalJson["tools"] = [ordered]@{
+ dotnet = (& dotnet --version)
+ }
+ $globalJson | ConvertTo-Json -Depth 5 | Set-Content "$adapter\global.json"
+
+ Write-Host "##vso[task.setvariable variable=ArcadeAdapterRoot]$adapter"
+ displayName: Prepare isolated Arcade adapter
+
+ - pwsh: |
+ $properties = @(
+ "/p:RepositoryEngineeringDir=$(ArcadeAdapterRoot)\eng\",
+ "/p:AndroidRepoRoot=$(Build.SourcesDirectory)\android",
+ "/p:AndroidSignList=$(AndroidSignList)",
+ "/p:ArtifactsDir=$(Build.SourcesDirectory)\android\artifacts\",
+ "/p:NuGetPackageRoot=$(Build.SourcesDirectory)\android\.packages\",
+ "/p:RestorePackagesPath=$(Build.SourcesDirectory)\android\.packages\",
+ "/p:RestoreConfigFile=$(Build.SourcesDirectory)\android\NuGet.config",
+ "/p:OfficialBuildId=$(_BuildOfficialId)",
+ "/p:DotNetSignType=$(_SignType)",
+ "/p:MicroBuildOverridePluginDirectory=$(Agent.TempDirectory)\MicroBuild\Plugins",
+ "/p:RepositoryName=dotnet/android"
+ )
+
+ & "$(ArcadeAdapterRoot)\eng\common\build.ps1" `
+ -configuration Release `
+ -msbuildEngine dotnet `
+ -projects "$(ArcadeAdapterRoot)\Workloads.proj" `
+ -restore `
+ -sign `
+ -ci `
+ -warnAsError:$false `
+ -binaryLogName "$(Build.StagingDirectory)\signing-logs\sign-nugets.binlog" `
+ @properties
+ displayName: Sign prebuilt NuGet packages with Arcade
+ env:
+ BUILD_REPOSITORY_NAME: dotnet/android
+ BUILD_REPOSITORY_URI: https://github.com/dotnet/android
+ NUGET_CONFIG: $(Build.SourcesDirectory)\android\NuGet.config
+ NUGET_PACKAGES: $(Build.SourcesDirectory)\android\.packages
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - pwsh: |
+ $properties = @(
+ "/p:RepositoryEngineeringDir=$(ArcadeAdapterRoot)\eng\",
+ "/p:AndroidRepoRoot=$(Build.SourcesDirectory)\android",
+ "/p:AndroidSignList=$(AndroidSignList)",
+ "/p:ArtifactsDir=$(Build.SourcesDirectory)\android\artifacts\",
+ "/p:NuGetPackageRoot=$(Build.SourcesDirectory)\android\.packages\",
+ "/p:RestorePackagesPath=$(Build.SourcesDirectory)\android\.packages\",
+ "/p:RestoreConfigFile=$(Build.SourcesDirectory)\android\NuGet.config",
+ "/p:OfficialBuildId=$(_BuildOfficialId)",
+ "/p:DotNetSignType=$(_SignType)",
+ "/p:SignWorkloadMsis=true",
+ "/p:MicroBuildOverridePluginDirectory=$(Agent.TempDirectory)\MicroBuild\Plugins",
+ "/p:RepositoryName=dotnet/android"
+ )
+
+ & "$(ArcadeAdapterRoot)\eng\common\build.ps1" `
+ -configuration Release `
+ -msbuildEngine dotnet `
+ -projects "$(ArcadeAdapterRoot)\Workloads.proj" `
+ -build `
+ -sign `
+ -ci `
+ -warnAsError:$false `
+ -binaryLogName "$(Build.StagingDirectory)\signing-logs\workload-msis.binlog" `
+ @properties
+ displayName: Build and sign workload MSIs with Arcade
+ env:
+ BUILD_REPOSITORY_NAME: dotnet/android
+ BUILD_REPOSITORY_URI: https://github.com/dotnet/android
+ NUGET_CONFIG: $(Build.SourcesDirectory)\android\NuGet.config
+ NUGET_PACKAGES: $(Build.SourcesDirectory)\android\.packages
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - pwsh: |
+ $properties = @(
+ "/p:RepositoryEngineeringDir=$(ArcadeAdapterRoot)\eng\",
+ "/p:AndroidRepoRoot=$(Build.SourcesDirectory)\android",
+ "/p:AndroidSignList=$(AndroidSignList)",
+ "/p:ArtifactsDir=$(Build.SourcesDirectory)\android\artifacts\",
+ "/p:NuGetPackageRoot=$(Build.SourcesDirectory)\android\.packages\",
+ "/p:RestorePackagesPath=$(Build.SourcesDirectory)\android\.packages\",
+ "/p:RestoreConfigFile=$(Build.SourcesDirectory)\android\NuGet.config",
+ "/p:OfficialBuildId=$(_BuildOfficialId)",
+ "/p:DotNetSignType=$(_SignType)",
+ "/p:MicroBuildOverridePluginDirectory=$(Agent.TempDirectory)\MicroBuild\Plugins",
+ "/p:RepositoryName=dotnet/android"
+ )
+
+ & "$(ArcadeAdapterRoot)\eng\common\build.ps1" `
+ -configuration Release `
+ -msbuildEngine dotnet `
+ -projects "$(ArcadeAdapterRoot)\Workloads.proj" `
+ -sign `
+ -ci `
+ -warnAsError:$false `
+ -binaryLogName "$(Build.StagingDirectory)\signing-logs\sign-msi-nugets.binlog" `
+ @properties
+ displayName: Sign workload MSI NuGet packages with Arcade
+ env:
+ BUILD_REPOSITORY_NAME: dotnet/android
+ BUILD_REPOSITORY_URI: https://github.com/dotnet/android
+ NUGET_CONFIG: $(Build.SourcesDirectory)\android\NuGet.config
+ NUGET_PACKAGES: $(Build.SourcesDirectory)\android\.packages
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+
+ - pwsh: |
+ $shipping = "$(Build.SourcesDirectory)\android\artifacts\packages\Release\Shipping"
+ $inputNames = @(Get-Content "$(Build.StagingDirectory)\unsigned-package-names.json" -Raw | ConvertFrom-Json)
+ foreach ($name in $inputNames) {
+ if (-not (Test-Path (Join-Path $shipping $name) -PathType Leaf)) {
+ throw "Signed output is missing '$name'."
+ }
+ }
+
+ $msiPackages = @(Get-ChildItem $shipping -Filter "*.nupkg" -File |
+ Where-Object { $_.Name -notin $inputNames })
+ if ($msiPackages.Count -eq 0) {
+ throw "The workload build did not generate any MSI NuGet packages."
+ }
+
+ $msiDirectory = "$(Build.StagingDirectory)\msi-nupkgs"
+ New-Item $msiDirectory -ItemType Directory -Force | Out-Null
+ Copy-Item $msiPackages.FullName $msiDirectory
+ displayName: Validate signed package outputs
+
+ - task: MicroBuildCodesignVerify@3
+ displayName: Verify signed workload artifacts
+ inputs:
+ TargetFolders: |
+ $(Build.SourcesDirectory)\android\artifacts\packages\Release\Shipping\manifests
+ $(Build.SourcesDirectory)\android\artifacts\packages\Release\Shipping\manifests-packs
+ $(Build.StagingDirectory)\msi-nupkgs
+ ExcludeSNVerify: true
+ ApprovalListPathForCerts: $(Build.StagingDirectory)\SignVerifyIgnore.txt
+
+ - task: PublishPipelineArtifact@1
+ displayName: Publish signed NuGet packages
+ inputs:
+ artifactName: nuget-signed
+ targetPath: $(Build.SourcesDirectory)\android\artifacts\packages\Release\Shipping
+
+ - task: PublishPipelineArtifact@1
+ displayName: Publish signing logs
+ condition: always()
+ inputs:
+ artifactName: signing-logs-$(System.StageAttempt)-$(System.JobAttempt)
+ targetPath: $(Build.StagingDirectory)\signing-logs
+
# MSBuild Tests Stage
- stage: msbuild_dotnet
displayName: MSBuild Tests
diff --git a/build-tools/automation/dnceng/arcade/Workloads.proj b/build-tools/automation/dnceng/arcade/Workloads.proj
new file mode 100644
index 00000000000..f1502298e8a
--- /dev/null
+++ b/build-tools/automation/dnceng/arcade/Workloads.proj
@@ -0,0 +1,218 @@
+
+
+ false
+ false
+ $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)', '..', '..', '..', '..'))
+
+
+
+
+
+ netstandard2.0
+ false
+ false
+ <_ArtifactsDir>$([MSBuild]::EnsureTrailingSlash('$(ArtifactsDir)'))
+ $(_ArtifactsDir)packages\Release\
+ $(ArtifactsPackagesDir)Shipping\
+ $(_ArtifactsDir)log\Release\
+ $(ArtifactsLogDir)workload-msi
+ $(_ArtifactsDir)obj\Release\
+ $(_ArtifactsDir)workload-msi\
+ $(IntermediateOutputPath)WorkloadOutputs.props
+ $(MSBuildThisFileDirectory)vsman\Workload.vsmanproj
+ $(ArtifactsShippingPackagesDir)\manifests
+ $(ArtifactsShippingPackagesDir)\manifests-pre
+ $(ArtifactsShippingPackagesDir)\manifests-packs
+ $(ArtifactsShippingPackagesDir)
+ $(ArtifactsShippingPackagesDir)
+ $(ArtifactsShippingPackagesDir)\vs-workload.props
+ 11.0.0-beta.26325.102
+ 1.1.922
+ 6.0.3-dotnet.4
+ 6.0.3-dotnet.4
+ 6.0.3-dotnet.4
+ 3.1.7
+ net$(BundledNETCoreAppTargetFrameworkVersion)
+ $(BUILD_BUILDID)
+ $(BUILD_SOURCEVERSIONSHORT)/$(BUILD_BUILDID)
+ $(PkgMicrosoft_VisualStudioEng_MicroBuild_Plugins_SwixBuild)\build\Microsoft.VisualStudioEng.MicroBuild.Plugins.SwixBuild.targets
+ $(PkgMicrosoft_Wix)\tools\net6.0\any\wix.exe
+ $(PkgMicrosoft_WixToolset_Heat)\tools\net472\x64\heat.exe
+ wixext6
+
+
+
+
+
+
+ false
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_PreviewMatch>$([System.Text.RegularExpressions.Regex]::Match(%(WorkloadPackages.Identity), `\-(preview|rc|ci.+).\d+`))
+ <_NuGetVersion>$([System.Version]::Parse('%(WorkloadPackages.Version)').Major).$([System.Version]::Parse('%(WorkloadPackages.Version)').Minor).$([System.Version]::Parse('%(WorkloadPackages.Version)').Build)
+
+
+ %(WorkloadPackages._NuGetVersion)
+
+
+
+
+
+
+ 5
+ 1996-04-01
+
+
+
+
+
+
+
+
+
+
+ $(_GeneratedMsiVersion)
+
+
+
+ <_GeneratedMsiVersion />
+
+
+
+
+
+ <_VSWherePath>$([MSBuild]::NormalizePath('$(Pkgvswhere)', 'tools', 'vswhere.exe'))
+
+
+
+
+
+ <_DesktopMSBuildPath>$(_VSInstallDirectory)\MSBuild\Current\Bin\MSBuild.exe
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_WorkloadOutputLines Include="<Project>" />
+ <_WorkloadOutputLines Include=" <ItemGroup>" />
+ <_WorkloadOutputLines Include="@(_WorkloadMsis->' <_WorkloadMsis Include="%(Identity)" PackageProject="%(PackageProject)" />')" />
+ <_WorkloadOutputLines Include="@(_SwixProjects->' <_SwixProjects Include="%(Identity)" PackageType="%(PackageType)" IsPreview="%(IsPreview)" />')" />
+ <_WorkloadOutputLines Include=" </ItemGroup>" />
+ <_WorkloadOutputLines Include="</Project>" />
+
+
+
+
+
+
+
+
+
+ <_PackProjects Include="@(_SwixProjects)" Condition="'%(PackageType)' == 'msi-pack'"
+ ManifestOutputPath="$(PackManifestOutputPath)"
+ LogGroup="packs"
+ ZipFile="Workload.VSDrop.$(TargetName).packs.zip" />
+ <_ComponentProjects Include="@(_SwixProjects)" Condition="'%(PackageType)' == 'msi-manifest' or '%(PackageType)' == 'manifest-package-group' or ('%(PackageType)' == 'component' and '%(IsPreview)' != 'true')"
+ ManifestOutputPath="$(ManifestOutputPath)"
+ LogGroup="components"
+ ZipFile="Workload.VSDrop.$(TargetName).components.zip" />
+ <_PreviewComponentProjects Include="@(_SwixProjects)" Condition="'%(PackageType)' == 'msi-manifest' or '%(PackageType)' == 'manifest-package-group' or ('%(PackageType)' == 'component' and '%(IsPreview)' == 'true')"
+ ManifestOutputPath="$(PreviewManifestOutputPath)"
+ LogGroup="components-pre"
+ ZipFile="Workload.VSDrop.$(TargetName)-pre.components.zip" />
+ <_InsertionProjects Include="@(_PackProjects);@(_ComponentProjects);@(_PreviewComponentProjects)" />
+
+
+
+ <_Drop Include="%(_InsertionProjects.ZipFile)" SourceDirectory="%(ManifestOutputPath)" />
+ <_DropMetadata Include="$(ManifestBuildVersion);$(BUILD_REPOSITORY_NAME);$(BUILD_SOURCEBRANCH)" />
+
+
+
+
+ <_VsmanArguments>"$(_DesktopMSBuildPath)" "$(VsmanProject)" /nologo /v:normal /nr:false /t:GenerateSetupManifest /p:SwixBuildTargets="$(SwixTargetsPath)" /p:WorkloadMsiGenProps="$(WorkloadMsiGenProps)"
+
+
+
+
+ <_PreviewManifests Include="$(PreviewManifestOutputPath)\*" />
+
+
+
+
+
+
+
+
+ _GenerateAndSignMsis;AfterBuild
+
+
diff --git a/build-tools/automation/dnceng/arcade/eng/AfterSigning.targets b/build-tools/automation/dnceng/arcade/eng/AfterSigning.targets
new file mode 100644
index 00000000000..e9034897aa2
--- /dev/null
+++ b/build-tools/automation/dnceng/arcade/eng/AfterSigning.targets
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/build-tools/automation/dnceng/arcade/eng/Signing.props b/build-tools/automation/dnceng/arcade/eng/Signing.props
new file mode 100644
index 00000000000..205700afe05
--- /dev/null
+++ b/build-tools/automation/dnceng/arcade/eng/Signing.props
@@ -0,0 +1,27 @@
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build-tools/automation/dnceng/arcade/vsman/Workload.vsmanproj b/build-tools/automation/dnceng/arcade/vsman/Workload.vsmanproj
new file mode 100644
index 00000000000..75a71f68aa4
--- /dev/null
+++ b/build-tools/automation/dnceng/arcade/vsman/Workload.vsmanproj
@@ -0,0 +1,83 @@
+
+
+
+ netstandard2.0
+ false
+ false
+ false
+ build-manifest
+ true
+ false
+ DotNetOptionalWorkloads
+ vs
+ 42.42.42
+ true
+ $(ManifestOutputPath)
+
+
+
+
+
+ $(TargetName).$(ManifestNameSuffix)
+ $(TargetName)
+ $(SYSTEM_TEAMPROJECT)
+ $(BUILD_REPOSITORY_NAME)
+ $(BUILD_SOURCEBRANCHNAME)
+ $(BUILD_BUILDID)
+ Products/$(ManifestTeamProject)/$(ManifestRepositoryName)/$(ManifestBuildBranch)
+ $(ManifestDropNameRoot)/$(ManifestBuildNumber)
+ $(ManifestDropNameRoot)/$(ManifestNameSuffix)/$(ManifestBuildNumber)
+ https://vsdrop.corp.microsoft.com/file/v1/$(ManifestDropName);
+ $(OutputPath)\obj\$(MSBuildProjectName)
+
+
+
+
+ /
+
+
+ /CHS/
+
+
+ /CHT/
+
+
+ /CSY/
+
+
+ /DEU/
+
+
+ /ENU/
+
+
+ /ESN/
+
+
+ /FRA/
+
+
+ /ITA/
+
+
+ /JPN/
+
+
+ /KOR/
+
+
+ /PLK/
+
+
+ /PTB/
+
+
+ /RUS/
+
+
+ /TRK/
+
+
+
+
+
diff --git a/build-tools/automation/dnceng/arcade/vsman/global.json b/build-tools/automation/dnceng/arcade/vsman/global.json
new file mode 100644
index 00000000000..ae9f38c48f8
--- /dev/null
+++ b/build-tools/automation/dnceng/arcade/vsman/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "version": "8.0.400",
+ "rollForward": "latestFeature"
+ }
+}