diff --git a/Documentation/OneLocBuild.md b/Documentation/OneLocBuild.md
index 6ff500455d2..0cc4f6858a9 100644
--- a/Documentation/OneLocBuild.md
+++ b/Documentation/OneLocBuild.md
@@ -26,6 +26,7 @@ you will want to conditionalize this step with the following:
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
```
To prevent OneLocBuild from running in the public project where it will fail.
+
3. Run the pipeline you want to use OneLocBuild on your test branch.
4. Open a ticket with the localization team using
[this template](https://ceapex.visualstudio.com/CEINTL/_workitems/create/Loc%20Request?templateId=60b0dcf9-9892-4910-934e-d5becddd1bc1&ownerId=c2e38d3d-0e9e-429f-955d-6e39fc6f0457).
diff --git a/Documentation/Projects/Build Analysis/BuildRetryOnboard.md b/Documentation/Projects/Build Analysis/BuildRetryOnboard.md
new file mode 100644
index 00000000000..b13ca0a1cb2
--- /dev/null
+++ b/Documentation/Projects/Build Analysis/BuildRetryOnboard.md
@@ -0,0 +1,106 @@
+# Build Retry
+
+## How it works?
+
+
+The build retry feature is composed of two parts.
+
+The first one is having the build configuration file as part of the build artifacts. In order to have this in place it is necessary to follow the [onboarding process](#how-to-onboard).
+
+The second part is what is done by the Build Result Analysis. When the build finishes, it starts getting processed. If it failed, the build is analyzed to see if it can be retried. In order to be retried, at least one of the rules specified in a build configuration file needs to be met.
+## How to onboard?
+1. In order to use the Build Retry feature it's necessary to have the `.NET Helix` GitHub application installed in the repo in which you intend to use the feature.
+If you want to get the application installed, you can contact the [.NET Core Engineering Services team](https://github.com/dotnet/core-eng/wiki/How-to-get-a-hold-of-Engineering-Servicing)
+
+
+1. Create the [build configuration file](#Build-configuration-file-structure). The name of the file should be: `build-configuration.json` and you can create the file inside any folder. That folder is the one that you are going to publish.
+Ex. \eng\BuildConfiguration\build-configuration.json
+1. [Publish an artifact having the `build-configuration.json` file to Azure Pipeline](https://docs.microsoft.com/en-us/azure/devops/pipelines/artifacts/pipeline-artifacts) in the repo that you are expecting to get retry. The name of the artifact should be: `BuildConfiguration`
+
+ Ex.
+ ```
+ - publish: $(Build.SourcesDirectory)\eng\BuildConfiguration
+ artifact: BuildConfiguration
+ ```
+
+## Build configuration file structure
+```json
+{
+ "RetryCountLimit":1,
+ "RetryByAnyError":false,
+ "RetryByErrors":[
+ {
+ "ErrorRegex":"Regex"
+ }
+ ],
+ "RetryByPipeline":{
+ "RetryJobs":[
+ {
+ "JobName":"JobName"
+ }
+ ],
+ "RetryStages":[
+ {
+ "StageName":"StageName"
+ }
+ ]
+ }
+}
+```
+
+- **RetryCountLimit:** Number of retries that can be done on your build.
+Ex. "RetryCountLimit": 1 means is going to be retried 1 time by the Build Result Analysis giving a total of 2 executions.
+Default value: 0. Max internal value: 10.
+
+- **RetryByAnyError:** The build is going to be retried independently of which was the reason of the failure.
+Default value: False.
+
+- **RetryByErrors:** List of 'ErrorRegex' (.NET flavor) that will look for a match on the build pipeline errors. In case there is an error matching the regex the build is going to be retried.
+
+ Ex.
+ In order to retry a build with the following pipeline errors
+ 
+ you could have a file with the following information:
+ ```json
+ {
+ "RetryCountLimit":1,
+ "RetryByErrors":[
+ {
+ "ErrorRegex":"Vstest failed with error.*"
+ }
+ ]
+ }
+ ```
+
+- **RetryByPipeline:** The retry by pipeline is expecting a list of Jobs or/and Stages names which in case on fail should cause a retry by the Build Result Analysis.
+
+ The job names reference are the ones on the pipeline:
+ Ex.
+ 
+ ```json
+ {
+ "RetryCountLimit":1,
+ "RetryByPipeline":{
+ "RetryJobs":[
+ {
+ "JobName":"Validate_Test_Failing"
+ }
+ ]
+ }
+ }
+ ```
+ The stage name references are the ones on the yaml
+ Ex.
+ 
+ ```json
+ {
+ "RetryCountLimit":1,
+ "RetryByPipeline":{
+ "RetryStages":[
+ {
+ "StageName":"Build"
+ }
+ ]
+ }
+ }
+ ```
diff --git a/Documentation/Projects/Build Analysis/Resources/BuildRetryWorkflow.png b/Documentation/Projects/Build Analysis/Resources/BuildRetryWorkflow.png
new file mode 100644
index 00000000000..d0c28da1740
Binary files /dev/null and b/Documentation/Projects/Build Analysis/Resources/BuildRetryWorkflow.png differ
diff --git a/Documentation/Projects/Build Analysis/Resources/JobNameErrorsExample.PNG b/Documentation/Projects/Build Analysis/Resources/JobNameErrorsExample.PNG
new file mode 100644
index 00000000000..3762a96ae63
Binary files /dev/null and b/Documentation/Projects/Build Analysis/Resources/JobNameErrorsExample.PNG differ
diff --git a/Documentation/Projects/Build Analysis/Resources/PipelineErrorsExample.PNG b/Documentation/Projects/Build Analysis/Resources/PipelineErrorsExample.PNG
new file mode 100644
index 00000000000..c5e0b6a9abd
Binary files /dev/null and b/Documentation/Projects/Build Analysis/Resources/PipelineErrorsExample.PNG differ
diff --git a/Documentation/Projects/Build Analysis/Resources/StageNameExample.PNG b/Documentation/Projects/Build Analysis/Resources/StageNameExample.PNG
new file mode 100644
index 00000000000..35141ed2fb8
Binary files /dev/null and b/Documentation/Projects/Build Analysis/Resources/StageNameExample.PNG differ
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 0bba4f3181d..31e3239b4d1 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -26,6 +26,12 @@ stages:
- stage: build
displayName: Build
jobs:
+ - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.SourceBranch'], 'refs/heads/main')) }}:
+ - template: /eng/common/templates/job/onelocbuild.yml
+ parameters:
+ MirrorRepo: arcade
+ LclSource: lclFilesFromPackage
+ LclPackageId: 'LCL-JUNO-PROD-ARCADE'
- template: /eng/common/templates/jobs/jobs.yml
parameters:
artifacts:
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 39f757d7cac..43c15427e49 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -11,25 +11,25 @@
-
+
https://github.com/dotnet/arcade
- a68ec1edf328e737b31a09cb49e1929c28e91d0c
+ 615fbd8c498067deae160a696701eaf33155da56
-
+
https://github.com/dotnet/arcade
- a68ec1edf328e737b31a09cb49e1929c28e91d0c
+ 615fbd8c498067deae160a696701eaf33155da56
-
+
https://github.com/dotnet/arcade
- a68ec1edf328e737b31a09cb49e1929c28e91d0c
+ 615fbd8c498067deae160a696701eaf33155da56
-
+
https://github.com/dotnet/arcade
- a68ec1edf328e737b31a09cb49e1929c28e91d0c
+ 615fbd8c498067deae160a696701eaf33155da56
-
+
https://github.com/dotnet/arcade
- a68ec1edf328e737b31a09cb49e1929c28e91d0c
+ 615fbd8c498067deae160a696701eaf33155da56
https://github.com/dotnet/arcade-services
@@ -39,17 +39,17 @@
https://github.com/dotnet/arcade-services
cac955fe259cb611f6a29d09209bd717deb69037
-
+
https://github.com/dotnet/xharness
- 0bc5e50dff0583fda68f52cfcd39c253e0dacbbe
+ 32c37bf7374fc77ef79255c8126d34c7a00cf78e
-
+
https://github.com/dotnet/roslyn
- 7ceb633154acb9d716fd3eb2b6df1a0468d8e416
+ 246ce641f04b67ef017655275d850bf902a8e40f
-
+
https://github.com/mono/linker
- 1c0138c71850bdab14d740e9c4c8808ed034dc51
+ 41fd293dda27c099b063f51d8917e607271a508e
https://github.com/dotnet/sourcelink
@@ -68,9 +68,9 @@
https://github.com/dotnet/symreader-converter
c5ba7c88f92e2dde156c324a8c8edc04d9fa4fe0
-
+
https://github.com/dotnet/xliff-tasks
- 71c811561ad4dcf46825a5077fbcc668ab74754f
+ 68c1b83a228fc70d4b2e8f11954ab4883e1f5a77
diff --git a/eng/Versions.props b/eng/Versions.props
index 2b1ab748514..132e20de59f 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -34,8 +34,8 @@
2.0.0
2.1.1
2.1.0
- 3.10.0-4.21318.11
- 6.0.100-preview.6.21327.1
+ 3.10.0-4.21329.37
+ 6.0.100-preview.6.21355.2
16.7.1
4.8.3
5.3.0.1
@@ -65,8 +65,8 @@
2.4.1
2.0.3
2.4.1
- 6.0.0-beta.21324.3
- 6.0.0-beta.21324.3
+ 6.0.0-beta.21355.2
+ 6.0.0-beta.21355.2
1.22.0
1.1.2
2.0.0
@@ -77,10 +77,10 @@
1.1.0-beta.20258.6
1.1.0-beta-21309-01
1.1.0-beta-21309-01
- 6.0.0-beta.21324.3
- 1.0.0-beta.21325.1
+ 6.0.0-beta.21355.2
+ 1.0.0-beta.21356.1
1.1.0-beta.21228.1
- 1.0.0-prerelease.21328.2
+ 1.0.0-prerelease.21351.2
1.1.156602
1.1.156602
6.0.100-preview.5.21254.11
diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1
index a0b5fc37f43..18823840b11 100644
--- a/eng/common/SetupNugetSources.ps1
+++ b/eng/common/SetupNugetSources.ps1
@@ -158,4 +158,10 @@ if ($dotnet5Source -ne $null) {
AddPackageSource -Sources $sources -SourceName "dotnet5-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-transport/nuget/v2" -Creds $creds -Username $userName -Password $Password
}
+$dotnet6Source = $sources.SelectSingleNode("add[@key='dotnet6']")
+if ($dotnet6Source -ne $null) {
+ AddPackageSource -Sources $sources -SourceName "dotnet6-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v2" -Creds $creds -Username $userName -Password $Password
+ AddPackageSource -Sources $sources -SourceName "dotnet6-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v2" -Creds $creds -Username $userName -Password $Password
+}
+
$doc.Save($filename)
diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh
index 2734601c13c..ad3fb74fd2c 100755
--- a/eng/common/SetupNugetSources.sh
+++ b/eng/common/SetupNugetSources.sh
@@ -129,6 +129,30 @@ if [ "$?" == "0" ]; then
PackageSources+=('dotnet5-internal-transport')
fi
+# Ensure dotnet6-internal and dotnet6-internal-transport are in the packageSources if the public dotnet6 feeds are present
+grep -i ""
+
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ fi
+ PackageSources+=('dotnet6-internal')
+
+ grep -i "" $ConfigFile
+ if [ "$?" != "0" ]; then
+ echo "Adding dotnet6-internal-transport to the packageSources."
+ PackageSourcesNodeFooter=""
+ PackageSourceTemplate="${TB}"
+
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ fi
+ PackageSources+=('dotnet6-internal-transport')
+fi
+
# I want things split line by line
PrevIFS=$IFS
IFS=$'\n'
diff --git a/global.json b/global.json
index 42eee1cae04..fc72486e109 100644
--- a/global.json
+++ b/global.json
@@ -3,7 +3,7 @@
"dotnet": "6.0.100-preview.4.21255.9"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21324.3",
- "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21324.3"
+ "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21355.2",
+ "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21355.2"
}
}
diff --git a/scripts/create-net6-preview-flow.ps1 b/scripts/create-net6-preview-flow.ps1
index d67150a11d7..c5a25d9f562 100644
--- a/scripts/create-net6-preview-flow.ps1
+++ b/scripts/create-net6-preview-flow.ps1
@@ -4,7 +4,10 @@ param
[Parameter(Mandatory=$true)][string]$SdkChannel,
[Parameter(Mandatory=$true)][string]$RuntimeBranch,
[Parameter(Mandatory=$true)][string]$SdkBranch,
- [Parameter(Mandatory=$true)][string]$VSChannel
+ [Parameter(Mandatory=$true)][string]$VSChannel,
+ [switch]$AddInternalFlow,
+ [string]$InternalRuntimeChannel,
+ [string]$InternalSdkChannel
)
function MakeDefaultChannel($repo, $branch, $channel)
@@ -13,18 +16,37 @@ function MakeDefaultChannel($repo, $branch, $channel)
& darc add-default-channel --repo "$repo" --branch "$branch" --channel "$channel" --quiet
}
+function DisableFlow($channel)
+{
+ Write-Host "Disabling flow on $channel"
+ & darc subscription-status --disable --channel "$channel" --quiet --exact
+}
+
function AddFlow($sourceRepo, $sourceChannel, $targetRepo, $targetBranch, $frequency)
{
Write-Host "Adding flow - $sourceRepo @ $sourceChannel -> $targetRepo @ $targetBranch ($frequency)"
& darc add-subscription --source-repo "$sourceRepo" --channel "$sourceChannel" --target-repo "$targetRepo" --target-branch "$targetBranch" --update-frequency "$frequency" --quiet --no-trigger --standard-automerge
}
+function AddBatchedFlow($sourceRepo, $sourceChannel, $targetRepo, $targetBranch, $frequency)
+{
+ Write-Host "Adding flow - $sourceRepo @ $sourceChannel -> $targetRepo @ $targetBranch ($frequency)"
+ & darc add-subscription --source-repo "$sourceRepo" --channel "$sourceChannel" --target-repo "$targetRepo" --target-branch "$targetBranch" --update-frequency "$frequency" --quiet --no-trigger --batchable
+}
+
+function AddBatchedMergePolicy($targetRepo, $targetBranch)
+{
+ Write-Host "Setting batched merge policy for $targetRepo @ $targetBranch"
+ & darc set-repository-policies --repo "$targetRepo" --branch "$targetBranch" --standard-automerge --quiet
+}
+
function AddArcadeFlow($targetRepo, $targetBranch)
{
AddFlow https://github.com/dotnet/arcade ".NET Eng - Latest" $targetRepo $targetBranch None
}
-# Make default channels
+$InternalRuntimeBranch = "internal/$RuntimeBranch"
+$InternalSdkBranch = "internal/$SdkBranch"
Write-Host "Making default channels for runtime repos"
MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int $RuntimeBranch $RuntimeChannel
@@ -38,15 +60,42 @@ MakeDefaultChannel https://github.com/dotnet/wpf $RuntimeBranch $RuntimeChannel
MakeDefaultChannel https://github.com/dotnet/winforms $RuntimeBranch $RuntimeChannel
MakeDefaultChannel https://github.com/mono/linker $RuntimeBranch $RuntimeChannel
+if ($AddInternalFlow) {
+ # Because of where internal fixes tend to be, we eliminate some leaves in the graph
+ # and flow them through the normal public channels: emsdk, icu, linker.
+ # wpf-int gets assigned to the internal channel in addition (since there is no public->internal merge)
+ Write-Host "Making default channels for internal branches of runtime repos"
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int $RuntimeBranch $InternalRuntimeChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore $InternalRuntimeBranch $InternalRuntimeChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-efcore $InternalRuntimeBranch $InternalRuntimeChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-runtime $InternalRuntimeBranch $InternalRuntimeChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop $InternalRuntimeBranch $InternalRuntimeChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-wpf $InternalRuntimeBranch $InternalRuntimeChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-winforms $InternalRuntimeBranch $InternalRuntimeChannel
+}
+
Write-Host "Making default channels for SDK repos"
MakeDefaultChannel https://github.com/dotnet/installer $SdkBranch $SdkChannel
MakeDefaultChannel https://github.com/dotnet/sdk $SdkBranch $SdkChannel
MakeDefaultChannel https://github.com/dotnet/roslyn-analyzers $SdkBranch $SdkChannel
MakeDefaultChannel https://github.com/dotnet/templating $SdkBranch $SdkChannel
-# Make dependency flow
+if ($AddInternalFlow) {
+ # Because of where internal fixes tend to be, we eliminate some leaves in the sdk graph
+ # and flow them through the normal public channels: templating, roslyn-analyzers
+ Write-Host "Making default channels for SDK repos"
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-installer $InternalSdkBranch $InternalSdkChannel
+ MakeDefaultChannel https://dev.azure.com/dnceng/internal/_git/dotnet-sdk $InternalSdkBranch $InternalSdkChannel
+}
+
+Write-Host "Setting up batched merge policies"
+AddBatchedMergePolicy https://github.com/dotnet/aspnetcore $RuntimeBranch
-Write-Host "Add arcade flow"
+if ($AddInternalFlow) {
+ AddBatchedMergePolicy https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore $InternalRuntimeBranch
+}
+
+Write-Host "Adding arcade flow"
AddArcadeFlow https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int $RuntimeBranch
AddArcadeFlow https://github.com/dotnet/aspnetcore $RuntimeBranch
AddArcadeFlow https://github.com/dotnet/efcore $RuntimeBranch
@@ -62,31 +111,64 @@ AddArcadeFlow https://github.com/dotnet/sdk $SdkBranch
AddArcadeFlow https://github.com/dotnet/roslyn-analyzers $SdkBranch
AddArcadeFlow https://github.com/dotnet/templating $SdkBranch
-Write-Host "Add runtime -> runtime flow"
+Write-Host "Adding runtime -> runtime flow"
AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int $RuntimeChannel https://github.com/dotnet/wpf $RuntimeBranch EveryBuild
-AddFlow https://github.com/dotnet/efcore $RuntimeChannel https://github.com/dotnet/aspnetcore $RuntimeBranch EveryBuild
-AddFlow https://github.com/dotnet/emsdk $RuntimeChannel https://github.com/dotnet/aspnetcore $RuntimeBranch EveryBuild
+AddBatchedFlow https://github.com/dotnet/efcore $RuntimeChannel https://github.com/dotnet/aspnetcore $RuntimeBranch EveryBuild
+AddBatchedFlow https://github.com/dotnet/emsdk $RuntimeChannel https://github.com/dotnet/aspnetcore $RuntimeBranch EveryBuild
AddFlow https://github.com/dotnet/emsdk $RuntimeChannel https://github.com/dotnet/runtime $RuntimeBranch EveryBuild
AddFlow https://github.com/dotnet/icu $RuntimeChannel https://github.com/dotnet/runtime $RuntimeBranch EveryBuild
-AddFlow https://github.com/dotnet/runtime $RuntimeChannel https://github.com/dotnet/aspnetcore $RuntimeBranch EveryBuild
+AddBatchedFlow https://github.com/dotnet/runtime $RuntimeChannel https://github.com/dotnet/aspnetcore $RuntimeBranch EveryBuild
AddFlow https://github.com/dotnet/runtime $RuntimeChannel https://github.com/dotnet/efcore $RuntimeBranch EveryBuild
AddFlow https://github.com/dotnet/runtime $RuntimeChannel https://github.com/dotnet/winforms $RuntimeBranch EveryBuild
AddFlow https://github.com/dotnet/winforms $RuntimeChannel https://github.com/dotnet/wpf $RuntimeBranch EveryBuild
AddFlow https://github.com/dotnet/wpf $RuntimeChannel https://github.com/dotnet/windowsdesktop $RuntimeBranch EveryBuild
AddFlow https://github.com/mono/linker $RuntimeChannel https://github.com/dotnet/runtime $RuntimeBranch EveryBuild
+if ($AddInternalFlow) {
+ Write-Host "Adding internal runtime -> internal runtime flow"
+ AddBatchedFlow https://dev.azure.com/dnceng/internal/_git/dotnet-efcore $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore $InternalRuntimeBranch EveryBuild
+ AddBatchedFlow https://dev.azure.com/dnceng/internal/_git/dotnet-runtime $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore $InternalRuntimeBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-wpf-int $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-wpf $InternalRuntimeBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-runtime $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-efcore $InternalRuntimeBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-runtime $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-winforms $InternalRuntimeBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-winforms $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-wpf $InternalRuntimeBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-wpf $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop $InternalRuntimeBranch EveryBuild
+
+ Write-Host "Disabling internal runtime -> internal runtime flow"
+ DisableFlow $InternalRuntimeChannel
+}
+
Write-Host "Add runtime->sdk flow"
AddFlow https://github.com/dotnet/aspnetcore $RuntimeChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
AddFlow https://github.com/dotnet/windowsdesktop $RuntimeChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
AddFlow https://github.com/dotnet/runtime $RuntimeChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
AddFlow https://github.com/mono/linker $RuntimeChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
+if ($AddInternalFlow) {
+ Write-Host "Adding internal runtime->internal sdk flow"
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-sdk $InternalSdkBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-sdk $InternalSdkBranch EveryBuild
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-runtime $InternalRuntimeChannel https://dev.azure.com/dnceng/internal/_git/dotnet-sdk $InternalSdkBranch EveryBuild
+
+ Write-Host "Disabling internal runtime->internal sdk flow"
+ DisableFlow $InternalRuntimeChannel
+}
+
Write-Host "Add sdk->sdk flow"
AddFlow https://github.com/dotnet/sdk $SdkChannel https://github.com/dotnet/installer $SdkBranch EveryBuild
AddFlow https://github.com/dotnet/roslyn-analyzers $SdkChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
AddFlow https://github.com/dotnet/templating $SdkChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
-Write-Host "Add tooling->sdk flow"
+if ($AddInternalFlow) {
+ Write-Host "Adding internal sdk->internal sdk flow"
+ # Nothing but SDK->installer flows internally
+ AddFlow https://dev.azure.com/dnceng/internal/_git/dotnet-sdk $InternalSdkChannel https://dev.azure.com/dnceng/internal/_git/dotnet-installer $InternalSdkBranch EveryBuild
+
+ Write-Host "Disabling internal sdk->internal sdk flow"
+ DisableFlow $InternalSdkChannel
+}
+
+Write-Host "Adding tooling->sdk flow"
AddFlow https://github.com/nuget/nuget.client $VSChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
AddFlow https://github.com/dotnet/roslyn $VSChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
AddFlow https://github.com/dotnet/fsharp $VSChannel https://github.com/dotnet/sdk $SdkBranch EveryBuild
diff --git a/scripts/flip-previewplus-flow.ps1 b/scripts/flip-previewplus-flow.ps1
new file mode 100644
index 00000000000..00ab240dd8f
--- /dev/null
+++ b/scripts/flip-previewplus-flow.ps1
@@ -0,0 +1,50 @@
+param
+(
+ [Parameter(Mandatory=$true)][string]"$RuntimeChannel",
+ [Parameter(Mandatory=$true)][string]"$SdkChannel",
+ [Parameter(Mandatory=$true)][string]"$InternalRuntimeChannel",
+ [Parameter(Mandatory=$true)][string]"$InternalSdkChannel",
+ [Parameter(Mandatory=$true)][ValidateSet('Preview','Preview+')][string]$FlowType,
+ [switch]$TriggerSubscriptions
+)
+
+Write-Host "Switching flow to $FlowType"
+
+switch ( $FlowType )
+{
+ 'Preview' {
+ # Switching to public flow is easy. Enable all the subscriptions in the public runtime and SDK channels
+ # and disable any on the internal channels
+ & darc subscription-status --disable --channel "$InternalRuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --channel "$InternalSdkChannel" --quiet --exact
+ & darc subscription-status --enable --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --enable --channel "$SdkChannel" --quiet --exact
+
+ # Trigger public subscriptions
+ if ($TriggerSubscriptions) {
+ & darc trigger-subscriptions --channel "$RuntimeChannel" --quiet --exact
+ & darc trigger-subscriptions --channel "$SdkChannel" --quiet --exact
+ }
+ }
+ 'Preview+' {
+ # Switching to internal flow is a little more subtle. Enable the internal subscriptions,
+ # then disable the corresponding public subscriptions, which is a subset of the full public channel
+ & darc subscription-status --enable --channel "$InternalRuntimeChannel" --quiet --exact
+ & darc subscription-status --enable --channel "$InternalSdkChannel" --quiet --exact
+
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/runtime --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/winforms --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/wpf --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/windowsdesktop --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/aspnetcore --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/efcore --channel "$RuntimeChannel" --quiet --exact
+ & darc subscription-status --disable --source-repo https://github.com/dotnet/sdk --channel "$SdkChannel" --quiet --exact
+
+ # Trigger internal subscriptions
+ if ($TriggerSubscriptions) {
+ & darc trigger-subscriptions --channel "$InternalRuntimeChannel" --quiet --exact
+ & darc trigger-subscriptions --channel "$InternalSdkChannel" --quiet --exact
+ }
+ }
+ default { Write-Error "Unknown flow type $FlowType" }
+}
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.cs.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.cs.xlf
index 2b886d8a1fa..9955162a2f7 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.cs.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.cs.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # Seznam rozhraní API pro {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ Výpis rozhraní API se řídí standardním formátováním rozdílů.
+Řádky před znakem + jsou přidané a znak - označuje odebrání.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # Rozdíly v rozhraních API mezi {0} a {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.de.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.de.xlf
index 934bce41566..920aaeec945 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.de.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.de.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API Liste von {0}
+ # API-Liste von {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- Die Änderungen sind im standard diff-Format aufgezählt.
-Die API-Zeilen, die mit einem '+' beginnen wurden hinzugefügt und die mit einem '-' wurden entfernt.
+ Die API-Auflistung folgt der Standard-Diff-Formatierung.
+Zeilen, denen ein "+" vorangestellt ist, sind Ergänzungen, und ein "-" gibt das Entfernen an.
# API Difference {0} vs {1}
- # API Änderungen von {0} zu {1}
+ # API-Unterschiede {0} im Vergleich zu {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.es.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.es.xlf
index a95e4aa5cc0..333e4e351b8 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.es.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.es.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # Lista de API de {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ La lista de API sigue el formato de diff estándar.
+Las líneas precedidas por un signo "+" son adiciones y un "-" indica una eliminación.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # Diferencias de API {0} frente a {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.fr.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.fr.xlf
index 3baf33dba93..b3a0136388a 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.fr.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.fr.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # Liste des API de {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ La liste des API respecte la mise en forme diff standard.
+Les lignes précédées d’un signe « + » sont des ajouts et « - » indique une suppression.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # Différence d’API {0} vs {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.it.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.it.xlf
index 1f910332f7e..35d6b35f3e4 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.it.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.it.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # Elenco delle API di {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ Per l'elenco delle API viene usata la formattazione standard delle differenze.
+Le righe precedute dal segno più ('+') sono aggiunte, mentre il segno meno ('-') contraddistingue quelle rimosse.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # Differenza API {0} rispetto a {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ja.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ja.xlf
index a2e082aaadc..dd529a8a0ba 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ja.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ja.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ {0} の # API リスト
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ API 一覧は、標準の差分形式に従います。
+ + ' が続く行は追加、'-' は削除を示します。
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # API 差分 {0} 対 {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ko.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ko.xlf
index 15cd02fd8ba..adbcf69d360 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ko.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ko.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # {0}의 API 목록
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ API 목록은 표준 차이 서식을 따릅니다.
+앞에 '+'로 시작하는 줄은 추가이며 '-'는 제거를 나타냅니다.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # API 차이 {0} 및 {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pl.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pl.xlf
index 262941aec35..05323de3b8a 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pl.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pl.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ Lista interfejsów API # z {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ Lista interfejsów API jest zgodna ze standardowym formatowaniem różnicowym.
+Wiersze poprzedzone znakiem "+" są dodawaniem, a znak "-" wskazuje usuwanie.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ Różnica interfejsu API # {0} w stosunku do {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pt-BR.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pt-BR.xlf
index e481c3ebaae..c5ea35bc9a8 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pt-BR.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.pt-BR.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # Lista de APIs de {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ A listagem da API segue a formatação de comparação padrão.
+Linhas precedidas por '+' são adições e '-' indica remoção.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # Diferença da API {0} vs {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ru.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ru.xlf
index fc2423c0378..9d1156bffe6 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ru.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.ru.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # Список API {0}
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ Списки API следуют стандартному форматированию различий.
+Строки, начинающиеся символом "+", являются дополнениями, а символ "-" означает удаление.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # Различие API {0} и {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.tr.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.tr.xlf
index e690363aed2..2972a564b9d 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.tr.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.tr.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # {0} API listesi
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ API listesi, standart fark biçimlendirmeyi izler.
+Başında '+' olması satırların ekleneceğini, '-' olması ise kaldırılacağını belirtir.
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # {0} ile {1} arasındaki API farkı
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hans.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hans.xlf
index 607aea34bfc..ae88e93fcfe 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hans.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hans.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # API {0} 列表
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ API 列表遵循标准差异格式。
+行前面有 "+" 的是添加,而 "-" 表示删除。
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # API 差异 {0} 与 {1}
diff --git a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hant.xlf b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hant.xlf
index 0435ed37712..837f19474a7 100644
--- a/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hant.xlf
+++ b/src/Microsoft.DotNet.AsmDiff/xlf/Resources.zh-Hant.xlf
@@ -4,19 +4,19 @@
# API List of {0}
- # API List of {0}
+ # {0} 的 API 清單
API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.
- API listing follows standard diff formatting.
-Lines preceded by a '+' are additions and a '-' indicates removal.
+ API 清單遵循標準差異格式。
+前面加上 '+' 的行是加法,而 '-' 表示移除。
# API Difference {0} vs {1}
- # API Difference {0} vs {1}
+ # API 差異 {0} 與 {1}
diff --git a/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/Microsoft.DotNet.Build.Tasks.Feed.Tests.csproj b/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/Microsoft.DotNet.Build.Tasks.Feed.Tests.csproj
index d100e0d8321..548fac7ecdb 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/Microsoft.DotNet.Build.Tasks.Feed.Tests.csproj
+++ b/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/Microsoft.DotNet.Build.Tasks.Feed.Tests.csproj
@@ -38,4 +38,5 @@
Always
+
diff --git a/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/PublishToSymbolServerTest.cs b/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/PublishToSymbolServerTest.cs
index 4b2784921bb..9e08f09b226 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/PublishToSymbolServerTest.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/PublishToSymbolServerTest.cs
@@ -1,6 +1,12 @@
+using System;
using System.Collections.Generic;
using System.IO;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.Arcade.Common;
using Microsoft.Arcade.Test.Common;
+using Microsoft.DotNet.Arcade.Test.Common;
using Microsoft.DotNet.Build.Tasks.Feed.Model;
using Microsoft.DotNet.Maestro.Client.Models;
using Xunit;
@@ -40,7 +46,6 @@ public void PublishToSymbolServersTest(SymbolTargetType symbolTargetType , strin
Assert.True(test.Count == 1);
}
-
[Fact]
public void PublishToBothSymbolServerTest()
{
@@ -139,5 +144,227 @@ public void PublishSymbolApiIsCalledTest()
false,
false).IsCompleted);
}
+
+ [Fact]
+ public void DownloadFileAsyncSucceedsForValidUrl()
+ {
+ var buildEngine = new MockBuildEngine();
+ var publishTask = new PublishArtifactsInManifestV3
+ {
+ BuildEngine = buildEngine,
+ };
+
+ var testFile = Path.Combine("Symbols", "test.txt");
+ var responseContent = TestInputs.ReadAllBytes(testFile);
+ var response = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new ByteArrayContent(responseContent)
+ };
+
+ using HttpClient client = FakeHttpClient.WithResponses(response);
+ var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());
+
+ var test = publishTask.DownloadFileAsync(
+ client,
+ PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
+ "1234",
+ "test.txt",
+ path);
+
+ Assert.True(File.Exists(path));
+ publishTask.DeleteTemporaryFiles(path);
+ publishTask.DeleteTemporaryDirectory(path);
+ }
+
+ [Theory]
+ [InlineData(HttpStatusCode.BadRequest)]
+ [InlineData(HttpStatusCode.NotFound)]
+ [InlineData(HttpStatusCode.GatewayTimeout)]
+ public async Task DownloadFileAsyncFailsForInValidUrlTest(HttpStatusCode httpStatus)
+ {
+ var buildEngine = new MockBuildEngine();
+ var publishTask = new PublishArtifactsInManifestV3
+ {
+ BuildEngine = buildEngine,
+ };
+ var testFile = Path.Combine("Symbols", "test.txt");
+ var responseContent = TestInputs.ReadAllBytes(testFile);
+ publishTask.RetryHandler = new ExponentialRetry() { MaxAttempts = 3, DelayBase = 1 };
+
+ var responses = new[]
+ {
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ }
+ };
+ using HttpClient client = FakeHttpClient.WithResponses(responses);
+ var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());
+
+ var actualError = await Assert.ThrowsAsync(() =>
+ publishTask.DownloadFileAsync(
+ client,
+ PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
+ "1234",
+ "test.txt",
+ path));
+ Assert.Contains($"Failed to download local file '{path}' after {publishTask.RetryHandler.MaxAttempts} attempts. See inner exception for details,", actualError.Message);
+ }
+
+ [Theory]
+ [InlineData(HttpStatusCode.BadRequest)]
+ [InlineData(HttpStatusCode.NotFound)]
+ [InlineData(HttpStatusCode.GatewayTimeout)]
+ public async Task DownloadFailureWhenStatusCodeIsInvalid(HttpStatusCode httpStatus)
+ {
+ var buildEngine = new MockBuildEngine();
+ var publishTask = new PublishArtifactsInManifestV3
+ {
+ BuildEngine = buildEngine,
+ };
+ var testFile = Path.Combine("Symbols", "test.txt");
+ var responseContent = TestInputs.ReadAllBytes(testFile);
+ publishTask.RetryHandler = new ExponentialRetry() { MaxAttempts = 3, DelayBase = 1 };
+
+ var responses = new[]
+ {
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ }
+ };
+ using HttpClient client = FakeHttpClient.WithResponses(responses);
+ var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());
+
+ var actualError = await Assert.ThrowsAsync(() =>
+ publishTask.DownloadFileAsync(
+ client,
+ PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
+ "1234",
+ "test.txt",
+ path));
+ Assert.Contains($"Failed to download local file '{path}' after {publishTask.RetryHandler.MaxAttempts} attempts. See inner exception for details,", actualError.Message);
+ }
+
+ [Theory]
+ [InlineData(HttpStatusCode.BadRequest)]
+ [InlineData(HttpStatusCode.NotFound)]
+ [InlineData(HttpStatusCode.GatewayTimeout)]
+ public async Task DownloadFileSuccessfulAfterRetryTest(HttpStatusCode httpStatus)
+ {
+ var buildEngine = new MockBuildEngine();
+ var publishTask = new PublishArtifactsInManifestV3
+ {
+ BuildEngine = buildEngine,
+ };
+ var testFile = Path.Combine("Symbols", "test.txt");
+ var responseContent = TestInputs.ReadAllBytes(testFile);
+ publishTask.RetryHandler = new ExponentialRetry() { MaxAttempts = 2, DelayBase = 1 };
+
+ var responses = new[]
+ {
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new ByteArrayContent(responseContent)
+ }
+ };
+ using HttpClient client = FakeHttpClient.WithResponses(responses);
+ var path = TestInputs.GetFullPath(Guid.NewGuid().ToString());
+
+ await publishTask.DownloadFileAsync(
+ client,
+ PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts,
+ "1234",
+ "test.txt",
+ path);
+ Assert.True(File.Exists(path));
+ publishTask.DeleteTemporaryFiles(path);
+ publishTask.DeleteTemporaryDirectory(path);
+ }
+
+ [Theory]
+ [InlineData(PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts, "1")]
+ [InlineData(PublishArtifactsInManifestBase.ArtifactName.PackageArtifacts, "1234")]
+ public async Task GetContainerIdToDownloadArtifactAsync(PublishArtifactsInManifestBase.ArtifactName artifactName, string containerId)
+ {
+ var buildEngine = new MockBuildEngine();
+ var publishTask = new PublishArtifactsInManifestV3
+ {
+ BuildEngine = buildEngine,
+ };
+ publishTask.BuildId = "1243456";
+ var testPackageName = Path.Combine("Symbols", "test.txt");
+ var responseContent = TestInputs.ReadAllBytes(testPackageName);
+ var responses = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new ByteArrayContent(responseContent)
+ };
+
+ using HttpClient client = FakeHttpClient.WithResponses(responses);
+ var test = await publishTask.GetContainerIdAsync(
+ client,
+ artifactName);
+ Assert.Equal(containerId, test);
+ }
+
+ [Theory]
+ [InlineData(HttpStatusCode.BadRequest)]
+ [InlineData(HttpStatusCode.NotFound)]
+ public async Task ErrorAfterMaxRetriesToGetContainerId(HttpStatusCode httpStatus)
+ {
+ var buildEngine = new MockBuildEngine();
+ var publishTask = new PublishArtifactsInManifestV3
+ {
+ BuildEngine = buildEngine,
+ };
+ publishTask.BuildId = "1243456";
+ publishTask.RetryHandler = new ExponentialRetry() {MaxAttempts = 3, DelayBase = 1};
+
+ var testPackageName = Path.Combine("Symbols", "test.txt");
+ var responseContent = TestInputs.ReadAllBytes(testPackageName);
+ var responses = new[]
+ {
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ },
+ new HttpResponseMessage(httpStatus)
+ {
+ Content = new ByteArrayContent(responseContent)
+ }
+ };
+
+ using HttpClient client = FakeHttpClient.WithResponses(responses);
+
+ var actualError = await Assert.ThrowsAsync(() =>
+ publishTask.GetContainerIdAsync(
+ client,
+ PublishArtifactsInManifestBase.ArtifactName.BlobArtifacts));
+ Assert.Contains($"Failed to get container id after {publishTask.RetryHandler.MaxAttempts} attempts. See inner exception for details,", actualError.Message);
+ }
}
}
diff --git a/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/TestInputs/Symbols/test.txt b/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/TestInputs/Symbols/test.txt
new file mode 100644
index 00000000000..5a604136aeb
--- /dev/null
+++ b/src/Microsoft.DotNet.Build.Tasks.Feed.Tests/TestInputs/Symbols/test.txt
@@ -0,0 +1,35 @@
+{
+ "count":1,
+ "value":[
+ {
+ "id":2124,
+ "name":"PackageArtifacts",
+ "source":"testSource",
+ "resource":{
+ "type":"Container",
+ "data":"#/1234/PackageArtifacts",
+ "properties":{
+ "localpath":"D:\\workspace\\_work\\1\\s\\artifacts\\output\\packages",
+ "artifactsize":"7644905"
+ },
+ "url":"https://dev.azure.com/dnceng/url",
+ "downloadUrl":"https://dev.azure.com/dnceng/_apis/build/builds/buildId/artifacts?artifactName=PackageArtifacts&api-version=6.0&%24format=zip"
+ }
+ },
+ {
+ "id":2123,
+ "name":"BlobArtifacts",
+ "source":"testSource",
+ "resource":{
+ "type":"Container",
+ "data":"#/1/BlobArtifacts",
+ "properties":{
+ "localpath":"D:\\workspace\\_work\\1\\s\\artifacts\\output\\packages",
+ "artifactsize":"7644905"
+ },
+ "url":"https://dev.azure.com/dnceng/_apis/build/builds/buildId/artifacts?artifactName=BlobArtifacts&api-version=6.0",
+ "downloadUrl":"https://dev.azure.com/dnceng/_apis/build/builds/buildId/artifacts?artifactName=PackageArtifacts&api-version=6.0&%24format=zip"
+ }
+ }
+ ]
+}
diff --git a/src/Microsoft.DotNet.Build.Tasks.Feed/src/PublishArtifactsInManifestBase.cs b/src/Microsoft.DotNet.Build.Tasks.Feed/src/PublishArtifactsInManifestBase.cs
index ddbbadb383a..8670e955c83 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Feed/src/PublishArtifactsInManifestBase.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Feed/src/PublishArtifactsInManifestBase.cs
@@ -185,13 +185,13 @@ public abstract class PublishArtifactsInManifestBase : Microsoft.Build.Utilities
///
public int RetryDelayMilliseconds { get; set; } = 5000;
- public readonly ExponentialRetry RetryHandler = new ExponentialRetry
+ public ExponentialRetry RetryHandler = new ExponentialRetry
{
MaxAttempts = 5,
DelayBase = 2.5 // 2.5 ^ 5 = ~1.5 minutes max wait between retries
};
- private enum ArtifactName
+ public enum ArtifactName
{
[Description("PackageArtifacts")]
PackageArtifacts,
@@ -401,7 +401,9 @@ public async Task PublishSymbolsUsingStreamingAsync(
Log.LogMessage(MessageImportance.High,
$"Performing symbol publishing... \nExpirationInDays : {ExpirationInDays} \nConvertPortablePdbsToWindowsPdb : false \ndryRun: false ");
var symbolCategory = TargetFeedContentType.Symbols;
- string containerId = await GetContainerIdAsync(ArtifactName.BlobArtifacts);
+
+ using HttpClient httpClient = CreateAzdoClient(AzureDevOpsOrg, false, AzureProject);
+ string containerId = await GetContainerIdAsync(httpClient, ArtifactName.BlobArtifacts);
if (Log.HasLoggedErrors)
{
@@ -830,7 +832,7 @@ public HttpClient CreateAzdoClient(
///
/// If it is PackageArtifacts or BlobArtifacts
/// ContainerId
- private async Task GetContainerIdAsync(ArtifactName artifactName)
+ public async Task GetContainerIdAsync(HttpClient client, ArtifactName artifactName)
{
string uri =
$"{AzureDevOpsBaseUrl}/{AzureDevOpsOrg}/{AzureProject}/_apis/build/builds/{BuildId}/artifacts?api-version={AzureDevOpsFeedsApiVersion}";
@@ -843,7 +845,6 @@ private async Task GetContainerIdAsync(ArtifactName artifactName)
CancellationTokenSource timeoutTokenSource =
new CancellationTokenSource(TimeSpan.FromMinutes(TimeoutInMinutes));
- using HttpClient client = CreateAzdoClient(AzureDevOpsOrg, false, AzureProject);
using HttpRequestMessage getMessage = new HttpRequestMessage(HttpMethod.Get, uri);
using HttpResponseMessage response = await client.GetAsync(uri, timeoutTokenSource.Token);
@@ -892,7 +893,7 @@ private async Task GetContainerIdAsync(ArtifactName artifactName)
/// ContainerId where the packageArtifact and BlobArtifacts are stored
/// Name the file we are trying to download
/// Path where the file is being downloaded
- private async Task DownloadFileAsync(
+ public async Task DownloadFileAsync(
HttpClient client,
ArtifactName artifactName,
string containerId,
@@ -1136,7 +1137,8 @@ private async Task PublishPackagesUsingStreamingToAzdoNugetAsync(
TargetFeedConfig feedConfig,
SemaphoreSlim clientThrottle)
{
- string containerId = await GetContainerIdAsync(ArtifactName.PackageArtifacts);
+ using HttpClient httpClient = CreateAzdoClient(AzureDevOpsOrg, false, AzureProject);
+ string containerId = await GetContainerIdAsync(httpClient, ArtifactName.PackageArtifacts);
if (Log.HasLoggedErrors)
{
@@ -1491,7 +1493,8 @@ private async Task PublishBlobsUsingStreamingToAzDoNugetAsync(
TargetFeedConfig feedConfig,
SemaphoreSlim clientThrottle)
{
- string containerId = await GetContainerIdAsync(ArtifactName.BlobArtifacts);
+ using HttpClient httpClient = CreateAzdoClient(AzureDevOpsOrg, false, AzureProject);
+ string containerId = await GetContainerIdAsync(httpClient, ArtifactName.BlobArtifacts);
if (Log.HasLoggedErrors)
{
@@ -1654,7 +1657,8 @@ private async Task PublishBlobsToAzureStorageNugetUsingStreamingPublishingAsync(
TargetFeedConfig feedConfig,
SemaphoreSlim clientThrottle)
{
- string containerId = await GetContainerIdAsync(ArtifactName.BlobArtifacts);
+ using HttpClient httpClient = CreateAzdoClient(AzureDevOpsOrg, false, AzureProject);
+ string containerId = await GetContainerIdAsync(httpClient, ArtifactName.BlobArtifacts);
if (Log.HasLoggedErrors)
{
diff --git a/src/Microsoft.DotNet.Build.Tasks.Feed/src/model/PublishingConstants.cs b/src/Microsoft.DotNet.Build.Tasks.Feed/src/model/PublishingConstants.cs
index 8d2b6673f70..488ca7ee6a5 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Feed/src/model/PublishingConstants.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Feed/src/model/PublishingConstants.cs
@@ -96,9 +96,9 @@ public enum BuildQuality
private const string FeedDotNet6Transport = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-transport/nuget/v3/index.json";
private const string FeedDotNet6Symbols = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-symbols/nuget/v3/index.json";
- private const string FeedDotNet6InternalShipping = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-internal/nuget/v3/index.json";
- private const string FeedDotNet6InternalTransport = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-internal-transport/nuget/v3/index.json";
- private const string FeedDotNet6InternalSymbols = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-internal-symbols/nuget/v3/index.json";
+ private const string FeedDotNet6InternalShipping = "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v3/index.json";
+ private const string FeedDotNet6InternalTransport = "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v3/index.json";
+ private const string FeedDotNet6InternalSymbols = "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-symbols/nuget/v3/index.json";
private const string FeedDotNet5InternalShipping = "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json";
private const string FeedDotNet5InternalTransport = "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-transport/nuget/v3/index.json";
diff --git a/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/README.md b/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/README.md
index 87b98b118c8..38c17756484 100644
--- a/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/README.md
+++ b/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/README.md
@@ -12,6 +12,12 @@ Supports copying to additional paths based on which `TargetFramework` among `Tar
- Metadata:
- TargetPath: when specified can indicate the relative path, including filename, to place the item.
+- BinPlaceDir
+ - Typically specified by the repository to control the output directories of projects. Unlike `BinPlaceTargetFramework` no conditions are applied.
+ - Identity: diretory to copy `BinPlaceItem`s to.
+ - Metadata:
+ - ItemName: An item name to use instead of `BinPlaceItem` for the source of items for this `BinPlaceDir`.
+
- BinPlaceTargetFramework
- Typically specified by the repository to control the output directories of projects.
- Identity: `TargetFramework` to binplace for. A `BinPlaceTargetFramework` is *active* if it is the best `TargetFramework` for the currently building project `TargetFramework`. When active it's behavior is defined by the metaadata below.
diff --git a/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/src/build/BinPlace.targets b/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/src/build/BinPlace.targets
index 6cfaee82e47..940d771be58 100644
--- a/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/src/build/BinPlace.targets
+++ b/src/Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk/src/build/BinPlace.targets
@@ -9,7 +9,7 @@
+ Condition="'$(EnableBinPlacing)' == 'true' OR '@(BinPlaceDir)' != ''" />
+
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/Microsoft.DotNet.Build.Tasks.Workloads.Tests.csproj b/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/Microsoft.DotNet.Build.Tasks.Workloads.Tests.csproj
index 74c5c5e2d05..978754b5ee5 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/Microsoft.DotNet.Build.Tasks.Workloads.Tests.csproj
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/Microsoft.DotNet.Build.Tasks.Workloads.Tests.csproj
@@ -19,4 +19,8 @@
+
+
+
+
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/VisualStudioComponentTests.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/VisualStudioComponentTests.cs
index f7e2c9e0a29..2e4c8c1518a 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/VisualStudioComponentTests.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/VisualStudioComponentTests.cs
@@ -80,6 +80,23 @@ public void ItCreatesSafeComponentIds()
Assert.Contains(@"microsoft.net.sdk.blazorwebassembly.aot", componentSwr);
}
+ [Fact]
+ public void ItCreatesComponentsWhenWorkloadsDoNotIncludePacks()
+ {
+ WorkloadManifest manifest = Create("mauiWorkloadManifest.json");
+ WorkloadDefinition definition = manifest.Workloads.FirstOrDefault().Value;
+ VisualStudioComponent component = VisualStudioComponent.Create(null, manifest, definition, NoItems, NoItems, NoItems, NoItems);
+
+ string swixProjDirectory = RandomPath;
+ Directory.CreateDirectory(swixProjDirectory);
+ component.Generate(swixProjDirectory);
+
+ string componentSwr = File.ReadAllText(Path.Combine(swixProjDirectory, "component.swr"));
+
+ Assert.Contains(@"vs.dependency id=maui.mobile", componentSwr);
+ Assert.Contains(@"vs.dependency id=maui.desktop", componentSwr);
+ }
+
private static WorkloadManifest Create(string filename)
{
return WorkloadManifestReader.ReadWorkloadManifest(Path.GetFileNameWithoutExtension(filename),
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/testassets/mauiWorkloadManifest.json b/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/testassets/mauiWorkloadManifest.json
new file mode 100644
index 00000000000..03e0b1a5285
--- /dev/null
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads.Tests/testassets/mauiWorkloadManifest.json
@@ -0,0 +1,12 @@
+{
+ "version": "6.0.100-preview.6.891",
+ "workloads": {
+ "maui": {
+ "description": ".NET MAUI SDK for all platforms",
+ "extends": [
+ "maui-mobile",
+ "maui-desktop"
+ ]
+ }
+ }
+}
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs
index 899f010c8b2..16bee2bad66 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs
@@ -184,7 +184,7 @@ public override bool Execute()
candle.PreprocessorDefinitions.Add($@"ProductCode={productCode}");
candle.PreprocessorDefinitions.Add($@"UpgradeCode={upgradeCode}");
// Override the default provider key
- candle.PreprocessorDefinitions.Add($@"DependencyProviderKey={nupkg.Id},{platform}");
+ candle.PreprocessorDefinitions.Add($@"DependencyProviderKeyName={ManifestId},{SdkFeatureBandVersion},{platform}");
candle.PreprocessorDefinitions.Add($@"ProductName={productName}");
candle.PreprocessorDefinitions.Add($@"Platform={platform}");
candle.PreprocessorDefinitions.Add($@"SourceDir={packageContentsDataDirectory}");
@@ -281,10 +281,10 @@ private string GeneratePackageProject(string msiPath, string msiJsonPath, string
Directory.CreateDirectory(msiPackageProjectDir);
- EmbeddedTemplates.Extract("Icon.png", msiPackageProjectDir);
- EmbeddedTemplates.Extract("LICENSE.TXT", msiPackageProjectDir);
-
- string licenseTextPath = Path.Combine(msiPackageProjectDir, "LICENSE.TXT");
+ string iconFileName = "Icon.png";
+ string licenseFileName = "LICENSE.TXT";
+ EmbeddedTemplates.Extract(iconFileName, msiPackageProjectDir);
+ EmbeddedTemplates.Extract(licenseFileName, msiPackageProjectDir);
XmlWriterSettings settings = new XmlWriterSettings
{
@@ -326,7 +326,8 @@ private string GeneratePackageProject(string msiPath, string msiJsonPath, string
writer.WriteStartElement("ItemGroup");
WriteItem(writer, "None", msiPath, @"\data");
WriteItem(writer, "None", msiJsonPath, @"\data\msi.json");
- WriteItem(writer, "None", licenseTextPath, @"\");
+ WriteItem(writer, "None", iconFileName, string.Empty);
+ WriteItem(writer, "None", licenseFileName, @"\");
writer.WriteEndElement();
writer.WriteEndElement();
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs
index 246e6d52b31..62fcf789438 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs
@@ -307,10 +307,10 @@ private string GeneratePackageProject(string msiPath, string msiJsonPath, string
Directory.CreateDirectory(msiPackageProjectDir);
- EmbeddedTemplates.Extract("Icon.png", msiPackageProjectDir);
- EmbeddedTemplates.Extract("LICENSE.TXT", msiPackageProjectDir);
-
- string licenseTextPath = Path.Combine(msiPackageProjectDir, "LICENSE.TXT");
+ string iconFileName = "Icon.png";
+ string licenseFileName = "LICENSE.TXT";
+ EmbeddedTemplates.Extract(iconFileName, msiPackageProjectDir);
+ EmbeddedTemplates.Extract(licenseFileName, msiPackageProjectDir);
XmlWriterSettings settings = new XmlWriterSettings
{
@@ -352,7 +352,8 @@ private string GeneratePackageProject(string msiPath, string msiJsonPath, string
writer.WriteStartElement("ItemGroup");
WriteItem(writer, "None", msiPath, @"\data");
WriteItem(writer, "None", msiJsonPath, @"\data\msi.json");
- WriteItem(writer, "None", licenseTextPath, @"\");
+ WriteItem(writer, "None", iconFileName, string.Empty);
+ WriteItem(writer, "None", licenseFileName, @"\");
writer.WriteEndElement();
writer.WriteEndElement();
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateWorkloadMsis.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateWorkloadMsis.cs
index f55d7355f6a..6f34c971a29 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateWorkloadMsis.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateWorkloadMsis.cs
@@ -117,7 +117,7 @@ private IEnumerable GetWorkloadPacks()
Select(w => w.Value).
Where(wd => (wd.Platforms == null) || wd.Platforms.Any(p => p.StartsWith("win")));
- var packIds = workloads.SelectMany(w => w.Packs).Distinct();
+ var packIds = workloads.Where(w => w.Packs != null).SelectMany(w => w.Packs).Distinct();
return manifests.SelectMany(m => m.Packs.Values).
Where(p => packIds.Contains(p.Id)).
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs
index 66cbae46436..574cbe373b1 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs
@@ -6,8 +6,10 @@
-
-
+
+
+
+
diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/VisualStudioComponent.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/VisualStudioComponent.cs
index ee7e9d6d39c..b6d523fb38e 100644
--- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/VisualStudioComponent.cs
+++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/VisualStudioComponent.cs
@@ -254,14 +254,17 @@ public static VisualStudioComponent Create(TaskLoggingHelper log, WorkloadManife
}
}
- // Visual Studio is case-insensitive.
- IEnumerable packIds = workload.Packs.Where(p => !missingPackIds.Contains($"{p}", StringComparer.OrdinalIgnoreCase));
- log?.LogMessage(MessageImportance.Low, $"Packs: {string.Join(", ", packIds.Select(p=>$"{p}"))}");
-
- foreach (WorkloadPackId packId in packIds)
+ if (workload.Packs != null)
{
- log?.LogMessage(MessageImportance.Low, $"Adding component dependency for {packId} ");
- component.AddDependency(manifest.Packs[packId]);
+ // Visual Studio is case-insensitive.
+ IEnumerable packIds = workload.Packs.Where(p => !missingPackIds.Contains($"{p}", StringComparer.OrdinalIgnoreCase));
+ log?.LogMessage(MessageImportance.Low, $"Packs: {string.Join(", ", packIds.Select(p => $"{p}"))}");
+
+ foreach (WorkloadPackId packId in packIds)
+ {
+ log?.LogMessage(MessageImportance.Low, $"Adding component dependency for {packId} ");
+ component.AddDependency(manifest.Packs[packId]);
+ }
}
return component;
diff --git a/src/Microsoft.DotNet.CMake.Sdk/build/Microsoft.DotNet.CMake.Sdk.targets b/src/Microsoft.DotNet.CMake.Sdk/build/Microsoft.DotNet.CMake.Sdk.targets
index 50567ff2682..0fa9a659f9e 100644
--- a/src/Microsoft.DotNet.CMake.Sdk/build/Microsoft.DotNet.CMake.Sdk.targets
+++ b/src/Microsoft.DotNet.CMake.Sdk/build/Microsoft.DotNet.CMake.Sdk.targets
@@ -31,7 +31,7 @@
<_CMakeMultiConfigurationGenerator>true
<_CMakePassArchitectureToGenerator>true
- [15,17.0)
+ [15,18.0)
Win32
@@ -50,6 +50,7 @@
Visual Studio 16 2019
+ Visual Studio 17 2022