diff --git a/NuGet.config b/NuGet.config index 680903c31d7e..4aee2671f707 100644 --- a/NuGet.config +++ b/NuGet.config @@ -24,8 +24,10 @@ + + @@ -35,11 +37,13 @@ + + @@ -68,10 +72,13 @@ + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1dde3cc070eb..67d6a8cc66e2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -15,42 +15,42 @@ b73682307aa0128c5edbec94c2e6a070d13ae6bb - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 @@ -59,14 +59,14 @@ https://github.com/dotnet/core-setup 7d57652f33493fa022125b7f63aad0d70c52d810 - + https://github.com/dotnet/emsdk - b634e009d59f72e9254f984a6b89e685955e0eb8 + 8e475db5d45016c77714cce29077ae8c66d12d53 - + https://github.com/dotnet/emsdk - b634e009d59f72e9254f984a6b89e685955e0eb8 + 8e475db5d45016c77714cce29077ae8c66d12d53 @@ -131,13 +131,13 @@ https://github.com/dotnet/roslyn 450493a9b4ec6337bced0120e97cb76f4ed783db - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 https://dev.azure.com/devdiv/DevDiv/_git/NuGet-NuGet.Client-Trusted @@ -226,99 +226,99 @@ 51441adcd6c424ae7315d66ce7e96baf34d70369 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 9c74c8784a90d64bcc5c5c552d5420eafb60fa4f + 889bd3cf7e1c61b6bdee233190da4931118b6e6d - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 9c74c8784a90d64bcc5c5c552d5420eafb60fa4f + 889bd3cf7e1c61b6bdee233190da4931118b6e6d - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 9c74c8784a90d64bcc5c5c552d5420eafb60fa4f + 889bd3cf7e1c61b6bdee233190da4931118b6e6d - + https://dev.azure.com/dnceng/internal/_git/dotnet-windowsdesktop - 9c74c8784a90d64bcc5c5c552d5420eafb60fa4f + 889bd3cf7e1c61b6bdee233190da4931118b6e6d - + https://dev.azure.com/dnceng/internal/_git/dotnet-wpf - a865df6e83bf8b34bbd6802fdcf25c5cdfb05191 + 15c7bd7f92ae827be47bfb0ca16660f8cd376189 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 @@ -339,30 +339,30 @@ 41f3afd466695ac2460260431537fe4d779ff446 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-winforms - 4569ad0b3bd84191660c74228ad6d18d29fbc1cb + fa8da0fffee2a42efa08aac643276cd0c482c49c - + https://dev.azure.com/dnceng/internal/_git/dotnet-wpf - a865df6e83bf8b34bbd6802fdcf25c5cdfb05191 + 15c7bd7f92ae827be47bfb0ca16660f8cd376189 https://github.com/dotnet/xdt @@ -411,9 +411,9 @@ - - https://github.com/dotnet/source-build-externals - 71dbdccd13f28cfd1a35649263b55ebbeab26ee7 + + https://dev.azure.com/dnceng/internal/_git/dotnet-source-build-externals + 9c6c10cce644179b2f41cbb8064f07efee903c55 @@ -469,89 +469,89 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-aspnetcore - 5edf41b9c09952f18e404ad38e25670991c1b513 + a95d6599f37762ec8394ba9ca01e8263b2e36a26 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 @@ -585,9 +585,9 @@ efce34e9f9f25af27e2b471fbbf8c21f1ac2e318 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - f2c8152eed158e72950025393fde498c90a57a6b + d839c41c85988aadc213e8e42269ecd7883a1790 https://github.com/dotnet/arcade-services diff --git a/eng/Versions.props b/eng/Versions.props index 01e04e02af6e..4baa32be194b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -81,61 +81,61 @@ - 9.0.17-servicing.26265.1 + 9.0.18-servicing.26316.2 - 9.0.17 - 9.0.17-servicing.26264.16 - 9.0.17 - 9.0.17 - 9.0.17-servicing.26264.16 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 + 9.0.18 + 9.0.18-servicing.26315.22 + 9.0.18 + 9.0.18 + 9.0.18-servicing.26315.22 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 8.0.0-rc.1.23414.4 - 9.0.17-servicing.26264.16 - 9.0.17-servicing.26264.16 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 + 9.0.18-servicing.26315.22 + 9.0.18-servicing.26315.22 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 2.1.0 - 9.0.17 + 9.0.18 8.0.0 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 8.0.0 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 - 9.0.17 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 + 9.0.18 4.5.1 4.5.5 8.0.5 4.5.4 - 9.0.17 - 9.0.17 + 9.0.18 + 9.0.18 - 9.0.17-servicing.26268.1 - 9.0.17-servicing.26268.1 - 9.0.17 - 9.0.17 + 9.0.18-servicing.26317.1 + 9.0.18-servicing.26317.1 + 9.0.18 + 9.0.18 @@ -217,19 +217,19 @@ - 9.0.17 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17 - 9.0.17 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 - 9.0.17-servicing.26269.7 + 9.0.18 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18 + 9.0.18 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 + 9.0.18-servicing.26323.11 @@ -239,8 +239,8 @@ - 9.0.17-rtm.26267.1 - 9.0.17-rtm.26267.1 + 9.0.18-rtm.26316.5 + 9.0.18-rtm.26316.5 @@ -319,7 +319,7 @@ 15.0.9617 18.0.9617 - 9.0.17 + 9.0.18 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100PackageVersion) 9.0.100$([System.Text.RegularExpressions.Regex]::Match($(EmscriptenWorkloadManifestVersion), `-(?!rtm)[A-z]*[\.]*\d*`)) diff --git a/eng/pipelines/templates/jobs/vmr-synchronization.yml b/eng/pipelines/templates/jobs/vmr-synchronization.yml index 94d3331e2f62..c568ad296ac4 100644 --- a/eng/pipelines/templates/jobs/vmr-synchronization.yml +++ b/eng/pipelines/templates/jobs/vmr-synchronization.yml @@ -1,93 +1,107 @@ -### This job synchronizes code from product repositories into the VMR (https://github.com/dotnet/dotnet) -### It synchronizes the content of the VMR to this new commit and pushes the changes - -parameters: -- name: targetRef - displayName: Target revision of dotnet/sdk to synchronize - type: string - default: $(Build.SourceVersion) - -- name: vmrBranch - displayName: dotnet/dotnet branch to use - type: string - default: $(Build.SourceBranch) - -- name: noPush - displayName: Don't push changes to dotnet/dotnet - type: boolean - default: false - -jobs: -- job: Synchronize_VMR - displayName: Synchronize VMR's ${{ parameters.vmrBranch }} - timeoutInMinutes: 120 - variables: - - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - template: /eng/common/templates/variables/pool-providers.yml - - ${{ else }}: - - template: /eng/common/templates-official/variables/pool-providers.yml - - name: vmrPath - value: $(Agent.BuildDirectory)/vmr - - ${{ if not(parameters.noPush) }}: - - ${{ if and( eq(variables['System.TeamProject'], 'internal'), or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - - group: DotNetBot-GitHub - - group: DotNetBot-GitHub-No-Scopes - - name: vmrPublicUrl - value: https://github.com/dotnet/dotnet - - ${{ if and( eq(variables['System.TeamProject'], 'internal'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/')) }}: - - name: vmrInternalUrl - value: https://dnceng@dev.azure.com/dnceng/internal/_git/dotnet-dotnet - - pool: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: $(DncEngPublicBuildPool) - image: build.azurelinux.3.amd64.open - os: linux - ${{ else }}: - name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals build.azurelinux.3.amd64 - os: linux - - steps: - - template: ../steps/vmr-prepare.yml - parameters: - vmrBranch: ${{ parameters.vmrBranch }} - - - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - template: /eng/common/templates-official/steps/get-federated-access-token.yml - parameters: - federatedServiceConnection: VmrSyncPipeline - outputVariableName: AzdoToken - - - template: ../steps/vmr-pull-updates.yml - parameters: - vmrPath: $(vmrPath) - vmrBranch: ${{ parameters.vmrBranch }} - targetRef: ${{ parameters.targetRef }} - - - ${{ if and(not(parameters.noPush), not(in(variables['Build.Reason'], 'PullRequest')), eq(variables['System.TeamProject'], 'internal')) }}: - # Push main and release branches to the public VMR - - ${{ if or(eq(parameters.vmrBranch, 'main'), startsWith(parameters.vmrBranch, 'release/')) }}: - - script: > - ./.dotnet/dotnet darc vmr push - --vmr '$(vmrPath)' - --commit-verification-pat '$(BotAccount-dotnet-maestro-bot-no-scopes-PAT)' - --branch '${{ parameters.vmrBranch }}' - --remote-url '$(vmrPublicUrl)' - --github-pat '$(BotAccount-dotnet-bot-repo-PAT)' - --verbose - displayName: Push changes to dotnet/dotnet (public) - workingDirectory: $(Agent.BuildDirectory)/sdk - - # Push internal/release branches to the internal VMR - - ${{ if startsWith(parameters.vmrBranch, 'internal/release/') }}: - - script: > - ./.dotnet/dotnet darc vmr push - --vmr '$(vmrPath)' - --skip-commit-verification - --branch '${{ parameters.vmrBranch }}' - --remote-url '$(vmrInternalUrl)' - --azdev-pat '$(AzdoToken)' - --verbose - displayName: Push changes to dotnet-dotnet (internal) - workingDirectory: $(Agent.BuildDirectory)/sdk +### This job synchronizes code from product repositories into the VMR (https://github.com/dotnet/dotnet) +### It synchronizes the content of the VMR to this new commit and pushes the changes + +parameters: +- name: targetRef + displayName: Target revision of dotnet/sdk to synchronize + type: string + default: $(Build.SourceVersion) + +- name: vmrBranch + displayName: dotnet/dotnet branch to use + type: string + default: $(Build.SourceBranch) + +- name: noPush + displayName: Don't push changes to dotnet/dotnet + type: boolean + default: false + +jobs: +- job: Synchronize_VMR + displayName: Synchronize VMR's ${{ parameters.vmrBranch }} + timeoutInMinutes: 120 + variables: + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - template: /eng/common/templates/variables/pool-providers.yml + - ${{ else }}: + - template: /eng/common/templates-official/variables/pool-providers.yml + - name: vmrPath + value: $(Agent.BuildDirectory)/vmr + - ${{ if not(parameters.noPush) }}: + - ${{ if and( eq(variables['System.TeamProject'], 'internal'), or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: + - group: DotNetBot-GitHub + - group: DotNetBot-GitHub-No-Scopes + - name: vmrPublicUrl + value: https://github.com/dotnet/dotnet + - ${{ if and( eq(variables['System.TeamProject'], 'internal'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/')) }}: + - name: vmrInternalUrl + value: https://dnceng@dev.azure.com/dnceng/internal/_git/dotnet-dotnet + + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: $(DncEngPublicBuildPool) + image: build.azurelinux.3.amd64.open + os: linux + ${{ else }}: + name: $(DncEngInternalBuildPool) + demands: ImageOverride -equals build.azurelinux.3.amd64 + os: linux + + steps: + - template: ../steps/vmr-prepare.yml + parameters: + vmrBranch: ${{ parameters.vmrBranch }} + + - ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - task: AzureCLI@2 + displayName: 'Mint AzDO token for VMR push' + inputs: + azureSubscription: 'dnceng-build-rw-code-rw-wif' + scriptType: 'pscore' + scriptLocation: 'inlineScript' + inlineScript: | + $token = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to acquire Azure DevOps access token via 'az account get-access-token'. Exit code: $LASTEXITCODE" + exit 1 + } + $token = $token.Trim() + if ([string]::IsNullOrWhiteSpace($token)) { + Write-Error "Received an empty or whitespace Azure DevOps access token from 'az account get-access-token'." + exit 1 + } + Write-Host "##vso[task.setvariable variable=AzdoToken;issecret=true]$token" + + - template: ../steps/vmr-pull-updates.yml + parameters: + vmrPath: $(vmrPath) + vmrBranch: ${{ parameters.vmrBranch }} + targetRef: ${{ parameters.targetRef }} + + - ${{ if and(not(parameters.noPush), not(in(variables['Build.Reason'], 'PullRequest')), eq(variables['System.TeamProject'], 'internal')) }}: + # Push main and release branches to the public VMR + - ${{ if or(eq(parameters.vmrBranch, 'main'), startsWith(parameters.vmrBranch, 'release/')) }}: + - script: > + ./.dotnet/dotnet darc vmr push + --vmr '$(vmrPath)' + --commit-verification-pat '$(BotAccount-dotnet-maestro-bot-no-scopes-PAT)' + --branch '${{ parameters.vmrBranch }}' + --remote-url '$(vmrPublicUrl)' + --github-pat '$(BotAccount-dotnet-bot-repo-PAT)' + --verbose + displayName: Push changes to dotnet/dotnet (public) + workingDirectory: $(Agent.BuildDirectory)/sdk + + # Push internal/release branches to the internal VMR + - ${{ if startsWith(parameters.vmrBranch, 'internal/release/') }}: + - script: > + ./.dotnet/dotnet darc vmr push + --vmr '$(vmrPath)' + --skip-commit-verification + --branch '${{ parameters.vmrBranch }}' + --remote-url '$(vmrInternalUrl)' + --azdev-pat '$(AzdoToken)' + --verbose + displayName: Push changes to dotnet-dotnet (internal) + workingDirectory: $(Agent.BuildDirectory)/sdk diff --git a/src/Containers/Microsoft.NET.Build.Containers/ContentStore.cs b/src/Containers/Microsoft.NET.Build.Containers/ContentStore.cs index 2fb16be3ec5d..488764482f27 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/ContentStore.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/ContentStore.cs @@ -8,30 +8,18 @@ namespace Microsoft.NET.Build.Containers; internal static class ContentStore { - public static string ArtifactRoot { get; set; } = Path.Combine(Path.GetTempPath(), "Containers"); + public static string ArtifactRoot { get; set; } = EnsureCacheDirectory(); public static string ContentRoot { get { string contentPath = Path.Join(ArtifactRoot, "Content"); - - Directory.CreateDirectory(contentPath); - + CreateCacheDirectory(contentPath); return contentPath; } } - public static string TempPath - { - get - { - string tempPath = Path.Join(ArtifactRoot, "Temp"); - - Directory.CreateDirectory(tempPath); - - return tempPath; - } - } + public static string TempPath { get; } = Directory.CreateTempSubdirectory().FullName; public static string PathForDescriptor(Descriptor descriptor) { @@ -62,8 +50,81 @@ public static string GetPathForHash(string contentHash) return Path.Combine(ContentRoot, contentHash); } - public static string GetTempFile() + public static string GetTempFile() => Path.Join(TempPath, Path.GetRandomFileName()); + + /// + /// Gets the path to the user cache directory for SDK container builds, creating it if it does + /// not already exist. + /// + private static string EnsureCacheDirectory() + { + string userCacheDir = GetUserCacheDirectoryPath(); + CreateCacheDirectory(userCacheDir); + + string dotnetCacheDir = Path.Join(userCacheDir, "dotnet"); + CreateCacheDirectory(dotnetCacheDir); + + string containersCacheDir = Path.Join(dotnetCacheDir, "Containers"); + CreateCacheDirectory(containersCacheDir); + + return containersCacheDir; + } + + /// + /// Creates a cache directory with user-scoped permissions based on the OS. + /// + /// + /// Permissions are only set for the leaf directory. The caller is expected to handle + /// permissions for intermediate directories. + /// + private static void CreateCacheDirectory(string path) + { + if (OperatingSystem.IsWindows()) + { + Directory.CreateDirectory(path); + } + else + { + // Per XDG_CACHE_HOME spec: if the cache directory doesn't exist, try to create it with + // permissions 0700. If it already exists, don't try to change the permissions. + // See https://specifications.freedesktop.org/basedir/latest/#referencing + Directory.CreateDirectory(path, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute); + } + } + + /// + /// Gets the user-scoped cache directory, accounting for OS differences. + /// + private static string GetUserCacheDirectoryPath() { - return Path.Join(TempPath, Path.GetRandomFileName()); + if (OperatingSystem.IsLinux()) + { + // See "XDG Base Directory Specification": + // https://specifications.freedesktop.org/basedir/latest/ + string? xdgCacheHome = Environment.GetEnvironmentVariable("XDG_CACHE_HOME"); + if (!string.IsNullOrEmpty(xdgCacheHome) && Path.IsPathFullyQualified(xdgCacheHome)) + { + return xdgCacheHome; + } + + // From the spec, if XDG_CACHE_HOME is not set then fall back to ~/.cache + string userHomeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + return Path.Join(userHomeDirectory, ".cache"); + } + + if (OperatingSystem.IsMacOS()) + { + // See "macOS Library Directory Details": + // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html + string userHomeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + return Path.Join(userHomeDirectory, "Library", "Caches"); + } + + // On other platforms, use the local application data folder. + string localAppData = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData, + Environment.SpecialFolderOption.DoNotVerify); + + return localAppData; } } diff --git a/src/Containers/Microsoft.NET.Build.Containers/DigestUtils.cs b/src/Containers/Microsoft.NET.Build.Containers/DigestUtils.cs index c0c7e16e6793..862c01298f2d 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/DigestUtils.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/DigestUtils.cs @@ -37,4 +37,17 @@ internal static string GetSha(string str) return Convert.ToHexStringLower(hash); } + + /// + /// Returns the encoded (hash) portion of a digest string as raw bytes. + /// + /// + /// GetEncodedValue("sha256:e3b0c4...") returns the bytes for "e3b0c4...". + /// + internal static byte[] GetEncodedValue(string digest) + { + int separatorIndex = digest.IndexOf(':'); + string encoded = separatorIndex >= 0 ? digest[(separatorIndex + 1)..] : digest; + return Convert.FromHexString(encoded); + } } diff --git a/src/Containers/Microsoft.NET.Build.Containers/Exceptions/InvalidDigestException.cs b/src/Containers/Microsoft.NET.Build.Containers/Exceptions/InvalidDigestException.cs new file mode 100644 index 000000000000..071f07682a99 --- /dev/null +++ b/src/Containers/Microsoft.NET.Build.Containers/Exceptions/InvalidDigestException.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Security.Cryptography; + +namespace Microsoft.NET.Build.Containers; + +internal sealed class InvalidDigestException : Exception +{ + public InvalidDigestException(string message) + : base(message) + { + } + + public static void ThrowIfMismatched(ReadOnlySpan expected, ReadOnlySpan actual) + { + if (!CryptographicOperations.FixedTimeEquals(expected, actual)) + { + string expectedHashString = Convert.ToHexString(expected).ToLowerInvariant(); + string actualHashString = Convert.ToHexString(actual).ToLowerInvariant(); + throw new InvalidDigestException($"Expected {expectedHashString}, got {actualHashString}."); + } + } +} diff --git a/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs b/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs index 3472ba1c53b2..36caa058dd1a 100644 --- a/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs +++ b/src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using Microsoft.NET.Build.Containers.Resources; using NuGet.RuntimeModel; +using System.Security.Cryptography; namespace Microsoft.NET.Build.Containers; @@ -90,7 +91,7 @@ internal sealed class Registry public string RegistryName { get; } internal Registry(string registryName, ILogger logger, IRegistryAPI registryAPI, RegistrySettings? settings = null, Func? retryDelayProvider = null) : - this(new Uri($"https://{registryName}"), logger, registryAPI, settings) + this(new Uri($"https://{registryName}"), logger, registryAPI, settings, retryDelayProvider) { } internal Registry(string registryName, ILogger logger, RegistryMode mode, RegistrySettings? settings = null) : @@ -99,7 +100,7 @@ internal Registry(string registryName, ILogger logger, RegistryMode mode, Regist internal Registry(Uri baseUri, ILogger logger, IRegistryAPI registryAPI, RegistrySettings? settings = null, Func? retryDelayProvider = null) : - this(baseUri, logger, new RegistryApiFactory(registryAPI), settings) + this(baseUri, logger, new RegistryApiFactory(registryAPI), settings, retryDelayProvider) { } internal Registry(Uri baseUri, ILogger logger, RegistryMode mode, RegistrySettings? settings = null) : @@ -408,15 +409,35 @@ public async Task DownloadBlobAsync(string repository, Descriptor descri { cancellationToken.ThrowIfCancellationRequested(); string localPath = ContentStore.PathForDescriptor(descriptor); - - if (File.Exists(localPath)) + + try { - // Assume file is up to date and just return it + var fileStream = File.OpenRead(localPath); + + var actualHash = SHA256.HashData(fileStream); + var expectedHash = DigestUtils.GetEncodedValue(descriptor.Digest); + InvalidDigestException.ThrowIfMismatched(expectedHash, actualHash); + return localPath; } - + catch (DirectoryNotFoundException) + { + // Cache miss + } + catch (FileNotFoundException) + { + // Cache miss + } + catch (InvalidDigestException exception) + { + // Incorrect digest + _logger.LogTrace( + "Digest validation failed for cached blob {1} ({2}), redownloading from registry.", + localPath, exception.Message); + } + string tempTarballPath = ContentStore.GetTempFile(); - + int retryCount = 0; while (retryCount < MaxDownloadRetries) { @@ -424,12 +445,14 @@ public async Task DownloadBlobAsync(string repository, Descriptor descri { // No local copy, so download one using Stream responseStream = await _registryAPI.Blob.GetStreamAsync(repository, descriptor.Digest, cancellationToken).ConfigureAwait(false); - + using (FileStream fs = File.Create(tempTarballPath)) { - await responseStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); + await responseStream + .CopyToAndVerifyAsync(fs, descriptor.Digest, cancellationToken) + .ConfigureAwait(false); } - + // Break the loop if successful break; } @@ -440,16 +463,16 @@ public async Task DownloadBlobAsync(string repository, Descriptor descri { throw new UnableToDownloadFromRepositoryException(repository); } - + _logger.LogTrace("Download attempt {0}/{1} for repository '{2}' failed. Error: {3}", retryCount, MaxDownloadRetries, repository, ex.ToString()); - + // Wait before retrying await Task.Delay(_retryDelayProvider(), cancellationToken).ConfigureAwait(false); } } - + File.Move(tempTarballPath, localPath, overwrite: true); - + return localPath; } @@ -566,7 +589,7 @@ public async Task PushManifestListAsync( _logger.LogInformation(Strings.Registry_TagUploadStarted, tag, RegistryName); await _registryAPI.Manifest.PutAsync(destinationImageReference.Repository, tag, multiArchImage.ImageIndex, multiArchImage.ImageIndexMediaType, cancellationToken).ConfigureAwait(false); _logger.LogInformation(Strings.Registry_TagUploaded, tag, RegistryName); - } + } } public Task PushAsync(BuiltImage builtImage, SourceImageReference source, DestinationImageReference destination, CancellationToken cancellationToken) diff --git a/src/Containers/Microsoft.NET.Build.Containers/StreamExtensions.cs b/src/Containers/Microsoft.NET.Build.Containers/StreamExtensions.cs new file mode 100644 index 000000000000..f66e88080ea8 --- /dev/null +++ b/src/Containers/Microsoft.NET.Build.Containers/StreamExtensions.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Security.Cryptography; + +namespace Microsoft.NET.Build.Containers; + +internal static class StreamExtensions +{ + public static async Task CopyToAndVerifyAsync( + this Stream source, + Stream destination, + string digest, + CancellationToken cancellationToken) + { + byte[] expectedHash = DigestUtils.GetEncodedValue(digest).ToArray(); + + // Assumption: SHA256 is the only supported algorithm. + // See DigestUtils > s_registeredAlgorithms for more details. + using HashAlgorithm hashAlgorithm = SHA256.Create(); + + await using var cryptoStream = new CryptoStream( + stream: source, + transform: hashAlgorithm, + mode: CryptoStreamMode.Read, + // cryptoStream will be disposed at the end of the method, but setting leaveOpen=true + // tells CryptoStream not to dispose the source Stream. The caller is responsible for + // the lifetime of the source Stream. + leaveOpen: true + ); + + await cryptoStream.CopyToAsync(destination, cancellationToken); + + InvalidDigestException.ThrowIfMismatched(expectedHash, hashAlgorithm.Hash ?? []); + } +} diff --git a/test/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs b/test/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs index 0c41f7ddb1b2..ada993249052 100644 --- a/test/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs +++ b/test/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs @@ -552,7 +552,10 @@ public async Task DownloadBlobAsync_RetriesOnFailure() var logger = _loggerFactory.CreateLogger(nameof(DownloadBlobAsync_RetriesOnFailure)); var repoName = "testRepo"; - var descriptor = new Descriptor(SchemaTypes.OciLayerGzipV1, "sha256:testdigest1234", 1234); + // The digest must be the actual SHA-256 of the response bytes so that the internal + // branch's CopyToAndVerifyAsync digest validation passes after the download succeeds. + var responseBytes = new byte[] { 1, 2, 3 }; + var descriptor = new Descriptor(SchemaTypes.OciLayerGzipV1, "sha256:039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81", 1234); var cancellationToken = CancellationToken.None; var mockRegistryAPI = new Mock(MockBehavior.Strict); @@ -560,7 +563,7 @@ public async Task DownloadBlobAsync_RetriesOnFailure() .SetupSequence(api => api.Blob.GetStreamAsync(repoName, descriptor.Digest, cancellationToken)) .ThrowsAsync(new Exception("Simulated failure 1")) // First attempt fails .ThrowsAsync(new Exception("Simulated failure 2")) // Second attempt fails - .ReturnsAsync(new MemoryStream(new byte[] { 1, 2, 3 })); // Third attempt succeeds + .ReturnsAsync(new MemoryStream(responseBytes)); // Third attempt succeeds Registry registry = new(repoName, logger, mockRegistryAPI.Object, null, () => TimeSpan.Zero); @@ -592,7 +595,7 @@ public async Task DownloadBlobAsync_ThrowsAfterMaxRetries() var logger = _loggerFactory.CreateLogger(nameof(DownloadBlobAsync_ThrowsAfterMaxRetries)); var repoName = "testRepo"; - var descriptor = new Descriptor(SchemaTypes.OciLayerGzipV1, "sha256:testdigest1234", 1234); + var descriptor = new Descriptor(SchemaTypes.OciLayerGzipV1, "sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2", 1234); var cancellationToken = CancellationToken.None; var mockRegistryAPI = new Mock(MockBehavior.Strict); diff --git a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs index 26191e8aaadf..0914da6c407f 100644 --- a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs +++ b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs @@ -452,7 +452,7 @@ public async Task Razor_Component_ScopedCssAndStaticAssets() /// Currently only works on Windows. /// Add TestPlatforms.OSX once https://github.com/dotnet/sdk/issues/45521 is fixed. /// - [PlatformSpecificFact(TestPlatforms.Windows)] + [PlatformSpecificFact(TestPlatforms.Windows, Skip = "https://github.com/dotnet/sdk/issues/54150")] public async Task MauiBlazor() { var testAsset = TestAssets.CopyTestAsset("WatchMauiBlazor")