diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 5d2f7feb1..e60546c00 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,19 +3,19 @@ "isRoot": true, "tools": { "powershell": { - "version": "7.4.4", + "version": "7.4.6", "commands": [ "pwsh" ] }, "dotnet-coverage": { - "version": "17.11.3", + "version": "17.12.6", "commands": [ "dotnet-coverage" ] }, "nbgv": { - "version": "3.6.139", + "version": "3.6.146", "commands": [ "nbgv" ] diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 6ed7f6e71..9626b31b5 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,5 +1,5 @@ # Refer to https://hub.docker.com/_/microsoft-dotnet-sdk for available versions -FROM mcr.microsoft.com/dotnet/sdk:8.0.300-jammy +FROM mcr.microsoft.com/dotnet/sdk:8.0.402-jammy # Installing mono makes `dotnet test` work without errors even for net472. # But installing it takes a long time, so it's excluded by default. diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml new file mode 100644 index 000000000..564d4af28 --- /dev/null +++ b/.github/workflows/libtemplate-update.yml @@ -0,0 +1,72 @@ +name: Library.Template update + +# PREREQUISITE: This workflow requires the repo to be configured to allow workflows to push commits and create pull requests. +# Visit https://github.com/USER/REPO/settings/actions +# Under "Workflow permissions", select "Read and write permissions" and check "Allow GitHub Actions to create ...pull requests" +# Click Save. + +on: + schedule: + - cron: "0 3 * * Mon" # Sun @ 8 or 9 PM Mountain Time (depending on DST) + workflow_dispatch: + +jobs: + merge: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # avoid shallow clone so nbgv can do its work. + + - name: merge + shell: pwsh + run: | + $LibTemplateBranch = & ./azure-pipelines/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + + git fetch https://github.com/aarnott/Library.Template $LibTemplateBranch + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + $LibTemplateCommit = git rev-parse FETCH_HEAD + + if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) { + Write-Host "There are no Library.Template updates to merge." + exit 0 + } + + git -c http.extraheader="AUTHORIZATION: bearer $env:GH_TOKEN" push origin -u FETCH_HEAD:refs/heads/auto/libtemplateUpdate + - name: pull request + shell: pwsh + run: | + # If there is already an active pull request, don't create a new one. + $existingPR = gh pr list -H auto/libtemplateUpdate --json url | ConvertFrom-Json + if ($existingPR) { + Write-Host "::warning::Skipping pull request creation because one already exists at $($existingPR[0].url)" + exit 0 + } + + $prTitle = "Merge latest Library.Template" + $prBody = "This merges the latest features and fixes from [Library.Template's branch](https://github.com/AArnott/Library.Template/tree/). + +
+ Merge conflicts? + Resolve merge conflicts locally by carrying out these steps: + + ``` + git fetch + git checkout auto/libtemplateUpdate + git merge origin/main + # resolve conflicts + git commit + git push + ``` +
+ + ⚠️ Do **not** squash this pull request when completing it. You must *merge* it." + + gh pr create -H auto/libtemplateUpdate -b $prBody -t $prTitle + env: + GH_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 3f1c5ed94..cc2b12470 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,9 @@ bld/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ +# Jetbrains Rider cache directory +.idea/ + # Visual Studio 2017 auto generated files Generated\ Files/ diff --git a/Directory.Build.props b/Directory.Build.props index 89bcca584..5534d928f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,6 +6,7 @@ $(RepoRootPath)obj\$([MSBuild]::MakeRelative($(RepoRootPath), $(MSBuildProjectDirectory)))\ $(RepoRootPath)bin\$(MSBuildProjectName)\ $(RepoRootPath)bin\Packages\$(Configuration)\NuGet\ + $(RepoRootPath)bin\Packages\$(Configuration)\Vsix\$(Platform)\ enable disable latest diff --git a/Directory.Packages.props b/Directory.Packages.props index 8365873e7..fb9416ee7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,7 +4,7 @@ true true - 2.0.162 + 2.0.165 3.11.0 4.4.0 1.1.1 @@ -25,7 +25,7 @@ - + @@ -44,14 +44,14 @@ - + - + diff --git a/azure-pipelines/Get-LibTemplateBasis.ps1 b/azure-pipelines/Get-LibTemplateBasis.ps1 new file mode 100644 index 000000000..2181c77b6 --- /dev/null +++ b/azure-pipelines/Get-LibTemplateBasis.ps1 @@ -0,0 +1,25 @@ +<# +.SYNOPSIS + Returns the name of the well-known branch in the Library.Template repository upon which HEAD is based. +#> +[CmdletBinding(SupportsShouldProcess = $true)] +Param( + [switch]$ErrorIfNotRelated +) + +# This list should be sorted in order of decreasing specificity. +$branchMarkers = @( + @{ commit = 'fd0a7b25ccf030bbd16880cca6efe009d5b1fffc'; branch = 'microbuild' }; + @{ commit = '05f49ce799c1f9cc696d53eea89699d80f59f833'; branch = 'main' }; +) + +foreach ($entry in $branchMarkers) { + if (git rev-list HEAD | Select-String -Pattern $entry.commit) { + return $entry.branch + } +} + +if ($ErrorIfNotRelated) { + Write-Error "Library.Template has not been previously merged with this repo. Please review https://github.com/AArnott/Library.Template/tree/main?tab=readme-ov-file#readme for instructions." + exit 1 +} diff --git a/azure-pipelines/GlobalVariables.yml b/azure-pipelines/GlobalVariables.yml index 12f94a842..a4691dbb4 100644 --- a/azure-pipelines/GlobalVariables.yml +++ b/azure-pipelines/GlobalVariables.yml @@ -2,3 +2,5 @@ variables: # These variables are required for MicroBuild tasks TeamName: VS Core - Special Projects TeamEmail: andarno@microsoft.com + # These variables influence insertion pipelines + ContainsVsix: false # This should be true when the repo builds a VSIX that should be inserted to VS. diff --git a/azure-pipelines/OptProf.yml b/azure-pipelines/OptProf.yml index b0872d8cb..3e37a929c 100644 --- a/azure-pipelines/OptProf.yml +++ b/azure-pipelines/OptProf.yml @@ -29,6 +29,8 @@ variables: value: false # avoid using nice version since we're building a preliminary/unoptimized package - name: IsOptProf value: true +- name: MicroBuild_NuPkgSigningEnabled + value: false # test-signed nuget packages fail to restore in the VS insertion PR validations. Just don't sign them *at all*. stages: - stage: Library @@ -40,12 +42,13 @@ stages: - template: build.yml parameters: Is1ESPT: false - RealSign: true + RealSign: false windowsPool: VSEngSS-MicroBuild2022-1ES EnableMacOSBuild: false ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }} IsOptProf: true RunTests: false + SkipCodesignVerify: true - stage: QueueVSBuild jobs: - job: QueueOptProf diff --git a/azure-pipelines/OptProf_part2.yml b/azure-pipelines/OptProf_part2.yml index 97cfe2546..d8c52941e 100644 --- a/azure-pipelines/OptProf_part2.yml +++ b/azure-pipelines/OptProf_part2.yml @@ -14,6 +14,8 @@ resources: - pipeline: DartLab.OptProf source: DartLab.OptProf branch: main + tags: + - production repositories: - repository: DartLabTemplates type: git @@ -22,7 +24,7 @@ resources: - repository: DartLabOptProfTemplates type: git name: DartLab.OptProf - ref: refs/heads/main + ref: refs/tags/Production parameters: diff --git a/azure-pipelines/Publish-Legacy-Symbols.ps1 b/azure-pipelines/Prepare-Legacy-Symbols.ps1 similarity index 91% rename from azure-pipelines/Publish-Legacy-Symbols.ps1 rename to azure-pipelines/Prepare-Legacy-Symbols.ps1 index 5c4035a19..ae0bc40cb 100644 --- a/azure-pipelines/Publish-Legacy-Symbols.ps1 +++ b/azure-pipelines/Prepare-Legacy-Symbols.ps1 @@ -33,5 +33,3 @@ Get-ChildItem "$ArtifactStagingFolder\*.pdb" -Recurse |% { Move-Item $legacyPdbPath $_ -Force } } - -Write-Host "##vso[artifact.upload containerfolder=symbols-legacy;artifactname=symbols-legacy;]$ArtifactStagingFolder" diff --git a/azure-pipelines/artifacts/VSInsertion.ps1 b/azure-pipelines/artifacts/VSInsertion.ps1 index de7899e60..ffc7e29ad 100644 --- a/azure-pipelines/artifacts/VSInsertion.ps1 +++ b/azure-pipelines/artifacts/VSInsertion.ps1 @@ -16,7 +16,9 @@ if (!$BuildConfiguration) { $BuildConfiguration = 'Debug' } -$NuGetPackages = "$RepoRoot/bin/Packages/$BuildConfiguration/NuGet" +$PackagesRoot = "$RepoRoot/bin/Packages/$BuildConfiguration" +$NuGetPackages = "$PackagesRoot/NuGet" +$VsixPackages = "$PackagesRoot/Vsix" if (!(Test-Path $NuGetPackages)) { Write-Warning "Skipping because NuGet packages haven't been built yet." @@ -27,8 +29,12 @@ $result = @{ "$NuGetPackages" = (Get-ChildItem $NuGetPackages -Recurse) } +if (Test-Path $VsixPackages) { + $result["$PackagesRoot"] += Get-ChildItem $VsixPackages -Recurse +} + if ($env:IsOptProf) { - $VSRepoPackages = "$RepoRoot/bin/Packages/$BuildConfiguration/VSRepo" + $VSRepoPackages = "$PackagesRoot/VSRepo" $result["$VSRepoPackages"] = (Get-ChildItem "$VSRepoPackages\*.VSInsertionMetadata.*.nupkg"); } diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index b41153f86..38e00696a 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -4,6 +4,12 @@ parameters: ##### Feel free to adjust their default value as needed. # Whether this repo uses OptProf to optimize the built binaries. +# When enabling this, be sure to update these files: +# - OptProf.targets: InstallationPath and match TestCase selection with what's in the VS repo. +# - The project file(s) for the libraries to optimize must import OptProf.targets (for multi-targeted projects, only import it for ONE target). +# - OptProf.yml: Search for LibraryName (or your library's name) and verify that those names are appropriate. +# - OptProf_part2.yml: Search for LibraryName (or your library's name) and verify that those names are appropriate. +# and create pipelines for OptProf.yml, OptProf_part2.yml - name: EnableOptProf type: boolean default: true @@ -65,6 +71,11 @@ parameters: type: boolean default: true +# Whether this is a special one-off build for inserting into VS for a validation insertion PR (that will never be merged). +- name: SkipCodesignVerify + type: boolean + default: false + - name: EnableAPIScan type: boolean default: false @@ -85,11 +96,11 @@ parameters: - name: linuxPool type: object default: - vmImage: ubuntu-20.04 + vmImage: ubuntu-22.04 - name: macOSPool type: object default: - vmImage: macOS-12 + vmImage: macOS-14 jobs: - job: Windows @@ -191,6 +202,7 @@ jobs: parameters: EnableOptProf: ${{ parameters.EnableOptProf }} IsOptProf: ${{ parameters.IsOptProf }} + SkipCodesignVerify: ${{ parameters.SkipCodesignVerify }} - ${{ if not(parameters.IsOptProf) }}: - ${{ if parameters.EnableLinuxBuild }}: @@ -263,6 +275,15 @@ jobs: - macOS pool: ${{ parameters.windowsPool }} # Use Windows agent because PublishSymbols task requires it (https://github.com/microsoft/azure-pipelines-tasks/issues/13821). condition: succeededOrFailed() + ${{ if eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9') }}: + templateContext: + outputParentDirectory: $(Build.ArtifactStagingDirectory) + outputs: + - output: pipelineArtifact + displayName: 📢 Publish symbols-legacy + targetPath: $(Build.ArtifactStagingDirectory)/symbols-legacy + artifactName: symbols-legacy + condition: succeededOrFailed() steps: - checkout: self fetchDepth: 0 # avoid shallow clone so nbgv can do its work. diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 196fd4b52..ef6152f2b 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -8,7 +8,7 @@ parameters: steps: -- script: dotnet build -t:build,pack --no-restore -c $(BuildConfiguration) -warnaserror /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog" +- script: dotnet build -t:build,pack --no-restore -c $(BuildConfiguration) -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog" displayName: 🛠 dotnet build - ${{ if not(parameters.IsOptProf) }}: diff --git a/azure-pipelines/libtemplate-update.yml b/azure-pipelines/libtemplate-update.yml new file mode 100644 index 000000000..a67a4ece8 --- /dev/null +++ b/azure-pipelines/libtemplate-update.yml @@ -0,0 +1,168 @@ +# This pipeline schedules regular merges of Library.Template into a repo that is based on it. +# Only Azure Repos are supported. GitHub support comes via a GitHub Actions workflow. + +trigger: none +pr: none +schedules: +- cron: "0 3 * * Mon" # Sun @ 8 or 9 PM Mountain Time (depending on DST) + displayName: Weekly trigger + branches: + include: + - main + always: true + +resources: + repositories: + - repository: MicroBuildTemplate + type: git + name: 1ESPipelineTemplates/MicroBuildTemplate + ref: refs/tags/release + +parameters: +- name: AutoComplete + displayName: Auto-complete pull request + type: boolean + default: false + +variables: +- template: GlobalVariables.yml + +extends: + template: azure-pipelines/MicroBuild.1ES.Unofficial.yml@MicroBuildTemplate + parameters: + sdl: + sourceAnalysisPool: + name: AzurePipelines-EO + demands: + - ImageOverride -equals 1ESPT-Windows2022 + + stages: + - stage: Merge + jobs: + - job: merge + pool: + name: AzurePipelines-EO + demands: + - ImageOverride -equals 1ESPT-Ubuntu22.04 + os: Linux + steps: + - checkout: self + fetchDepth: 0 + clean: true + - pwsh: | + $LibTemplateBranch = & ./azure-pipelines/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + + git fetch https://github.com/aarnott/Library.Template $LibTemplateBranch + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + $LibTemplateCommit = git rev-parse FETCH_HEAD + + if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) { + Write-Host "There are no Library.Template updates to merge." + exit 0 + } + + $UpdateBranchName = 'auto/libtemplateUpdate' + git -c http.extraheader="AUTHORIZATION: bearer $(System.AccessToken)" push origin -f FETCH_HEAD:refs/heads/$UpdateBranchName + + Write-Host "Creating pull request" + $contentType = 'application/json'; + $headers = @{ Authorization = 'Bearer $(System.AccessToken)' }; + $rawRequest = @{ + sourceRefName = "refs/heads/$UpdateBranchName"; + targetRefName = "refs/heads/main"; + title = 'Merge latest Library.Template'; + description = "This merges the latest features and fixes from [Library.Template's $LibTemplateBranch branch](https://github.com/AArnott/Library.Template/tree/$LibTemplateBranch)."; + } + $request = ConvertTo-Json $rawRequest + + $prApiBaseUri = '$(System.TeamFoundationCollectionUri)/$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/pullrequests' + $prCreationUri = $prApiBaseUri + "?api-version=6.0" + Write-Host "POST $prCreationUri" + Write-Host $request + + $prCreationResult = Invoke-RestMethod -uri $prCreationUri -method POST -Headers $headers -ContentType $contentType -Body $request + $prUrl = "$($prCreationResult.repository.webUrl)/pullrequest/$($prCreationResult.pullRequestId)" + Write-Host "Pull request: $prUrl" + $prApiBaseUri += "/$($prCreationResult.pullRequestId)" + + $SummaryPath = Join-Path '$(Agent.TempDirectory)' 'summary.md' + Set-Content -Path $SummaryPath -Value "[Insertion pull request]($prUrl)" + Write-Host "##vso[task.uploadsummary]$SummaryPath" + + # Tag the PR + $tagUri = "$prApiBaseUri/labels?api-version=7.0" + $rawRequest = @{ + name = 'auto-template-merge'; + } + $request = ConvertTo-Json $rawRequest + Invoke-RestMethod -uri $tagUri -method POST -Headers $headers -ContentType $contentType -Body $request | Out-Null + + # Add properties to the PR that we can programatically parse later. + Function Set-PRProperties($properties) { + $rawRequest = $properties.GetEnumerator() |% { + @{ + op = 'add' + path = "/$($_.key)" + from = $null + value = $_.value + } + } + $request = ConvertTo-Json $rawRequest + $setPrPropertyUri = "$prApiBaseUri/properties?api-version=7.0" + Write-Debug "$request" + $setPrPropertyResult = Invoke-RestMethod -uri $setPrPropertyUri -method PATCH -Headers $headers -ContentType 'application/json-patch+json' -Body $request -StatusCodeVariable setPrPropertyStatus -SkipHttpErrorCheck + if ($setPrPropertyStatus -ne 200) { + Write-Host "##vso[task.logissue type=warning]Failed to set pull request properties. Result: $setPrPropertyStatus. $($setPrPropertyResult.message)" + } + } + Write-Host "Setting pull request properties" + Set-PRProperties @{ + 'AutomatedMerge.SourceBranch' = $LibTemplateBranch + 'AutomatedMerge.SourceCommit' = $LibTemplateCommit + } + + # Add an *active* PR comment to warn users to *merge* the pull request instead of squash it. + $request = ConvertTo-Json @{ + comments = @( + @{ + parentCommentId = 0 + content = "Do **not** squash this pull request when completing it. You must *merge* it." + commentType = 'system' + } + ) + status = 'active' + } + $result = Invoke-RestMethod -uri "$prApiBaseUri/threads?api-version=7.1" -method POST -Headers $headers -ContentType $contentType -Body $request -StatusCodeVariable addCommentStatus -SkipHttpErrorCheck + if ($addCommentStatus -ne 200) { + Write-Host "##vso[task.logissue type=warning]Failed to post comment on pull request. Result: $addCommentStatus. $($result.message)" + } + + # Set auto-complete on the PR + if ('${{ parameters.AutoComplete }}' -eq 'True') { + Write-Host "Setting auto-complete" + $mergeMessage = "Merged PR $($prCreationResult.pullRequestId): " + $commitMessage + $rawRequest = @{ + autoCompleteSetBy = @{ + id = $prCreationResult.createdBy.id + }; + completionOptions = @{ + deleteSourceBranch = $true; + mergeCommitMessage = $mergeMessage; + mergeStrategy = 'noFastForward'; + }; + } + $request = ConvertTo-Json $rawRequest + Write-Host $request + $uri = "$($prApiBaseUri)?api-version=6.0" + $result = Invoke-RestMethod -uri $uri -method PATCH -Headers $headers -ContentType $contentType -Body $request -StatusCodeVariable autoCompleteStatus -SkipHttpErrorCheck + if ($autoCompleteStatus -ne 200) { + Write-Host "##vso[task.logissue type=warning]Failed to set auto-complete on pull request. Result: $autoCompleteStatus. $($result.message)" + } + } + + displayName: Create pull request diff --git a/azure-pipelines/microbuild.after.yml b/azure-pipelines/microbuild.after.yml index 67f43b2c5..e21074331 100644 --- a/azure-pipelines/microbuild.after.yml +++ b/azure-pipelines/microbuild.after.yml @@ -5,14 +5,19 @@ parameters: - name: IsOptProf type: boolean default: false +- name: SkipCodesignVerify + type: boolean steps: -- task: MicroBuildCodesignVerify@3 - displayName: 🔍 Verify Signed Files - inputs: - TargetFolders: | - $(Build.SourcesDirectory)/bin/Packages/$(BuildConfiguration) - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) +- ${{ if not(parameters.SkipCodesignVerify) }}: # skip CodesignVerify on validation builds because we don't even test-sign nupkg's. + - task: MicroBuildCodesignVerify@3 + displayName: 🔍 Verify Signed Files + inputs: + ApprovalListPathForSigs: $(Build.SourcesDirectory)\azure-pipelines\no_strongname.txt + ApprovalListPathForCerts: $(Build.SourcesDirectory)\azure-pipelines\no_authenticode.txt + TargetFolders: | + $(Build.SourcesDirectory)/bin/Packages/$(BuildConfiguration) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - ${{ if parameters.IsOptProf }}: - task: ms-vscs-artifact.build-tasks.artifactDropTask-1.artifactDropTask@0 @@ -24,7 +29,6 @@ steps: usePat: true displayName: 📢 Publish to Artifact Services - ProfilingInputs condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) - continueOnError: true - task: PublishBuildArtifacts@1 inputs: diff --git a/azure-pipelines/no_authenticode.txt b/azure-pipelines/no_authenticode.txt new file mode 100644 index 000000000..262625ac9 --- /dev/null +++ b/azure-pipelines/no_authenticode.txt @@ -0,0 +1,2 @@ +bin\packages\release\vsix\_manifest\manifest.cat,sbom signed +bin\packages\release\vsix\_manifest\spdx_2.2\manifest.cat,sbom signed diff --git a/azure-pipelines/no_strongname.txt b/azure-pipelines/no_strongname.txt new file mode 100644 index 000000000..e69de29bb diff --git a/azure-pipelines/official.yml b/azure-pipelines/official.yml index 0351a7498..da5bfed53 100644 --- a/azure-pipelines/official.yml +++ b/azure-pipelines/official.yml @@ -128,6 +128,3 @@ extends: os: macOS EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }} RunTests: ${{ parameters.RunTests }} - - template: /azure-pipelines/prepare-insertion-stages.yml@self - parameters: - RealSign: false diff --git a/azure-pipelines/prepare-insertion-stages.yml b/azure-pipelines/prepare-insertion-stages.yml index adb9afedc..c190920d4 100644 --- a/azure-pipelines/prepare-insertion-stages.yml +++ b/azure-pipelines/prepare-insertion-stages.yml @@ -5,63 +5,74 @@ parameters: - name: RealSign displayName: Real sign? type: boolean +- name: PackagePush + type: boolean + default: true stages: -- stage: release - displayName: Publish - condition: and(succeeded(), eq('${{ parameters.RealSign }}', 'true')) - jobs: - - ${{ if parameters.ArchiveSymbols }}: - - job: symbol_archive - displayName: Archive symbols - pool: VSEngSS-MicroBuild2022-1ES - steps: - - checkout: none - - download: current - artifact: Variables-Windows - displayName: 🔻 Download Variables-Windows artifact - - powershell: $(Pipeline.Workspace)/Variables-Windows/_pipelines.ps1 - displayName: ⚙️ Set pipeline variables based on artifacts - - download: current - artifact: symbols-legacy - displayName: 🔻 Download symbols-legacy artifact - - task: MicroBuildArchiveSymbols@5 - displayName: 🔣 Archive symbols to Symweb - inputs: - SymbolsFeatureName: $(SymbolsFeatureName) - SymbolsProject: VS - SymbolsAgentPath: $(Pipeline.Workspace)/symbols-legacy +- ${{ if or(parameters.ArchiveSymbols, parameters.PackagePush) }}: + - stage: release + displayName: Publish + jobs: + - ${{ if parameters.ArchiveSymbols }}: + - job: symbol_archive + displayName: Archive symbols + pool: VSEngSS-MicroBuild2022-1ES + steps: + - checkout: none + - download: current + artifact: Variables-Windows + displayName: 🔻 Download Variables-Windows artifact + - powershell: $(Pipeline.Workspace)/Variables-Windows/_pipelines.ps1 + displayName: ⚙️ Set pipeline variables based on artifacts + - download: current + artifact: symbols-legacy + displayName: 🔻 Download symbols-legacy artifact + - task: MicroBuildArchiveSymbols@5 + displayName: 🔣 Archive symbols to Symweb + inputs: + SymbolsFeatureName: $(SymbolsFeatureName) + SymbolsProject: VS + SymbolsAgentPath: $(Pipeline.Workspace)/symbols-legacy - - ${{ if true }}: # leave the condition to avoid merge conflicts later. - - job: push - displayName: azure-public/vssdk feed - ${{ if parameters.ArchiveSymbols }}: - dependsOn: symbol_archive - pool: - name: AzurePipelines-EO - demands: - - ImageOverride -equals 1ESPT-Ubuntu22.04 - os: Linux - templateContext: - outputs: - - output: nuget - displayName: 📦 Push nuget packages - packagesToPush: '$(Pipeline.Workspace)/deployables-Windows/NuGet/*.nupkg' - packageParentPath: $(Pipeline.Workspace)/deployables-Windows/NuGet - allowPackageConflicts: true - nuGetFeedType: external - publishFeedCredentials: azure-public/vssdk - steps: - - checkout: none - - download: current - artifact: Variables-Windows - displayName: 🔻 Download Variables-Windows artifact - - powershell: $(Pipeline.Workspace)/Variables-Windows/_pipelines.ps1 - displayName: ⚙️ Set pipeline variables based on artifacts - - download: current - artifact: deployables-Windows - displayName: 🔻 Download deployables-Windows artifact - - template: WIFtoPATauth.yml - parameters: - wifServiceConnectionName: azure-public/vside package push - deadPATServiceConnectionId: 42175e93-c771-4a4f-a132-3cca78f44b3b # azure-public/vssdk + - ${{ if parameters.PackagePush }}: + - job: push + ${{ if parameters.RealSign }}: + displayName: azure-public/vssdk feed + ${{ else }}: + displayName: devdiv/vs-impl feed # Leave this as-is, since non-signed builds must not be pushed to public feeds. + ${{ if parameters.ArchiveSymbols }}: + dependsOn: symbol_archive + pool: + name: AzurePipelines-EO + demands: + - ImageOverride -equals 1ESPT-Ubuntu22.04 + os: Linux + templateContext: + outputs: + - output: nuget + displayName: 📦 Push nuget packages + packagesToPush: '$(Pipeline.Workspace)/deployables-Windows/NuGet/*.nupkg' + packageParentPath: $(Pipeline.Workspace)/deployables-Windows/NuGet + allowPackageConflicts: true + ${{ if parameters.RealSign }}: + nuGetFeedType: external + publishFeedCredentials: azure-public/vssdk + ${{ else }}: + nuGetFeedType: internal + publishVstsFeed: vs-impl # Leave this as-is, since non-signed builds must not be pushed to public feeds. + steps: + - checkout: none + - download: current + artifact: Variables-Windows + displayName: 🔻 Download Variables-Windows artifact + - powershell: $(Pipeline.Workspace)/Variables-Windows/_pipelines.ps1 + displayName: ⚙️ Set pipeline variables based on artifacts + - download: current + artifact: deployables-Windows + displayName: 🔻 Download deployables-Windows artifact + - ${{ if parameters.RealSign }}: + - template: WIFtoPATauth.yml + parameters: + wifServiceConnectionName: azure-public/vside package push + deadPATServiceConnectionId: 42175e93-c771-4a4f-a132-3cca78f44b3b # azure-public/vssdk diff --git a/azure-pipelines/publish-codecoverage.yml b/azure-pipelines/publish-codecoverage.yml index c6247a115..987b2fe23 100644 --- a/azure-pipelines/publish-codecoverage.yml +++ b/azure-pipelines/publish-codecoverage.yml @@ -21,9 +21,8 @@ steps: continueOnError: true - powershell: azure-pipelines/Merge-CodeCoverage.ps1 -Path '$(Pipeline.Workspace)' -OutputFile coveragereport/merged.cobertura.xml -Format Cobertura -Verbose displayName: ⚙ Merge coverage -- task: PublishCodeCoverageResults@1 +- task: PublishCodeCoverageResults@2 displayName: 📢 Publish code coverage results to Azure DevOps inputs: - codeCoverageTool: cobertura summaryFileLocation: coveragereport/merged.cobertura.xml failIfCoverageEmpty: true diff --git a/azure-pipelines/publish-symbols.yml b/azure-pipelines/publish-symbols.yml index ddf82352f..9078ea25a 100644 --- a/azure-pipelines/publish-symbols.yml +++ b/azure-pipelines/publish-symbols.yml @@ -63,5 +63,5 @@ steps: SymbolServerType: TeamServices displayName: 📢 Publish test symbols -- powershell: azure-pipelines/Publish-Legacy-Symbols.ps1 -Path $(Pipeline.Workspace)/symbols/Windows - displayName: 📢 Publish symbols for symbol archival +- powershell: azure-pipelines/Prepare-Legacy-Symbols.ps1 -Path $(Pipeline.Workspace)/symbols/Windows + displayName: ⚙ Prepare symbols for symbol archival diff --git a/azure-pipelines/variables/InsertJsonValues.ps1 b/azure-pipelines/variables/InsertJsonValues.ps1 new file mode 100644 index 000000000..807ca1cbb --- /dev/null +++ b/azure-pipelines/variables/InsertJsonValues.ps1 @@ -0,0 +1,18 @@ +$vstsDropNames = & "$PSScriptRoot\VstsDropNames.ps1" +$BuildConfiguration = $env:BUILDCONFIGURATION +if (!$BuildConfiguration) { + $BuildConfiguration = 'Debug' +} + +$BasePath = "$PSScriptRoot\..\..\bin\Packages\$BuildConfiguration\Vsix" + +if (Test-Path $BasePath) { + $vsmanFiles = @() + Get-ChildItem $BasePath *.vsman -Recurse -File |% { + $version = (Get-Content $_.FullName | ConvertFrom-Json).info.buildVersion + $fn = $_.Name + $vsmanFiles += "LibraryName.vsman{$version}=https://vsdrop.corp.microsoft.com/file/v1/$vstsDropNames;$fn" + } + + [string]::join(',',$vsmanFiles) +} diff --git a/azure-pipelines/variables/VstsDropNames.ps1 b/azure-pipelines/variables/VstsDropNames.ps1 new file mode 100644 index 000000000..4ff36b2c9 --- /dev/null +++ b/azure-pipelines/variables/VstsDropNames.ps1 @@ -0,0 +1 @@ +"Products/$env:SYSTEM_TEAMPROJECT/$env:BUILD_REPOSITORY_NAME/$env:BUILD_SOURCEBRANCHNAME/$env:BUILD_BUILDID" diff --git a/azure-pipelines/vs-insertion.yml b/azure-pipelines/vs-insertion.yml index c83ad5027..5d6d72df5 100644 --- a/azure-pipelines/vs-insertion.yml +++ b/azure-pipelines/vs-insertion.yml @@ -40,6 +40,13 @@ extends: - download: CI artifact: VSInsertion-Windows displayName: 🔻 Download VSInsertion-Windows artifact + - ${{ if eq(variables['ContainsVsix'], 'true') }}: + - task: 1ES.MicroBuildVstsDrop@1 + displayName: 🔺 Upload VSTS Drop + inputs: + dropFolder: $(Pipeline.Workspace)/CI/VSInsertion-windows/Vsix + dropName: $(VstsDropNames) + accessToken: $(System.AccessToken) - task: 1ES.PublishNuget@1 displayName: 📦 Push VS-repo packages to VS feed inputs: diff --git a/azure-pipelines/vs-validation.yml b/azure-pipelines/vs-validation.yml index e8497f813..1bb9f22e2 100644 --- a/azure-pipelines/vs-validation.yml +++ b/azure-pipelines/vs-validation.yml @@ -14,6 +14,8 @@ resources: variables: - template: GlobalVariables.yml +- name: MicroBuild_NuPkgSigningEnabled + value: false # test-signed nuget packages fail to restore in the VS insertion PR validations. Just don't sign them *at all*. extends: template: azure-pipelines/MicroBuild.1ES.Unofficial.yml@MicroBuildTemplate @@ -27,21 +29,31 @@ extends: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages/ BuildConfiguration: Release - ValidationBuild: true + SkipCodesignVerify: true jobs: - template: /azure-pipelines/build.yml@self parameters: Is1ESPT: true - RealSign: true + RealSign: false windowsPool: VSEngSS-MicroBuild2022-1ES + linuxPool: + name: AzurePipelines-EO + demands: + - ImageOverride -equals 1ESPT-Ubuntu22.04 + os: Linux + macOSPool: + name: Azure Pipelines + vmImage: macOS-12 + os: macOS EnableMacOSBuild: false RunTests: false + SkipCodesignVerify: true - template: /azure-pipelines/prepare-insertion-stages.yml@self parameters: ArchiveSymbols: false - RealSign: true + RealSign: false - stage: insertion displayName: VS insertion @@ -61,6 +73,13 @@ extends: - download: current artifact: VSInsertion-Windows displayName: 🔻 Download VSInsertion-Windows artifact + - ${{ if eq(variables['ContainsVsix'], 'true') }}: + - task: 1ES.MicroBuildVstsDrop@1 + displayName: 🔺 Upload VSTS Drop + inputs: + dropFolder: $(Pipeline.Workspace)/VSInsertion-windows/Vsix + dropName: $(VstsDropNames) + accessToken: $(System.AccessToken) - task: 1ES.PublishNuget@1 displayName: 📦 Push VS-repo packages to VS feed inputs: @@ -73,12 +92,13 @@ extends: inputs: TeamName: $(TeamName) TeamEmail: $(TeamEmail) - InsertionPayloadName: $(Build.Repository.Name) VALIDATION BUILD $(Build.BuildNumber) ($(Build.SourceBranch)) [Skip-SymbolCheck] + InsertionPayloadName: $(Build.Repository.Name) VALIDATION BUILD $(Build.BuildNumber) ($(Build.SourceBranch)) [Skip-SymbolCheck] [Skip-HashCheck] [Skip-SignCheck] InsertionDescription: | This PR is for **validation purposes only** for !$(System.PullRequest.PullRequestId). **Do not complete**. CustomScriptExecutionCommand: src/VSSDK/NuGet/AllowUnstablePackages.ps1 InsertionBuildPolicy: Request Perf DDRITs InsertionReviewers: $(Build.RequestedFor) + DraftPR: false # set to true and update InsertionBuildPolicy when we can specify all the validations we want to run (https://dev.azure.com/devdiv/DevDiv/_workitems/edit/2224288) AutoCompletePR: false ShallowClone: true - powershell: | diff --git a/azurepipelines-coverage.yml b/azurepipelines-coverage.yml new file mode 100644 index 000000000..0cd5dad36 --- /dev/null +++ b/azurepipelines-coverage.yml @@ -0,0 +1,6 @@ +# https://learn.microsoft.com/azure/devops/pipelines/test/codecoverage-for-pullrequests?view=azure-devops +coverage: + status: + comments: on # add comment to PRs reporting diff in coverage of modified files + diff: # diff coverage is code coverage only for the lines changed in a pull request. + target: 70% # set this to a desired %. Default is 70% diff --git a/global.json b/global.json index 80d378100..b5764a59c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.300", + "version": "8.0.402", "rollForward": "patch", "allowPrerelease": false }, diff --git a/init.ps1 b/init.ps1 index d68026acb..7bfadb006 100755 --- a/init.ps1 +++ b/init.ps1 @@ -148,7 +148,9 @@ try { if ($SBOM) { Write-Host "Installing MicroBuild SBOM plugin" -ForegroundColor $HeaderColor & $InstallNuGetPkgScriptPath MicroBuild.Plugins.Sbom -source $MicroBuildPackageSource -Verbosity $nugetVerbosity - $PkgMicrosoft_ManifestTool_CrossPlatform = & $InstallNuGetPkgScriptPath Microsoft.ManifestTool.CrossPlatform -source 'https://1essharedassets.pkgs.visualstudio.com/1esPkgs/_packaging/SBOMTool/nuget/v3/index.json' -Verbosity $nugetVerbosity + # The feed with the latest versions of the tool is at 'https://1essharedassets.pkgs.visualstudio.com/1esPkgs/_packaging/SBOMTool/nuget/v3/index.json', + # but we'll use the feed that the SBOM task itself uses to install the tool for consistency. + $PkgMicrosoft_ManifestTool_CrossPlatform = & $InstallNuGetPkgScriptPath Microsoft.ManifestTool.CrossPlatform -source $MicroBuildPackageSource -Verbosity $nugetVerbosity $EnvVars['GenerateSBOM'] = "true" $EnvVars['PkgMicrosoft_ManifestTool_CrossPlatform'] = $PkgMicrosoft_ManifestTool_CrossPlatform } diff --git a/src/OptProf.targets b/src/OptProf.targets new file mode 100644 index 000000000..d0167d7c1 --- /dev/null +++ b/src/OptProf.targets @@ -0,0 +1,17 @@ + + + + IBC + Common7\IDE\PrivateAssemblies\$(TargetFileName) + /ExeConfig:"%VisualStudio.InstallationUnderTest.Path%\Common7\IDE\vsn.exe" + + + + + + + + + + + diff --git a/src/VSInsertionMetadata/VSInsertionMetadata.targets b/src/VSInsertionMetadata/VSInsertionMetadata.targets index 9b23536c6..84ebb5a88 100644 --- a/src/VSInsertionMetadata/VSInsertionMetadata.targets +++ b/src/VSInsertionMetadata/VSInsertionMetadata.targets @@ -33,6 +33,7 @@ + +[CmdletBinding(SupportsShouldProcess = $true)] +Param( + [string]$LocalBranch = "dev/$($env:USERNAME)/libtemplateUpdate" +) + +Function Spawn-Tool($command, $commandArgs, $workingDirectory, $allowFailures) { + if ($workingDirectory) { + Push-Location $workingDirectory + } + try { + if ($env:TF_BUILD) { + Write-Host "$pwd >" + Write-Host "##[command]$command $commandArgs" + } + else { + Write-Host "$command $commandArgs" -ForegroundColor Yellow + } + if ($commandArgs) { + & $command @commandArgs + } else { + Invoke-Expression $command + } + if ((!$allowFailures) -and ($LASTEXITCODE -ne 0)) { exit $LASTEXITCODE } + } + finally { + if ($workingDirectory) { + Pop-Location + } + } +} + +$remoteBranch = & $PSScriptRoot\..\azure-pipelines\Get-LibTemplateBasis.ps1 -ErrorIfNotRelated +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} + +$LibTemplateUrl = 'https://github.com/aarnott/Library.Template' +Spawn-Tool 'git' ('fetch', $LibTemplateUrl, $remoteBranch) +$SourceCommit = Spawn-Tool 'git' ('rev-parse', 'FETCH_HEAD') +$BaseBranch = Spawn-Tool 'git' ('branch', '--show-current') +$SourceCommitUrl = "$LibTemplateUrl/commit/$SourceCommit" + +# To reduce the odds of merge conflicts at this stage, we always move HEAD to the last successful merge. +$basis = Spawn-Tool 'git' ('rev-parse', 'HEAD') # TODO: consider improving this later + +Write-Host "Merging the $remoteBranch branch of Library.Template ($SourceCommit) into local repo $basis" -ForegroundColor Green + +Spawn-Tool 'git' ('checkout', '-b', $LocalBranch, $basis) $null $true +if ($LASTEXITCODE -eq 128) { + Spawn-Tool 'git' ('checkout', $LocalBranch) + Spawn-Tool 'git' ('merge', $basis) +} + +Spawn-Tool 'git' ('merge', 'FETCH_HEAD', '--no-ff', '-m', "Merge the $remoteBranch branch from $LibTemplateUrl`n`nSpecifically, this merges [$SourceCommit from that repo]($SourceCommitUrl).") +if ($LASTEXITCODE -eq 1) { + Write-Error "Merge conflict detected. Manual resolution required." + exit 1 +} +elseif ($LASTEXITCODE -ne 0) { + Write-Error "Merge failed with exit code $LASTEXITCODE." + exit $LASTEXITCODE +} + +$result = New-Object PSObject -Property @{ + BaseBranch = $BaseBranch # The original branch that was checked out when the script ran. + LocalBranch = $LocalBranch # The name of the local branch that was created before the merge. + SourceCommit = $SourceCommit # The commit from Library.Template that was merged in. + SourceBranch = $remoteBranch # The branch from Library.Template that was merged in. +} + +Write-Host $result +Write-Output $result