From d1642c83b01df8c9b0449e8eb0f606ebe4212262 Mon Sep 17 00:00:00 2001 From: Joshua Larkin <70237359+j0shuams@users.noreply.github.com> Date: Thu, 16 Dec 2021 13:42:58 -0800 Subject: [PATCH] Static YML build pipeline (#1065) * Templates, maestro --- .../CsWinRT-BuildAndTest-Stage.yml | 427 ++++++++++++++++++ .../CsWinRT-Pipeline.yml | 11 + .../CsWinRT-PublishToMaestro-Stage.yml | 49 ++ .../CsWinRT-PublishToNuget-Stage.yml | 261 +++++++++++ docs/structure.md | 9 + .../Maestro-PublishBuildToMaestro-Steps.yml | 201 +++++++++ .../ConvertVersionDetailsToPackageConfig.ps1 | 33 ++ eng/common/scripts/MaestroGetRequest.ps1 | 34 ++ eng/common/scripts/MaestroHelpers.ps1 | 81 ++++ eng/common/scripts/MaestroPostRequest.ps1 | 40 ++ .../scripts/UpdateVersionDetailsConfig.ps1 | 34 ++ 11 files changed, 1180 insertions(+) create mode 100644 build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml create mode 100644 build/AzurePipelineTemplates/CsWinRT-Pipeline.yml create mode 100644 build/AzurePipelineTemplates/CsWinRT-PublishToMaestro-Stage.yml create mode 100644 build/AzurePipelineTemplates/CsWinRT-PublishToNuget-Stage.yml create mode 100644 eng/common/AzurePipelineTemplates/Maestro-PublishBuildToMaestro-Steps.yml create mode 100644 eng/common/scripts/ConvertVersionDetailsToPackageConfig.ps1 create mode 100644 eng/common/scripts/MaestroGetRequest.ps1 create mode 100644 eng/common/scripts/MaestroHelpers.ps1 create mode 100644 eng/common/scripts/MaestroPostRequest.ps1 create mode 100644 eng/common/scripts/UpdateVersionDetailsConfig.ps1 diff --git a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml new file mode 100644 index 000000000..0a520c811 --- /dev/null +++ b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml @@ -0,0 +1,427 @@ +stages: +- stage: BuildAndTest + displayName: Build/Test Stage + jobs: + - job: BuildAndTest + pool: + vmImage: windows-2019 + timeoutInMinutes: 90 + # https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration + strategy: + maxParallel: 10 + matrix: + x64_Debug: + BuildPlatform: x64 + BuildConfiguration: debug + x86_Debug: + BuildPlatform: x86 + BuildConfiguration: debug + arm64_Debug: + BuildPlatform: arm64 + BuildConfiguration: debug + x64_Release: + BuildPlatform: x64 + BuildConfiguration: release + x86_Release: + BuildPlatform: x86 + BuildConfiguration: release + arm64_Release: + BuildPlatform: arm64 + BuildConfiguration: release + + steps: + - checkout: self + clean: true + persistCredentials: true + +# Clone TestWinRT + - task: CmdLine@2 + displayName: Clone TestWinRT + enabled: false + inputs: + script: get_testwinrt.cmd + workingDirectory: $(Build.SourcesDirectory) + +# Download procdump + - task: PowerShell@2 + displayName: Download procdump + enabled: false + inputs: + targetType: inline + script: | + mkdir $env:Agent_TempDirectory\procdump + + Invoke-WebRequest -Uri https://download.sysinternals.com/files/Procdump.zip -OutFile $env:Agent_TempDirectory\procdump\Procdump.zip + + Expand-Archive -Path $env:Agent_TempDirectory\procdump\Procdump.zip $env:Agent_TempDirectory\procdump\ + + set PROCDUMP_PATH=$env:Agent_TempDirectory\procdump\ + + Write-Host ##vso[task.setvariable variable=PATH;]${env:Agent_TempDirectory}\procdump;${env:PATH}; + +# Use .NET Core SDK 2.1 + - task: UseDotNet@2 + displayName: Use .NET Core SDK 2.1 + inputs: + version: 2.1.x + installationPath: C:\Users\VssAdministrator\AppData\Local\Microsoft\dotnet\ + performMultiLevelLookup: true + +# Install .NET 5 SDK + - task: PowerShell@2 + displayName: Install .NET 5 SDK + inputs: + targetType: inline + failOnStderr: true + script: | + Write-Host ##vso[task.setvariable variable=PATH;]${env:LocalAppData}\Microsoft\dotnet;${env:PATH}; + + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; + + &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version "$($env:NET5_SDK_VERSION)" -Architecture "x64" -AzureFeed "$($env:NET5_SDK_FEED)" + +# Install .NET 6 SDK + - task: PowerShell@2 + displayName: Install .NET 6 SDK + inputs: + targetType: inline + failOnStderr: true + script: | + Write-Host ##vso[task.setvariable variable=PATH;]${env:LocalAppData}\Microsoft\dotnet;${env:PATH}; + + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; + + dotnet new globaljson --sdk-version "$($env:NET6_SDK_VERSION)" + + &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version "$($env:NET6_SDK_VERSION)" -Architecture "x64" -AzureFeed "$($env:NET5_SDK_FEED)" + +# Verify .NET SDK + - task: CmdLine@2 + displayName: Verify .NET SDK + inputs: + workingDirectory: $(Build.SourcesDirectory) + script: | + where dotnet + dotnet --info + +# Parse Version + - task: CmdLine@2 + displayName: Parse Version + inputs: + workingDirectory: $(Build.SourcesDirectory) + script: | + rem Parse the build-generated Build.BuildNumber into components that + rem can be recombined for version resources, nuget packages, etc. + @echo off + + rem Encode the build date/rev into a 16 bit value for resource versions + if "$(PrereleaseVersion)"=="" ( + set RevisionBase=30000 + ) else ( + set RevisionBase=0 + ) + + for /f "tokens=4,5 delims=." %%i in ("$(Build.BuildNumber)") do set BuildMetadata=%%i.%%j & set /a BuildRevision=%RevisionBase%+(((%%i/10000)-20)*366+((%%i)%%10000)/100*31+((%%i)%%100))*10+%%j + + set VersionNumber=$(MajorVersion).$(MinorVersion).$(PatchVersion).%BuildRevision% + + if "$(PrereleaseVersion)"=="" ( + set NugetVersion=$(MajorVersion).$(MinorVersion).$(PatchVersion) + ) else ( + set NugetVersion=$(Build.BuildNumber) + ) + + rem Export generated version numbers back for subsequent tasks + echo ##vso[task.setvariable variable=BuildMetadata;]%BuildMetadata% + echo ##vso[task.setvariable variable=BuildRevision;]%BuildRevision% + echo ##vso[task.setvariable variable=VersionNumber;]%VersionNumber% + echo ##vso[task.setvariable variable=NugetVersion;]%NugetVersion% + + +# Build Prerelease Targets + - task: CmdLine@2 + displayName: Build Prerelease Targets + inputs: + workingDirectory: $(Build.SourcesDirectory) + script: | + if "$(PrereleaseVersion)"=="" goto :eof + + set prerelease_targets=nuget\Microsoft.Windows.CsWinRT.Prerelease.targets + echo ^ > %prerelease_targets% + echo ^> %prerelease_targets% + echo Condition=" '$(NetCoreSdkVersion)' ^!= '$($env:NET5_SDK_VERSION)' and '$(Net5SdkVersion)' ^!= '$($env:NET5_SDK_VERSION)' "^> >> %prerelease_targets% + echo ^ >> %prerelease_targets% + echo ^ >> %prerelease_targets% + echo ^ >> %prerelease_targets% + + +# Build Tool + - task: CmdLine@2 + displayName: Build Tool + inputs: + workingDirectory: $(Build.SourcesDirectory)\src + script: | + if "%VSCMD_VER%"=="" ( + pushd c: + call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" >nul 2>&1 + popd + ) + + set cswinrt_echo=on + set cswinrt_build_only=true + set cswinrt_build_params=/bl:$(Build.SourcesDirectory)\cswinrt.binlog /p:CleanIntermediateDirs=true + build.cmd $(BuildPlatform) $(BuildConfiguration) $(VersionNumber) $(Build.BuildNumber) $(WinRT.Runtime.AssemblyVersion) + +# Mask BuildConfiguration + - task: CmdLine@2 + displayName: Mask BuildConfiguration + enabled: False + inputs: + script: | + @echo off + + rem Although BuildConfiguration is PipelineRelease or PipelineDebug, the build outputs still go to Release or Debug + rem change BuildConfiguration variable so staging succeeds + rem the alternative would be to add configuration property for Pipeline* to every project in cswinrt.sln + + if "$(BuildConfiguration)"=="PipelineRelease" ( + set NewBuildConfiguration=Release + ) else if "$(BuildConfiguration)"=="PipelineDebug" ( + set NewBuildConfiguration=Debug + ) + + if "%NewBuildConfiguration%"!="" ( + echo ##vso[task.setvariable variable=BuildConfiguration;]%NewBuildConfiguration% + ) + +# Component Detection + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + +# Stage BinLog + - task: CopyFiles@2 + displayName: Stage BinLog + condition: always() + inputs: + SourceFolder: $(Build.SourcesDirectory) + Contents: cswinrt.binlog + TargetFolder: $(Build.ArtifactStagingDirectory)\binlog + +# Publish BinLog + - task: PublishBuildArtifacts@1 + displayName: Publish BinLog + condition: always() + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)\binlog + ArtifactName: $(BuildConfiguration)_$(BuildPlatform)_binlog + +# Stage Windows projection + - task: ArchiveFiles@2 + displayName: Stage Windows projection + enabled: False + inputs: + rootFolderOrFile: $(Build.SourcesDirectory)\Projections\Windows\Generated Files + includeRootFolder: false + sevenZipCompression: 5 + archiveFile: $(Build.ArtifactStagingDirectory)\Windows\sources.zip + +# Publish Windows projection + - task: PublishBuildArtifacts@1 + displayName: Publish Windows projection + enabled: False + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)\Windows + ArtifactName: $(BuildConfiguration)_$(BuildPlatform)_Windows + +# Stage CsWinRT + - task: CopyFiles@2 + displayName: Stage CsWinRT + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\_build\$(BuildPlatform)\$(BuildConfiguration)\cswinrt\bin + Contents: | + cswinrt.exe + cswinrt.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\native + +# Stage WinRT.Interop.winmd + - task: CopyFiles@2 + displayName: Stage WinRT.Interop.winmd + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + continueOnError: True + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\_build\$(BuildPlatform)\$(BuildConfiguration)\cswinrt\bin + Contents: WinRT.Interop.winmd + TargetFolder: $(Build.ArtifactStagingDirectory)\native + +# Stage WinRT.Host + - task: CopyFiles@2 + displayName: Stage WinRT.Host + continueOnError: True + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\_build\$(BuildPlatform)\$(BuildConfiguration)\WinRT.Host\bin + Contents: | + WinRT.Host.dll + WinRT.Host.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\native + +# Stage Unit Test + - task: CopyFiles@2 + displayName: Stage Unit Test + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\Tests\UnitTest\bin\$(BuildPlatform)\$(BuildConfiguration)\net5.0 + Contents: | + unittest.dll + unittest.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\native + +# Publish Native + - task: PublishBuildArtifacts@1 + displayName: Publish Native + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)\native + ArtifactName: $(BuildConfiguration)_$(BuildPlatform) + +# Stage NetStandard 2.0 + - task: CopyFiles@2 + displayName: Stage NetStandard 2.0 + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\WinRT.Runtime\bin\$(BuildConfiguration)\netstandard2.0 + Contents: | + WinRT.Runtime.dll + WinRT.Runtime.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\release_netstandard2.0\ + +# Stage Source Generator + - task: CopyFiles@2 + displayName: Stage Source Generator + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\Authoring\WinRT.SourceGenerator\bin\$(BuildConfiguration)\netstandard2.0 + Contents: | + WinRT.SourceGenerator.dll + WinRT.SourceGenerator.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\release_netstandard2.0\ + +# Publish NetStandard 2.0 + - task: PublishBuildArtifacts@1 + displayName: Publish NetStandard 2.0 + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)\release_netstandard2.0 + ArtifactName: netstandard2.0 + +# Stage Net5.0 + - task: CopyFiles@2 + displayName: Stage Net5.0 + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\WinRT.Runtime\bin\$(BuildConfiguration)\net5.0 + Contents: | + WinRT.Runtime.dll + WinRT.Runtime.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\release_net5.0 + +# Stage WinRT.Host.Shim + - task: CopyFiles@2 + displayName: Stage WinRT.Host.Shim + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + continueOnError: True + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\Authoring\WinRT.Host.Shim\bin\$(BuildConfiguration)\net5.0 + Contents: | + WinRT.Host.Shim.dll + WinRT.Host.Shim.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\release_net5.0 + +# Stage IID Optimizer + - task: CopyFiles@2 + displayName: Stage IID Optimizer + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + continueOnError: True + inputs: + SourceFolder: $(Build.SourcesDirectory)\src\Perf\IIDOptimizer\bin\$(BuildConfiguration)\net5.0 + Contents: | + IIDOptimizer.exe + IIDOptimizer.dll + IIDOptimizer.deps.json + IIDOptimizer.runtimeconfig.json + Mono.Cecil.dll + Mono.Cecil.Mdb.dll + Mono.Cecil.Pdb.dll + Mono.Cecil.Rocks.dll + System.CommandLine.dll + cs/System.CommandLine.resources.dll + de/System.CommandLine.resources.dll + es/System.CommandLine.resources.dll + fr/System.CommandLine.resources.dll + it/System.CommandLine.resources.dll + ja/System.CommandLine.resources.dll + ko/System.CommandLine.resources.dll + pl/System.CommandLine.resources.dll + pt-BR/System.CommandLine.resources.dll + ru/System.CommandLine.resources.dll + tr/System.CommandLine.resources.dll + zh-Hans/System.CommandLine.resources.dll + zh-Hant/System.CommandLine.resources.dll + TargetFolder: $(Build.ArtifactStagingDirectory)\release_net5.0\IIDOptimizer + +# Publish Net5.0 + - task: PublishBuildArtifacts@1 + displayName: Publish Net5.0 + condition: and(succeeded(), eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release')) + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)\release_net5.0 + ArtifactName: net5.0 + +# Run Unit Tests + - task: DotNetCoreCLI@2 + displayName: Run Unit Tests + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + inputs: + command: test + projects: 'src/Tests/UnitTest/UnitTest.csproj ' + arguments: --diag $(Build.ArtifactStagingDirectory)\unittest\test.log --no-build --logger xunit;LogFilePath=UNITTEST-$(Build.BuildNumber).xml /nologo /m /p:platform=$(BuildPlatform);configuration=$(BuildConfiguration) + testRunTitle: Unit Tests + +# Run Object Lifetime Tests + - task: VSTest@2 + displayName: Run Object Lifetime Tests + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + inputs: + testAssemblyVer2: Tests\ObjectLifetimeTests\bin\$(BuildPlatform)\$(BuildConfiguration)\net5.0-windows10.0.19041.0\win10-$(BuildPlatform)\ObjectLifetimeTests.Lifted.build.appxrecipe + searchFolder: $(Build.SourcesDirectory)\src + +# Publish Test Log + - task: PublishBuildArtifacts@1 + displayName: Publish Test Log + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)\unittest + ArtifactName: $(BuildConfiguration)_$(BuildPlatform)_UnitTest + +# Run Host Tests + - task: CmdLine@2 + displayName: Run Host Tests + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + continueOnError: True + inputs: + workingDirectory: $(Build.SourcesDirectory)\src + script: | + dir _build\$(BuildPlatform)\$(BuildConfiguration)\HostTest\bin + _build\$(BuildPlatform)\$(BuildConfiguration)\HostTest\bin\HostTest.exe --gtest_output=xml:HOSTTEST-$(Build.BuildNumber).xml + exit /b 0 + +# Run Source Generator Tests + - task: CmdLine@2 + displayName: Run Source Generator Tests + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + continueOnError: True + inputs: + workingDirectory: $(Build.SourcesDirectory)\src + script: | + dir _build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringConsumptionTest\bin + _build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringConsumptionTest\bin\AuthoringConsumptionTest.exe --gtest_output=xml:AUTHORINGTEST-$(Build.BuildNumber).xml + exit /b 0 diff --git a/build/AzurePipelineTemplates/CsWinRT-Pipeline.yml b/build/AzurePipelineTemplates/CsWinRT-Pipeline.yml new file mode 100644 index 000000000..d562207a7 --- /dev/null +++ b/build/AzurePipelineTemplates/CsWinRT-Pipeline.yml @@ -0,0 +1,11 @@ +# This file is used as basis for the ADO pipeline +name: $(MajorVersion).$(MinorVersion).$(PatchVersion)$(PrereleaseVersion).$(date:yyMMdd)$(rev:.r) + +stages: +- template: CsWinRT-BuildAndTest-Stage.yml + +- template: CsWinRT-PublishToNuget-Stage.yml + +# if we are doing a release build, publish the build to Maestro +- ${{ if eq( '$(PrereleaseVersion)', '') }}: + template: CsWinRT-PublishToMaestro-Stage.yml \ No newline at end of file diff --git a/build/AzurePipelineTemplates/CsWinRT-PublishToMaestro-Stage.yml b/build/AzurePipelineTemplates/CsWinRT-PublishToMaestro-Stage.yml new file mode 100644 index 000000000..bc1811fa6 --- /dev/null +++ b/build/AzurePipelineTemplates/CsWinRT-PublishToMaestro-Stage.yml @@ -0,0 +1,49 @@ +stages: +- stage: PublishToMaestro + displayName: Trigger Maestro Publish + jobs: + - job: TriggerMaestroPublish + variables: + _DotNetCoreRuntimeVersion: 5.0.11 # matches with SDK v. 5.0.402 + _WindowsSdkPackageVersion: 10.0.18362.22 # matches with one consumed in WindowsAppSdk + pool: + vmImage: windows-2019 + steps: + + # Parse Versions needed for offical CsWinRT version of build + - task: CmdLine@2 + displayName: Parse Versions + inputs: + workingDirectory: $(Build.SourcesDirectory) + script: | + rem Parse the build-generated Build.BuildNumber into components that + rem can be recombined for version resources, nuget packages, etc. + + @echo off + + rem Encode the build date/rev into a 16 bit value for resource versions + if "$(PrereleaseVersion)"=="" ( + set RevisionBase=30000 + ) else ( + set RevisionBase=0 + ) + for /f "tokens=4,5 delims=." %%i in ("$(Build.BuildNumber)") do set BuildMetadata=%%i.%%j & set /a BuildRevision=%RevisionBase%+(((%%i/10000)-20)*366+((%%i)%%10000)/100*31+((%%i)%%100))*10+%%j + + set VersionNumber=$(MajorVersion).$(MinorVersion).$(PatchVersion).%BuildRevision% + + if "$(PrereleaseVersion)"=="" ( + set NugetVersion=$(MajorVersion).$(MinorVersion).$(PatchVersion) + ) else ( + set NugetVersion=$(Build.BuildNumber) + ) + + rem Export generated version numbers back for subsequent tasks + echo ##vso[task.setvariable variable=BuildMetadata;]%BuildMetadata% + echo ##vso[task.setvariable variable=BuildRevision;]%BuildRevision% + echo ##vso[task.setvariable variable=VersionNumber;]%VersionNumber% + echo ##vso[task.setvariable variable=NugetVersion;]%NugetVersion% + + - template: ..\..\eng\common\AzurePipelineTemplates\Maestro-PublishBuildToMaestro-Steps.yml + parameters: + AssetNames: Microsoft.Windows.CsWinRT;CsWinRT.Dependency.DotNetCoreSdk;CsWinRT.Dependency.DotNetCoreRuntime;CsWinRT.Dependency.WindowsSdkPackage + AssetVersions: $(NugetVersion);$(Net5.Sdk.Version);$(_DotNetCoreRuntimeVersion);$(_WindowsSdkPackageVersion) \ No newline at end of file diff --git a/build/AzurePipelineTemplates/CsWinRT-PublishToNuget-Stage.yml b/build/AzurePipelineTemplates/CsWinRT-PublishToNuget-Stage.yml new file mode 100644 index 000000000..936ffeffc --- /dev/null +++ b/build/AzurePipelineTemplates/CsWinRT-PublishToNuget-Stage.yml @@ -0,0 +1,261 @@ +stages: +- stage: Publish + displayName: Publish To Internal Nuget Feed Stage + jobs: + - job: PublishTo_CsWinRT_InternalFeed + pool: + vmImage: windows-2019 + steps: + - checkout: self + clean: True + persistCredentials: True + +# Use NuGet 5.3 + - task: NuGetToolInstaller@1 + displayName: Use NuGet 5.3 + continueOnError: True + inputs: + versionSpec: 5.3 + +# Component Detection + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + +# Download x86 + - task: DownloadBuildArtifacts@0 + displayName: 'Download x86 ' + inputs: + artifactName: release_x86 + itemPattern: '' + downloadPath: $(Build.SourcesDirectory) + extractTars: false + +# Download x64 + - task: DownloadBuildArtifacts@0 + displayName: Download x64 + inputs: + artifactName: release_x64 + itemPattern: '' + downloadPath: $(Build.SourcesDirectory) + extractTars: false + +# Download arm64 + - task: DownloadBuildArtifacts@0 + displayName: Download arm64 + inputs: + artifactName: release_arm64 + itemPattern: '' + downloadPath: $(Build.SourcesDirectory) + extractTars: false + +# Download NetStandard2.0 + - task: DownloadBuildArtifacts@0 + displayName: Download NetStandard 2.0 + inputs: + artifactName: netstandard2.0 + itemPattern: '' + downloadPath: $(Build.SourcesDirectory) + extractTars: false + +# Download Net5.0 + - task: DownloadBuildArtifacts@0 + displayName: 'Download Net5.0 ' + inputs: + artifactName: net5.0 + itemPattern: '' + downloadPath: $(Build.SourcesDirectory) + extractTars: false + +# Stage Binaries + - task: CmdLine@2 + displayName: Stage Binaries + inputs: + workingDirectory: $(Build.SourcesDirectory) + script: | + copy release_x86\cswinrt.exe cswinrt.exe + copy release_x86\WinRT.Interop.winmd WinRT.Interop.winmd + +# ESRP Codesigning + - task: EsrpCodeSigning@1 + displayName: ESRP CodeSigning + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.SourcesDirectory) + Pattern: | + cswinrt.exe + WinRT.Interop.winmd + netstandard2.0\WinRT.Runtime.dll + netstandard2.0\WinRT.Host.Shim.dll + netstandard2.0\WinRT.SourceGenerator.dll + net5.0\WinRT.Runtime.dll + net5.0\WinRT.Host.Shim.dll + release_x64\WinRT.Host.dll + release_x86\WinRT.Host.dll + release_arm64\WinRT.Host.dll + net5.0\IIDOptimizer\IIDOptimizer.exe + net5.0\IIDOptimizer\IIDOptimizer.dll + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd sha256" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "signtool.exe", + "toolVersion": "6.2.9304.0" + } + ] + +# ESRP CodeSigning 3rd Party + - task: EsrpCodeSigning@1 + displayName: ESRP CodeSigning 3rd party + continueOnError: True + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.SourcesDirectory) + Pattern: | + net5.0\IIDOptimizer\Mono.Cecil.dll + net5.0\IIDOptimizer\Mono.Cecil.Mdb.dll + net5.0\IIDOptimizer\Mono.Cecil.Pdb.dll + net5.0\IIDOptimizer\Mono.Cecil.Rocks.dll + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-231522", + "OperationCode" : "SigntoolSign", + "Parameters" : { + "OpusName" : "Microsoft", + "OpusInfo" : "http://www.microsoft.com", + "Append" : "/as", + "FileDigest" : "/fd \"SHA256\"", + "PageHash" : "/NPH", + "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-231522", + "OperationCode" : "SigntoolVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + +# Parse Versions + - task: CmdLine@2 + displayName: Parse Versions + inputs: + workingDirectory: $(Build.SourcesDirectory) + script: | + rem Parse the build-generated Build.BuildNumber into components that + rem can be recombined for version resources, nuget packages, etc. + + @echo off + + rem Encode the build date/rev into a 16 bit value for resource versions + if "$(PrereleaseVersion)"=="" ( + set RevisionBase=30000 + ) else ( + set RevisionBase=0 + ) + for /f "tokens=4,5 delims=." %%i in ("$(Build.BuildNumber)") do set BuildMetadata=%%i.%%j & set /a BuildRevision=%RevisionBase%+(((%%i/10000)-20)*366+((%%i)%%10000)/100*31+((%%i)%%100))*10+%%j + + set VersionNumber=$(MajorVersion).$(MinorVersion).$(PatchVersion).%BuildRevision% + + if "$(PrereleaseVersion)"=="" ( + set NugetVersion=$(MajorVersion).$(MinorVersion).$(PatchVersion) + ) else ( + set NugetVersion=$(Build.BuildNumber) + ) + + rem Export generated version numbers back for subsequent tasks + echo ##vso[task.setvariable variable=BuildMetadata;]%BuildMetadata% + echo ##vso[task.setvariable variable=BuildRevision;]%BuildRevision% + echo ##vso[task.setvariable variable=VersionNumber;]%VersionNumber% + echo ##vso[task.setvariable variable=NugetVersion;]%NugetVersion% + +# NuGet Pack + - task: NuGetCommand@2 + displayName: NuGet pack + inputs: + command: pack + searchPatternPack: nuget/Microsoft.Windows.CsWinRT.nuspec + configurationToPack: Release + buildProperties: cswinrt_nuget_version=$(NugetVersion);cswinrt_exe=$(Build.SourcesDirectory)\cswinrt.exe;interop_winmd=$(Build.SourcesDirectory)\WinRT.Interop.winmd;netstandard2_runtime=$(Build.SourcesDirectory)\netstandard2.0\WinRT.Runtime.dll;net5_runtime=$(Build.SourcesDirectory)\net5.0\WinRT.Runtime.dll;source_generator=$(Build.SourcesDirectory)\netstandard2.0\WinRT.SourceGenerator.dll;winrt_shim=$(Build.SourcesDirectory)\net5.0\WinRT.Host.Shim.dll;winrt_host_x86=$(Build.SourcesDirectory)\release_x86\WinRT.Host.dll;winrt_host_x64=$(Build.SourcesDirectory)\release_x64\WinRT.Host.dll;winrt_host_arm64=$(Build.SourcesDirectory)\release_arm64\WinRT.Host.dll;guid_patch=$(Build.SourcesDirectory)\net5.0\IIDOptimizer\*.* + +# ESRP CodeSigning + - task: EsrpCodeSigning@1 + displayName: ESRP CodeSigning + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.ArtifactStagingDirectory) + Pattern: '*.nupkg' + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetSign", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + +# NuGet push + - task: NuGetCommand@2 + displayName: NuGet push + inputs: + command: push + searchPatternPush: $(Build.ArtifactStagingDirectory)/**/*.nupkg + feedPublish: cfbb8a6b-97b7-4070-a6e8-a4081b046ae0 + externalEndpoint: 80b1372e-52e9-486d-934f-92d5590c2241 + +# NuGet publish + - task: PublishPipelineArtifact@1 + displayName: NuGet publish + inputs: + path: $(Build.ArtifactStagingDirectory) + artifactName: Publish + +# Publish Symbols + - task: PublishSymbols@2 + displayName: Publish Symbols + inputs: + SearchPattern: '**/*.pdb' + IndexSources: false + SymbolServerType: TeamServices + SymbolsProduct: C#/WinRT \ No newline at end of file diff --git a/docs/structure.md b/docs/structure.md index 4b0f9a3fc..d3325d7ad 100644 --- a/docs/structure.md +++ b/docs/structure.md @@ -2,6 +2,15 @@ This document describes the CsWinRT repository organization. Documentation and specs are located in the [`/docs`](.) folder. All source code for CsWinRT is located in the [`/src`](../src) folder, and files for generating the NuGet package are located in [`/nuget`](../nuget). +## [`build`](../build) + +Contains source files for Azure DevOps pipeline that handles official builds and testing for C#/WinRT. Uses Maestro to publish builds conveniently for dependent projects; Maestro is a dependency manager +developed by dotnet as part of the [Arcade Build System](https://github.com/dotnet/arcade). + +## [`eng`](../eng) + +Contains files that assist with publishing to Maestro. + ## [`nuget`](../nuget) Contains source files for producing a C#/WinRT NuGet package, which is regularly built, signed, and published to nuget.org by Microsoft. The C#/WinRT NuGet package contains the **cswinrt.exe** compiler and the runtime assembly, `WinRT.Runtime.dll`. diff --git a/eng/common/AzurePipelineTemplates/Maestro-PublishBuildToMaestro-Steps.yml b/eng/common/AzurePipelineTemplates/Maestro-PublishBuildToMaestro-Steps.yml new file mode 100644 index 000000000..ac46567c0 --- /dev/null +++ b/eng/common/AzurePipelineTemplates/Maestro-PublishBuildToMaestro-Steps.yml @@ -0,0 +1,201 @@ +# Parameters: +# AssetNames and AssetVersions can be separated by ';' for publishing build with multiple assets +# The lengths when split by ';' must match between both of these parameters +# Example: +# AssetNames: "PackageName1;PackageName2" +# AssetVersions: "1.1;1.2" +# +# TriggerSubscription will publish the build to the default channel. +parameters: + AssetNames: '' + AssetVersions: '' + TriggerSubscription: true + BranchTag: '' + +steps: + - task: PowerShell@2 + displayName: Check prerequisites + inputs: + targetType: 'inline' + script: | + Write-Host "Pipeline Variable 'MaestroToken' and 'MaestroUri' must have a value" + Write-Host "##vso[task.complete result=Failed;]DONE" + condition: or(eq(variables['MaestroUri'], ''), eq(variables['MaestroToken'], '')) + + - task: PowerShell@2 + displayName: Build JsonBody + inputs: + targetType: 'inline' + script: | + . .\eng\common\Scripts\MaestroHelpers.ps1 + + $jsonBase = @{} + + $branchTag = '' + if ('${{ parameters.BranchTag }}' -ne '') + { + $branchTag = "-${{ parameters.BranchTag }}" + } + + $assetNames = '${{ parameters.AssetNames }}'.Split(";") + $assetVersions = '${{ parameters.AssetVersions }}'.Split(";") + + if ($assetNames.length -ne $assetVersions.length) + { + Write-Host "AssetNames and AssetVersions must have equal lengths" + Write-Host "##vso[task.complete result=Failed;]DONE" + exit 1 + } + + $assetList = New-Object System.Collections.ArrayList + for ($i = 0; $i -lt ($assetNames.length); $i += 1) + { + $assetList.Add( + @{ + "name"=$assetNames[$i]; + "version"=$assetVersions[$i]; + "nonShipping"=$false; + "locations"=$null + } + ) + } + + # These fields below are unused but can be enabled in the future + # $locationList = New-Object System.Collections.ArrayList + # $locationList.Add(@{"location"="maestroTestValue";"type"="none"}) + + # $dependenciesList = New-Object System.Collections.ArrayList + # $dependenciesList.Add( + # @{ + # "buildId"=0; + # "isProduct"=$true; + # "timeToInclusionInMinutes"=0; + # } + # ) + + # $incoherenciesList = New-Object System.Collections.ArrayList + # $incoherenciesList.Add( + # @{ + # "name"="maestroTestValue"; + # "version"="maestroTestValue"; + # "repository"="maestroTestValue"; + # "commit"="maestroTestValue"; + # } + # ) + + Write-Host "collectionuri: $(System.CollectionUri)" + $devOpsAccount = ExtractOrgFromAzureDevOpsCollectionUri '$(System.CollectionUri)' + Write-Host "reposiitory: $(Build.Repository.Uri)" + Write-Host "account: " $devOpsAccount + + $gitHubRepo = "$(Build.Repository.Uri)" + $azureDevOpsRepo = "$(Build.Repository.Uri)" + + $jsonBase = + @{ + "commit"="$(Build.SourceVersion)"; + "assets"=$assetList; + "dependencies"=$null; + "azureDevOpsBuildId"=$(Build.BuildId); + "azureDevOpsBuildDefinitionId"=$(System.DefinitionId); + "azureDevOpsAccount"=$devOpsAccount; + "azureDevOpsProject"="$(System.TeamProject)"; + "azureDevOpsBuildNumber"="$(Build.BuildNumber)"; + "azureDevOpsRepository"=$azureDevOpsRepo; + "azureDevOpsBranch"="$(Build.SourceBranch)$branchTag"; + "gitHubRepository"=$gitHubRepo; + "gitHubBranch"="$(Build.SourceBranch)$branchTag"; + "released"=$true; + "stable"=$true + "incoherencies"=$null; + } + + $jsonBase | ConvertTo-Json -Depth 10 | Out-File '$(Build.SourcesDirectory)\eng\common\maestro-build.json' + $body = Get-Content -Raw -Path '$(Build.SourcesDirectory)\eng\common\maestro-build.json' + Write-host $body + + - task: powershell@2 + displayName: 'Post build to Maestro' + inputs: + targetType: filePath + filePath: eng\common\Scripts\MaestroPostRequest.ps1 + arguments: -url '$(MaestroUri)' -Token '$(MaestroToken)' -api '/api/builds' -jsonBodyPath '$(Build.SourcesDirectory)\eng\common\maestro-build.json' + + - ${{ if eq(parameters.TriggerSubscription, 'true') }}: + - task: powershell@2 + displayName: 'Publish Build to Default Channel' + inputs: + targetType: 'inline' + script: | + . .\eng\common\Scripts\MaestroHelpers.ps1 + + $branchTag = '' + if ('${{ parameters.BranchTag }}' -ne '') + { + $branchTag = "-${{ parameters.BranchTag }}" + } + + $repository = '$(Build.Repository.Uri)' + if (!(IsGitHubRepo($repository))) + { + # Maestro expects https://dev.azure.com/microsoft/xx/_git/xx + # But Build.Repository.Uri returns https://microsoft.visualstudio.com/xx/_git/xx + # So we convert it into the right form here + $repository = ConvertToMaestroFriendlyAzureDevOpUri $repository + } + + # Get the id of the default channel of this branch + $api = "/api/default-channels" + $queryParam = "&repository=" + $repository + "&branch=$(Build.SourceBranch)$branchTag" + $response = &".\eng\common\Scripts\MaestroGetRequest.ps1" -url '$(MaestroUri)' -Token '$(MaestroToken)' -api $api -queryParameters $queryParam + $jsonObj = ConvertFrom-Json $response.Content + $channelId = $jsonObj.channel.id + if ([string]::IsNullOrEmpty($channelId)) + { + Write-Host "Error: Default channel not found. Please use darc add-default-channel to add a default channel for this repo and branch" + Write-Host "##vso[task.complete result=SucceededWithIssues;]DONE" + } + else + { + # Get the id of the build posted earlier + $api = "/api/builds" + $queryParam = "&repository=" + $repository + "&commit=$(Build.SourceVersion)" + $response = &".\eng\common\Scripts\MaestroGetRequest.ps1" -url '$(MaestroUri)' -Token '$(MaestroToken)' -api $api -queryParameters $queryParam + $jsonObj = ConvertFrom-Json $response.Content + $buildId = $jsonObj.id + if ([string]::IsNullOrEmpty($buildId)) + { + Write-Host "Error: build not found in Maestro" + Write-Host "##vso[task.complete result=Failed;]DONE" + } + + # AddBuildToChannel with the corresponding build id and channel id + $api = "/api/channels/" + $channelId + "/builds/" + $buildId + # buildId may return a space separated numbers if there are more than one build for the same commit + $api = $api.Split(" ")[0] + $response = &".\eng\common\Scripts\MaestroPostRequest.ps1" -url '$(MaestroUri)' -Token '$(MaestroToken)' -api $api -jsonBodyPath '' + + # Get the list of subscriptions on the channel + $api = "/api/subscriptions" + $queryParams = "&channelId=" + $channelId + $response = &".\eng\common\Scripts\MaestroGetRequest.ps1" -url '$(MaestroUri)' -Token '$(MaestroToken)' -api $api -queryParameters $queryParams + $jsonObj = ConvertFrom-Json $response.Content + foreach ($sub in $jsonObj) + { + if ($sub.sourceRepository -eq $repository) + { + # Trigger the subscription + $id = $sub.id + $updateFrequency = $sub.policy.updateFrequency + Write-Host "updateFrequency " $updateFrequency + if ($updateFrequency -eq 'everyBuild') + { + Write-Host "Triggering subscription on " $id + # bar-build-id is always 0 + $api = "/api/subscriptions/" + $id + "/trigger" + $response = &".\eng\common\Scripts\MaestroPostRequest.ps1" -url '$(MaestroUri)' -Token '$(MaestroToken)' -api $api -jsonBodyPath '' -queryParameters '&bar-build-id=0' + } + } + } + } + diff --git a/eng/common/scripts/ConvertVersionDetailsToPackageConfig.ps1 b/eng/common/scripts/ConvertVersionDetailsToPackageConfig.ps1 new file mode 100644 index 000000000..ec69b80bd --- /dev/null +++ b/eng/common/scripts/ConvertVersionDetailsToPackageConfig.ps1 @@ -0,0 +1,33 @@ +Param( + [Parameter(Position=0)] + [string]$versionDetailsPath = "", + [Parameter(Position=1)] + [string]$packageConfigPath = "" +) + +[xml]$buildConfig = Get-Content -Path $versionDetailsPath + +$packagesText = +@" + + + + +"@ +foreach ($dependency in $buildConfig.Dependencies.ProductDependencies.Dependency) +{ + $name = $dependency.name + $ver = $dependency.version + Write-Host "id: " $name + Write-Host "ver: " $ver + $packagesText += ' +' + } +$packagesText += +@" + +"@ + +Write-Host $packagesText + +Set-Content -Value $packagesText $packageConfigPath diff --git a/eng/common/scripts/MaestroGetRequest.ps1 b/eng/common/scripts/MaestroGetRequest.ps1 new file mode 100644 index 000000000..1555f90ad --- /dev/null +++ b/eng/common/scripts/MaestroGetRequest.ps1 @@ -0,0 +1,34 @@ +[CmdLetBinding()] +Param( + [string]$url, + [string]$token, + [string]$api, + [string]$queryParameters +) + +$headers = @{ + Authorization="Bearer $token" +} + +$contentType = 'application/json' +$api = $api + '?api-version=2020-02-20' + $queryParameters +$fullUri = $url + $api + +Write-Host $fullUri + +$response = Invoke-WebRequest -Method 'GET' -Uri $fullUri -Headers $headers -ContentType $contentType +Write-Host $response + +if ($Response.statuscode -lt '200') +{ + Write-Host $Response.statuscode + Write-Host "##vso[task.complete result=Failed;]DONE" +} +if ($Response.statuscode -ge '300') +{ + Write-Host $Response.statuscode + Write-Host "##vso[task.complete result=Failed;]DONE" +} + + +return $response \ No newline at end of file diff --git a/eng/common/scripts/MaestroHelpers.ps1 b/eng/common/scripts/MaestroHelpers.ps1 new file mode 100644 index 000000000..962e99f9a --- /dev/null +++ b/eng/common/scripts/MaestroHelpers.ps1 @@ -0,0 +1,81 @@ +# Param: CollectionUri must be in the form below +# https://microsoft.visualstudio.com[/]* +function ExtractOrgFromAzureDevOpsCollectionUri([string]$CollectionUri) +{ + $CollectionUri = $CollectionUri.TrimEnd('/') + $Split1 = $CollectionUri.Split(".") + if ($Split1.Length -ne 3) + { + Write-Host "##vso[task.complete result=Failed;]Format Error" + Exit 1 + } + if ($split1[1] -ne "visualstudio") + { + Write-Host "##vso[task.complete result=Failed;]Format Error" + Exit 1 + } + if ($split1[2].Substring(0,3) -ne "com") + { + Write-Host "##vso[task.complete result=Failed;]Format Error" + Exit 1 + } + $temp1 = $Split1[0] + $result = $temp1.Substring(8) + return $result +} + +# Param: buildRepositoryUri must be in the form below +# https://microsoft.visualstudio.com/xxx/_git/xxx[/] +function ConvertToMaestroFriendlyAzureDevOpUri([string]$buildRepositoryUri) +{ + $buildRepositoryUri = $buildRepositoryUri.TrimEnd('/') + if (IsGitHubRepo($buildRepositoryUri)) + { + Write-Host "URI is github" + return $buildRepositoryUri + } + if (IsMaestroFriendlyAzureDevOpUri($buildRepositoryUri)) + { + Write-Host "URI is already Maestro friendly" + return $buildRepositoryUri + } + $devOpsAccount = ExtractOrgFromAzureDevOpsCollectionUri $buildRepositoryUri + $buildRepositoryUriSplit = $buildRepositoryUri.Split("/") + if ($buildRepositoryUriSplit.Length -ne 6) + { + Write-Host "##vso[task.complete result=Failed;]Format Error" + Exit 1 + } + + $repository = "https://dev.azure.com/" + $devOpsAccount + "/" + $buildRepositoryUriSplit[3] + "/" + $buildRepositoryUriSplit[4] + "/" + $buildRepositoryUriSplit[5] + return $repository +} + +function IsGitHubRepo([string]$buildRepositoryUri) +{ + $githubUrls = @("https://github.com", "https://wwww.github.com") + for ($i = 0; $i -le ($githubUrls.length); $i += 1) + { + if ($buildRepositoryUri.length -ge $githubUrls[$i].length) + { + if($buildRepositoryUri.Substring(0, $githubUrls[$i].length) -eq $githubUrls[$i]) + { + return $true + } + } + } + return $false +} + +function IsMaestroFriendlyAzureDevOpUri([string]$buildRepositoryUri) +{ + $azdoUri = "https://dev.azure.com" + if ($buildRepositoryUri.length -ge $azdoUri.length) + { + if($buildRepositoryUri.Substring(0, $azdoUri.length) -eq $azdoUri) + { + return $true + } + } + return $false +} \ No newline at end of file diff --git a/eng/common/scripts/MaestroPostRequest.ps1 b/eng/common/scripts/MaestroPostRequest.ps1 new file mode 100644 index 000000000..5b6f50278 --- /dev/null +++ b/eng/common/scripts/MaestroPostRequest.ps1 @@ -0,0 +1,40 @@ +[CmdLetBinding()] +Param( + [string]$url, + [string]$token, + [string]$api, + [string]$jsonBodyPath, + [string]$queryParameters = '' +) + +$headers = @{ + Authorization="Bearer $token" +} + +$body = '' +if (-not [string]::IsNullOrEmpty($jsonBodyPath)) +{ + $body = Get-Content -Raw -Path $jsonBodyPath +} + +$contentType = 'application/json' +$api = $api + '?api-version=2020-02-20' + $queryParameters +$fullUri = $url + $api + +Write-Host $fullUri + +$Response = Invoke-WebRequest -Method 'POST' -Uri $fullUri -Headers $headers -Body $body -ContentType $contentType +Write-Host $Response + +if ($Response.statuscode -lt '200') +{ + Write-Host $Response.statuscode + Write-Host "##vso[task.complete result=Failed;]DONE" +} +if ($Response.statuscode -ge '300') +{ + Write-Host $Response.statuscode + Write-Host "##vso[task.complete result=Failed;]DONE" +} + +return $Response \ No newline at end of file diff --git a/eng/common/scripts/UpdateVersionDetailsConfig.ps1 b/eng/common/scripts/UpdateVersionDetailsConfig.ps1 new file mode 100644 index 000000000..13c5ce3f5 --- /dev/null +++ b/eng/common/scripts/UpdateVersionDetailsConfig.ps1 @@ -0,0 +1,34 @@ +[CmdLetBinding()] +Param( + [string]$dependencyName, + [string]$dependencyVersion +) + +Write-Host $dependencyName +Write-Host $dependencyVersion + +# Get the root of the repo. +$scriptFullPath = (split-path -parent $MyInvocation.MyCommand.Definition) +$engPath = (split-path -parent (split-path -parent $scriptFullPath)) + +Function CheckFile($filename) +{ + if(-not (Test-Path $filename)) + { + write-host "File not found: $filename" + exit 1 + } +} + +$configFilename = "$engPath\Version.Details.xml" +CheckFile $configFilename + +# Load the build.config, update the requested version entry, then write it back out +$xmldoc = [System.Xml.XmlDocument](Get-Content $configFilename) +Write-Host $xmldoc + +$node = $xmldoc.Dependencies.ProductDependencies.Dependency | ?{$_.Name -eq $dependencyName} +$node.Version = $dependencyVersion +$xmldoc.Save($configFilename) + +Write-Host "Updated $configFilename"