From 762e59b1da12fe95ffd7130420957d6bcd2c4794 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 2 Nov 2024 15:10:42 -0600 Subject: [PATCH 001/109] Verify formatted code on GitHub workflows --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 00b3dd3f..50cf99c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,6 +47,10 @@ jobs: - name: ๐Ÿงช test run: azure-pipelines/dotnet-test-cloud.ps1 -Configuration ${{ env.BUILDCONFIGURATION }} -Agent ${{ runner.os }} shell: pwsh + - name: ๐Ÿ’…๐Ÿป Verify formatted code + run: dotnet format --verify-no-changes --no-restore + shell: pwsh + if: runner.os == 'Linux' - name: โš™ Update pipeline variables based on build outputs run: azure-pipelines/variables/_pipelines.ps1 shell: pwsh From d046e43768e1553461a261a72ccfa5a26d46e76d Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 5 Nov 2024 08:26:15 -0700 Subject: [PATCH 002/109] Add docfx site placeholder --- .config/dotnet-tools.json | 16 +++++++++--- .github/workflows/docs.yml | 41 ++++++++++++++++++++++++++++++ CONTRIBUTING.md | 9 +++++++ Expand-Template.ps1 | 6 +++++ docfx/.gitignore | 2 ++ docfx/docfx.json | 48 +++++++++++++++++++++++++++++++++++ docfx/docs/features.md | 3 +++ docfx/docs/getting-started.md | 12 +++++++++ docfx/docs/toc.yml | 5 ++++ docfx/index.md | 9 +++++++ docfx/toc.yml | 4 +++ 11 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 docfx/.gitignore create mode 100644 docfx/docfx.json create mode 100644 docfx/docs/features.md create mode 100644 docfx/docs/getting-started.md create mode 100644 docfx/docs/toc.yml create mode 100644 docfx/index.md create mode 100644 docfx/toc.yml diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index e60546c0..a333e70b 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -6,19 +6,29 @@ "version": "7.4.6", "commands": [ "pwsh" - ] + ], + "rollForward": false }, "dotnet-coverage": { "version": "17.12.6", "commands": [ "dotnet-coverage" - ] + ], + "rollForward": false }, "nbgv": { "version": "3.6.146", "commands": [ "nbgv" - ] + ], + "rollForward": false + }, + "docfx": { + "version": "2.77.0", + "commands": [ + "docfx" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..6e6e64a0 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,41 @@ +name: ๐Ÿ“š Docs + +on: + push: + branches: + - main + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + actions: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: pages + cancel-in-progress: false + +jobs: + publish-docs: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: โš™ Install prerequisites + run: ./init.ps1 -UpgradePrerequisites + + - run: dotnet docfx docfx/docfx.json + name: ๐Ÿ“š Generate documentation + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docfx/_site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e56631dd..7ec56f4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,3 +40,12 @@ This repository can be built on Windows, Linux, and OSX. Building, testing, and packing this repository can be done by using the standard dotnet CLI commands (e.g. `dotnet build`, `dotnet test`, `dotnet pack`, etc.). [pwsh]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell?view=powershell-6 + +## Tutorial and API documentation + +API and hand-written docs are found under the `docfx/` directory. and are built by [docfx](https://dotnet.github.io/docfx/). + +You can make changes and host the site locally to preview them by switching to that directory and running the `dotnet docfx --serve` command. +After making a change, you can rebuild the docs site while the localhost server is running by running `dotnet docfx` again from a separate terminal. + +The `.github/workflows/docs.yml` GitHub Actions workflow publishes the content of these docs to github.io if the workflow itself and [GitHub Pages is enabled for your repository](https://docs.github.com/en/pages/quickstart). diff --git a/Expand-Template.ps1 b/Expand-Template.ps1 index e9a567c1..44ef6826 100755 --- a/Expand-Template.ps1 +++ b/Expand-Template.ps1 @@ -166,6 +166,12 @@ try { "(?m)^.*\[GitHub Actions status\].*`r?`n"="" "(?m)^.*\[codecov\].*`r?`n"="" } + Replace-Placeholders -Path "docfx/docfx.json" -Replacements @{ + 'Library'=$LibraryName + } + Replace-Placeholders -Path "docfx/docs/getting-started.md" -Replacements @{ + 'Library'=$LibraryName + } # Specially handle azure-pipelines .yml edits Replace-Placeholders -Path "azure-pipelines/build.yml" -Replacements @{ diff --git a/docfx/.gitignore b/docfx/.gitignore new file mode 100644 index 00000000..d5bcab17 --- /dev/null +++ b/docfx/.gitignore @@ -0,0 +1,2 @@ +_site/ +api/ diff --git a/docfx/docfx.json b/docfx/docfx.json new file mode 100644 index 00000000..729d6731 --- /dev/null +++ b/docfx/docfx.json @@ -0,0 +1,48 @@ +{ + "metadata": [ + { + "src": [ + { + "src": "../src/Library", + "files": [ + "**/*.csproj" + ] + } + ], + "dest": "api" + } + ], + "build": { + "content": [ + { + "files": [ + "**/*.{md,yml}" + ], + "exclude": [ + "_site/**" + ] + } + ], + "resource": [ + { + "files": [ + "images/**" + ] + } + ], + "xref": [ + "https://learn.microsoft.com/en-us/dotnet/.xrefmap.json" + ], + "output": "_site", + "template": [ + "default", + "modern" + ], + "globalMetadata": { + "_appName": "Library", + "_appTitle": "Library", + "_enableSearch": true, + "pdf": false + } + } +} diff --git a/docfx/docs/features.md b/docfx/docs/features.md new file mode 100644 index 00000000..eb3fbeb0 --- /dev/null +++ b/docfx/docs/features.md @@ -0,0 +1,3 @@ +# Features + +TODO diff --git a/docfx/docs/getting-started.md b/docfx/docs/getting-started.md new file mode 100644 index 00000000..eff2c2fb --- /dev/null +++ b/docfx/docs/getting-started.md @@ -0,0 +1,12 @@ +# Getting Started + +## Installation + +Consume this library via its NuGet Package. +Click on the badge to find its latest version and the instructions for consuming it that best apply to your project. + +[![NuGet package](https://img.shields.io/nuget/v/Library.svg)](https://nuget.org/packages/Library) + +## Usage + +TODO diff --git a/docfx/docs/toc.yml b/docfx/docs/toc.yml new file mode 100644 index 00000000..36a38020 --- /dev/null +++ b/docfx/docs/toc.yml @@ -0,0 +1,5 @@ +- name: Features + href: features.md +- name: Getting Started + href: getting-started.md + diff --git a/docfx/index.md b/docfx/index.md new file mode 100644 index 00000000..fc1b9e28 --- /dev/null +++ b/docfx/index.md @@ -0,0 +1,9 @@ +--- +_layout: landing +--- + +# Overview + +This is your docfx landing page. + +Click "Docs" across the top to get get started. diff --git a/docfx/toc.yml b/docfx/toc.yml new file mode 100644 index 00000000..abd17b8c --- /dev/null +++ b/docfx/toc.yml @@ -0,0 +1,4 @@ +- name: Docs + href: docs/ +- name: API + href: api/ From 9b5b71c64552f5cf37cfee9cf96138829b2a6769 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 5 Nov 2024 10:10:16 -0700 Subject: [PATCH 003/109] Fix release notes link to work by default It also makes it work in the case where `PackageProjectUrl` isn't the github.com repository itself. --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 803396d0..98b987f6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -51,7 +51,7 @@ - $(PackageProjectUrl)/releases/tag/v$(Version) + $(RepositoryUrl)/releases/tag/v$(Version) From 373a8ad2d2da268a7879dc937a2377a7b0b50786 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 5 Nov 2024 21:00:24 -0700 Subject: [PATCH 004/109] Fix flags sent to codecov.io It only wants one flag, but we were sending two. --- .github/workflows/build.yml | 2 +- azure-pipelines/dotnet.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 50cf99c8..24bc7d9e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -112,7 +112,7 @@ jobs: path: ${{ runner.temp }}/_artifacts/deployables if: always() - name: ๐Ÿ“ข Publish code coverage results to codecov.io - run: ./azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}Host,${{ env.BUILDCONFIGURATION }}" + run: ./azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" shell: pwsh timeout-minutes: 3 continue-on-error: true diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index b422cfc9..2444928f 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -24,7 +24,7 @@ steps: - powershell: | $ArtifactStagingFolder = & "azure-pipelines/Get-ArtifactsStagingDirectory.ps1" $CoverageResultsFolder = Join-Path $ArtifactStagingFolder "coverageResults-$(Agent.JobName)" - azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "$(codecov_token)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)Host,$(BuildConfiguration)" + azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "$(codecov_token)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)" displayName: ๐Ÿ“ข Publish code coverage results to codecov.io timeoutInMinutes: 3 continueOnError: true From 2c7d5a30fdee9c14f1851aeff77bc4f17439053f Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:10:15 -0700 Subject: [PATCH 005/109] Bump .NET SDK to 9.0 --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 1f0eafb4..088f23e1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.402", + "version": "9.0.100", "rollForward": "patch", "allowPrerelease": false } From 134713d8d28c432aae1d108d230b5088d777fc7e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:17:51 -0700 Subject: [PATCH 006/109] Target .NET 8 instead of .NET 6 Today, .NET 6 falls out of support. --- src/Library/Library.csproj | 2 +- test/Library.Tests/CalculatorTests.cs | 2 +- test/Library.Tests/Library.Tests.csproj | 2 +- tools/Install-NuGetCredProvider.ps1 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Library/Library.csproj b/src/Library/Library.csproj index 50aff997..89f06234 100644 --- a/src/Library/Library.csproj +++ b/src/Library/Library.csproj @@ -1,5 +1,5 @@ - net6.0;netstandard2.0 + net8.0;netstandard2.0 diff --git a/test/Library.Tests/CalculatorTests.cs b/test/Library.Tests/CalculatorTests.cs index 0e7e8339..a35947bc 100644 --- a/test/Library.Tests/CalculatorTests.cs +++ b/test/Library.Tests/CalculatorTests.cs @@ -14,7 +14,7 @@ public CalculatorTests() public void AddOrSubtract() { // This tests aggregation of code coverage across test runs. -#if NET6_0_OR_GREATER +#if NET8_0_OR_GREATER Assert.Equal(3, Calculator.Add(1, 2)); #else Assert.Equal(-1, Calculator.Subtract(1, 2)); diff --git a/test/Library.Tests/Library.Tests.csproj b/test/Library.Tests/Library.Tests.csproj index 134f0669..a853dc7d 100644 --- a/test/Library.Tests/Library.Tests.csproj +++ b/test/Library.Tests/Library.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 $(TargetFrameworks);net472 diff --git a/tools/Install-NuGetCredProvider.ps1 b/tools/Install-NuGetCredProvider.ps1 index 496049a2..857324b6 100755 --- a/tools/Install-NuGetCredProvider.ps1 +++ b/tools/Install-NuGetCredProvider.ps1 @@ -43,7 +43,7 @@ if ($IsMacOS -or $IsLinux) { chmod u+x $installerScript } -& $installerScript -Force:$Force -AddNetfx -InstallNet6 +& $installerScript -Force:$Force -AddNetfx -InstallNet8 if ($AccessToken) { $endpoints = @() From 5669382ddd7349508448df01f8a73e7e0ab7ef58 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:00:36 -0700 Subject: [PATCH 007/109] Fix token permissions for Library.Template update workflow --- .github/workflows/libtemplate-update.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index 564d4af2..b6990a51 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -13,6 +13,9 @@ on: jobs: merge: runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: - uses: actions/checkout@v4 with: From f49fb31babda83725b6ee872c5c750c5cb271410 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:39:15 -0700 Subject: [PATCH 008/109] Print diff of what has changed recently --- .github/workflows/libtemplate-update.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index b6990a51..e8b0a696 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -34,6 +34,7 @@ jobs: exit $LASTEXITCODE } $LibTemplateCommit = git rev-parse FETCH_HEAD + git diff --stat ...FETCH_HEAD if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) { Write-Host "There are no Library.Template updates to merge." From 0459d740a79b3981b13dc96d3ee2e058da876b6b Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:39:38 -0700 Subject: [PATCH 009/109] Skip PR creation step when no changes are present to merge --- .github/workflows/libtemplate-update.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index e8b0a696..351ee3f4 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -22,6 +22,7 @@ jobs: fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - name: merge + id: merge shell: pwsh run: | $LibTemplateBranch = & ./azure-pipelines/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated @@ -38,12 +39,14 @@ jobs: if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) { Write-Host "There are no Library.Template updates to merge." + echo "::set-output name=uptodate::true" 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 + if: success() && steps.merge.outputs.uptodate != 'true' 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 From faade5e8eb4f3164832ec23f25234518ecc5d8ca Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:51:17 -0700 Subject: [PATCH 010/109] Compile with C# language version 13 --- Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index ecd71a31..ffbdb502 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,7 @@ - 12 + 13 16.9 From 928d88e02c2c660edff0b9f0c8da02199b4ff91d Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 16:59:43 -0700 Subject: [PATCH 011/109] Fix to avoid deprecation warning --- .github/workflows/libtemplate-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index 351ee3f4..079d900f 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -39,7 +39,7 @@ jobs: if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) { Write-Host "There are no Library.Template updates to merge." - echo "::set-output name=uptodate::true" + echo "uptodate=true" >> $env:GITHUB_OUTPUT exit 0 } From 57a21a8bfa44e9929011aaf1cece5b86fadfbc5d Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 17:12:02 -0700 Subject: [PATCH 012/109] Update prerequisite verbiage --- .github/workflows/libtemplate-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index 079d900f..b0fdd16a 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -1,8 +1,8 @@ name: Library.Template update -# PREREQUISITE: This workflow requires the repo to be configured to allow workflows to push commits and create pull requests. +# PREREQUISITE: This workflow requires the repo to be configured to allow workflows to 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" +# Under "Workflow permissions" check "Allow GitHub Actions to create ...pull requests" # Click Save. on: From 53ba423e0b4b80af3918ecfb153cea8b6349a2c5 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 17:23:09 -0700 Subject: [PATCH 013/109] Avoid pushing workflow changes in Library.Template updates --- .github/workflows/libtemplate-update.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index b0fdd16a..3c7fc94f 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -43,7 +43,26 @@ jobs: exit 0 } - git -c http.extraheader="AUTHORIZATION: bearer $env:GH_TOKEN" push origin -u FETCH_HEAD:refs/heads/auto/libtemplateUpdate + # Pushing commits that add or change files under .github/workflows will cause our workflow to fail. + # But it usually isn't necessary because the target branch already has (or doesn't have) these changes. + # So if the merged doesn't bring in any changes to these files, try the merge locally and push that + # to keep github happy. + if ((git rev-list FETCH_HEAD ^HEAD --count -- .github/workflows) -eq 0) { + # Indeed there are no changes in that area. So merge locally to try to appease GitHub. + git checkout -b auto/libtemplateUpdate + git config user.name "Andrew Arnott" + git config user.email "andrewarnott@live.com" + git merge FETCH_HEAD + if ($LASTEXITCODE -ne 0) { + Write-Host "Merge conflicts prevent creating the pull request. Please run tools/MergeFrom-Template.ps1 locally and push the result as a pull request." + exit 2 + } + + git -c http.extraheader="AUTHORIZATION: bearer $env:GH_TOKEN" push origin -u HEAD + } else { + Write-Host "Changes to github workflows are included in this update. Please run tools/MergeFrom-Template.ps1 locally and push the result as a pull request." + exit 1 + } - name: pull request shell: pwsh if: success() && steps.merge.outputs.uptodate != 'true' From 77ef017a4ba024f8e5c8edf19be45d614be13128 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 12 Nov 2024 17:39:15 -0700 Subject: [PATCH 014/109] Improve placement of warning --- .github/workflows/libtemplate-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index 3c7fc94f..0831ced6 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -77,6 +77,8 @@ jobs: $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/). + โš ๏ธ Do **not** squash this pull request when completing it. You must *merge* it." +
Merge conflicts? Resolve merge conflicts locally by carrying out these steps: @@ -91,8 +93,6 @@ jobs: ```
- โš ๏ธ 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 }} From 7f14687b14264f5919b03676b7937546f4b5a6cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 07:53:33 -0700 Subject: [PATCH 015/109] Bump docfx from 2.77.0 to 2.78.0 (#311) Bumps [docfx](https://github.com/dotnet/docfx) from 2.77.0 to 2.78.0. - [Release notes](https://github.com/dotnet/docfx/releases) - [Changelog](https://github.com/dotnet/docfx/blob/main/RELEASENOTE.md) - [Commits](https://github.com/dotnet/docfx/compare/v2.77.0...v2.78.0) --- updated-dependencies: - dependency-name: docfx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a333e70b..85b44b22 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -24,7 +24,7 @@ "rollForward": false }, "docfx": { - "version": "2.77.0", + "version": "2.78.0", "commands": [ "docfx" ], From 64483bf071f2691dcd96a7c691dfe0ddfc8f44c0 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 18 Nov 2024 13:59:43 -0700 Subject: [PATCH 016/109] Fix libtemplate update workflow It had a quote in the wrong place. --- .github/workflows/libtemplate-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index 0831ced6..0501d5ee 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -77,7 +77,7 @@ jobs: $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/). - โš ๏ธ Do **not** squash this pull request when completing it. You must *merge* it." + โš ๏ธ Do **not** squash this pull request when completing it. You must *merge* it.
Merge conflicts? @@ -91,7 +91,7 @@ jobs: git commit git push ``` -
+ " gh pr create -H auto/libtemplateUpdate -b $prBody -t $prTitle env: From 20e285c4d956424d2686261faa32f8721d5a7acf Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 19 Nov 2024 07:35:32 -0700 Subject: [PATCH 017/109] Avoid `dotnet format` hang Workaround https://github.com/dotnet/sdk/issues/44951 --- Directory.Packages.props | 3 ++- azure-pipelines/build.yml | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4baf6ece..aa1a719d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -13,7 +13,8 @@ - + + diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index 10825828..5c106ade 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -37,8 +37,10 @@ jobs: - template: dotnet.yml parameters: RunTests: ${{ parameters.RunTests }} - - script: dotnet format --verify-no-changes --no-restore + - script: dotnet format --verify-no-changes displayName: ๐Ÿ’… Verify formatted code + env: + dotnetformat: true # part of a workaround for https://github.com/dotnet/sdk/issues/44951 - template: expand-template.yml - job: macOS From 6775c31bac407a3dbb392d37861e3ec01b2d8214 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 19 Nov 2024 13:01:49 -0700 Subject: [PATCH 018/109] Update devcontainer for latest SDK and extension --- .devcontainer/Dockerfile | 2 +- .devcontainer/devcontainer.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 9626b31b..42fd12a7 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.402-jammy +FROM mcr.microsoft.com/dotnet/sdk:9.0.100-noble # 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/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f4e3b31a..01a087c7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,11 +10,12 @@ "ms-dotnettools.csharp", "k--kato.docomment", "editorconfig.editorconfig", + "esbenp.prettier-vscode", "pflannery.vscode-versionlens", "davidanson.vscode-markdownlint", "dotjoshjohnson.xml", "ms-vscode-remote.remote-containers", "ms-azuretools.vscode-docker", - "ms-vscode.powershell" + "tintoy.msbuild-project-tools" ] } From 5bd86bbe7bca8843b2f0f0b9ea79d60892d0845e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 19 Nov 2024 17:45:09 -0700 Subject: [PATCH 019/109] Get dependabot to help us keep the .NET SDK current https://github.blog/changelog/2024-11-19-dependabot-can-now-perform-version-updates-for-the-net-sdk/ --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 63e3e890..b168ac6d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,3 +7,7 @@ updates: directory: / schedule: interval: weekly +- package-ecosystem: dotnet-sdk + directory: / + schedule: + interval: monthly From 325831ec518b94a4fe7f0622bccf50d93817ce90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:24:33 -0700 Subject: [PATCH 020/109] Bump docfx from 2.78.0 to 2.78.1 (#313) Bumps [docfx](https://github.com/dotnet/docfx) from 2.78.0 to 2.78.1. - [Release notes](https://github.com/dotnet/docfx/releases) - [Changelog](https://github.com/dotnet/docfx/blob/main/RELEASENOTE.md) - [Commits](https://github.com/dotnet/docfx/compare/v2.78.0...2.78.1) --- updated-dependencies: - dependency-name: docfx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 85b44b22..1c5d6944 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -24,7 +24,7 @@ "rollForward": false }, "docfx": { - "version": "2.78.0", + "version": "2.78.1", "commands": [ "docfx" ], From 2d80693eb0017d6a7cd9bf83d8e19417452bbb11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:24:58 -0700 Subject: [PATCH 021/109] Bump Microsoft.NET.Test.Sdk from 17.11.1 to 17.12.0 (#312) Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.11.1 to 17.12.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.11.1...v17.12.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index aa1a719d..1a464d15 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ true - + From 49241ecb5b85fc42897ae0ec0457d572eff630f7 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 22 Nov 2024 18:49:08 -0700 Subject: [PATCH 022/109] Use `-LiteralPath` instead of `-Path` in ps1 scripts Fixes #314 --- Expand-Template.ps1 | 4 ++-- azure-pipelines/Get-CodeCovTool.ps1 | 2 +- azure-pipelines/Merge-CodeCoverage.ps1 | 2 +- azure-pipelines/artifacts/Variables.ps1 | 4 ++-- azure-pipelines/artifacts/_pipelines.ps1 | 2 +- azure-pipelines/artifacts/_stage_all.ps1 | 2 +- azure-pipelines/artifacts/coverageResults.ps1 | 4 ++-- azure-pipelines/dotnet-test-cloud.ps1 | 2 +- azure-pipelines/publish-CodeCov.ps1 | 2 +- azure-pipelines/variables/DotNetSdkVersion.ps1 | 2 +- azure-pipelines/variables/_pipelines.ps1 | 4 ++-- tools/Install-DotNetSdk.ps1 | 4 ++-- tools/Install-NuGetCredProvider.ps1 | 2 +- tools/Set-EnvVars.ps1 | 12 ++++++------ 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Expand-Template.ps1 b/Expand-Template.ps1 index 44ef6826..9f9db676 100755 --- a/Expand-Template.ps1 +++ b/Expand-Template.ps1 @@ -40,7 +40,7 @@ function Replace-Placeholders { $Path = Resolve-Path $Path Write-Host "Replacing tokens in `"$Path`"" - $content = Get-Content -Path $Path | Out-String + $content = Get-Content -LiteralPath $Path | Out-String $Replacements.GetEnumerator() |% { $modifiedContent = $content -replace $_.Key,$_.Value if ($modifiedContent -eq $content) { @@ -199,7 +199,7 @@ try { # Self-integrity check Get-ChildItem -Recurse -File -Exclude bin,obj,README.md,Expand-Template.* |? { -not $_.FullName.Contains("obj") } |% { - $PLACEHOLDERS = Get-Content -Path $_.FullName |? { $_.Contains('PLACEHOLDER') } + $PLACEHOLDERS = Get-Content -LiteralPath $_.FullName |? { $_.Contains('PLACEHOLDER') } if ($PLACEHOLDERS) { Write-Error "PLACEHOLDER discovered in $($_.FullName)" } diff --git a/azure-pipelines/Get-CodeCovTool.ps1 b/azure-pipelines/Get-CodeCovTool.ps1 index ca580b4d..734ee607 100644 --- a/azure-pipelines/Get-CodeCovTool.ps1 +++ b/azure-pipelines/Get-CodeCovTool.ps1 @@ -68,7 +68,7 @@ if (!(Test-Path $finalToolPath)) { } Write-Host "Verifying hash on downloaded tool" -ForegroundColor Yellow - $actualHash = (Get-FileHash -Path $tool -Algorithm SHA256).Hash + $actualHash = (Get-FileHash -LiteralPath $tool -Algorithm SHA256).Hash $expectedHash = (Get-Content $sha).Split()[0] if ($actualHash -ne $expectedHash) { # Validation failed. Delete the tool so we can't execute it. diff --git a/azure-pipelines/Merge-CodeCoverage.ps1 b/azure-pipelines/Merge-CodeCoverage.ps1 index 5ecabbc9..308f5754 100644 --- a/azure-pipelines/Merge-CodeCoverage.ps1 +++ b/azure-pipelines/Merge-CodeCoverage.ps1 @@ -28,7 +28,7 @@ try { if ($reports) { $reports |% { $_.FullName } |% { # In addition to replacing {reporoot}, we also normalize on one kind of slash so that the report aggregates data for a file whether data was collected on Windows or not. - $xml = [xml](Get-Content -Path $_) + $xml = [xml](Get-Content -LiteralPath $_) $xml.coverage.packages.package.classes.class |? { $_.filename} |% { $_.filename = $_.filename.Replace('{reporoot}', $RepoRoot).Replace([IO.Path]::AltDirectorySeparatorChar, [IO.Path]::DirectorySeparatorChar) } diff --git a/azure-pipelines/artifacts/Variables.ps1 b/azure-pipelines/artifacts/Variables.ps1 index 4bc6d216..7a320c7e 100644 --- a/azure-pipelines/artifacts/Variables.ps1 +++ b/azure-pipelines/artifacts/Variables.ps1 @@ -32,10 +32,10 @@ Get-ChildItem "$PSScriptRoot/../variables" |% { # If that didn't get us anything, just copy the script itself if (-not $value) { - $value = Get-Content -Path $_.FullName + $value = Get-Content -LiteralPath $_.FullName } - Set-Content -Path "$VariablesArtifactPath/$($_.Name)" -Value $value + Set-Content -LiteralPath "$VariablesArtifactPath/$($_.Name)" -Value $value } @{ diff --git a/azure-pipelines/artifacts/_pipelines.ps1 b/azure-pipelines/artifacts/_pipelines.ps1 index 47321ed5..5f259a51 100644 --- a/azure-pipelines/artifacts/_pipelines.ps1 +++ b/azure-pipelines/artifacts/_pipelines.ps1 @@ -16,7 +16,7 @@ Function Set-PipelineVariable($name, $value) { return # already set } - #New-Item -Path "Env:\$name".ToUpper() -Value $value -Force | Out-Null + #New-Item -LiteralPath "Env:\$name".ToUpper() -Value $value -Force | Out-Null Write-Host "##vso[task.setvariable variable=$name]$value" } diff --git a/azure-pipelines/artifacts/_stage_all.ps1 b/azure-pipelines/artifacts/_stage_all.ps1 index 74d7a38d..bf961ce5 100644 --- a/azure-pipelines/artifacts/_stage_all.ps1 +++ b/azure-pipelines/artifacts/_stage_all.ps1 @@ -51,7 +51,7 @@ $Artifacts |% { if (Test-Path -PathType Leaf $_.Source) { # skip folders $TargetPath = Join-Path $DestinationFolder $Name if ($AvoidSymbolicLinks) { - Copy-Item -Path $_.Source -Destination $TargetPath + Copy-Item -LiteralPath $_.Source -Destination $TargetPath } else { Create-SymbolicLink -Link $TargetPath -Target $_.Source } diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/azure-pipelines/artifacts/coverageResults.ps1 index 280ff9ae..a6c8f420 100644 --- a/azure-pipelines/artifacts/coverageResults.ps1 +++ b/azure-pipelines/artifacts/coverageResults.ps1 @@ -6,8 +6,8 @@ $coverageFiles = @(Get-ChildItem "$RepoRoot/test/*.cobertura.xml" -Recurse | Whe if ($env:SYSTEM_DEFAULTWORKINGDIRECTORY) { Write-Host "Substituting $env:SYSTEM_DEFAULTWORKINGDIRECTORY with `"{reporoot}`"" $coverageFiles |% { - $content = Get-Content -Path $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } - Set-Content -Path $_ -Value $content -Encoding UTF8 + $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } + Set-Content -LiteralPath $_ -Value $content -Encoding UTF8 } } else { Write-Warning "coverageResults: Azure Pipelines not detected. Machine-neutral token replacement skipped." diff --git a/azure-pipelines/dotnet-test-cloud.ps1 b/azure-pipelines/dotnet-test-cloud.ps1 index 24bf812a..33ff3d7c 100755 --- a/azure-pipelines/dotnet-test-cloud.ps1 +++ b/azure-pipelines/dotnet-test-cloud.ps1 @@ -61,7 +61,7 @@ Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% { Copy-Item $_ -Destination $ArtifactStagingFolder/test_logs/ if ($PublishResults) { - $x = [xml](Get-Content -Path $_) + $x = [xml](Get-Content -LiteralPath $_) $runTitle = $null if ($x.TestRun.TestDefinitions -and $x.TestRun.TestDefinitions.GetElementsByTagName('UnitTest')) { $storage = $x.TestRun.TestDefinitions.GetElementsByTagName('UnitTest')[0].storage -replace '\\','/' diff --git a/azure-pipelines/publish-CodeCov.ps1 b/azure-pipelines/publish-CodeCov.ps1 index 9926f018..1d736511 100644 --- a/azure-pipelines/publish-CodeCov.ps1 +++ b/azure-pipelines/publish-CodeCov.ps1 @@ -22,7 +22,7 @@ Param ( $RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path -Get-ChildItem -Recurse -Path $PathToCodeCoverage -Filter "*.cobertura.xml" | % { +Get-ChildItem -Recurse -LiteralPath $PathToCodeCoverage -Filter "*.cobertura.xml" | % { $relativeFilePath = Resolve-Path -relative $_.FullName Write-Host "Uploading: $relativeFilePath" -ForegroundColor Yellow diff --git a/azure-pipelines/variables/DotNetSdkVersion.ps1 b/azure-pipelines/variables/DotNetSdkVersion.ps1 index b213fbc2..722cc584 100644 --- a/azure-pipelines/variables/DotNetSdkVersion.ps1 +++ b/azure-pipelines/variables/DotNetSdkVersion.ps1 @@ -1,2 +1,2 @@ -$globalJson = Get-Content -Path "$PSScriptRoot\..\..\global.json" | ConvertFrom-Json +$globalJson = Get-Content -LiteralPath "$PSScriptRoot\..\..\global.json" | ConvertFrom-Json $globalJson.sdk.version diff --git a/azure-pipelines/variables/_pipelines.ps1 b/azure-pipelines/variables/_pipelines.ps1 index 11748b81..d40e5cf1 100644 --- a/azure-pipelines/variables/_pipelines.ps1 +++ b/azure-pipelines/variables/_pipelines.ps1 @@ -24,8 +24,8 @@ param ( # and the second that works across jobs and stages but must be fully qualified when referenced. Write-Host "##vso[task.setvariable variable=$keyCaps;isOutput=true]$($_.Value)" } elseif ($env:GITHUB_ACTIONS) { - Add-Content -Path $env:GITHUB_ENV -Value "$keyCaps=$($_.Value)" + Add-Content -LiteralPath $env:GITHUB_ENV -Value "$keyCaps=$($_.Value)" } - Set-Item -Path "env:$keyCaps" -Value $_.Value + Set-Item -LiteralPath "env:$keyCaps" -Value $_.Value } } diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 index e190fcfb..ffb52203 100644 --- a/tools/Install-DotNetSdk.ps1 +++ b/tools/Install-DotNetSdk.ps1 @@ -55,8 +55,8 @@ $runtimeVersions = @() $windowsDesktopRuntimeVersions = @() $aspnetRuntimeVersions = @() if (!$SdkOnly) { - Get-ChildItem "$PSScriptRoot\..\src\*.*proj","$PSScriptRoot\..\test\*.*proj","$PSScriptRoot\..\Directory.Build.props" -Recurse |% { - $projXml = [xml](Get-Content -Path $_) + Get-ChildItem "$PSScriptRoot\..\src\*.*proj", "$PSScriptRoot\..\test\*.*proj", "$PSScriptRoot\..\Directory.Build.props" -Recurse | % { + $projXml = [xml](Get-Content -LiteralPath $_) $pg = $projXml.Project.PropertyGroup if ($pg) { $targetFrameworks = @() diff --git a/tools/Install-NuGetCredProvider.ps1 b/tools/Install-NuGetCredProvider.ps1 index 857324b6..2b904e33 100755 --- a/tools/Install-NuGetCredProvider.ps1 +++ b/tools/Install-NuGetCredProvider.ps1 @@ -50,7 +50,7 @@ if ($AccessToken) { $endpointURIs = @() Get-ChildItem "$PSScriptRoot\..\nuget.config" -Recurse |% { - $nugetConfig = [xml](Get-Content -Path $_) + $nugetConfig = [xml](Get-Content -LiteralPath $_) $nugetConfig.configuration.packageSources.add |? { ($_.value -match '^https://pkgs\.dev\.azure\.com/') -or ($_.value -match '^https://[\w\-]+\.pkgs\.visualstudio\.com/') } |% { if ($endpointURIs -notcontains $_.Value) { diff --git a/tools/Set-EnvVars.ps1 b/tools/Set-EnvVars.ps1 index 3f6f86ba..2bd3ca4d 100644 --- a/tools/Set-EnvVars.ps1 +++ b/tools/Set-EnvVars.ps1 @@ -45,14 +45,14 @@ if ($env:GITHUB_ACTIONS) { $CmdEnvScript = '' $Variables.GetEnumerator() |% { - Set-Item -Path env:$($_.Key) -Value $_.Value + Set-Item -LiteralPath env:$($_.Key) -Value $_.Value # If we're running in a cloud CI, set these environment variables so they propagate. if ($env:TF_BUILD) { Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)" } if ($env:GITHUB_ACTIONS) { - Add-Content -Path $env:GITHUB_ENV -Value "$($_.Key)=$($_.Value)" + Add-Content -LiteralPath $env:GITHUB_ENV -Value "$($_.Key)=$($_.Value)" } if ($cmdInstructions) { @@ -70,7 +70,7 @@ if ($IsMacOS -or $IsLinux) { if ($PrependPath) { $PrependPath |% { $newPathValue = "$_$pathDelimiter$env:PATH" - Set-Item -Path env:PATH -Value $newPathValue + Set-Item -LiteralPath env:PATH -Value $newPathValue if ($cmdInstructions) { Write-Host "SET PATH=$newPathValue" } @@ -79,7 +79,7 @@ if ($PrependPath) { Write-Host "##vso[task.prependpath]$_" } if ($env:GITHUB_ACTIONS) { - Add-Content -Path $env:GITHUB_PATH -Value $_ + Add-Content -LiteralPath $env:GITHUB_PATH -Value $_ } $CmdEnvScript += "SET PATH=$_$pathDelimiter%PATH%" @@ -88,10 +88,10 @@ if ($PrependPath) { if ($env:CmdEnvScriptPath) { if (Test-Path $env:CmdEnvScriptPath) { - $CmdEnvScript = (Get-Content -Path $env:CmdEnvScriptPath) + $CmdEnvScript + $CmdEnvScript = (Get-Content -LiteralPath $env:CmdEnvScriptPath) + $CmdEnvScript } - Set-Content -Path $env:CmdEnvScriptPath -Value $CmdEnvScript + Set-Content -LiteralPath $env:CmdEnvScriptPath -Value $CmdEnvScript } return !$cmdInstructions From 110da233b0796e2c3e9a3acfabe9df70334a796e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 25 Nov 2024 06:51:07 -0700 Subject: [PATCH 023/109] Replace `Nullable` with `PolySharp` as a dependency PolySharp is far more exhaustive in the polyfills than Nullable is. --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1a464d15..237b3c2c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,7 +15,7 @@ - +
From f8235e44613937e4f524aeae1654c1438fd1d612 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 27 Nov 2024 11:36:45 -0700 Subject: [PATCH 024/109] Add docfx verification to build --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 24bc7d9e..6b1fb606 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,8 +3,8 @@ name: CI on: push: branches: - - main - - validate/* + - main + - validate/* pull_request: env: @@ -51,6 +51,9 @@ jobs: run: dotnet format --verify-no-changes --no-restore shell: pwsh if: runner.os == 'Linux' + - name: ๐Ÿ“š Verify docfx build + run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures + if: runner.os == 'Linux' - name: โš™ Update pipeline variables based on build outputs run: azure-pipelines/variables/_pipelines.ps1 shell: pwsh From 45279a7aaf81400e9420099490a33c41d87bd2c4 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 27 Nov 2024 12:02:22 -0700 Subject: [PATCH 025/109] Fix nb.gv failure during docfx build --- .github/workflows/docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6e6e64a0..1820866e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,6 +25,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - name: โš™ Install prerequisites run: ./init.ps1 -UpgradePrerequisites From 3a32d099657cdfddc0175cdacbd55a450c171a6e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 30 Nov 2024 09:02:09 -0700 Subject: [PATCH 026/109] Remove double word from boilerplate docfx text --- docfx/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docfx/index.md b/docfx/index.md index fc1b9e28..391ee6ec 100644 --- a/docfx/index.md +++ b/docfx/index.md @@ -6,4 +6,4 @@ _layout: landing This is your docfx landing page. -Click "Docs" across the top to get get started. +Click "Docs" across the top to get started. From feb1a4651ff6fcf933deae89478c1f06dab2db6c Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 2 Dec 2024 07:10:53 -0700 Subject: [PATCH 027/109] Bump docfx to 2.78.2 --- .config/dotnet-tools.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1c5d6944..81e88d25 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -24,11 +24,11 @@ "rollForward": false }, "docfx": { - "version": "2.78.1", + "version": "2.78.2", "commands": [ "docfx" ], "rollForward": false } } -} \ No newline at end of file +} From 130ad679bb04f5a57b2cbf111675303eb6f531e1 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 8 Dec 2024 18:27:14 -0700 Subject: [PATCH 028/109] Bump dotnet-coverage to 17.13.1 --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 81e88d25..aaff6e7f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,7 +10,7 @@ "rollForward": false }, "dotnet-coverage": { - "version": "17.12.6", + "version": "17.13.1", "commands": [ "dotnet-coverage" ], From 8a0d319d2a5fdac363f11c092ff83561234eeb0a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 8 Dec 2024 19:56:33 -0700 Subject: [PATCH 029/109] Move artifact publishing into a composite action --- .github/actions/publish-artifacts/action.yaml | 67 +++++++++++++++++++ .github/workflows/build.yml | 60 +---------------- 2 files changed, 70 insertions(+), 57 deletions(-) create mode 100644 .github/actions/publish-artifacts/action.yaml diff --git a/.github/actions/publish-artifacts/action.yaml b/.github/actions/publish-artifacts/action.yaml new file mode 100644 index 00000000..94b74261 --- /dev/null +++ b/.github/actions/publish-artifacts/action.yaml @@ -0,0 +1,67 @@ +name: Publish artifacts +description: Publish artifacts + +runs: + using: composite + steps: + - name: ๐Ÿ“ฅ Collect artifacts + run: azure-pipelines/artifacts/_stage_all.ps1 + shell: pwsh + if: always() + +# TODO: replace this hard-coded list with a loop that utilizes the NPM package at +# https://github.com/actions/toolkit/tree/main/packages/artifact (or similar) to push the artifacts. + + - name: ๐Ÿ“ข Upload project.assets.json files + if: always() + uses: actions/upload-artifact@v4 + with: + name: projectAssetsJson-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/projectAssetsJson + continue-on-error: true + - name: ๐Ÿ“ข Upload variables + uses: actions/upload-artifact@v4 + with: + name: variables-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/Variables + continue-on-error: true + - name: ๐Ÿ“ข Upload build_logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: build_logs-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/build_logs + continue-on-error: true + - name: ๐Ÿ“ข Upload test_logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: test_logs-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/test_logs + continue-on-error: true + - name: ๐Ÿ“ข Upload testResults + if: always() + uses: actions/upload-artifact@v4 + with: + name: testResults-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/testResults + continue-on-error: true + - name: ๐Ÿ“ข Upload coverageResults + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverageResults-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/coverageResults + continue-on-error: true + - name: ๐Ÿ“ข Upload symbols + uses: actions/upload-artifact@v4 + with: + name: symbols-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/symbols + continue-on-error: true + - name: ๐Ÿ“ข Upload deployables + uses: actions/upload-artifact@v4 + with: + name: deployables-${{ runner.os }} + path: ${{ runner.temp }}/_artifacts/deployables + if: always() diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b1fb606..9d87be99 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,6 +15,7 @@ env: jobs: build: + name: ๐Ÿญ Build runs-on: ${{ matrix.os }} strategy: @@ -57,63 +58,8 @@ jobs: - name: โš™ Update pipeline variables based on build outputs run: azure-pipelines/variables/_pipelines.ps1 shell: pwsh - - name: ๐Ÿ“ฅ Collect artifacts - run: azure-pipelines/artifacts/_stage_all.ps1 - shell: pwsh - if: always() - - name: ๐Ÿ“ข Upload project.assets.json files - if: always() - uses: actions/upload-artifact@v4 - with: - name: projectAssetsJson-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/projectAssetsJson - continue-on-error: true - - name: ๐Ÿ“ข Upload variables - uses: actions/upload-artifact@v4 - with: - name: variables-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/Variables - continue-on-error: true - - name: ๐Ÿ“ข Upload build_logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: build_logs-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/build_logs - continue-on-error: true - - name: ๐Ÿ“ข Upload test_logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: test_logs-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/test_logs - continue-on-error: true - - name: ๐Ÿ“ข Upload testResults - if: always() - uses: actions/upload-artifact@v4 - with: - name: testResults-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/testResults - continue-on-error: true - - name: ๐Ÿ“ข Upload coverageResults - if: always() - uses: actions/upload-artifact@v4 - with: - name: coverageResults-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/coverageResults - continue-on-error: true - - name: ๐Ÿ“ข Upload symbols - uses: actions/upload-artifact@v4 - with: - name: symbols-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/symbols - continue-on-error: true - - name: ๐Ÿ“ข Upload deployables - uses: actions/upload-artifact@v4 - with: - name: deployables-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/deployables - if: always() + - name: ๐Ÿ“ข Publish artifacts + uses: ./.github/actions/publish-artifacts - name: ๐Ÿ“ข Publish code coverage results to codecov.io run: ./azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" shell: pwsh From 904ff78e41c6c0b5c508080012583a063d4e0eef Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 8 Dec 2024 19:59:31 -0700 Subject: [PATCH 030/109] Make the CI workflow dispatchable --- .github/workflows/build.yml | 3 ++- .github/workflows/libtemplate-update.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d87be99..5334bac5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: CI +name: ๐Ÿญ Build on: push: @@ -6,6 +6,7 @@ on: - main - validate/* pull_request: + workflow_dispatch: env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index 0501d5ee..f78c7e08 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -1,4 +1,4 @@ -name: Library.Template update +name: โ›œ Library.Template update # PREREQUISITE: This workflow requires the repo to be configured to allow workflows to create pull requests. # Visit https://github.com/USER/REPO/settings/actions From 9bbf8a32612f990db1c8972293af5a972febb406 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 9 Dec 2024 11:17:13 -0700 Subject: [PATCH 031/109] Fix docfx build on private repos --- .github/workflows/docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 1820866e..70b779b5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -10,6 +10,7 @@ permissions: actions: read pages: write id-token: write + contents: read # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. From 4fa9e72acb9f30a3cdb4f15c60681fc2b71273f0 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 9 Dec 2024 11:17:23 -0700 Subject: [PATCH 032/109] Fix code coverage merge on GitHub Actions --- azure-pipelines/artifacts/coverageResults.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/azure-pipelines/artifacts/coverageResults.ps1 index a6c8f420..8c68216e 100644 --- a/azure-pipelines/artifacts/coverageResults.ps1 +++ b/azure-pipelines/artifacts/coverageResults.ps1 @@ -3,14 +3,16 @@ $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") $coverageFiles = @(Get-ChildItem "$RepoRoot/test/*.cobertura.xml" -Recurse | Where {$_.FullName -notlike "*/In/*" -and $_.FullName -notlike "*\In\*" }) # Prepare code coverage reports for merging on another machine -if ($env:SYSTEM_DEFAULTWORKINGDIRECTORY) { - Write-Host "Substituting $env:SYSTEM_DEFAULTWORKINGDIRECTORY with `"{reporoot}`"" +$repoRoot = $env:SYSTEM_DEFAULTWORKINGDIRECTORY +if (!$repoRoot) { $repoRoot = $env:GITHUB_WORKSPACE } +if ($repoRoot) { + Write-Host "Substituting $repoRoot with `"{reporoot}`"" $coverageFiles |% { - $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } + $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($repoRoot), "{reporoot}" } Set-Content -LiteralPath $_ -Value $content -Encoding UTF8 } } else { - Write-Warning "coverageResults: Azure Pipelines not detected. Machine-neutral token replacement skipped." + Write-Warning "coverageResults: Cloud build not detected. Machine-neutral token replacement skipped." } if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return } From 89afbfc38b5726d311954e4902e8f2c75f62f535 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 9 Dec 2024 11:17:37 -0700 Subject: [PATCH 033/109] Add release workflow --- .github/workflows/release.yml | 87 +++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..d6f5cc45 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,87 @@ +name: ๐ŸŽ Release + +on: + release: + types: [published] + workflow_dispatch: + inputs: + ship_run_id: + description: ID of the GitHub workflow run to ship + required: true + +run-name: ${{ github.ref_name }} + +permissions: + actions: read + contents: write + +jobs: + release: + runs-on: ubuntu-22.04 + steps: + - name: โš™๏ธ Initialization + shell: pwsh + run: | + if ('${{ secrets.NUGET_API_KEY }}') { + echo "NUGET_API_KEY_DEFINED=true" >> $GITHUB_ENV + } + + - name: ๐Ÿ”Ž Search for build of ${{ github.ref }} + shell: pwsh + id: findrunid + env: + GH_TOKEN: ${{ github.token }} + run: | + if ('${{ inputs.ship_run_id }}') { + $runid = '${{ inputs.ship_run_id }}' + } else { + $restApiRoot = '/repos/${{ github.repository }}' + + # Resolve the tag reference to a commit sha + $resolvedRef = gh api ` + -H "Accept: application/vnd.github+json" ` + -H "X-GitHub-Api-Version: 2022-11-28" ` + $restApiRoot/git/ref/tags/${{ github.ref_name }} ` + | ConvertFrom-Json + $commitSha = $resolvedRef.object.sha + + Write-Host "Resolved ${{ github.ref_name }} to $commitSha" + + $releases = gh run list -R ${{ github.repository }} -c $commitSha -w .github/workflows/build.yml -s success --json databaseId,startedAt ` + | ConvertFrom-Json | Sort-Object startedAt -Descending + + if ($releases.length -eq 0) { + Write-Error "No successful builds found for ${{ github.ref }}." + } elseif ($releases.length -gt 1) { + Write-Warning "More than one successful run found for ${{ github.ref }}. Artifacts from the most recent successful run will ship." + } + + $runid = $releases[0].databaseId + } + + Write-Host "Using artifacts from run-id: $runid" + + Echo "runid=$runid" >> $env:GITHUB_OUTPUT + + - name: ๐Ÿ”ป Download deployables artifacts + uses: actions/download-artifact@v4 + with: + name: deployables-Linux + path: ${{ runner.temp }}/deployables + run-id: ${{ steps.findrunid.outputs.runid }} + github-token: ${{ github.token }} + + - name: ๐Ÿ’ฝ Upload artifacts to release + shell: pwsh + if: ${{ github.event.release.assets_url }} != '' + env: + GH_TOKEN: ${{ github.token }} + run: | + Get-ChildItem '${{ runner.temp }}/deployables' |% { + Write-Host "Uploading $($_.Name) to release..." + gh release -R ${{ github.repository }} upload "${{ github.ref_name }}" $_.FullName + } + + - name: ๐Ÿš€ Push NuGet packages + run: dotnet nuget push ${{ runner.temp }}/deployables/*.nupkg --source https://api.nuget.org/v3/index.json -k '${{ secrets.NUGET_API_KEY }}' + if: ${{ env.NUGET_API_KEY_DEFINED == 'true' }} From 1a06053669fe6f6c7d67d8f76ba5b139ab691b5e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 9 Dec 2024 11:53:03 -0700 Subject: [PATCH 034/109] Document release process --- CONTRIBUTING.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7ec56f4d..52d83a88 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,6 +41,29 @@ Building, testing, and packing this repository can be done by using the standard [pwsh]: https://docs.microsoft.com/powershell/scripting/install/installing-powershell?view=powershell-6 +## Releases + +Use `nbgv tag` to create a tag for a particular commit that you mean to release. +[Learn more about `nbgv` and its `tag` and `prepare-release` commands](https://github.com/dotnet/Nerdbank.GitVersioning/blob/main/doc/nbgv-cli.md). + +Push the tag. + +### GitHub Actions + +When your repo is hosted by GitHub and you are using GitHub Actions, you should create a GitHub Release using the standard GitHub UI. +Having previously used `nbgv tag` and pushing the tag will help you identify the precise commit and name to use for this release. + +After publishing the release, the `.github\workflows\release.yml` workflow will be automatically triggered, which will: + +1. Find the most recent `.github\workflows\build.yml` GitHub workflow run of the tagged release. +1. Upload the `deployables` artifact from that workflow run to your GitHub Release. +1. If you have `NUGET_API_KEY` defined as a secret variable for your repo or org, any nuget packages in the `deployables` artifact will be pushed to nuget.org. + +### Azure Pipelines + +When your repo builds with Azure Pipelines, use the `azure-pipelines/release.yml` pipeline. +Trigger the pipeline by adding the `auto-release` tag on a run of your main `azure-pipelines.yml` pipeline. + ## Tutorial and API documentation API and hand-written docs are found under the `docfx/` directory. and are built by [docfx](https://dotnet.github.io/docfx/). From 7bb9a6c37c9cc09513b5e6c0a950e410dfb8d70e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 11 Dec 2024 10:25:36 -0700 Subject: [PATCH 035/109] Publish test results when they fail on github workflows --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5334bac5..474d90c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,6 +61,7 @@ jobs: shell: pwsh - name: ๐Ÿ“ข Publish artifacts uses: ./.github/actions/publish-artifacts + if: always() - name: ๐Ÿ“ข Publish code coverage results to codecov.io run: ./azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" shell: pwsh From f6204f39ccd73fde0e4890d66f5019d467a9348a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 13 Dec 2024 09:16:31 -0700 Subject: [PATCH 036/109] Fix push to nuget.org in github release workflow --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6f5cc45..ed0f5924 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,8 @@ jobs: shell: pwsh run: | if ('${{ secrets.NUGET_API_KEY }}') { - echo "NUGET_API_KEY_DEFINED=true" >> $GITHUB_ENV + Write-Host "NUGET_API_KEY secret detected. NuGet packages will be pushed." + echo "NUGET_API_KEY_DEFINED=true" >> $env:GITHUB_ENV } - name: ๐Ÿ”Ž Search for build of ${{ github.ref }} From 0a42cd9afd1e40f6a5392850a5115ca5f42dfd9a Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 15 Dec 2024 20:35:38 -0700 Subject: [PATCH 037/109] Bump nbgv and Nerdbank.GitVersioning to 3.7.112 --- .config/dotnet-tools.json | 2 +- Directory.Packages.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index aaff6e7f..3f79bdec 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -17,7 +17,7 @@ "rollForward": false }, "nbgv": { - "version": "3.6.146", + "version": "3.7.112", "commands": [ "nbgv" ], diff --git a/Directory.Packages.props b/Directory.Packages.props index 237b3c2c..1023acab 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,7 +14,7 @@ - + From d8df5c88cf22b9a90fb7a48b73ee3fa7dcf7eb07 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 18 Dec 2024 11:29:15 -0700 Subject: [PATCH 038/109] Activate GitHub Actions test reporting --- Directory.Packages.props | 1 + azure-pipelines/dotnet-test-cloud.ps1 | 35 ++++++++++++++++++++++++--- test/Directory.Build.props | 3 +++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1023acab..1f94284a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,6 +6,7 @@ true + diff --git a/azure-pipelines/dotnet-test-cloud.ps1 b/azure-pipelines/dotnet-test-cloud.ps1 index 33ff3d7c..c0be8672 100755 --- a/azure-pipelines/dotnet-test-cloud.ps1 +++ b/azure-pipelines/dotnet-test-cloud.ps1 @@ -25,6 +25,8 @@ Param( $RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path $ArtifactStagingFolder = & "$PSScriptRoot/Get-ArtifactsStagingDirectory.ps1" +$TestLogsPath = "$ArtifactStagingFolder/test_logs" +if (!(Test-Path $TestLogsPath)) { New-Item -ItemType Directory -Path $TestLogsPath | Out-Null } $dotnet = 'dotnet' if ($x86) { @@ -44,21 +46,46 @@ if ($x86) { } } +$dotnetTestArgs = @() +$dotnetTestArgs2 = @() + +# The GitHubActions test logger fails when combined with certain switches, but only on mac/linux. +# We avoid those switches in that specific context. +# Failure symptoms when using the wrong switch combinations on mac/linux are (depending on the switches) EITHER: +# - The test runner fails with exit code 1 (and no error message) +# - The test runner succeeds but the GitHubActions logger only adds annotations on Windows agents. +# See https://github.com/Tyrrrz/GitHubActionsTestLogger/discussions/37 for more info. +# Thus, the mess of conditions you see below, in order to get GitHubActions to work +# without undermining other value we have when running in other contexts. +if ($env:GITHUB_WORKFLOW -and ($IsLinux -or $IsMacOS)) { + $dotnetTestArgs += '--collect','Xplat Code Coverage' + $dotnetTestArgs2 += 'DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover' +} else { + $dotnetTestArgs += '--diag','$$TestLogsPath/diag.log;TraceLevel=info' + $dotnetTestArgs += '--collect','Code Coverage;Format=cobertura' + $dotnetTestArgs += '--settings',"$PSScriptRoot/test.runsettings" +} + +if ($env:GITHUB_WORKFLOW) { + $dotnetTestArgs += '--logger','GitHubActions' + $dotnetTestArgs2 += 'RunConfiguration.CollectSourceInformation=true' +} + & $dotnet test $RepoRoot ` --no-build ` -c $Configuration ` --filter "TestCategory!=FailsInCloudTest" ` - --collect "Code Coverage;Format=cobertura" ` - --settings "$PSScriptRoot/test.runsettings" ` --blame-hang-timeout 60s ` --blame-crash ` -bl:"$ArtifactStagingFolder/build_logs/test.binlog" ` - --diag "$ArtifactStagingFolder/test_logs/diag.log;TraceLevel=info" ` --logger trx ` + @dotnetTestArgs ` + -- ` + @dotnetTestArgs2 $unknownCounter = 0 Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% { - Copy-Item $_ -Destination $ArtifactStagingFolder/test_logs/ + Copy-Item $_ -Destination $TestLogsPath/ if ($PublishResults) { $x = [xml](Get-Content -LiteralPath $_) diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 6c7aa71d..65b3bade 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -7,4 +7,7 @@ true + + +
From d2f4c5e339b1be2bb8bccff6ef13b0a3fe63c81e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 18 Dec 2024 15:10:28 -0700 Subject: [PATCH 039/109] Revert "Merge pull request #319 from AArnott/betterTestingLibTemplate" This reverts commit 01eeb1aff44be490aea525baa92f89240ba2f682, reversing changes made to 0a42cd9afd1e40f6a5392850a5115ca5f42dfd9a. --- Directory.Packages.props | 1 - azure-pipelines/dotnet-test-cloud.ps1 | 35 +++------------------------ test/Directory.Build.props | 3 --- 3 files changed, 4 insertions(+), 35 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1f94284a..1023acab 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,6 @@ true - diff --git a/azure-pipelines/dotnet-test-cloud.ps1 b/azure-pipelines/dotnet-test-cloud.ps1 index c0be8672..33ff3d7c 100755 --- a/azure-pipelines/dotnet-test-cloud.ps1 +++ b/azure-pipelines/dotnet-test-cloud.ps1 @@ -25,8 +25,6 @@ Param( $RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path $ArtifactStagingFolder = & "$PSScriptRoot/Get-ArtifactsStagingDirectory.ps1" -$TestLogsPath = "$ArtifactStagingFolder/test_logs" -if (!(Test-Path $TestLogsPath)) { New-Item -ItemType Directory -Path $TestLogsPath | Out-Null } $dotnet = 'dotnet' if ($x86) { @@ -46,46 +44,21 @@ if ($x86) { } } -$dotnetTestArgs = @() -$dotnetTestArgs2 = @() - -# The GitHubActions test logger fails when combined with certain switches, but only on mac/linux. -# We avoid those switches in that specific context. -# Failure symptoms when using the wrong switch combinations on mac/linux are (depending on the switches) EITHER: -# - The test runner fails with exit code 1 (and no error message) -# - The test runner succeeds but the GitHubActions logger only adds annotations on Windows agents. -# See https://github.com/Tyrrrz/GitHubActionsTestLogger/discussions/37 for more info. -# Thus, the mess of conditions you see below, in order to get GitHubActions to work -# without undermining other value we have when running in other contexts. -if ($env:GITHUB_WORKFLOW -and ($IsLinux -or $IsMacOS)) { - $dotnetTestArgs += '--collect','Xplat Code Coverage' - $dotnetTestArgs2 += 'DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover' -} else { - $dotnetTestArgs += '--diag','$$TestLogsPath/diag.log;TraceLevel=info' - $dotnetTestArgs += '--collect','Code Coverage;Format=cobertura' - $dotnetTestArgs += '--settings',"$PSScriptRoot/test.runsettings" -} - -if ($env:GITHUB_WORKFLOW) { - $dotnetTestArgs += '--logger','GitHubActions' - $dotnetTestArgs2 += 'RunConfiguration.CollectSourceInformation=true' -} - & $dotnet test $RepoRoot ` --no-build ` -c $Configuration ` --filter "TestCategory!=FailsInCloudTest" ` + --collect "Code Coverage;Format=cobertura" ` + --settings "$PSScriptRoot/test.runsettings" ` --blame-hang-timeout 60s ` --blame-crash ` -bl:"$ArtifactStagingFolder/build_logs/test.binlog" ` + --diag "$ArtifactStagingFolder/test_logs/diag.log;TraceLevel=info" ` --logger trx ` - @dotnetTestArgs ` - -- ` - @dotnetTestArgs2 $unknownCounter = 0 Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% { - Copy-Item $_ -Destination $TestLogsPath/ + Copy-Item $_ -Destination $ArtifactStagingFolder/test_logs/ if ($PublishResults) { $x = [xml](Get-Content -LiteralPath $_) diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 65b3bade..6c7aa71d 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -7,7 +7,4 @@ true - - - From 7b18fd08172526499129f394ae71878cfc0acc63 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 20 Dec 2024 08:14:30 -0700 Subject: [PATCH 040/109] Resolve schema validation error in VS Code for docfx yml files --- docfx/docs/toc.yml | 2 +- docfx/toc.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docfx/docs/toc.yml b/docfx/docs/toc.yml index 36a38020..518ffadd 100644 --- a/docfx/docs/toc.yml +++ b/docfx/docs/toc.yml @@ -1,5 +1,5 @@ +items: - name: Features href: features.md - name: Getting Started href: getting-started.md - diff --git a/docfx/toc.yml b/docfx/toc.yml index abd17b8c..8e9a6700 100644 --- a/docfx/toc.yml +++ b/docfx/toc.yml @@ -1,3 +1,4 @@ +items: - name: Docs href: docs/ - name: API From ad4ff0f092dfc147fdb6f5f2151c7071c9b8bc6e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 20 Dec 2024 10:19:52 -0700 Subject: [PATCH 041/109] Bump xunit.runner.visualstudio to 3.0.0 --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1023acab..b10eaee7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,7 +7,7 @@ - + From 2e9751f002252714719de4d2f914156902b8aae5 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 20 Dec 2024 10:19:58 -0700 Subject: [PATCH 042/109] Bump .NET SDK to 9.0.101 --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 088f23e1..f3e0b323 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100", + "version": "9.0.101", "rollForward": "patch", "allowPrerelease": false } From 0c33c695660191469a486f8f9de195f378f1bd2d Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 20 Dec 2024 10:35:40 -0700 Subject: [PATCH 043/109] Organize Directory.Packages.props to reduce merge conflicts going forward --- Directory.Packages.props | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Directory.Packages.props b/Directory.Packages.props index b10eaee7..32113f54 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,11 +6,17 @@ true + + + + + + From 99ee1fcd49f2d7ce9cf8e5c1d2927260548d0171 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 22 Dec 2024 18:50:42 -0700 Subject: [PATCH 044/109] Bump to Xunit v3 --- Directory.Packages.props | 4 ++-- test/Library.Tests/Library.Tests.csproj | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 32113f54..63808e7c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + @@ -24,4 +24,4 @@ - + \ No newline at end of file diff --git a/test/Library.Tests/Library.Tests.csproj b/test/Library.Tests/Library.Tests.csproj index a853dc7d..5cbc1e1f 100644 --- a/test/Library.Tests/Library.Tests.csproj +++ b/test/Library.Tests/Library.Tests.csproj @@ -3,6 +3,7 @@ net8.0 $(TargetFrameworks);net472 + Exe @@ -13,7 +14,7 @@ - + From 94eba4a33a15fd28a0693bba3e3e5086d0df8d24 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 23 Dec 2024 09:48:35 -0700 Subject: [PATCH 045/109] Build servicing branches --- .github/workflows/build.yml | 1 + azure-pipelines.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 474d90c2..fbd7115c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - 'v*.*' - validate/* pull_request: workflow_dispatch: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9867b3db..4d372fe0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -3,6 +3,7 @@ trigger: branches: include: - main + - 'v*.*' - 'validate/*' paths: exclude: From 275a44b6c5cb089a21ac2b2456c55d66ec172236 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 23 Dec 2024 11:39:09 -0700 Subject: [PATCH 046/109] Do not publish artifacts on cancelled GitHub workflows --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbd7115c..58e56ccc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: shell: pwsh - name: ๐Ÿ“ข Publish artifacts uses: ./.github/actions/publish-artifacts - if: always() + if: cancelled() == false - name: ๐Ÿ“ข Publish code coverage results to codecov.io run: ./azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" shell: pwsh From 8870497c3473ebc75324c5356b36b4361f2a9065 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 24 Dec 2024 09:12:10 -0700 Subject: [PATCH 047/109] Move scripts that apply to github workflows from azp to tools --- .github/workflows/build.yml | 4 ++-- .github/workflows/libtemplate-update.yml | 2 +- azure-pipelines/artifacts/_stage_all.ps1 | 2 +- azure-pipelines/artifacts/build_logs.ps1 | 2 +- azure-pipelines/dotnet.yml | 6 +++--- azure-pipelines/libtemplate-update.yml | 2 +- init.ps1 | 2 +- .../Get-ArtifactsStagingDirectory.ps1 | 0 {azure-pipelines => tools}/Get-CodeCovTool.ps1 | 0 {azure-pipelines => tools}/Get-LibTemplateBasis.ps1 | 0 {azure-pipelines => tools}/Get-NuGetTool.ps1 | 0 {azure-pipelines => tools}/Get-ProcDump.ps1 | 0 {azure-pipelines => tools}/Get-TempToolsPath.ps1 | 0 tools/Install-NuGetCredProvider.ps1 | 2 +- tools/MergeFrom-Template.ps1 | 2 +- {azure-pipelines => tools}/dotnet-test-cloud.ps1 | 0 {azure-pipelines => tools}/publish-CodeCov.ps1 | 0 {azure-pipelines => tools}/test.runsettings | 0 18 files changed, 12 insertions(+), 12 deletions(-) rename {azure-pipelines => tools}/Get-ArtifactsStagingDirectory.ps1 (100%) rename {azure-pipelines => tools}/Get-CodeCovTool.ps1 (100%) rename {azure-pipelines => tools}/Get-LibTemplateBasis.ps1 (100%) rename {azure-pipelines => tools}/Get-NuGetTool.ps1 (100%) rename {azure-pipelines => tools}/Get-ProcDump.ps1 (100%) rename {azure-pipelines => tools}/Get-TempToolsPath.ps1 (100%) rename {azure-pipelines => tools}/dotnet-test-cloud.ps1 (100%) mode change 100755 => 100644 rename {azure-pipelines => tools}/publish-CodeCov.ps1 (100%) rename {azure-pipelines => tools}/test.runsettings (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58e56ccc..5e338ffa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,7 @@ jobs: - name: ๐Ÿ›  build run: dotnet build -t:build,pack --no-restore -c ${{ env.BUILDCONFIGURATION }} -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"${{ runner.temp }}/_artifacts/build_logs/build.binlog" - name: ๐Ÿงช test - run: azure-pipelines/dotnet-test-cloud.ps1 -Configuration ${{ env.BUILDCONFIGURATION }} -Agent ${{ runner.os }} + run: tools/dotnet-test-cloud.ps1 -Configuration ${{ env.BUILDCONFIGURATION }} -Agent ${{ runner.os }} shell: pwsh - name: ๐Ÿ’…๐Ÿป Verify formatted code run: dotnet format --verify-no-changes --no-restore @@ -64,7 +64,7 @@ jobs: uses: ./.github/actions/publish-artifacts if: cancelled() == false - name: ๐Ÿ“ข Publish code coverage results to codecov.io - run: ./azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" + run: ./tools/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" shell: pwsh timeout-minutes: 3 continue-on-error: true diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index f78c7e08..c6b8fb4a 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -25,7 +25,7 @@ jobs: id: merge shell: pwsh run: | - $LibTemplateBranch = & ./azure-pipelines/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated + $LibTemplateBranch = & ./tools/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/azure-pipelines/artifacts/_stage_all.ps1 b/azure-pipelines/artifacts/_stage_all.ps1 index bf961ce5..08e9844c 100644 --- a/azure-pipelines/artifacts/_stage_all.ps1 +++ b/azure-pipelines/artifacts/_stage_all.ps1 @@ -11,7 +11,7 @@ param ( [switch]$AvoidSymbolicLinks ) -$ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" -CleanIfLocal +$ArtifactStagingFolder = & "$PSScriptRoot/../../tools/Get-ArtifactsStagingDirectory.ps1" -CleanIfLocal function Create-SymbolicLink { param ( diff --git a/azure-pipelines/artifacts/build_logs.ps1 b/azure-pipelines/artifacts/build_logs.ps1 index f05358e0..10c5478b 100644 --- a/azure-pipelines/artifacts/build_logs.ps1 +++ b/azure-pipelines/artifacts/build_logs.ps1 @@ -1,4 +1,4 @@ -$ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" +$ArtifactStagingFolder = & "$PSScriptRoot/../../tools/Get-ArtifactsStagingDirectory.ps1" if (!(Test-Path $ArtifactStagingFolder/build_logs)) { return } diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 2444928f..2ce80af3 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -6,7 +6,7 @@ steps: - 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 -- powershell: azure-pipelines/dotnet-test-cloud.ps1 -Configuration $(BuildConfiguration) -Agent $(Agent.JobName) -PublishResults +- powershell: tools/dotnet-test-cloud.ps1 -Configuration $(BuildConfiguration) -Agent $(Agent.JobName) -PublishResults displayName: ๐Ÿงช dotnet test condition: and(succeeded(), ${{ parameters.RunTests }}) @@ -22,9 +22,9 @@ steps: - ${{ if and(ne(variables['codecov_token'], ''), parameters.RunTests) }}: - powershell: | - $ArtifactStagingFolder = & "azure-pipelines/Get-ArtifactsStagingDirectory.ps1" + $ArtifactStagingFolder = & "tools/Get-ArtifactsStagingDirectory.ps1" $CoverageResultsFolder = Join-Path $ArtifactStagingFolder "coverageResults-$(Agent.JobName)" - azure-pipelines/publish-CodeCov.ps1 -CodeCovToken "$(codecov_token)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)" + tools/publish-CodeCov.ps1 -CodeCovToken "$(codecov_token)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)" displayName: ๐Ÿ“ข Publish code coverage results to codecov.io timeoutInMinutes: 3 continueOnError: true diff --git a/azure-pipelines/libtemplate-update.yml b/azure-pipelines/libtemplate-update.yml index 87302b06..fdfa1df5 100644 --- a/azure-pipelines/libtemplate-update.yml +++ b/azure-pipelines/libtemplate-update.yml @@ -28,7 +28,7 @@ stages: fetchDepth: 0 clean: true - pwsh: | - $LibTemplateBranch = & ./azure-pipelines/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated + $LibTemplateBranch = & ./tools/Get-LibTemplateBasis.ps1 -ErrorIfNotRelated if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/init.ps1 b/init.ps1 index e2849855..b4004e79 100755 --- a/init.ps1 +++ b/init.ps1 @@ -71,7 +71,7 @@ if (!$NoPrerequisites) { # The procdump tool and env var is required for dotnet test to collect hang/crash dumps of tests. # But it only works on Windows. if ($env:OS -eq 'Windows_NT') { - $EnvVars['PROCDUMP_PATH'] = & "$PSScriptRoot\azure-pipelines\Get-ProcDump.ps1" + $EnvVars['PROCDUMP_PATH'] = & "$PSScriptRoot\tools\Get-ProcDump.ps1" } } diff --git a/azure-pipelines/Get-ArtifactsStagingDirectory.ps1 b/tools/Get-ArtifactsStagingDirectory.ps1 similarity index 100% rename from azure-pipelines/Get-ArtifactsStagingDirectory.ps1 rename to tools/Get-ArtifactsStagingDirectory.ps1 diff --git a/azure-pipelines/Get-CodeCovTool.ps1 b/tools/Get-CodeCovTool.ps1 similarity index 100% rename from azure-pipelines/Get-CodeCovTool.ps1 rename to tools/Get-CodeCovTool.ps1 diff --git a/azure-pipelines/Get-LibTemplateBasis.ps1 b/tools/Get-LibTemplateBasis.ps1 similarity index 100% rename from azure-pipelines/Get-LibTemplateBasis.ps1 rename to tools/Get-LibTemplateBasis.ps1 diff --git a/azure-pipelines/Get-NuGetTool.ps1 b/tools/Get-NuGetTool.ps1 similarity index 100% rename from azure-pipelines/Get-NuGetTool.ps1 rename to tools/Get-NuGetTool.ps1 diff --git a/azure-pipelines/Get-ProcDump.ps1 b/tools/Get-ProcDump.ps1 similarity index 100% rename from azure-pipelines/Get-ProcDump.ps1 rename to tools/Get-ProcDump.ps1 diff --git a/azure-pipelines/Get-TempToolsPath.ps1 b/tools/Get-TempToolsPath.ps1 similarity index 100% rename from azure-pipelines/Get-TempToolsPath.ps1 rename to tools/Get-TempToolsPath.ps1 diff --git a/tools/Install-NuGetCredProvider.ps1 b/tools/Install-NuGetCredProvider.ps1 index 2b904e33..b776f56d 100755 --- a/tools/Install-NuGetCredProvider.ps1 +++ b/tools/Install-NuGetCredProvider.ps1 @@ -21,7 +21,7 @@ Param ( $envVars = @{} -$toolsPath = & "$PSScriptRoot\..\azure-pipelines\Get-TempToolsPath.ps1" +$toolsPath = & "$PSScriptRoot\Get-TempToolsPath.ps1" if ($IsMacOS -or $IsLinux) { $installerScript = "installcredprovider.sh" diff --git a/tools/MergeFrom-Template.ps1 b/tools/MergeFrom-Template.ps1 index 3f721c6a..240a5709 100644 --- a/tools/MergeFrom-Template.ps1 +++ b/tools/MergeFrom-Template.ps1 @@ -36,7 +36,7 @@ Function Spawn-Tool($command, $commandArgs, $workingDirectory, $allowFailures) { } } -$remoteBranch = & $PSScriptRoot\..\azure-pipelines\Get-LibTemplateBasis.ps1 -ErrorIfNotRelated +$remoteBranch = & $PSScriptRoot\Get-LibTemplateBasis.ps1 -ErrorIfNotRelated if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/azure-pipelines/dotnet-test-cloud.ps1 b/tools/dotnet-test-cloud.ps1 old mode 100755 new mode 100644 similarity index 100% rename from azure-pipelines/dotnet-test-cloud.ps1 rename to tools/dotnet-test-cloud.ps1 diff --git a/azure-pipelines/publish-CodeCov.ps1 b/tools/publish-CodeCov.ps1 similarity index 100% rename from azure-pipelines/publish-CodeCov.ps1 rename to tools/publish-CodeCov.ps1 diff --git a/azure-pipelines/test.runsettings b/tools/test.runsettings similarity index 100% rename from azure-pipelines/test.runsettings rename to tools/test.runsettings From bb60632aa68a206d37505999b65228f2de86b032 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 24 Dec 2024 09:25:56 -0700 Subject: [PATCH 048/109] Remove unused nuget.config file --- azure-pipelines/justnugetorg.nuget.config | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 azure-pipelines/justnugetorg.nuget.config diff --git a/azure-pipelines/justnugetorg.nuget.config b/azure-pipelines/justnugetorg.nuget.config deleted file mode 100644 index 765346e5..00000000 --- a/azure-pipelines/justnugetorg.nuget.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - From abbd6b001e55897f9922dd90ddce51b8ad6bb818 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 24 Dec 2024 09:33:58 -0700 Subject: [PATCH 049/109] Move artifacts and variables scripts to `tools` --- .github/actions/publish-artifacts/action.yaml | 2 +- .github/workflows/build.yml | 4 ++-- .../{variables/_pipelines.ps1 => define_variables.ps1} | 2 +- azure-pipelines/dotnet.yml | 4 ++-- azure-pipelines/install-dependencies.yml | 2 +- .../{artifacts/_pipelines.ps1 => publish_artifacts.ps1} | 2 +- {azure-pipelines => tools}/Get-SymbolFiles.ps1 | 0 tools/Install-DotNetSdk.ps1 | 2 +- {azure-pipelines => tools}/artifacts/Variables.ps1 | 0 {azure-pipelines => tools}/artifacts/_all.ps1 | 0 {azure-pipelines => tools}/artifacts/_stage_all.ps1 | 0 {azure-pipelines => tools}/artifacts/build_logs.ps1 | 0 {azure-pipelines => tools}/artifacts/coverageResults.ps1 | 0 {azure-pipelines => tools}/artifacts/deployables.ps1 | 0 {azure-pipelines => tools}/artifacts/projectAssetsJson.ps1 | 0 {azure-pipelines => tools}/artifacts/symbols.ps1 | 0 {azure-pipelines => tools}/artifacts/testResults.ps1 | 0 {azure-pipelines => tools}/artifacts/test_symbols.ps1 | 0 {azure-pipelines => tools}/variables/DotNetSdkVersion.ps1 | 0 {azure-pipelines => tools}/variables/_all.ps1 | 0 20 files changed, 9 insertions(+), 9 deletions(-) rename azure-pipelines/{variables/_pipelines.ps1 => define_variables.ps1} (95%) rename azure-pipelines/{artifacts/_pipelines.ps1 => publish_artifacts.ps1} (92%) rename {azure-pipelines => tools}/Get-SymbolFiles.ps1 (100%) rename {azure-pipelines => tools}/artifacts/Variables.ps1 (100%) rename {azure-pipelines => tools}/artifacts/_all.ps1 (100%) mode change 100755 => 100644 rename {azure-pipelines => tools}/artifacts/_stage_all.ps1 (100%) rename {azure-pipelines => tools}/artifacts/build_logs.ps1 (100%) rename {azure-pipelines => tools}/artifacts/coverageResults.ps1 (100%) rename {azure-pipelines => tools}/artifacts/deployables.ps1 (100%) rename {azure-pipelines => tools}/artifacts/projectAssetsJson.ps1 (100%) rename {azure-pipelines => tools}/artifacts/symbols.ps1 (100%) rename {azure-pipelines => tools}/artifacts/testResults.ps1 (100%) rename {azure-pipelines => tools}/artifacts/test_symbols.ps1 (100%) rename {azure-pipelines => tools}/variables/DotNetSdkVersion.ps1 (100%) rename {azure-pipelines => tools}/variables/_all.ps1 (100%) mode change 100755 => 100644 diff --git a/.github/actions/publish-artifacts/action.yaml b/.github/actions/publish-artifacts/action.yaml index 94b74261..228b6404 100644 --- a/.github/actions/publish-artifacts/action.yaml +++ b/.github/actions/publish-artifacts/action.yaml @@ -5,7 +5,7 @@ runs: using: composite steps: - name: ๐Ÿ“ฅ Collect artifacts - run: azure-pipelines/artifacts/_stage_all.ps1 + run: tools/artifacts/_stage_all.ps1 shell: pwsh if: always() diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e338ffa..e6ffd301 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: } shell: pwsh - name: โš™๏ธ Set pipeline variables based on source - run: azure-pipelines/variables/_pipelines.ps1 + run: azure-pipelines/define_variables.ps1 shell: pwsh - name: ๐Ÿ›  build run: dotnet build -t:build,pack --no-restore -c ${{ env.BUILDCONFIGURATION }} -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"${{ runner.temp }}/_artifacts/build_logs/build.binlog" @@ -58,7 +58,7 @@ jobs: run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures if: runner.os == 'Linux' - name: โš™ Update pipeline variables based on build outputs - run: azure-pipelines/variables/_pipelines.ps1 + run: azure-pipelines/define_variables.ps1 shell: pwsh - name: ๐Ÿ“ข Publish artifacts uses: ./.github/actions/publish-artifacts diff --git a/azure-pipelines/variables/_pipelines.ps1 b/azure-pipelines/define_variables.ps1 similarity index 95% rename from azure-pipelines/variables/_pipelines.ps1 rename to azure-pipelines/define_variables.ps1 index d40e5cf1..9cf36286 100644 --- a/azure-pipelines/variables/_pipelines.ps1 +++ b/azure-pipelines/define_variables.ps1 @@ -11,7 +11,7 @@ param ( ) -(& "$PSScriptRoot\_all.ps1").GetEnumerator() |% { +(& "$PSScriptRoot\..\tools\variables\_all.ps1").GetEnumerator() |% { # Always use ALL CAPS for env var names since Azure Pipelines converts variable names to all caps and on non-Windows OS, env vars are case sensitive. $keyCaps = $_.Key.ToUpper() if ((Test-Path "env:$keyCaps") -and (Get-Content "env:$keyCaps")) { diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 2ce80af3..f0942238 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -10,12 +10,12 @@ steps: displayName: ๐Ÿงช dotnet test condition: and(succeeded(), ${{ parameters.RunTests }}) -- powershell: azure-pipelines/variables/_pipelines.ps1 +- powershell: azure-pipelines/define_variables.ps1 failOnStderr: true displayName: โš™ Update pipeline variables based on build outputs condition: succeededOrFailed() -- powershell: azure-pipelines/artifacts/_pipelines.ps1 -ArtifactNameSuffix "-$(Agent.JobName)" -Verbose +- powershell: azure-pipelines/publish_artifacts.ps1 -ArtifactNameSuffix "-$(Agent.JobName)" -Verbose failOnStderr: true displayName: ๐Ÿ“ข Publish artifacts condition: succeededOrFailed() diff --git a/azure-pipelines/install-dependencies.yml b/azure-pipelines/install-dependencies.yml index 81782668..ce88b25e 100644 --- a/azure-pipelines/install-dependencies.yml +++ b/azure-pipelines/install-dependencies.yml @@ -19,7 +19,7 @@ steps: } displayName: โš™ Install prerequisites -- powershell: azure-pipelines/variables/_pipelines.ps1 +- powershell: azure-pipelines/define_variables.ps1 failOnStderr: true displayName: โš™ Set pipeline variables based on source name: SetPipelineVariables diff --git a/azure-pipelines/artifacts/_pipelines.ps1 b/azure-pipelines/publish_artifacts.ps1 similarity index 92% rename from azure-pipelines/artifacts/_pipelines.ps1 rename to azure-pipelines/publish_artifacts.ps1 index 5f259a51..3f35cc6e 100644 --- a/azure-pipelines/artifacts/_pipelines.ps1 +++ b/azure-pipelines/publish_artifacts.ps1 @@ -25,7 +25,7 @@ Function Test-ArtifactUploaded($artifactName) { Test-Path "env:$varName" } -& "$PSScriptRoot/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix -AvoidSymbolicLinks:$AvoidSymbolicLinks |% { +& "$PSScriptRoot/../tools/artifacts/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix -AvoidSymbolicLinks:$AvoidSymbolicLinks |% { # Set a variable which will out-live this script so that a subsequent attempt to collect and upload artifacts # will skip this one from a check in the _all.ps1 script. Set-PipelineVariable "ARTIFACTSTAGED_$($_.Name.ToUpper())" 'true' diff --git a/azure-pipelines/Get-SymbolFiles.ps1 b/tools/Get-SymbolFiles.ps1 similarity index 100% rename from azure-pipelines/Get-SymbolFiles.ps1 rename to tools/Get-SymbolFiles.ps1 diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 index ffb52203..e08571bc 100644 --- a/tools/Install-DotNetSdk.ps1 +++ b/tools/Install-DotNetSdk.ps1 @@ -36,7 +36,7 @@ if (!(Test-Path $DotNetInstallScriptRoot)) { New-Item -ItemType Directory -Path $DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot # Look up actual required .NET SDK version from global.json -$sdkVersion = & "$PSScriptRoot/../azure-pipelines/variables/DotNetSdkVersion.ps1" +$sdkVersion = & "$PSScriptRoot/variables/DotNetSdkVersion.ps1" If ($IncludeX86 -and ($IsMacOS -or $IsLinux)) { Write-Verbose "Ignoring -IncludeX86 switch because 32-bit runtimes are only supported on Windows." diff --git a/azure-pipelines/artifacts/Variables.ps1 b/tools/artifacts/Variables.ps1 similarity index 100% rename from azure-pipelines/artifacts/Variables.ps1 rename to tools/artifacts/Variables.ps1 diff --git a/azure-pipelines/artifacts/_all.ps1 b/tools/artifacts/_all.ps1 old mode 100755 new mode 100644 similarity index 100% rename from azure-pipelines/artifacts/_all.ps1 rename to tools/artifacts/_all.ps1 diff --git a/azure-pipelines/artifacts/_stage_all.ps1 b/tools/artifacts/_stage_all.ps1 similarity index 100% rename from azure-pipelines/artifacts/_stage_all.ps1 rename to tools/artifacts/_stage_all.ps1 diff --git a/azure-pipelines/artifacts/build_logs.ps1 b/tools/artifacts/build_logs.ps1 similarity index 100% rename from azure-pipelines/artifacts/build_logs.ps1 rename to tools/artifacts/build_logs.ps1 diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/tools/artifacts/coverageResults.ps1 similarity index 100% rename from azure-pipelines/artifacts/coverageResults.ps1 rename to tools/artifacts/coverageResults.ps1 diff --git a/azure-pipelines/artifacts/deployables.ps1 b/tools/artifacts/deployables.ps1 similarity index 100% rename from azure-pipelines/artifacts/deployables.ps1 rename to tools/artifacts/deployables.ps1 diff --git a/azure-pipelines/artifacts/projectAssetsJson.ps1 b/tools/artifacts/projectAssetsJson.ps1 similarity index 100% rename from azure-pipelines/artifacts/projectAssetsJson.ps1 rename to tools/artifacts/projectAssetsJson.ps1 diff --git a/azure-pipelines/artifacts/symbols.ps1 b/tools/artifacts/symbols.ps1 similarity index 100% rename from azure-pipelines/artifacts/symbols.ps1 rename to tools/artifacts/symbols.ps1 diff --git a/azure-pipelines/artifacts/testResults.ps1 b/tools/artifacts/testResults.ps1 similarity index 100% rename from azure-pipelines/artifacts/testResults.ps1 rename to tools/artifacts/testResults.ps1 diff --git a/azure-pipelines/artifacts/test_symbols.ps1 b/tools/artifacts/test_symbols.ps1 similarity index 100% rename from azure-pipelines/artifacts/test_symbols.ps1 rename to tools/artifacts/test_symbols.ps1 diff --git a/azure-pipelines/variables/DotNetSdkVersion.ps1 b/tools/variables/DotNetSdkVersion.ps1 similarity index 100% rename from azure-pipelines/variables/DotNetSdkVersion.ps1 rename to tools/variables/DotNetSdkVersion.ps1 diff --git a/azure-pipelines/variables/_all.ps1 b/tools/variables/_all.ps1 old mode 100755 new mode 100644 similarity index 100% rename from azure-pipelines/variables/_all.ps1 rename to tools/variables/_all.ps1 From fe7350fbebf12912487fa3397bd5c9bd95127859 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 24 Dec 2024 09:51:28 -0700 Subject: [PATCH 050/109] Move variable definition script --- .github/workflows/build.yml | 4 ++-- azure-pipelines/dotnet.yml | 2 +- azure-pipelines/install-dependencies.yml | 2 +- .../define_variables.ps1 => tools/variables/_define.ps1 | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename azure-pipelines/define_variables.ps1 => tools/variables/_define.ps1 (95%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e6ffd301..5b4fc7be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: } shell: pwsh - name: โš™๏ธ Set pipeline variables based on source - run: azure-pipelines/define_variables.ps1 + run: tools/variables/_define.ps1 shell: pwsh - name: ๐Ÿ›  build run: dotnet build -t:build,pack --no-restore -c ${{ env.BUILDCONFIGURATION }} -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"${{ runner.temp }}/_artifacts/build_logs/build.binlog" @@ -58,7 +58,7 @@ jobs: run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures if: runner.os == 'Linux' - name: โš™ Update pipeline variables based on build outputs - run: azure-pipelines/define_variables.ps1 + run: tools/variables/_define.ps1 shell: pwsh - name: ๐Ÿ“ข Publish artifacts uses: ./.github/actions/publish-artifacts diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index f0942238..30bb4107 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -10,7 +10,7 @@ steps: displayName: ๐Ÿงช dotnet test condition: and(succeeded(), ${{ parameters.RunTests }}) -- powershell: azure-pipelines/define_variables.ps1 +- powershell: tools/variables/_define.ps1 failOnStderr: true displayName: โš™ Update pipeline variables based on build outputs condition: succeededOrFailed() diff --git a/azure-pipelines/install-dependencies.yml b/azure-pipelines/install-dependencies.yml index ce88b25e..5944bc9e 100644 --- a/azure-pipelines/install-dependencies.yml +++ b/azure-pipelines/install-dependencies.yml @@ -19,7 +19,7 @@ steps: } displayName: โš™ Install prerequisites -- powershell: azure-pipelines/define_variables.ps1 +- powershell: tools/variables/_define.ps1 failOnStderr: true displayName: โš™ Set pipeline variables based on source name: SetPipelineVariables diff --git a/azure-pipelines/define_variables.ps1 b/tools/variables/_define.ps1 similarity index 95% rename from azure-pipelines/define_variables.ps1 rename to tools/variables/_define.ps1 index 9cf36286..d40e5cf1 100644 --- a/azure-pipelines/define_variables.ps1 +++ b/tools/variables/_define.ps1 @@ -11,7 +11,7 @@ param ( ) -(& "$PSScriptRoot\..\tools\variables\_all.ps1").GetEnumerator() |% { +(& "$PSScriptRoot\_all.ps1").GetEnumerator() |% { # Always use ALL CAPS for env var names since Azure Pipelines converts variable names to all caps and on non-Windows OS, env vars are case sensitive. $keyCaps = $_.Key.ToUpper() if ((Test-Path "env:$keyCaps") -and (Get-Content "env:$keyCaps")) { From bd10eaad9c1069e96c282383132765797b0344de Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 26 Dec 2024 15:16:12 -0700 Subject: [PATCH 051/109] Group dependabot update PRs --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b168ac6d..a7a1782f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,14 @@ updates: directory: / schedule: interval: weekly + groups: + nerdbank-gitversioning: + patterns: + - nbgv + - nerdbank.gitversioning + xunit: + patterns: + - 'xunit*' - package-ecosystem: dotnet-sdk directory: / schedule: From 05072c1f50722d8eaa99e1a17299c57d5f1a5365 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 26 Dec 2024 16:06:41 -0700 Subject: [PATCH 052/109] Switch from Dependabot to Renovate --- .github/dependabot.yml | 21 --------------------- .github/renovate.json | 24 ++++++++++++++++++++++++ CONTRIBUTING.md | 10 ++++++++++ 3 files changed, 34 insertions(+), 21 deletions(-) delete mode 100644 .github/dependabot.yml create mode 100644 .github/renovate.json diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index a7a1782f..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Please see the documentation for all configuration options: -# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - -version: 2 -updates: -- package-ecosystem: nuget - directory: / - schedule: - interval: weekly - groups: - nerdbank-gitversioning: - patterns: - - nbgv - - nerdbank.gitversioning - xunit: - patterns: - - 'xunit*' -- package-ecosystem: dotnet-sdk - directory: / - schedule: - interval: monthly diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..a9fbeb23 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ], + "semanticCommits": "disabled", + "prHourlyLimit": 5, + "labels": ["dependencies"], + "packageRules": [ + { + "matchPackageNames": ["nbgv", "nerdbank.gitversioning"], + "groupName": "nbgv and nerdbank.gitversioning updates" + }, + { + "matchPackageNames": ["xunit*"], + "groupName": "xunit" + }, + { + "matchDatasources": ["dotnet-version", "docker"], + "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], + "groupName": "Dockerfile and global.json updates" + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52d83a88..77f5e0a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,3 +72,13 @@ You can make changes and host the site locally to preview them by switching to t After making a change, you can rebuild the docs site while the localhost server is running by running `dotnet docfx` again from a separate terminal. The `.github/workflows/docs.yml` GitHub Actions workflow publishes the content of these docs to github.io if the workflow itself and [GitHub Pages is enabled for your repository](https://docs.github.com/en/pages/quickstart). + +## Updating dependencies + +This repo uses Renovate to keep dependencies current. +Configuration is in the `.github/renovate.json` file. +[Learn more about configuring Renovate](https://docs.renovatebot.com/configuration-options/). + +When changing the renovate.json file, follow [these validation steps](https://docs.renovatebot.com/config-validation/). + +If Renovate is not creating pull requests when you expect it to, check that the [Renovate GitHub App](https://github.com/apps/renovate) is configured for your account or repo. From 72caf2d7baaa56bb5638dfd71e60e42de014e12f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 26 Dec 2024 23:08:25 +0000 Subject: [PATCH 053/109] Update mcr.microsoft.com/dotnet/sdk Docker tag to v9.0.101 --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 42fd12a7..3674e182 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:9.0.100-noble +FROM mcr.microsoft.com/dotnet/sdk:9.0.101-noble # Installing mono makes `dotnet test` work without errors even for net472. # But installing it takes a long time, so it's excluded by default. From b353d1fb965bd85f73fee096eda88de20ae206dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 26 Dec 2024 23:08:30 +0000 Subject: [PATCH 054/109] Update dependency ubuntu to v24 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed0f5924..766ebaf5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ permissions: jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: โš™๏ธ Initialization shell: pwsh From 147f846d07821941e3c40f8ba8747d2bd62fa76b Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 26 Dec 2024 18:00:17 -0700 Subject: [PATCH 055/109] Drop renovate PR hourly limit back to default --- .github/renovate.json | 1 - README.md | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index a9fbeb23..498ca420 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -4,7 +4,6 @@ "config:recommended" ], "semanticCommits": "disabled", - "prHourlyLimit": 5, "labels": ["dependencies"], "packageRules": [ { diff --git a/README.md b/README.md index 33ddbfab..610e6504 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Further customize your repo by: 1. Verify the license is suitable for your goal as it appears in the LICENSE and stylecop.json files and the Directory.Build.props file's `PackageLicenseExpression` property. 1. Reset or replace the badges at the top of this file. +[Activate Renovate automated dependency updates](https://docs.renovatebot.com/getting-started/installing-onboarding/) for your repo. + ### Maintaining your repo based on this template The best way to keep your repo in sync with this template's evolving features and best practices is to periodically merge the template into your repo: From ddc4c2d1b86ea10672fb07e69279d94308dc76aa Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 28 Dec 2024 08:39:07 -0700 Subject: [PATCH 056/109] Use JSON5 for renovate configuration --- .devcontainer/devcontainer.json | 3 ++- .github/.editorconfig | 2 ++ .github/renovate.json | 23 ----------------------- .github/renovate.json5 | 21 +++++++++++++++++++++ .vscode/extensions.json | 3 ++- 5 files changed, 27 insertions(+), 25 deletions(-) create mode 100644 .github/.editorconfig delete mode 100644 .github/renovate.json create mode 100644 .github/renovate.json5 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 01a087c7..8f77d288 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -16,6 +16,7 @@ "dotjoshjohnson.xml", "ms-vscode-remote.remote-containers", "ms-azuretools.vscode-docker", - "tintoy.msbuild-project-tools" + "tintoy.msbuild-project-tools", + "mrmlnc.vscode-json5" ] } diff --git a/.github/.editorconfig b/.github/.editorconfig new file mode 100644 index 00000000..2b7682ef --- /dev/null +++ b/.github/.editorconfig @@ -0,0 +1,2 @@ +[renovate.json*] +indent_style = tab diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index 498ca420..00000000 --- a/.github/renovate.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:recommended" - ], - "semanticCommits": "disabled", - "labels": ["dependencies"], - "packageRules": [ - { - "matchPackageNames": ["nbgv", "nerdbank.gitversioning"], - "groupName": "nbgv and nerdbank.gitversioning updates" - }, - { - "matchPackageNames": ["xunit*"], - "groupName": "xunit" - }, - { - "matchDatasources": ["dotnet-version", "docker"], - "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], - "groupName": "Dockerfile and global.json updates" - } - ] -} diff --git a/.github/renovate.json5 b/.github/renovate.json5 new file mode 100644 index 00000000..76f2fb1f --- /dev/null +++ b/.github/renovate.json5 @@ -0,0 +1,21 @@ +{ + $schema: "https://docs.renovatebot.com/renovate-schema.json", + extends: ["config:recommended"], + semanticCommits: "disabled", + labels: ["dependencies"], + packageRules: [ + { + matchPackageNames: ["nbgv", "nerdbank.gitversioning"], + groupName: "nbgv and nerdbank.gitversioning updates", + }, + { + matchPackageNames: ["xunit*"], + groupName: "xunit", + }, + { + matchDatasources: ["dotnet-version", "docker"], + matchDepNames: ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], + groupName: "Dockerfile and global.json updates", + }, + ], +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index acaf0213..b289e507 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -13,7 +13,8 @@ "dotjoshjohnson.xml", "ms-vscode-remote.remote-containers", "ms-azuretools.vscode-docker", - "tintoy.msbuild-project-tools" + "tintoy.msbuild-project-tools", + "mrmlnc.vscode-json5" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] From 7e3ea7889b92003802fa9222740226ed2bb78f8c Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 28 Dec 2024 08:40:04 -0700 Subject: [PATCH 057/109] Update devcontainer schema --- .devcontainer/devcontainer.json | 38 ++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8f77d288..3be99af4 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,22 +1,26 @@ { "name": "Dev space", "dockerFile": "Dockerfile", - "settings": { - "terminal.integrated.shell.linux": "/usr/bin/pwsh" + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.shell.linux": "/usr/bin/pwsh" + }, + "extensions": [ + "ms-azure-devops.azure-pipelines", + "ms-dotnettools.csharp", + "k--kato.docomment", + "editorconfig.editorconfig", + "esbenp.prettier-vscode", + "pflannery.vscode-versionlens", + "davidanson.vscode-markdownlint", + "dotjoshjohnson.xml", + "ms-vscode-remote.remote-containers", + "ms-azuretools.vscode-docker", + "tintoy.msbuild-project-tools", + "mrmlnc.vscode-json5" + ] + } }, - "postCreateCommand": "./init.ps1 -InstallLocality machine", - "extensions": [ - "ms-azure-devops.azure-pipelines", - "ms-dotnettools.csharp", - "k--kato.docomment", - "editorconfig.editorconfig", - "esbenp.prettier-vscode", - "pflannery.vscode-versionlens", - "davidanson.vscode-markdownlint", - "dotjoshjohnson.xml", - "ms-vscode-remote.remote-containers", - "ms-azuretools.vscode-docker", - "tintoy.msbuild-project-tools", - "mrmlnc.vscode-json5" - ] + "postCreateCommand": "./init.ps1 -InstallLocality machine" } From 6ad0c9460ff72b51497e102fde1f3029a1442792 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 29 Dec 2024 18:48:38 -0700 Subject: [PATCH 058/109] Rename renovate config back to .json .json5 was fine, but VS Code doesn't have native support for it, and the popular JSON5 extension doesn't support JSON schema. --- .devcontainer/devcontainer.json | 3 +-- .github/renovate.json | 21 +++++++++++++++++++++ .github/renovate.json5 | 21 --------------------- .vscode/extensions.json | 3 +-- 4 files changed, 23 insertions(+), 25 deletions(-) create mode 100644 .github/renovate.json delete mode 100644 .github/renovate.json5 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3be99af4..1a3a0086 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -17,8 +17,7 @@ "dotjoshjohnson.xml", "ms-vscode-remote.remote-containers", "ms-azuretools.vscode-docker", - "tintoy.msbuild-project-tools", - "mrmlnc.vscode-json5" + "tintoy.msbuild-project-tools" ] } }, diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..c140014f --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:recommended"], + "semanticCommits": "disabled", + "labels": ["dependencies"], + "packageRules": [ + { + "matchPackageNames": ["nbgv", "nerdbank.gitversioning"], + "groupName": "nbgv and nerdbank.gitversioning updates" + }, + { + "matchPackageNames": ["xunit*"], + "groupName": "xunit" + }, + { + "matchDatasources": ["dotnet-version", "docker"], + "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], + "groupName": "Dockerfile and global.json updates" + } + ] +} diff --git a/.github/renovate.json5 b/.github/renovate.json5 deleted file mode 100644 index 76f2fb1f..00000000 --- a/.github/renovate.json5 +++ /dev/null @@ -1,21 +0,0 @@ -{ - $schema: "https://docs.renovatebot.com/renovate-schema.json", - extends: ["config:recommended"], - semanticCommits: "disabled", - labels: ["dependencies"], - packageRules: [ - { - matchPackageNames: ["nbgv", "nerdbank.gitversioning"], - groupName: "nbgv and nerdbank.gitversioning updates", - }, - { - matchPackageNames: ["xunit*"], - groupName: "xunit", - }, - { - matchDatasources: ["dotnet-version", "docker"], - matchDepNames: ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], - groupName: "Dockerfile and global.json updates", - }, - ], -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index b289e507..acaf0213 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -13,8 +13,7 @@ "dotjoshjohnson.xml", "ms-vscode-remote.remote-containers", "ms-azuretools.vscode-docker", - "tintoy.msbuild-project-tools", - "mrmlnc.vscode-json5" + "tintoy.msbuild-project-tools" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] From fadd4eb10683551901b3b04899c3dd74b2b7ec1f Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 31 Dec 2024 16:16:17 -0700 Subject: [PATCH 059/109] Fix test logs collection They are intended to be collected as part of the `testResults` artifact. --- .github/actions/publish-artifacts/action.yaml | 7 ------- tools/artifacts/testResults.ps1 | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/actions/publish-artifacts/action.yaml b/.github/actions/publish-artifacts/action.yaml index 228b6404..2a75c4d2 100644 --- a/.github/actions/publish-artifacts/action.yaml +++ b/.github/actions/publish-artifacts/action.yaml @@ -32,13 +32,6 @@ runs: name: build_logs-${{ runner.os }} path: ${{ runner.temp }}/_artifacts/build_logs continue-on-error: true - - name: ๐Ÿ“ข Upload test_logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: test_logs-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/test_logs - continue-on-error: true - name: ๐Ÿ“ข Upload testResults if: always() uses: actions/upload-artifact@v4 diff --git a/tools/artifacts/testResults.ps1 b/tools/artifacts/testResults.ps1 index 301a4376..07146957 100644 --- a/tools/artifacts/testResults.ps1 +++ b/tools/artifacts/testResults.ps1 @@ -7,7 +7,8 @@ $result = @{} $testRoot = Resolve-Path "$PSScriptRoot\..\..\test" $result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File) -$testlogsPath = "$env:BUILD_ARTIFACTSTAGINGDIRECTORY\test_logs" +$artifactStaging = & "$PSScriptRoot\..\Get-ArtifactsStagingDirectory.ps1" +$testlogsPath = Join-Path $artifactStaging "test_logs" if (Test-Path $testlogsPath) { $result[$testlogsPath] = Get-ChildItem "$testlogsPath\*"; } From 16f72e358da97fb5058f32eef4002a1dc33a6e3d Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 1 Jan 2025 10:30:13 -0700 Subject: [PATCH 060/109] Take care to use proper slashes per OS for testing --- tools/Get-ArtifactsStagingDirectory.ps1 | 2 +- tools/artifacts/testResults.ps1 | 2 +- tools/dotnet-test-cloud.ps1 | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/Get-ArtifactsStagingDirectory.ps1 b/tools/Get-ArtifactsStagingDirectory.ps1 index 391e5713..18967f4c 100644 --- a/tools/Get-ArtifactsStagingDirectory.ps1 +++ b/tools/Get-ArtifactsStagingDirectory.ps1 @@ -4,7 +4,7 @@ Param( if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { $ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY } elseif ($env:RUNNER_TEMP) { - $ArtifactStagingFolder = "$env:RUNNER_TEMP\_artifacts" + $ArtifactStagingFolder = Join-Path $env:RUNNER_TEMP _artifacts } else { $ArtifactStagingFolder = [System.IO.Path]::GetFullPath("$PSScriptRoot/../obj/_artifacts") if ($CleanIfLocal -and (Test-Path $ArtifactStagingFolder)) { diff --git a/tools/artifacts/testResults.ps1 b/tools/artifacts/testResults.ps1 index 07146957..519a63c0 100644 --- a/tools/artifacts/testResults.ps1 +++ b/tools/artifacts/testResults.ps1 @@ -10,7 +10,7 @@ $result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory $artifactStaging = & "$PSScriptRoot\..\Get-ArtifactsStagingDirectory.ps1" $testlogsPath = Join-Path $artifactStaging "test_logs" if (Test-Path $testlogsPath) { - $result[$testlogsPath] = Get-ChildItem "$testlogsPath\*"; + $result[$testlogsPath] = Get-ChildItem $testlogsPath -Recurse; } $result diff --git a/tools/dotnet-test-cloud.ps1 b/tools/dotnet-test-cloud.ps1 index 33ff3d7c..10cd4311 100644 --- a/tools/dotnet-test-cloud.ps1 +++ b/tools/dotnet-test-cloud.ps1 @@ -44,6 +44,9 @@ if ($x86) { } } +$testBinLog = Join-Path $ArtifactStagingFolder (Join-Path build_logs test.binlog) +$testDiagLog = Join-Path $ArtifactStagingFolder (Join-Path test_logs diag.log) + & $dotnet test $RepoRoot ` --no-build ` -c $Configuration ` @@ -52,8 +55,8 @@ if ($x86) { --settings "$PSScriptRoot/test.runsettings" ` --blame-hang-timeout 60s ` --blame-crash ` - -bl:"$ArtifactStagingFolder/build_logs/test.binlog" ` - --diag "$ArtifactStagingFolder/test_logs/diag.log;TraceLevel=info" ` + -bl:"$testBinLog" ` + --diag "$testDiagLog;TraceLevel=info" ` --logger trx ` $unknownCounter = 0 From 656c5ff5cb3897ca2151842a1e050598c422b140 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sun, 5 Jan 2025 13:15:50 -0700 Subject: [PATCH 061/109] Match test assemblies that are built as exe's Fixes #332 --- tools/dotnet-test-cloud.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dotnet-test-cloud.ps1 b/tools/dotnet-test-cloud.ps1 index 10cd4311..02891d97 100644 --- a/tools/dotnet-test-cloud.ps1 +++ b/tools/dotnet-test-cloud.ps1 @@ -68,7 +68,7 @@ Get-ChildItem -Recurse -Path $RepoRoot\test\*.trx |% { $runTitle = $null if ($x.TestRun.TestDefinitions -and $x.TestRun.TestDefinitions.GetElementsByTagName('UnitTest')) { $storage = $x.TestRun.TestDefinitions.GetElementsByTagName('UnitTest')[0].storage -replace '\\','/' - if ($storage -match '/(?net[^/]+)/(?:(?[^/]+)/)?(?[^/]+)\.dll$') { + if ($storage -match '/(?net[^/]+)/(?:(?[^/]+)/)?(?[^/]+)\.(dll|exe)$') { if ($matches.rid) { $runTitle = "$($matches.lib) ($($matches.tfm), $($matches.rid), $Agent)" } else { From 5f9a3444985dc683c096209870eb7bff36f26e67 Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Fri, 7 Jun 2024 19:46:00 -0700 Subject: [PATCH 062/109] Ensure Expand-Template uses UTF-8 when replacing placeholders. --- Expand-Template.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Expand-Template.ps1 b/Expand-Template.ps1 index 9f9db676..ae162313 100755 --- a/Expand-Template.ps1 +++ b/Expand-Template.ps1 @@ -40,7 +40,7 @@ function Replace-Placeholders { $Path = Resolve-Path $Path Write-Host "Replacing tokens in `"$Path`"" - $content = Get-Content -LiteralPath $Path | Out-String + $content = Get-Content -Encoding UTF8 -LiteralPath $Path | Out-String $Replacements.GetEnumerator() |% { $modifiedContent = $content -replace $_.Key,$_.Value if ($modifiedContent -eq $content) { From b3fc0f3f597580e67990716ef8aad9cb47d74b9d Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 6 Jan 2025 19:34:39 -0700 Subject: [PATCH 063/109] Simplify certain ps1 script paths --- tools/artifacts/_stage_all.ps1 | 2 +- tools/artifacts/build_logs.ps1 | 2 +- tools/artifacts/testResults.ps1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/artifacts/_stage_all.ps1 b/tools/artifacts/_stage_all.ps1 index 08e9844c..bf961ce5 100644 --- a/tools/artifacts/_stage_all.ps1 +++ b/tools/artifacts/_stage_all.ps1 @@ -11,7 +11,7 @@ param ( [switch]$AvoidSymbolicLinks ) -$ArtifactStagingFolder = & "$PSScriptRoot/../../tools/Get-ArtifactsStagingDirectory.ps1" -CleanIfLocal +$ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" -CleanIfLocal function Create-SymbolicLink { param ( diff --git a/tools/artifacts/build_logs.ps1 b/tools/artifacts/build_logs.ps1 index 10c5478b..f05358e0 100644 --- a/tools/artifacts/build_logs.ps1 +++ b/tools/artifacts/build_logs.ps1 @@ -1,4 +1,4 @@ -$ArtifactStagingFolder = & "$PSScriptRoot/../../tools/Get-ArtifactsStagingDirectory.ps1" +$ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" if (!(Test-Path $ArtifactStagingFolder/build_logs)) { return } diff --git a/tools/artifacts/testResults.ps1 b/tools/artifacts/testResults.ps1 index 519a63c0..5310fb52 100644 --- a/tools/artifacts/testResults.ps1 +++ b/tools/artifacts/testResults.ps1 @@ -7,7 +7,7 @@ $result = @{} $testRoot = Resolve-Path "$PSScriptRoot\..\..\test" $result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File) -$artifactStaging = & "$PSScriptRoot\..\Get-ArtifactsStagingDirectory.ps1" +$artifactStaging = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1" $testlogsPath = Join-Path $artifactStaging "test_logs" if (Test-Path $testlogsPath) { $result[$testlogsPath] = Get-ChildItem $testlogsPath -Recurse; From 048010c3a101eb0b26965759e55b188dd576c37f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 Jan 2025 07:14:33 -0700 Subject: [PATCH 064/109] Update xunit (#336) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 63808e7c..c3f32204 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,8 +10,8 @@ - - + + From 6ac5aae85808499ecfe561ffeac39a50aaa21b84 Mon Sep 17 00:00:00 2001 From: Matteo Prosperi <41970398+matteo-prosperi@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:19:51 -0800 Subject: [PATCH 065/109] Fix InsertJsonValues script (#337) * Fix InsertJsonValues script I believe that `LibraryName` here is a typo considering that it is in a loop and we couldn't just replace it with a fixed string (even one that is specific to the repo) * Fix vsman file URL formatting * Update Expand-Template.ps1 --- Expand-Template.ps1 | 4 ---- tools/variables/InsertJsonValues.ps1 | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Expand-Template.ps1 b/Expand-Template.ps1 index 70191c72..0bc5f440 100755 --- a/Expand-Template.ps1 +++ b/Expand-Template.ps1 @@ -172,10 +172,6 @@ try { 'LibraryNoDots' = $LibraryName.Replace('.',''); } - Replace-Placeholders -Path "tools/variables/InsertJsonValues.ps1" -Replacements @{ - 'LibraryName' = $LibraryName; - } - Replace-Placeholders -Path "tools/variables/SymbolsFeatureName.ps1" -Replacements @{ 'LibraryName' = $LibraryName; } diff --git a/tools/variables/InsertJsonValues.ps1 b/tools/variables/InsertJsonValues.ps1 index 807ca1cb..7aa8d30c 100644 --- a/tools/variables/InsertJsonValues.ps1 +++ b/tools/variables/InsertJsonValues.ps1 @@ -11,7 +11,7 @@ if (Test-Path $BasePath) { 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" + $vsmanFiles += "$fn{$version}=https://vsdrop.corp.microsoft.com/file/v1/$vstsDropNames;$fn" } [string]::join(',',$vsmanFiles) From b47196d0fd54776d22fea52f03d75086cc071ffe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:43:52 -0700 Subject: [PATCH 066/109] Update nbgv and nerdbank.gitversioning updates to 3.7.115 (#338) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- Directory.Packages.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3f79bdec..3a7b9b69 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -17,7 +17,7 @@ "rollForward": false }, "nbgv": { - "version": "3.7.112", + "version": "3.7.115", "commands": [ "nbgv" ], diff --git a/Directory.Packages.props b/Directory.Packages.props index c3f32204..8811c1ea 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -20,7 +20,7 @@ - + From 48ff6ea445004c5b71c7e89eba5ceb7381871961 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 13 Jan 2025 15:11:33 -0700 Subject: [PATCH 067/109] Bump MicroBuildInsertVsPayload to v5 --- azure-pipelines/OptProf.yml | 2 +- azure-pipelines/vs-insertion.yml | 2 +- azure-pipelines/vs-validation.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines/OptProf.yml b/azure-pipelines/OptProf.yml index b196e345..a70b9362 100644 --- a/azure-pipelines/OptProf.yml +++ b/azure-pipelines/OptProf.yml @@ -90,7 +90,7 @@ stages: packagesToPush: $(Agent.TempDirectory)/VSInsertion-Windows/*.nupkg publishVstsFeed: 97a41293-2972-4f48-8c0e-05493ae82010 # VS feed allowPackageConflicts: true - - task: MicroBuildInsertVsPayload@4 + - task: MicroBuildInsertVsPayload@5 displayName: Insert VS Payload inputs: TeamName: $(TeamName) diff --git a/azure-pipelines/vs-insertion.yml b/azure-pipelines/vs-insertion.yml index add241f0..f8998736 100644 --- a/azure-pipelines/vs-insertion.yml +++ b/azure-pipelines/vs-insertion.yml @@ -54,7 +54,7 @@ extends: packageParentPath: $(Pipeline.Workspace)/CI/VSInsertion-Windows allowPackageConflicts: true publishVstsFeed: VS - - task: MicroBuildInsertVsPayload@4 + - task: MicroBuildInsertVsPayload@5 displayName: ๐Ÿญ Insert VS Payload inputs: TeamName: $(TeamName) diff --git a/azure-pipelines/vs-validation.yml b/azure-pipelines/vs-validation.yml index eded8319..2a0f0900 100644 --- a/azure-pipelines/vs-validation.yml +++ b/azure-pipelines/vs-validation.yml @@ -87,7 +87,7 @@ extends: packageParentPath: $(Pipeline.Workspace)/VSInsertion-Windows allowPackageConflicts: true publishVstsFeed: VS - - task: MicroBuildInsertVsPayload@4 + - task: MicroBuildInsertVsPayload@5 displayName: ๐Ÿญ Insert VS Payload inputs: TeamName: $(TeamName) From 8819ea6092146216ee27258b321e1be5604b6caa Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 13 Jan 2025 19:40:30 -0700 Subject: [PATCH 068/109] Replace github build workflow with just docfx validation --- .github/workflows/build.yml | 72 ----------------------------- .github/workflows/docs_validate.yml | 22 +++++++++ 2 files changed, 22 insertions(+), 72 deletions(-) delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/docs_validate.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 7617cd99..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: ๐Ÿญ Build - -on: - push: - branches: - - main - - 'v*.*' - - microbuild - - validate/* - pull_request: - workflow_dispatch: - -env: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - BUILDCONFIGURATION: Release - # codecov_token: 4dc9e7e2-6b01-4932-a180-847b52b43d35 # Get a new one from https://codecov.io/ - NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages/ - -jobs: - build: - name: ๐Ÿญ Build - - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-22.04 - - macos-14 - - windows-2022 - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - - name: โš™ Install prerequisites - run: | - ./init.ps1 -UpgradePrerequisites - dotnet --info - - # Print mono version if it is present. - if (Get-Command mono -ErrorAction SilentlyContinue) { - mono --version - } - shell: pwsh - - name: โš™๏ธ Set pipeline variables based on source - run: tools/variables/_define.ps1 - shell: pwsh - - name: ๐Ÿ›  build - run: dotnet build -t:build,pack --no-restore -c ${{ env.BUILDCONFIGURATION }} -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"${{ runner.temp }}/_artifacts/build_logs/build.binlog" - - name: ๐Ÿงช test - run: tools/dotnet-test-cloud.ps1 -Configuration ${{ env.BUILDCONFIGURATION }} -Agent ${{ runner.os }} - shell: pwsh - - name: ๐Ÿ’…๐Ÿป Verify formatted code - run: dotnet format --verify-no-changes --no-restore - shell: pwsh - if: runner.os == 'Linux' - - name: ๐Ÿ“š Verify docfx build - run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures - if: runner.os == 'Linux' - - name: โš™ Update pipeline variables based on build outputs - run: tools/variables/_define.ps1 - shell: pwsh - - name: ๐Ÿ“ข Publish artifacts - uses: ./.github/actions/publish-artifacts - if: cancelled() == false - - name: ๐Ÿ“ข Publish code coverage results to codecov.io - run: ./tools/publish-CodeCov.ps1 -CodeCovToken "${{ env.codecov_token }}" -PathToCodeCoverage "${{ runner.temp }}/_artifacts/coverageResults" -Name "${{ runner.os }} Coverage Results" -Flags "${{ runner.os }}" - shell: pwsh - timeout-minutes: 3 - continue-on-error: true - if: env.codecov_token != '' diff --git a/.github/workflows/docs_validate.yml b/.github/workflows/docs_validate.yml new file mode 100644 index 00000000..9be82c56 --- /dev/null +++ b/.github/workflows/docs_validate.yml @@ -0,0 +1,22 @@ +name: ๐Ÿ“ƒ Docfx Validate + +on: + pull_request: + workflow_dispatch: + +jobs: + build: + name: ๐Ÿ“š docfx + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # avoid shallow clone so nbgv can do its work. + - name: โš™ Install prerequisites + run: | + ./init.ps1 -UpgradePrerequisites + dotnet --info + shell: pwsh + - name: ๐Ÿ“š Verify docfx build + run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures + if: runner.os == 'Linux' From 84258fcadc61a58d352d064dbeab7fb62370db4b Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 14 Jan 2025 07:15:57 -0700 Subject: [PATCH 069/109] Adapt to breaking change in MicroBuildInsertVsPayload@5 --- azure-pipelines/vs-insertion.yml | 2 +- azure-pipelines/vs-validation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines/vs-insertion.yml b/azure-pipelines/vs-insertion.yml index f8998736..6aaba41c 100644 --- a/azure-pipelines/vs-insertion.yml +++ b/azure-pipelines/vs-insertion.yml @@ -60,7 +60,7 @@ extends: TeamName: $(TeamName) TeamEmail: $(TeamEmail) InsertionPayloadName: $(Build.Repository.Name) $(Build.BuildNumber) - InsertionBuildPolicy: Request Perf DDRITs + InsertionBuildPolicies: Request Perf DDRITs InsertionReviewers: $(Build.RequestedFor) # Append `,Your team name` (without quotes) AutoCompletePR: true AutoCompleteMergeStrategy: Squash diff --git a/azure-pipelines/vs-validation.yml b/azure-pipelines/vs-validation.yml index 2a0f0900..2fa5086d 100644 --- a/azure-pipelines/vs-validation.yml +++ b/azure-pipelines/vs-validation.yml @@ -96,7 +96,7 @@ extends: 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 + InsertionBuildPolicies: 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 From 5a6c72d984bfd5baef7a70f77010905dbc9b9d00 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 14 Jan 2025 08:39:06 -0700 Subject: [PATCH 070/109] Bring back Dependabot --- .github/dependabot.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..a7a1782f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +# Please see the documentation for all configuration options: +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: +- package-ecosystem: nuget + directory: / + schedule: + interval: weekly + groups: + nerdbank-gitversioning: + patterns: + - nbgv + - nerdbank.gitversioning + xunit: + patterns: + - 'xunit*' +- package-ecosystem: dotnet-sdk + directory: / + schedule: + interval: monthly From 862f998b734e016e71fa5045909e64208de05437 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 14 Jan 2025 11:52:44 -0700 Subject: [PATCH 071/109] Fix Install-NuGetPackage.ps1 script --- azure-pipelines/Install-NuGetPackage.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines/Install-NuGetPackage.ps1 b/azure-pipelines/Install-NuGetPackage.ps1 index 9afde055..f1db577a 100644 --- a/azure-pipelines/Install-NuGetPackage.ps1 +++ b/azure-pipelines/Install-NuGetPackage.ps1 @@ -33,7 +33,7 @@ Param( [string]$Verbosity='normal' ) -$nugetPath = & "$PSScriptRoot\Get-NuGetTool.ps1" +$nugetPath = & "$PSScriptRoot\..\tools\Get-NuGetTool.ps1" try { Write-Verbose "Installing $PackageId..." From d1583877d80f8b6447cfc22986391b4e54e7b780 Mon Sep 17 00:00:00 2001 From: Matteo Prosperi <41970398+matteo-prosperi@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:06:13 -0800 Subject: [PATCH 072/109] Create a separate unofficial.yml pipeline (#334) --- Expand-Template.ps1 | 2 +- azure-pipelines/apiscan.yml | 8 ++ azure-pipelines/build.yml | 1 + azure-pipelines/official.yml | 129 +++++++++++---------------------- azure-pipelines/unofficial.yml | 90 +++++++++++++++++++++++ 5 files changed, 141 insertions(+), 89 deletions(-) create mode 100644 azure-pipelines/unofficial.yml diff --git a/Expand-Template.ps1 b/Expand-Template.ps1 index 0bc5f440..9ba1f04e 100755 --- a/Expand-Template.ps1 +++ b/Expand-Template.ps1 @@ -156,7 +156,7 @@ try { $YmlReplacements = @{ "(?m)^\s+- microbuild`r?`n"="" } - Replace-Placeholders -Path "azure-pipelines\official.yml" -Replacements $YmlReplacements + Replace-Placeholders -Path "azure-pipelines\unofficial.yml" -Replacements $YmlReplacements Replace-Placeholders -Path "azure-pipelines.yml" -Replacements $YmlReplacements $YmlReplacements = @{} diff --git a/azure-pipelines/apiscan.yml b/azure-pipelines/apiscan.yml index af78f15c..c3c8aed1 100644 --- a/azure-pipelines/apiscan.yml +++ b/azure-pipelines/apiscan.yml @@ -1,6 +1,8 @@ parameters: - name: windowsPool type: object +- name: RealSign + type: boolean jobs: - job: apiscan @@ -9,6 +11,12 @@ jobs: pool: ${{ parameters.windowsPool }} timeoutInMinutes: 120 templateContext: + ${{ if not(parameters.RealSign) }}: + mb: + signing: # if the build is test-signed, install the signing plugin so that CSVTestSignPolicy.xml is available + enabled: true + zipSources: false + signType: test outputs: - output: pipelineArtifact displayName: ๐Ÿ“ข collect apiscan artifact diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index 279c10a6..1a830586 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -313,3 +313,4 @@ jobs: - template: apiscan.yml parameters: windowsPool: ${{ parameters.windowsPool }} + RealSign: ${{ parameters.RealSign }} diff --git a/azure-pipelines/official.yml b/azure-pipelines/official.yml index 35beb818..a9b5b81e 100644 --- a/azure-pipelines/official.yml +++ b/azure-pipelines/official.yml @@ -1,17 +1,5 @@ -trigger: - batch: true - branches: - include: - - main - - microbuild - - 'validate/*' - paths: - exclude: - - doc/ - - '*.md' - - .vscode/ - - azure-pipelines/release.yml - - azure-pipelines/vs-insertion.yml +trigger: none # We only want to trigger manually or based on a schedule +pr: none #schedules: #- cron: "0 3 * * *" # Daily @ 8 PM PST # displayName: Daily vs-insertion @@ -23,10 +11,6 @@ parameters: # As an entrypoint pipeline yml file, all parameters here show up in the Queue Run dialog. # If any paramaters should NOT be queue-time options, they should be removed from here # and references to them in this file replaced with hard-coded values. -- name: ForceOfficialBuild - displayName: Official build (sign, compliance, etc.) - type: boolean - default: false # this should remain false so PR builds using this pipeline are unofficial # - name: ShouldSkipOptimize # Uncomment this and references to it below when setting EnableOptProf to true in build.yml. # displayName: Skip OptProf optimization # type: boolean @@ -55,75 +39,44 @@ variables: - template: GlobalVariables.yml extends: - ${{ if or(parameters.ForceOfficialBuild, eq(variables['Build.Reason'],'Schedule')) }}: - template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate - parameters: - sdl: - sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES - codeSignValidation: - enabled: true - break: true - additionalTargetsGlobPattern: -|Variables-*\*.ps1;-|APIScanInputs-*\**;-|test_symbols-*\**;-|MicroBuild\** - policheck: - enabled: true - exclusionsFile: $(System.DefaultWorkingDirectory)\azure-pipelines\PoliCheckExclusions.xml - suppression: - suppressionFile: $(System.DefaultWorkingDirectory)\azure-pipelines\falsepositives.gdnsuppress - sbom: - enabled: true - stages: - - stage: Build - variables: - - template: /azure-pipelines/BuildStageVariables.yml@self - jobs: - - template: /azure-pipelines/build.yml@self - parameters: - Is1ESPT: true - RealSign: true - # ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }} - EnableAPIScan: ${{ and(parameters.EnableAPIScan, ne(variables['Build.Reason'], 'pullRequest')) }} - windowsPool: VSEngSS-MicroBuild2022-1ES - linuxPool: - name: AzurePipelines-EO - demands: - - ImageOverride -equals 1ESPT-Ubuntu22.04 - os: Linux - macOSPool: - name: Azure Pipelines - vmImage: macOS-14 - os: macOS - EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }} - RunTests: ${{ parameters.RunTests }} - - template: /azure-pipelines/prepare-insertion-stages.yml@self + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate + parameters: + sdl: + sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES + codeSignValidation: + enabled: true + break: true + additionalTargetsGlobPattern: -|Variables-*\*.ps1;-|APIScanInputs-*\**;-|test_symbols-*\**;-|MicroBuild\** + policheck: + enabled: true + exclusionsFile: $(System.DefaultWorkingDirectory)\azure-pipelines\PoliCheckExclusions.xml + suppression: + suppressionFile: $(System.DefaultWorkingDirectory)\azure-pipelines\falsepositives.gdnsuppress + sbom: + enabled: true + stages: + - stage: Build + variables: + - template: /azure-pipelines/BuildStageVariables.yml@self + jobs: + - template: /azure-pipelines/build.yml@self parameters: + Is1ESPT: true RealSign: true - ${{ else }}: - template: azure-pipelines/MicroBuild.1ES.Unofficial.yml@MicroBuildTemplate - parameters: - sdl: - sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES - suppression: - suppressionFile: $(System.DefaultWorkingDirectory)\azure-pipelines\falsepositives.gdnsuppress - stages: - - stage: Build - variables: - - template: /azure-pipelines/BuildStageVariables.yml@self - jobs: - - template: /azure-pipelines/build.yml@self - parameters: - Is1ESPT: true - RealSign: false - # ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }} - EnableAPIScan: false - windowsPool: VSEngSS-MicroBuild2022-1ES - linuxPool: - name: AzurePipelines-EO - demands: - - ImageOverride -equals 1ESPT-Ubuntu22.04 - os: Linux - macOSPool: - name: Azure Pipelines - vmImage: macOS-14 - os: macOS - EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }} - RunTests: ${{ parameters.RunTests }} + # ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }} + EnableAPIScan: ${{ parameters.EnableAPIScan }} + windowsPool: VSEngSS-MicroBuild2022-1ES + linuxPool: + name: AzurePipelines-EO + demands: + - ImageOverride -equals 1ESPT-Ubuntu22.04 + os: Linux + macOSPool: + name: Azure Pipelines + vmImage: macOS-14 + os: macOS + EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }} + RunTests: ${{ parameters.RunTests }} + - template: /azure-pipelines/prepare-insertion-stages.yml@self + parameters: + RealSign: true diff --git a/azure-pipelines/unofficial.yml b/azure-pipelines/unofficial.yml new file mode 100644 index 00000000..afce810b --- /dev/null +++ b/azure-pipelines/unofficial.yml @@ -0,0 +1,90 @@ +trigger: + batch: true + branches: + include: + - main + - microbuild + - 'validate/*' + paths: + exclude: + - doc/ + - '*.md' + - .vscode/ + - azure-pipelines/release.yml + - azure-pipelines/vs-insertion.yml + +parameters: +# As an entrypoint pipeline yml file, all parameters here show up in the Queue Run dialog. +# If any paramaters should NOT be queue-time options, they should be removed from here +# and references to them in this file replaced with hard-coded values. +# - name: ShouldSkipOptimize # Uncomment this and references to it below when setting EnableOptProf to true in build.yml. +# displayName: Skip OptProf optimization +# type: boolean +# default: false +- name: EnableMacOSBuild + displayName: Build on macOS + type: boolean + default: false # macOS is often bogged down in Azure Pipelines +- name: RunTests + displayName: Run tests + type: boolean + default: true +- name: EnableAPIScan + displayName: Include APIScan with compliance tools + type: boolean + default: false +- name: EnableProductionSDL + displayName: Enable Production SDL + type: boolean + default: false + +resources: + repositories: + - repository: MicroBuildTemplate + type: git + name: 1ESPipelineTemplates/MicroBuildTemplate + ref: refs/tags/release + +variables: +- template: GlobalVariables.yml + +extends: + template: azure-pipelines/MicroBuild.1ES.Unofficial.yml@MicroBuildTemplate + parameters: + sdl: + sourceAnalysisPool: VSEngSS-MicroBuild2022-1ES + suppression: + suppressionFile: $(System.DefaultWorkingDirectory)\azure-pipelines\falsepositives.gdnsuppress + enableProductionSDL: ${{ parameters.EnableProductionSDL }} + codeSignValidation: + enabled: ${{ parameters.EnableProductionSDL }} + break: true + policyFile: $(MBSIGN_APPFOLDER)\CSVTestSignPolicy.xml + policheck: + enabled: ${{ parameters.EnableProductionSDL }} + exclusionsFile: $(System.DefaultWorkingDirectory)\azure-pipelines\PoliCheckExclusions.xml + sbom: + enabled: ${{ parameters.EnableProductionSDL }} + stages: + - stage: Build + variables: + - template: /azure-pipelines/BuildStageVariables.yml@self + jobs: + - template: /azure-pipelines/build.yml@self + parameters: + Is1ESPT: true + RealSign: false + # ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }} + EnableAPIScan: ${{ parameters.EnableAPIScan }} + windowsPool: VSEngSS-MicroBuild2022-1ES + linuxPool: + name: AzurePipelines-EO + demands: + - ImageOverride -equals 1ESPT-Ubuntu22.04 + os: Linux + macOSPool: + name: Azure Pipelines + vmImage: macOS-14 + os: macOS + EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }} + RunTests: ${{ parameters.RunTests }} From 2545e3021b61162d5f23b4b41e7405f1b25dbbfb Mon Sep 17 00:00:00 2001 From: Matteo Prosperi <41970398+matteo-prosperi@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:18:08 -0800 Subject: [PATCH 073/109] Add back signcheck exclusion for unofficial builds --- azure-pipelines/unofficial.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines/unofficial.yml b/azure-pipelines/unofficial.yml index afce810b..ff3c2b5d 100644 --- a/azure-pipelines/unofficial.yml +++ b/azure-pipelines/unofficial.yml @@ -59,6 +59,7 @@ extends: codeSignValidation: enabled: ${{ parameters.EnableProductionSDL }} break: true + additionalTargetsGlobPattern: -|Variables-*\*.ps1;-|APIScanInputs-*\**;-|test_symbols-*\**;-|MicroBuild\** policyFile: $(MBSIGN_APPFOLDER)\CSVTestSignPolicy.xml policheck: enabled: ${{ parameters.EnableProductionSDL }} From 8c45970cd587e8923048ebef3db71ad559a870a3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 18:21:19 -0700 Subject: [PATCH 074/109] Update Dockerfile and global.json updates to v9.0.102 (#340) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/Dockerfile | 2 +- global.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3674e182..6952a419 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:9.0.101-noble +FROM mcr.microsoft.com/dotnet/sdk:9.0.102-noble # 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/global.json b/global.json index f3e0b323..119eff7e 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.101", + "version": "9.0.102", "rollForward": "patch", "allowPrerelease": false } From 25d6df9315be95115c164411a39ee242b29de0ed Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 14 Jan 2025 18:27:14 -0700 Subject: [PATCH 075/109] Migrate xunit settings from app.config to xunit.runner.json --- test/Directory.Build.targets | 4 ++++ test/Library.Tests/app.config | 5 ----- test/Library.Tests/xunit.runner.json | 4 ++++ 3 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 test/Library.Tests/app.config create mode 100644 test/Library.Tests/xunit.runner.json diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets index a6e0f4ac..9f32cd06 100644 --- a/test/Directory.Build.targets +++ b/test/Directory.Build.targets @@ -1,4 +1,8 @@ + + + + diff --git a/test/Library.Tests/app.config b/test/Library.Tests/app.config deleted file mode 100644 index 61890f05..00000000 --- a/test/Library.Tests/app.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/test/Library.Tests/xunit.runner.json b/test/Library.Tests/xunit.runner.json new file mode 100644 index 00000000..8465a454 --- /dev/null +++ b/test/Library.Tests/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", + "shadowCopy": false +} From b9f8bc9561e76aa68cac7e4ec41ece0364c123a0 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 15 Jan 2025 10:05:41 -0700 Subject: [PATCH 076/109] Fix typo --- .github/workflows/libtemplate-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml index c6b8fb4a..53df80ff 100644 --- a/.github/workflows/libtemplate-update.yml +++ b/.github/workflows/libtemplate-update.yml @@ -45,7 +45,7 @@ jobs: # Pushing commits that add or change files under .github/workflows will cause our workflow to fail. # But it usually isn't necessary because the target branch already has (or doesn't have) these changes. - # So if the merged doesn't bring in any changes to these files, try the merge locally and push that + # So if the merge doesn't bring in any changes to these files, try the merge locally and push that # to keep github happy. if ((git rev-list FETCH_HEAD ^HEAD --count -- .github/workflows) -eq 0) { # Indeed there are no changes in that area. So merge locally to try to appease GitHub. From df5243521eabba1568f50f15e503d1e2dda0ee78 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 18 Jan 2025 10:36:33 -0700 Subject: [PATCH 077/109] Add GitS sponsorship badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 610e6504..f7a79262 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ ![GitHub Actions status](https://github.com/aarnott/Library.Template/workflows/CI/badge.svg) [![codecov](https://codecov.io/gh/aarnott/library.template/branch/main/graph/badge.svg)](https://codecov.io/gh/aarnott/library.template) +[](https://api.gitsponsors.com/api/badge/link?p=MCQ+F+FQ4qDG3aB7nxcFJ9OIaaCARvdUdn6994QBDixzmF6GkU1V7l/Zk+7MwNTbZGdGMw06hyJAs80v04cpo08nYPaOeWn9BMLwruCMqnmr8AoX5dTC4OcDg3r1juk0nocxT2n22yvq8MyXIS32EQ==) + ## Features * Follow the best and simplest patterns of build, pack and test with dotnet CLI. From 02bf9eeae2ac8aa8b3efe3641ec46eee8d9c3529 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 20 Jan 2025 07:13:46 -0700 Subject: [PATCH 078/109] Revert "Add GitS sponsorship badge" This reverts commit df5243521eabba1568f50f15e503d1e2dda0ee78. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index f7a79262..610e6504 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ ![GitHub Actions status](https://github.com/aarnott/Library.Template/workflows/CI/badge.svg) [![codecov](https://codecov.io/gh/aarnott/library.template/branch/main/graph/badge.svg)](https://codecov.io/gh/aarnott/library.template) -[](https://api.gitsponsors.com/api/badge/link?p=MCQ+F+FQ4qDG3aB7nxcFJ9OIaaCARvdUdn6994QBDixzmF6GkU1V7l/Zk+7MwNTbZGdGMw06hyJAs80v04cpo08nYPaOeWn9BMLwruCMqnmr8AoX5dTC4OcDg3r1juk0nocxT2n22yvq8MyXIS32EQ==) - ## Features * Follow the best and simplest patterns of build, pack and test with dotnet CLI. From aa8e87054f2ad8fb64a0de043f39b959a7e5ce51 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:14:15 -0700 Subject: [PATCH 079/109] Update dependency powershell to 7.5.0 (#341) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3a7b9b69..1b8c58ce 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "powershell": { - "version": "7.4.6", + "version": "7.5.0", "commands": [ "pwsh" ], From 37306430894c3d18854bbdc8dcb0b0c228b588d8 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 23 Jan 2025 22:39:45 -0700 Subject: [PATCH 080/109] Bump all microbuild packages at once --- .github/renovate.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/renovate.json b/.github/renovate.json index c140014f..55602947 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -16,6 +16,10 @@ "matchDatasources": ["dotnet-version", "docker"], "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], "groupName": "Dockerfile and global.json updates" + }, + { + "matchPackageNames": ["Microsoft.VisualStudio.Internal.MicroBuild*"], + "groupName": "microbuild" } ] } From 66fe1ca6c9d3c86887bccd2c550d92587f27b2da Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 27 Jan 2025 08:28:00 -0700 Subject: [PATCH 081/109] Add markup link checker to GitHub workflow --- .github/workflows/build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5b4fc7be..2d951062 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,3 +69,13 @@ jobs: timeout-minutes: 3 continue-on-error: true if: env.codecov_token != '' + + docs: + name: ๐Ÿ“ƒ Docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: ๐Ÿ”— Markup Link Checker (mlc) + uses: becheran/mlc@v0.19.0 + with: + args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx From b3b3da2f87f080d451e7514865717c7cd6540ecd Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 27 Jan 2025 08:35:34 -0700 Subject: [PATCH 082/109] Fix stale link in CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77f5e0a3..56dd666f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,7 +25,7 @@ You should install the version specified in `global.json` or a later version wit the same major.minor.Bxx "hundreds" band. For example if 2.2.300 is specified, you may install 2.2.300, 2.2.301, or 2.2.310 while the 2.2.400 version would not be considered compatible by .NET SDK. -See [.NET Core Versioning](https://docs.microsoft.com/dotnet/core/versions/) for more information. +See [.NET Core Versioning](https://learn.microsoft.com/dotnet/core/versions/) for more information. ## Package restore @@ -44,7 +44,7 @@ Building, testing, and packing this repository can be done by using the standard ## Releases Use `nbgv tag` to create a tag for a particular commit that you mean to release. -[Learn more about `nbgv` and its `tag` and `prepare-release` commands](https://github.com/dotnet/Nerdbank.GitVersioning/blob/main/doc/nbgv-cli.md). +[Learn more about `nbgv` and its `tag` and `prepare-release` commands](https://dotnet.github.io/Nerdbank.GitVersioning/docs/nbgv-cli.html). Push the tag. From 1da386324a06ce360c03270dd19c01133270c4c0 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 27 Jan 2025 09:25:14 -0700 Subject: [PATCH 083/109] Skip aka.ms links that don't validate --- .github/workflows/docs_validate.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs_validate.yml b/.github/workflows/docs_validate.yml index 07dd8b9a..d1c8b8fb 100644 --- a/.github/workflows/docs_validate.yml +++ b/.github/workflows/docs_validate.yml @@ -6,7 +6,7 @@ on: jobs: build: - name: ๐Ÿ“š docfx + name: ๐Ÿ“š Doc validation runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -15,7 +15,7 @@ jobs: - name: ๐Ÿ”— Markup Link Checker (mlc) uses: becheran/mlc@v0.19.0 with: - args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx + args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dev.azure.com/*,https://app.codecov.io/*,https://msrc.microsoft.com/*,https://www.microsoft.com/en-us/msrc* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://www.microsoft.com/msrc/cvd,https://www.microsoft.com/msrc - name: โš™ Install prerequisites run: | ./init.ps1 -UpgradePrerequisites From 9409f44674386eb10f9721ecbed1cb1b7aa1e2db Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 27 Jan 2025 14:25:15 -0700 Subject: [PATCH 084/109] Bump nuget.exe build tool to 6.12.2 --- tools/Get-NuGetTool.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/Get-NuGetTool.ps1 b/tools/Get-NuGetTool.ps1 index 3097c873..8a3b9eed 100644 --- a/tools/Get-NuGetTool.ps1 +++ b/tools/Get-NuGetTool.ps1 @@ -6,7 +6,7 @@ #> Param( [Parameter()] - [string]$NuGetVersion='6.4.0' + [string]$NuGetVersion='6.12.2' ) $toolsPath = & "$PSScriptRoot\Get-TempToolsPath.ps1" From e25313b90d5f26b11211c61c7adff7f0a94eb4c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 21:27:02 +0000 Subject: [PATCH 085/109] Update becheran/mlc action to v0.19.1 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d951062..42f5a005 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,6 +76,6 @@ jobs: steps: - uses: actions/checkout@v4 - name: ๐Ÿ”— Markup Link Checker (mlc) - uses: becheran/mlc@v0.19.0 + uses: becheran/mlc@v0.19.1 with: args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx From 83228fe554696ec1508b2ff3e214832dd4df182e Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 14:42:42 -0700 Subject: [PATCH 086/109] Suppress an expected doc warning --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42f5a005..d3d9d2f8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,4 +78,4 @@ jobs: - name: ๐Ÿ”— Markup Link Checker (mlc) uses: becheran/mlc@v0.19.1 with: - args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx + args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx From 3114358825e4c20cf9d49597c2616c067e25b3f3 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 16:06:31 -0700 Subject: [PATCH 087/109] Remove dependabot.yml --- .github/dependabot.yml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index a7a1782f..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Please see the documentation for all configuration options: -# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - -version: 2 -updates: -- package-ecosystem: nuget - directory: / - schedule: - interval: weekly - groups: - nerdbank-gitversioning: - patterns: - - nbgv - - nerdbank.gitversioning - xunit: - patterns: - - 'xunit*' -- package-ecosystem: dotnet-sdk - directory: / - schedule: - interval: monthly From 3856c54130c323dd2fa8a48e9fc13eb0c23d8f0c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:11:26 -0700 Subject: [PATCH 088/109] Update becheran/mlc action to v0.19.2 (#345) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3d9d2f8..7eb7860e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,6 +76,6 @@ jobs: steps: - uses: actions/checkout@v4 - name: ๐Ÿ”— Markup Link Checker (mlc) - uses: becheran/mlc@v0.19.1 + uses: becheran/mlc@v0.19.2 with: args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx From 399d3d5d8f13ac06a82a58dd50dcd6adf0b96767 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 18:00:20 -0700 Subject: [PATCH 089/109] Stick with .NET 8 packages --- .github/renovate.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/renovate.json b/.github/renovate.json index 55602947..86c3fe2f 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -17,6 +17,20 @@ "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], "groupName": "Dockerfile and global.json updates" }, + { + "matchPackageNames": [ + "System.Collections.Immutable", + "System.Composition*", + "System.Diagnostics.DiagnosticSource", + "System.IO.Pipelines", + "System.Reflection.Metadata", + "System.Text.Json", + "System.Threading.Tasks.Dataflow", + "Microsoft.Bcl.AsyncInterfaces" + ], + "allowedVersions": "<9.0", + "groupName": "Included in .NET runtime" + }, { "matchPackageNames": ["Microsoft.VisualStudio.Internal.MicroBuild*"], "groupName": "microbuild" From 56ac6706a56b22a46358901886e9b679ac6cbee6 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 18:01:04 -0700 Subject: [PATCH 090/109] Update microbuild to 2.0.181 --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 659d9c00..6606c84a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ true true - 2.0.171 + 2.0.181 From 37e48d01b7bdd9990b6449cc8d361e94b81fa798 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 18:01:27 -0700 Subject: [PATCH 091/109] Update dependency ubuntu to v24 --- .github/workflows/docs_validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs_validate.yml b/.github/workflows/docs_validate.yml index d1c8b8fb..f7125817 100644 --- a/.github/workflows/docs_validate.yml +++ b/.github/workflows/docs_validate.yml @@ -7,7 +7,7 @@ on: jobs: build: name: ๐Ÿ“š Doc validation - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: From 28c5968eb57d442d2a9eb82d95c3776069f028fc Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 18:12:58 -0700 Subject: [PATCH 092/109] Avoid daily updates of VS packages --- .github/renovate.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/renovate.json b/.github/renovate.json index 86c3fe2f..409b27d9 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -34,6 +34,11 @@ { "matchPackageNames": ["Microsoft.VisualStudio.Internal.MicroBuild*"], "groupName": "microbuild" + }, + { + "matchPackageNames": ["Microsoft.VisualStudio.*"], + "matchUpdateTypes": ["patch"], + "enabled": false } ] } From b4a369cbcf6bf536dbf608d08520b3655d3db046 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 18:15:50 -0700 Subject: [PATCH 093/109] Group VS SDK package updates --- .github/renovate.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/renovate.json b/.github/renovate.json index 409b27d9..c9d99b7f 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -35,6 +35,10 @@ "matchPackageNames": ["Microsoft.VisualStudio.Internal.MicroBuild*"], "groupName": "microbuild" }, + { + "matchPackageNames": ["Microsoft.VisualStudio.*"], + "groupName": "Visual Studio SDK" + }, { "matchPackageNames": ["Microsoft.VisualStudio.*"], "matchUpdateTypes": ["patch"], From 2d06ba40adda405cab7ebab4ace694ee8e40a413 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 4 Feb 2025 21:28:14 -0700 Subject: [PATCH 094/109] Update becheran/mlc action to v0.19.2 --- .github/workflows/docs_validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs_validate.yml b/.github/workflows/docs_validate.yml index 4bf30d42..380cc03c 100644 --- a/.github/workflows/docs_validate.yml +++ b/.github/workflows/docs_validate.yml @@ -13,7 +13,7 @@ jobs: with: fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - name: ๐Ÿ”— Markup Link Checker (mlc) - uses: becheran/mlc@v0.19.0 + uses: becheran/mlc@v0.19.2 with: args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/*,https://msrc.microsoft.com/*,https://www.microsoft.com/en-us/msrc* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://www.microsoft.com/msrc/cvd,https://www.microsoft.com/msrc - name: โš™ Install prerequisites From 429e76f7d36b71ad3014c0c9712a238a26bed45b Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 5 Feb 2025 14:36:16 -0700 Subject: [PATCH 095/109] Fix mlc suppressions for SECURITY.md --- .github/workflows/docs_validate.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs_validate.yml b/.github/workflows/docs_validate.yml index 380cc03c..e100eba6 100644 --- a/.github/workflows/docs_validate.yml +++ b/.github/workflows/docs_validate.yml @@ -3,6 +3,10 @@ name: ๐Ÿ“ƒ Docfx Validate on: pull_request: workflow_dispatch: + push: + branches: + - main + - microbuild jobs: build: @@ -15,7 +19,7 @@ jobs: - name: ๐Ÿ”— Markup Link Checker (mlc) uses: becheran/mlc@v0.19.2 with: - args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/*,https://msrc.microsoft.com/*,https://www.microsoft.com/en-us/msrc* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://www.microsoft.com/msrc/cvd,https://www.microsoft.com/msrc + args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://msrc.microsoft.com/*,https://www.microsoft.com/msrc*,https://microsoft.com/msrc* - name: โš™ Install prerequisites run: | ./init.ps1 -UpgradePrerequisites From 8eb0937bad6dd628f70d29a75e76bff112d8a707 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 5 Feb 2025 21:42:18 -0700 Subject: [PATCH 096/109] Renovate should not update to versions from non-release branches --- .github/renovate.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/renovate.json b/.github/renovate.json index c140014f..a41e0267 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -16,6 +16,11 @@ "matchDatasources": ["dotnet-version", "docker"], "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], "groupName": "Dockerfile and global.json updates" + }, + { + "matchPackageNames": ["*"], + "allowedVersions": "!/-g[a-f0-9]+$/", + "groupName": "Ignore versions built from non-release branches" } ] } From 9db1062760fc20f2124ec32a012aced5666372bf Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 5 Feb 2025 22:36:37 -0700 Subject: [PATCH 097/109] Drop group name in renovate --- .github/renovate.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index a41e0267..092ed049 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -19,8 +19,7 @@ }, { "matchPackageNames": ["*"], - "allowedVersions": "!/-g[a-f0-9]+$/", - "groupName": "Ignore versions built from non-release branches" + "allowedVersions": "!/-g[a-f0-9]+$/" } ] } From 574886f56785776ec9246585256d3056228cd021 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Feb 2025 07:20:17 -0700 Subject: [PATCH 098/109] Update xunit (#346) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 8811c1ea..8703de3f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,8 +10,8 @@ - - + + From a71c97c2377c9d17faafb1a570350c213169efd0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 09:58:39 -0700 Subject: [PATCH 099/109] Update becheran/mlc action to v0.21.0 (#347) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7eb7860e..da3e9e1f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,6 +76,6 @@ jobs: steps: - uses: actions/checkout@v4 - name: ๐Ÿ”— Markup Link Checker (mlc) - uses: becheran/mlc@v0.19.2 + uses: becheran/mlc@v0.21.0 with: args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx From a8d08d4856b60c9a2911b3a2fd0f1f297bd4a7ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 09:59:19 -0700 Subject: [PATCH 100/109] Update dependency Microsoft.NET.Test.Sdk to 17.13.0 (#348) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 8703de3f..350c7eb5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -9,7 +9,7 @@ - + From 62c89782b8d88a4cfef61338775a14522874e001 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Mon, 10 Feb 2025 10:01:53 -0700 Subject: [PATCH 101/109] Bump MicroBuildVersion to 2.0.187 --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c2c31959..f9d52e8e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ true true - 2.0.181 + 2.0.187 From 2f88853b64bb324048a034af7ef1153848e7382a Mon Sep 17 00:00:00 2001 From: Eric Arndt Date: Thu, 20 Feb 2025 13:53:24 -0800 Subject: [PATCH 102/109] Handle spaces in GlobalSection definition. --- .../Serializer/SlnV12/SlnFileV12Serializer.Reader.cs | 2 +- .../SlnAssets/SampleMany.sln.txt | 3 +++ .../SlnAssets/SampleMany.slnx.xml | 3 +++ version.json | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs index 40ec8ede..ed558a64 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs @@ -491,7 +491,7 @@ private bool ReadLine(out StringTokenizer lineScanner) // So that is valid: ProjectSection ((( ))XXX===(())preProect // We have to keep that behaviour, only slight difference will allow space in adition to tab at the end of name // With all wierd syntaxes old will accepet, it will not accept ProjectSection( Foo ) (but will do ) ProjectSection( Foo) ... - StringSpan sectionName = tokenizer.NextToken(SlnConstants.SectionSeparators).Trim(); + StringSpan sectionName = tokenizer.NextToken(SlnConstants.SectionSeparators2).Trim(); this.SolutionAssert(!sectionName.IsEmpty, Errors.MissingSectionName); StringSpan sectionScopeStr = tokenizer.NextToken(SlnConstants.SectionSeparators).Trim(); this.SolutionAssert(TryParseScope(sectionScopeStr, isSolution, out PropertiesScope scope), Errors.InvalidScope); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.sln.txt index 6646ab2f..b73af6eb 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.sln.txt +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.sln.txt @@ -226,6 +226,9 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {210A5C78-8B93-42DA-8FB9-A667D3B01618} EndGlobalSection + GlobalSection(DevPartner Solution Properties) = postSolution + SharedCPS\SharedCPS.vcxitems*{919107bb-2e8e-4dbb-ac5d-36ff8a211ffc}*SharedItemsImports = 9 + EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution CSharpShared\CSharpShared.projitems*{51cc7781-a8d3-4c60-8065-f3ceedba8032}*SharedItemsImports = 13 SharedCPS\SharedCPS.vcxitems*{919107bb-2e8e-4dbb-ac5d-36ff8a211ffc}*SharedItemsImports = 9 diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.slnx.xml b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.slnx.xml index 596d0511..7963d890 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.slnx.xml +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/SampleMany.slnx.xml @@ -77,4 +77,7 @@ + + + diff --git a/version.json b/version.json index 0085c75a..db09b818 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", "version": "1.0", + "versionHeightOffset": "10", "publicReleaseRefSpec": [ "^refs/heads/main$", "^refs/heads/v\\d+(?:\\.\\d+)?$" From 2fb9c3d92e5a38053752f56d09a7d61976f1d189 Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Thu, 20 Feb 2025 16:14:59 -0800 Subject: [PATCH 103/109] Remove github actions. --- .github/.editorconfig | 2 - .github/actions/publish-artifacts/action.yaml | 60 ------------ .github/renovate.json | 52 ---------- .github/workflows/docs.yml | 44 --------- .github/workflows/docs_validate.yml | 30 ------ .github/workflows/libtemplate-update.yml | 98 ------------------- .github/workflows/release.yml | 88 ----------------- 7 files changed, 374 deletions(-) delete mode 100644 .github/.editorconfig delete mode 100644 .github/actions/publish-artifacts/action.yaml delete mode 100644 .github/renovate.json delete mode 100644 .github/workflows/docs.yml delete mode 100644 .github/workflows/docs_validate.yml delete mode 100644 .github/workflows/libtemplate-update.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/.editorconfig b/.github/.editorconfig deleted file mode 100644 index 2b7682ef..00000000 --- a/.github/.editorconfig +++ /dev/null @@ -1,2 +0,0 @@ -[renovate.json*] -indent_style = tab diff --git a/.github/actions/publish-artifacts/action.yaml b/.github/actions/publish-artifacts/action.yaml deleted file mode 100644 index 2a75c4d2..00000000 --- a/.github/actions/publish-artifacts/action.yaml +++ /dev/null @@ -1,60 +0,0 @@ -name: Publish artifacts -description: Publish artifacts - -runs: - using: composite - steps: - - name: ๐Ÿ“ฅ Collect artifacts - run: tools/artifacts/_stage_all.ps1 - shell: pwsh - if: always() - -# TODO: replace this hard-coded list with a loop that utilizes the NPM package at -# https://github.com/actions/toolkit/tree/main/packages/artifact (or similar) to push the artifacts. - - - name: ๐Ÿ“ข Upload project.assets.json files - if: always() - uses: actions/upload-artifact@v4 - with: - name: projectAssetsJson-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/projectAssetsJson - continue-on-error: true - - name: ๐Ÿ“ข Upload variables - uses: actions/upload-artifact@v4 - with: - name: variables-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/Variables - continue-on-error: true - - name: ๐Ÿ“ข Upload build_logs - if: always() - uses: actions/upload-artifact@v4 - with: - name: build_logs-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/build_logs - continue-on-error: true - - name: ๐Ÿ“ข Upload testResults - if: always() - uses: actions/upload-artifact@v4 - with: - name: testResults-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/testResults - continue-on-error: true - - name: ๐Ÿ“ข Upload coverageResults - if: always() - uses: actions/upload-artifact@v4 - with: - name: coverageResults-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/coverageResults - continue-on-error: true - - name: ๐Ÿ“ข Upload symbols - uses: actions/upload-artifact@v4 - with: - name: symbols-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/symbols - continue-on-error: true - - name: ๐Ÿ“ข Upload deployables - uses: actions/upload-artifact@v4 - with: - name: deployables-${{ runner.os }} - path: ${{ runner.temp }}/_artifacts/deployables - if: always() diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index 72080431..00000000 --- a/.github/renovate.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended"], - "semanticCommits": "disabled", - "labels": ["dependencies"], - "packageRules": [ - { - "matchPackageNames": ["nbgv", "nerdbank.gitversioning"], - "groupName": "nbgv and nerdbank.gitversioning updates" - }, - { - "matchPackageNames": ["xunit*"], - "groupName": "xunit" - }, - { - "matchDatasources": ["dotnet-version", "docker"], - "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"], - "groupName": "Dockerfile and global.json updates" - }, - { - "matchPackageNames": ["*"], - "allowedVersions": "!/-g[a-f0-9]+$/" - }, - { - "matchPackageNames": [ - "System.Collections.Immutable", - "System.Composition*", - "System.Diagnostics.DiagnosticSource", - "System.IO.Pipelines", - "System.Reflection.Metadata", - "System.Text.Json", - "System.Threading.Tasks.Dataflow", - "Microsoft.Bcl.AsyncInterfaces" - ], - "allowedVersions": "<9.0", - "groupName": "Included in .NET runtime" - }, - { - "matchPackageNames": ["Microsoft.VisualStudio.Internal.MicroBuild*"], - "groupName": "microbuild" - }, - { - "matchPackageNames": ["Microsoft.VisualStudio.*"], - "groupName": "Visual Studio SDK" - }, - { - "matchPackageNames": ["Microsoft.VisualStudio.*"], - "matchUpdateTypes": ["patch"], - "enabled": false - } - ] -} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 70b779b5..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: ๐Ÿ“š Docs - -on: - push: - branches: - - main - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - actions: read - pages: write - id-token: write - contents: read - -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. -concurrency: - group: pages - cancel-in-progress: false - -jobs: - publish-docs: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - - name: โš™ Install prerequisites - run: ./init.ps1 -UpgradePrerequisites - - - run: dotnet docfx docfx/docfx.json - name: ๐Ÿ“š Generate documentation - - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: docfx/_site - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/docs_validate.yml b/.github/workflows/docs_validate.yml deleted file mode 100644 index 2425d742..00000000 --- a/.github/workflows/docs_validate.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: ๐Ÿ“ƒ Docfx Validate - -on: - pull_request: - workflow_dispatch: - push: - branches: - - main - - microbuild - -jobs: - build: - name: ๐Ÿ“š Doc validation - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - - name: ๐Ÿ”— Markup Link Checker (mlc) - uses: becheran/mlc@v0.21.0 - with: - args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://msrc.microsoft.com/*,https://www.microsoft.com/msrc*,https://microsoft.com/msrc* - - name: โš™ Install prerequisites - run: | - ./init.ps1 -UpgradePrerequisites - dotnet --info - shell: pwsh - - name: ๐Ÿ“š Verify docfx build - run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures - if: runner.os == 'Linux' diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml deleted file mode 100644 index 53df80ff..00000000 --- a/.github/workflows/libtemplate-update.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: โ›œ Library.Template update - -# PREREQUISITE: This workflow requires the repo to be configured to allow workflows to create pull requests. -# Visit https://github.com/USER/REPO/settings/actions -# Under "Workflow permissions" 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 - permissions: - contents: write - pull-requests: write - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # avoid shallow clone so nbgv can do its work. - - - name: merge - id: merge - shell: pwsh - run: | - $LibTemplateBranch = & ./tools/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 - git diff --stat ...FETCH_HEAD - - if ((git rev-list FETCH_HEAD ^HEAD --count) -eq 0) { - Write-Host "There are no Library.Template updates to merge." - echo "uptodate=true" >> $env:GITHUB_OUTPUT - exit 0 - } - - # Pushing commits that add or change files under .github/workflows will cause our workflow to fail. - # But it usually isn't necessary because the target branch already has (or doesn't have) these changes. - # So if the merge doesn't bring in any changes to these files, try the merge locally and push that - # to keep github happy. - if ((git rev-list FETCH_HEAD ^HEAD --count -- .github/workflows) -eq 0) { - # Indeed there are no changes in that area. So merge locally to try to appease GitHub. - git checkout -b auto/libtemplateUpdate - git config user.name "Andrew Arnott" - git config user.email "andrewarnott@live.com" - git merge FETCH_HEAD - if ($LASTEXITCODE -ne 0) { - Write-Host "Merge conflicts prevent creating the pull request. Please run tools/MergeFrom-Template.ps1 locally and push the result as a pull request." - exit 2 - } - - git -c http.extraheader="AUTHORIZATION: bearer $env:GH_TOKEN" push origin -u HEAD - } else { - Write-Host "Changes to github workflows are included in this update. Please run tools/MergeFrom-Template.ps1 locally and push the result as a pull request." - exit 1 - } - - name: pull request - shell: pwsh - if: success() && steps.merge.outputs.uptodate != 'true' - 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/). - - โš ๏ธ Do **not** squash this pull request when completing it. You must *merge* it. - -
- 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 - ``` -
" - - gh pr create -H auto/libtemplateUpdate -b $prBody -t $prTitle - env: - GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 766ebaf5..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: ๐ŸŽ Release - -on: - release: - types: [published] - workflow_dispatch: - inputs: - ship_run_id: - description: ID of the GitHub workflow run to ship - required: true - -run-name: ${{ github.ref_name }} - -permissions: - actions: read - contents: write - -jobs: - release: - runs-on: ubuntu-24.04 - steps: - - name: โš™๏ธ Initialization - shell: pwsh - run: | - if ('${{ secrets.NUGET_API_KEY }}') { - Write-Host "NUGET_API_KEY secret detected. NuGet packages will be pushed." - echo "NUGET_API_KEY_DEFINED=true" >> $env:GITHUB_ENV - } - - - name: ๐Ÿ”Ž Search for build of ${{ github.ref }} - shell: pwsh - id: findrunid - env: - GH_TOKEN: ${{ github.token }} - run: | - if ('${{ inputs.ship_run_id }}') { - $runid = '${{ inputs.ship_run_id }}' - } else { - $restApiRoot = '/repos/${{ github.repository }}' - - # Resolve the tag reference to a commit sha - $resolvedRef = gh api ` - -H "Accept: application/vnd.github+json" ` - -H "X-GitHub-Api-Version: 2022-11-28" ` - $restApiRoot/git/ref/tags/${{ github.ref_name }} ` - | ConvertFrom-Json - $commitSha = $resolvedRef.object.sha - - Write-Host "Resolved ${{ github.ref_name }} to $commitSha" - - $releases = gh run list -R ${{ github.repository }} -c $commitSha -w .github/workflows/build.yml -s success --json databaseId,startedAt ` - | ConvertFrom-Json | Sort-Object startedAt -Descending - - if ($releases.length -eq 0) { - Write-Error "No successful builds found for ${{ github.ref }}." - } elseif ($releases.length -gt 1) { - Write-Warning "More than one successful run found for ${{ github.ref }}. Artifacts from the most recent successful run will ship." - } - - $runid = $releases[0].databaseId - } - - Write-Host "Using artifacts from run-id: $runid" - - Echo "runid=$runid" >> $env:GITHUB_OUTPUT - - - name: ๐Ÿ”ป Download deployables artifacts - uses: actions/download-artifact@v4 - with: - name: deployables-Linux - path: ${{ runner.temp }}/deployables - run-id: ${{ steps.findrunid.outputs.runid }} - github-token: ${{ github.token }} - - - name: ๐Ÿ’ฝ Upload artifacts to release - shell: pwsh - if: ${{ github.event.release.assets_url }} != '' - env: - GH_TOKEN: ${{ github.token }} - run: | - Get-ChildItem '${{ runner.temp }}/deployables' |% { - Write-Host "Uploading $($_.Name) to release..." - gh release -R ${{ github.repository }} upload "${{ github.ref_name }}" $_.FullName - } - - - name: ๐Ÿš€ Push NuGet packages - run: dotnet nuget push ${{ runner.temp }}/deployables/*.nupkg --source https://api.nuget.org/v3/index.json -k '${{ secrets.NUGET_API_KEY }}' - if: ${{ env.NUGET_API_KEY_DEFINED == 'true' }} From 9601565e5d65b148bc55c316d4b08cee2d151892 Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Thu, 20 Feb 2025 16:34:00 -0800 Subject: [PATCH 104/109] Fixes after updating to xunit v3. --- Directory.Packages.props | 2 +- .../Microsoft.VisualStudio.SolutionPersistence.Tests.csproj | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3aede57b..7c0e7fed 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - +
diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj index 91d2e70f..14bc733c 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj @@ -3,6 +3,7 @@ net8.0 $(TargetFrameworks);net472 + Exe @@ -13,7 +14,7 @@ - + From 7dbc1c5933e459283bcd4d50676754d8a32f6a4f Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Tue, 21 Jan 2025 17:46:14 -0800 Subject: [PATCH 105/109] Improve error message when duplicate project name is detected. --- .../Errors.Designer.cs | 6 +++--- src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx | 4 ++-- .../Model/SolutionModel.cs | 4 +++- .../Serialization/Folders.cs | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs index 1f985ed7..95ecaeaf 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs @@ -115,11 +115,11 @@ internal static string DuplicateName_Args2 { } /// - /// Looks up a localized string similar to Project name '{0}' already exists in the solution folder.. + /// Looks up a localized string similar to Project name '{0}' already exists in the '{1}' solution folder.. /// - internal static string DuplicateProjectName_Arg1 { + internal static string DuplicateProjectName_Arg2 { get { - return ResourceManager.GetString("DuplicateProjectName_Arg1", resourceCulture); + return ResourceManager.GetString("DuplicateProjectName_Arg2", resourceCulture); } } diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx index a3755c1b..fb39ab19 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx @@ -209,8 +209,8 @@ Project path '{0}' already exists in the solution. Error message. {0} is the file path that already exists. - - Project name '{0}' already exists in the solution folder. + + Project name '{0}' already exists in the '{1}' solution folder. Error message. {0} is the name of the folder. diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs index 39d69f68..9ac34f21 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs @@ -588,6 +588,8 @@ internal void ValidateProjectName(SolutionProjectModel project) } string displayName = project.ActualDisplayName; + string folderPath = project.Parent?.Path ?? "Root"; + foreach (SolutionProjectModel existingProject in this.SolutionProjects) { if (!ReferenceEquals(existingProject.Parent, project.Parent) || ReferenceEquals(existingProject, project)) @@ -597,7 +599,7 @@ internal void ValidateProjectName(SolutionProjectModel project) if (existingProject.ActualDisplayName.Equals(displayName, StringComparison.OrdinalIgnoreCase)) { - throw new SolutionArgumentException(string.Format(Errors.DuplicateProjectName_Arg1, displayName), SolutionErrorType.DuplicateProjectName); + throw new SolutionArgumentException(string.Format(Errors.DuplicateProjectName_Arg2, displayName, folderPath), SolutionErrorType.DuplicateProjectName); } } } diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Folders.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Folders.cs index 894a8aa1..a9d72984 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Folders.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Folders.cs @@ -143,7 +143,7 @@ public void MoveProjectToFolder() // Try moving project to folder with existing project ArgumentException ex = Assert.Throws(() => wanderingProject.MoveToFolder(folderA)); - Assert.Equal(string.Format(Errors.DuplicateProjectName_Arg1, wanderingProject.ActualDisplayName), ex.Message); + Assert.Equal(string.Format(Errors.DuplicateProjectName_Arg2, wanderingProject.ActualDisplayName, folderA.Path), ex.Message); Assert.Equal("/This/Is/A/Nested/Folder/", wanderingProject.Parent.ItemRef); // Move project to root From d99bf6f2159439e5eab02bfbb137a3e4c4d59cdc Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Fri, 21 Feb 2025 21:12:32 -0800 Subject: [PATCH 106/109] Reduce dependency version requirement for System.Memory. --- Directory.Packages.props | 2 +- .../Microsoft.VisualStudio.SolutionPersistence.Tests.csproj | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 7c0e7fed..3aede57b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,7 +12,7 @@ - + diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj index 14bc733c..f0663bf9 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Microsoft.VisualStudio.SolutionPersistence.Tests.csproj @@ -15,12 +15,13 @@ + + - From 5ae4f93d15b2aba42c93492a45ba2fd487c86ffc Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Fri, 21 Feb 2025 19:57:04 -0800 Subject: [PATCH 107/109] Preserve legacy behavior when loading sln with duplicate project ids. --- SolutionPersistence.sln | 68 ------------ global.json | 2 +- .../SlnV12/SlnFileV12Serializer.Reader.cs | 54 ++++++++- .../Serialization/Format.cs | 6 - .../Serialization/IdGenerator.cs | 6 - .../Serialization/InvalidSolutions.cs | 104 ++++++++++++++++-- .../Serialization/LegacyValues.cs | 12 -- .../Serialization/MakeSlnx.MakeSlnxFixture.cs | 5 +- .../Serialization/MakeSlnx.cs | 12 -- .../Serialization/ManipulateXmlKitchenSink.cs | 6 - .../Serialization/PathSlashes.cs | 12 -- .../Serialization/Project.cs | 12 -- .../Serialization/RoundTripClassicSln.cs | 6 - .../RoundTripClassicSlnThruSlnxStream.cs | 6 - .../Serialization/RoundTripXmlSlnx.cs | 6 - .../RoundTripXmlSlnxThruModelCopy.cs | 12 -- .../Serialization/Samples.cs | 6 - .../DuplicateProjectId-After.sln.txt | 30 +++++ .../SlnAssets/Invalid/DuplicateItemId.sln.txt | 26 +++++ .../Invalid/DuplicateProjectId.sln.txt | 30 +++++ .../Invalid/DuplicateProjectId.slnx.xml | 9 ++ .../Invalid/InvalidProjectType.sln.txt | 18 +++ .../Utilities/SlnAssets.cs | 4 +- .../Utilities/SlnTestHelper.cs | 9 -- 24 files changed, 262 insertions(+), 199 deletions(-) delete mode 100644 SolutionPersistence.sln create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/DuplicateProjectId-After.sln.txt create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateItemId.sln.txt create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.sln.txt create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.slnx.xml create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/InvalidProjectType.sln.txt diff --git a/SolutionPersistence.sln b/SolutionPersistence.sln deleted file mode 100644 index 1c61458e..00000000 --- a/SolutionPersistence.sln +++ /dev/null @@ -1,68 +0,0 @@ -๏ปฟ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29322.22 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1CE9670B-D5FF-46A7-9D00-24E70E6ED48B}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - Directory.Packages.props = Directory.Packages.props - global.json = global.json - nuget.config = nuget.config - README.md = README.md - stylecop.json = stylecop.json - version.json = version.json - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9E154A29-1796-4B85-BD81-B6A385D8FF71}" - ProjectSection(SolutionItems) = preProject - src\.editorconfig = src\.editorconfig - src\Directory.Build.props = src\Directory.Build.props - src\Directory.Build.targets = src\Directory.Build.targets - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{36CCE840-6FE5-4DB9-A8D5-8CF3CB6D342A}" - ProjectSection(SolutionItems) = preProject - test\.editorconfig = test\.editorconfig - test\Directory.Build.props = test\Directory.Build.props - test\Directory.Build.targets = test\Directory.Build.targets - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7743A30D-6296-44C3-B8FB-369D37566D94}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SolutionPersistence", "src\Microsoft.VisualStudio.SolutionPersistence\Microsoft.VisualStudio.SolutionPersistence.csproj", "{43507C4F-E739-426F-8070-5260D668C3D9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{1EBF1959-C483-46AC-ADB6-5D5A72544EDF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.SolutionPersistence.Tests", "test\Microsoft.VisualStudio.SolutionPersistence.Tests\Microsoft.VisualStudio.SolutionPersistence.Tests.csproj", "{9D224F03-C60B-49D5-84D9-FAF6913EFB9E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {43507C4F-E739-426F-8070-5260D668C3D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43507C4F-E739-426F-8070-5260D668C3D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43507C4F-E739-426F-8070-5260D668C3D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43507C4F-E739-426F-8070-5260D668C3D9}.Release|Any CPU.Build.0 = Release|Any CPU - {9D224F03-C60B-49D5-84D9-FAF6913EFB9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9D224F03-C60B-49D5-84D9-FAF6913EFB9E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9D224F03-C60B-49D5-84D9-FAF6913EFB9E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9D224F03-C60B-49D5-84D9-FAF6913EFB9E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {9E154A29-1796-4B85-BD81-B6A385D8FF71} = {1CE9670B-D5FF-46A7-9D00-24E70E6ED48B} - {36CCE840-6FE5-4DB9-A8D5-8CF3CB6D342A} = {1CE9670B-D5FF-46A7-9D00-24E70E6ED48B} - {43507C4F-E739-426F-8070-5260D668C3D9} = {7743A30D-6296-44C3-B8FB-369D37566D94} - {9D224F03-C60B-49D5-84D9-FAF6913EFB9E} = {1EBF1959-C483-46AC-ADB6-5D5A72544EDF} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E3944F6A-384B-4B0F-B93F-3BD513DC57BD} - EndGlobalSection -EndGlobal diff --git a/global.json b/global.json index 20b589f8..6306f36b 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.102", + "version": "9.0.200", "rollForward": "patch", "allowPrerelease": false }, diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs index ed558a64..be070214 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs @@ -69,6 +69,11 @@ internal ValueTask ParseAsync(ISolutionSerializer serializer, str // Some property bags need to be loaded after all projects have been resolved. List<(SolutionItemModel, SolutionPropertyBag)> delayLoadProperties = []; + // Keep track of projects with duplicate ids so that we can + // duplicate the configuration after all projects have been loaded. + // This preserves the orginial buggy behavior of the solution parser. + List<(Guid NewId, SolutionProjectModel DuplicateProject)> fixedProjectIds = []; + try { using (solutionModel.SuspendProjectValidation()) @@ -87,7 +92,7 @@ internal ValueTask ParseAsync(ISolutionSerializer serializer, str case LineType.Project: this.TarnishIf(inProject); inProject = true; - currentProject = this.ReadProjectInfo(solutionModel, ref tokenizer); + currentProject = this.ReadProjectInfo(solutionModel, ref tokenizer, fixedProjectIds); break; case LineType.EndProject: @@ -200,6 +205,17 @@ internal ValueTask ParseAsync(ISolutionSerializer serializer, str this.TarnishIf(!item.AddSlnProperties(properties)); } + foreach ((Guid newId, SolutionProjectModel duplicateProject) in fixedProjectIds) + { + // The newly generated id will not have configurations, so make a + // copy of the original project configurations. + // This preserves the orginial buggy behavior of the solution parser. + if (solutionModel.FindItemById(newId) is SolutionProjectModel project) + { + project.ProjectConfigurationRules = duplicateProject.ProjectConfigurationRules; + } + } + VisualStudioProperties vsProperties = solutionModel.VisualStudioProperties; vsProperties.OpenWith = CommentToOpenWithVS(openWithVsVersion.AsSpan()); vsProperties.MinimumVersion = minVsVersion; @@ -218,6 +234,9 @@ internal ValueTask ParseAsync(ISolutionSerializer serializer, str return new ValueTask(solutionModel); + // Adds the property bag to the project or folder. + // Handles special cases for the sln parser. + // Returns false if there was an error reading the properties and the solution file should be considered tarnished. static bool AddProjectProperties( SolutionItemModel? currentProject, SolutionPropertyBag? currentPropertyBag, @@ -498,7 +517,7 @@ private bool ReadLine(out StringTokenizer lineScanner) return checkOnly ? null : new SolutionPropertyBag(sectionName.ToString(), scope); } - private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringTokenizer tokenizer) + private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringTokenizer tokenizer, List<(Guid NewId, SolutionProjectModel DuplicateProject)> fixedProjectIds) { // Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App1", "App1\App1.csproj", "{B0D4AB54-EB86-4C88-A2A4-C55D0C200244}" // ^ <- this is tokenizer pos. @@ -527,6 +546,8 @@ private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringToke this.SolutionAssert(!projectUniqueId.IsEmpty, Errors.MissingProjectId); this.TarnishIf(!Guid.TryParse(projectUniqueId.ToString(), out Guid projectId)); + SolutionItemModel? duplicateItem = solution.FindItemById(projectId); + if (projectTypeId == ProjectTypeTable.SolutionFolder) { #pragma warning disable CS0618 // Type or member is obsolete (Temporaily create a potentially invalid solution folder until nested projects is interpreted.) @@ -534,7 +555,7 @@ private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringToke #pragma warning restore CS0618 // Type or member is obsolete // Solution folders with duplicate ids should not error when reading sln files to preserve legacy behavior. - if (solution.FindItemById(projectId) is not null) + if (duplicateItem is not null) { projectId = Guid.NewGuid(); this.tarnished = true; @@ -545,9 +566,27 @@ private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringToke } else { + string path = PathExtensions.ConvertBackslashToModel(relativePath.ToString()); + + // This should error, or remove any configuration associated with the duplicate id. + // However some old parsers would just ignore the duplicate id and continue. + if (duplicateItem is SolutionFolderModel duplicateFolder) + { + duplicateFolder.Id = Guid.NewGuid(); + this.tarnished = true; + } + else if (duplicateItem is SolutionProjectModel duplicateProject) + { + projectId = CreateNewProjectId(solution, path); + this.tarnished = true; + + // Record the new project id so it's configuration can be duplicated. + fixedProjectIds.Add((projectId, duplicateProject)); + } + #pragma warning disable CS0618 // Type or member is obsolete (Temporaily create a potentially invalid solution folder until nested projects is interpreted.) SolutionProjectModel project = solution.AddSlnProject( - filePath: PathExtensions.ConvertBackslashToModel(relativePath.ToString()), + filePath: path, projectTypeId: projectTypeId, folder: null); #pragma warning restore CS0618 // Type or member is obsolete @@ -555,6 +594,13 @@ private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringToke project.DisplayName = displayName.ToString(); return project; } + + // If creating a new project id, go ahead and try to use the slnx default id. + static Guid CreateNewProjectId(SolutionModel solution, string path) + { + Guid id = DefaultIdGenerator.CreateIdFrom(path); + return solution.FindItemById(id) is null ? id : Guid.NewGuid(); + } } // Condition that would mark solution file as "tarnished" diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Format.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Format.cs index 93cbf323..911d3ff2 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Format.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Format.cs @@ -14,12 +14,6 @@ public class Format [Fact] public async Task ConvertASCIItoUTF8Async() { - if (IsMono) - { - // Mono is not supported. - return; - } - const string asciiFolderName = "directory123"; const string utf8FolderName = "rรฉpertoire123"; diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/IdGenerator.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/IdGenerator.cs index a382ba22..ccf0133a 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/IdGenerator.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/IdGenerator.cs @@ -77,12 +77,6 @@ public void CheckGeneratedIds() [Fact] public async Task CheckModelIds() { - if (IsMono) - { - // Mono is not supported. - return; - } - SolutionModel solution = await SolutionSerializers.SlnXml.OpenAsync(SlnAssets.XmlSlnxMany.Stream, CancellationToken.None); SolutionProjectModel? urlProject = solution.FindProject("http://localhost:8080"); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs index b5fc7a13..6a36ff37 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs @@ -29,12 +29,6 @@ public Task InvalidXmlSlnxAsync() [Fact] public async Task InvalidSlnxAsync() { - if (IsMono) - { - // Mono is not supported. - return; - } - ResourceStream wrongRoot = SlnAssets.LoadResource("Invalid/WrongRoot.slnx"); string wrongRootFile = wrongRoot.SaveResourceToTempFile(); @@ -55,12 +49,6 @@ public async Task InvalidSlnxAsync() [Fact] public async Task InvalidSlnAsync() { - if (IsMono) - { - // Mono is not supported. - return; - } - ResourceStream invalidSln = SlnAssets.LoadResource("Invalid/Invalid.sln"); string invalidSlnFile = invalidSln.SaveResourceToTempFile(); @@ -239,4 +227,96 @@ public async Task DuplicateFolderIdSlnxAsync() Assert.Equal(3, ex.Line); Assert.Equal(4, ex.Column); } + + /// + /// Ensure the slnx parser does fail if project id collides with folder id. + /// Expected behavior is the folder id is changed to a new value. + /// + [Fact] + public async Task DuplicateItemIdSlnAsync() + { + ResourceStream duplicateId = SlnAssets.LoadResource("Invalid/DuplicateItemId.sln"); + SolutionModel solution = await SolutionSerializers.SlnFileV12.OpenAsync(duplicateId.Stream, CancellationToken.None); + Assert.NotNull(solution.SerializerExtension); + Assert.True(solution.SerializerExtension.Tarnished); + + SolutionProjectModel? projectModel = solution.FindProject("DuplicateProjectId.csproj"); + Assert.NotNull(projectModel); + Assert.Equal(projectModel.Id, new Guid("11111111-1111-1111-1111-111111111111")); + + SolutionFolderModel? folderModel = solution.FindFolder("/DuplicateFolderId/"); + Assert.NotNull(folderModel); + Assert.NotEqual(folderModel.Id, new Guid("11111111-1111-1111-1111-111111111111")); + } + + /// + /// Recreate legacy bug behavior when duplicate project id guids are found in .sln files. + /// Use corrupt configuration and change second project id to new value. + /// + [Fact] + public async Task DuplicateProjectIdSlnAsync() + { + ResourceStream duplicateId = SlnAssets.LoadResource("Invalid/DuplicateProjectId.sln"); + SolutionModel solution = await SolutionSerializers.SlnFileV12.OpenAsync(duplicateId.Stream, CancellationToken.None); + Assert.NotNull(solution.SerializerExtension); + Assert.True(solution.SerializerExtension.Tarnished); + + SolutionProjectModel? project = solution.FindProject("DuplicateProjectId.csproj"); + Assert.NotNull(project); + Assert.Equal(project.Id, new Guid("8BADBEEF-1111-2222-3333-444444444444")); + + SolutionProjectModel? project2 = solution.FindProject("DuplicateProjectIdOpposite.csproj"); + Assert.NotNull(project2); + Assert.NotEqual(project2.Id, new Guid("8BADBEEF-2222-3333-4444-555555555555")); + + (string? buildType, string? platform, bool build, bool deploy) = project.GetProjectConfiguration(BuildTypeNames.Debug, PlatformNames.AnySpaceCPU); + + (string? buildType2, string? platform2, bool build2, bool deploy2) = project2.GetProjectConfiguration(BuildTypeNames.Debug, PlatformNames.AnySpaceCPU); + + // The configuration from the "opposite" project should be used by both as it appears last in the file. + Assert.Equal(BuildTypeNames.Release, buildType); + Assert.Equal(PlatformNames.AnySpaceCPU, platform); + Assert.True(build); + Assert.False(deploy); + + // The configuration from the "opposite" project should be used by both as it appears last in the file. + Assert.Equal(BuildTypeNames.Release, buildType2); + Assert.Equal(PlatformNames.AnySpaceCPU, platform2); + Assert.True(build2); + Assert.False(deploy2); + + // Compare the new model to the 'After' sln (Change the new Guid to FFFF to match). + project2.Id = new Guid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"); + ResourceStream duplicateIdAfter = SlnAssets.LoadResource("DuplicateProjectId-After.sln"); + AssertSolutionsAreEqual(duplicateIdAfter.ToLines(), await solution.ToLinesAsync(SolutionSerializers.SlnFileV12)); + } + + /// + /// Ensure the slnx parser does fail on duplicate project guids. + /// + [Fact] + public async Task DuplicateProjectIdSlnxAsync() + { + ResourceStream duplicateId = SlnAssets.LoadResource("Invalid/DuplicateProjectId.slnx"); + SolutionException ex = await Assert.ThrowsAsync( + async () => _ = await SolutionSerializers.SlnXml.OpenAsync(duplicateId.Stream, CancellationToken.None)); + + Assert.StartsWith(string.Format(Errors.DuplicateItemRef_Args2, "8badbeef-1111-2222-3333-444444444444", nameof(SolutionProjectModel)), ex.Message); + Assert.Equal(5, ex.Line); + Assert.Equal(6, ex.Column); + } + + /// + /// Checks that an error is thrown if the solution contains an invalid project type id. + /// + [Fact] + public async Task InvalidProjectTypeSlnAsync() + { + ResourceStream invalidProjectType = SlnAssets.LoadResource("Invalid/InvalidProjectType.sln"); + SolutionException ex = await Assert.ThrowsAsync( + async () => _ = await SolutionSerializers.SlnFileV12.OpenAsync(invalidProjectType.Stream, CancellationToken.None)); + Assert.StartsWith(Errors.InvalidProjectType, ex.Message); + Assert.Equal(5, ex.Line); + Assert.Null(ex.Column); + } } diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/LegacyValues.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/LegacyValues.cs index d1298411..87624b4b 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/LegacyValues.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/LegacyValues.cs @@ -40,12 +40,6 @@ public async Task TrimVisualStudioPropertiesAsync() [Fact] public async Task IgnoreDisplayNameSlnx() { - if (IsMono) - { - // Mono is not supported. - return; - } - await ValidateModifiedSolutionAsync(CreateModifiedModel, SlnAssets.XmlSlnxSingleNativeProject, SlnAssets.XmlSlnxSingleNativeProject); static void CreateModifiedModel(SolutionModel solution) @@ -64,12 +58,6 @@ static void CreateModifiedModel(SolutionModel solution) [Fact] public async Task IgnoreDisplayNameSln() { - if (IsMono) - { - // Mono is not supported. - return; - } - await ValidateModifiedSolutionAsync(CreateModifiedModel, SlnAssets.ClassicSlnSingleNativeProject, SlnAssets.ClassicSlnSingleNativeProject, SolutionSerializers.SlnFileV12); static void CreateModifiedModel(SolutionModel solution) diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.MakeSlnxFixture.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.MakeSlnxFixture.cs index e145774e..80c6ce15 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.MakeSlnxFixture.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.MakeSlnxFixture.cs @@ -24,7 +24,10 @@ public class MakeSlnxFixture /// public MakeSlnxFixture() { - string outputDirectory = Path.Combine(Path.GetTempPath(), OutputDirectory); + // Split output based on the .NET version (so we can run tests in parallel) + string netVersion = "net" + Environment.Version.ToString(3); + + string outputDirectory = Path.Combine(Path.GetTempPath(), OutputDirectory, netVersion); if (Directory.Exists(outputDirectory)) { Directory.Delete(outputDirectory, true); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.cs index e3a3cf77..efa18630 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/MakeSlnx.cs @@ -32,12 +32,6 @@ public sealed partial class MakeSlnx(MakeSlnx.MakeSlnxFixture fixture) : IClassF [Trait("TestCategory", "FailsInCloudTest")] public async Task ConvertSlnToSlnxAsync(ResourceName slnFileName) { - if (IsMono) - { - // Mono is not supported. - return; - } - ResourceStream slnFile = slnFileName.Load(); int sampleFileSize = checked((int)slnFile.Stream.Length); string slnToSlnxFile = Path.ChangeExtension(Path.Join(fixture.SlnToSlnxDirectory, slnFile.Name), SolutionSerializers.SlnXml.DefaultFileExtension); @@ -65,12 +59,6 @@ public async Task ConvertSlnToSlnxAsync(ResourceName slnFileName) [Trait("TestCategory", "FailsInCloudTest")] public async Task ConvertSlnxToSlnAsync(ResourceName slnxFileName) { - if (IsMono) - { - // Mono is not supported. - return; - } - ResourceStream slnxFile = slnxFileName.Load(); string slnxToSlnFile = Path.ChangeExtension(Path.Join(fixture.SlnxToSlnDirectory, slnxFile.Name), SolutionSerializers.SlnFileV12.DefaultFileExtension); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/ManipulateXmlKitchenSink.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/ManipulateXmlKitchenSink.cs index b3fdd143..7d63791f 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/ManipulateXmlKitchenSink.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/ManipulateXmlKitchenSink.cs @@ -20,12 +20,6 @@ public class ManipulateXmlKitchenSink [Fact] public async Task AddConfigurations() { - if (IsMono) - { - // Mono is not supported. - return; - } - await ValidateModifiedSolutionAsync( CreateModifiedModel, SlnAssets.LoadResource("SlnxWhitespace/KitchenSink.slnx"), diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/PathSlashes.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/PathSlashes.cs index 2bd2c228..3a604976 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/PathSlashes.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/PathSlashes.cs @@ -17,12 +17,6 @@ public sealed class PathSlashes [Fact] public async Task VerifyModelSlahesAsync() { - if (IsMono) - { - // Mono is not supported. - return; - } - ResourceStream slashesResource = SlnAssets.LoadResource("Invalid/PathSlashes.slnx"); SolutionModel solution = await SolutionSerializers.SlnXml.OpenAsync(slashesResource.Stream, CancellationToken.None); @@ -64,12 +58,6 @@ public async Task VerifyModelSlahesAsync() [Fact] public async Task ProjectReferencesFixedUpAsync() { - if (IsMono) - { - // Mono is not supported. - return; - } - FileContents fixedSlashesResource = SlnAssets.LoadResource("PathSlashes.slnx").ToLines(); // Save the Model back to stream. diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Project.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Project.cs index d63dc4ee..d8b624b2 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Project.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Project.cs @@ -58,12 +58,6 @@ public void AddProject() [Fact] public async Task RemoveProjectAsync() { - if (IsMono) - { - // Mono is not supported. - return; - } - SolutionModel solution = await SolutionSerializers.SlnXml.OpenAsync(SlnAssets.XmlSlnxEverything.Stream, CancellationToken.None); string toRemove = Path.Join("src", "CoreMauiApp", "CoreMauiApp.csproj"); @@ -84,12 +78,6 @@ public async Task RemoveProjectAsync() [Fact] public async Task MoveProjectAsync() { - if (IsMono) - { - // Mono is not supported. - return; - } - SolutionModel solution = await SolutionSerializers.SlnXml.OpenAsync(SlnAssets.XmlSlnxEverything.Stream, CancellationToken.None); string toMove = Path.Join("BlazorApp1", "BlazorApp1.csproj"); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs index 5e6c80f4..5c495e30 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs @@ -56,12 +56,6 @@ public Task AllClassicSolutionAsync(ResourceName sampleFile) /// Task to track the asynchronous call status. private static async Task TestRoundTripSerializerAsync(ResourceStream slnStream) { - if (IsMono) - { - // Mono is not supported. - return; - } - FileContents originalSolution = slnStream.ToLines(); // Open the Model from stream. diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs index dc44b54f..4580cd11 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs @@ -46,12 +46,6 @@ private static async Task TestRoundTripSerializerAsync( ResourceStream slnStream, ResourceStream viaSlnxStream) { - if (IsMono) - { - // Mono is not supported. - return; - } - FileContents originalSolution = slnStream.ToLines(); // Open the Model from stream. diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs index 2b86b671..6a588175 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs @@ -60,12 +60,6 @@ public Task AllXmlSolutionAsync(ResourceName sampleFile) private static async Task TestRoundTripSerializerAsync(ResourceStream slnStream) { - if (IsMono) - { - // Mono is not supported. - return; - } - // Open the Model from stream. SolutionModel model = await SolutionSerializers.SlnXml.OpenAsync(slnStream.Stream, CancellationToken.None); AssertNotTarnished(model); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs index 24987ff0..1f79e3e3 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs @@ -16,12 +16,6 @@ public class RoundTripXmlSlnxThruModelCopy [Fact] public Task CommentsAsync() { - if (IsMono) - { - // Mono is not supported. - return Task.CompletedTask; - } - return Assert.ThrowsAsync(() => TestRoundTripSerializerAsync(SlnAssets.XmlSlnxComments)); } @@ -57,12 +51,6 @@ public Task CommentsAsync() private static async Task TestRoundTripSerializerAsync(ResourceStream slnStream) { - if (IsMono) - { - // Mono is not supported. - return; - } - // Open the Model from stream. SolutionModel model = await SolutionSerializers.SlnXml.OpenAsync(slnStream.Stream, CancellationToken.None); AssertNotTarnished(model); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Samples.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Samples.cs index 061ff31b..a8d08974 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Samples.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/Samples.cs @@ -14,12 +14,6 @@ public class Samples [Fact] public async Task ConvertToSlnx() { - if (IsMono) - { - // Mono is not supported. - return; - } - string filePath = SlnAssets.ClassicSlnEverything.SaveResourceToTempFile(); string slnxFilePath = Path.ChangeExtension(filePath, SolutionSerializers.SlnXml.DefaultFileExtension); diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/DuplicateProjectId-After.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/DuplicateProjectId-After.sln.txt new file mode 100644 index 00000000..c8584a59 --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/DuplicateProjectId-After.sln.txt @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35819.311 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicateProjectId", "DuplicateProjectId.csproj", "{8BADBEEF-1111-2222-3333-444444444444}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicateProjectIdOpposite", "DuplicateProjectIdOpposite.csproj", "{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8BADBEEF-1111-2222-3333-444444444444}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Debug|Any CPU.Build.0 = Release|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Release|Any CPU.Build.0 = Debug|Any CPU + {FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}.Debug|Any CPU.Build.0 = Release|Any CPU + {FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}.Release|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E0F1003A-31EB-42B8-8684-F82D4D7B9108} + EndGlobalSection +EndGlobal diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateItemId.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateItemId.sln.txt new file mode 100644 index 00000000..a7af068b --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateItemId.sln.txt @@ -0,0 +1,26 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35819.311 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DuplicateFolderId", "DuplicateFolderId", "{11111111-1111-1111-1111-111111111111}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicateProjectId", "DuplicateProjectId.csproj", "{11111111-1111-1111-1111-111111111111}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {11111111-1111-1111-1111-111111111111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11111111-1111-1111-1111-111111111111}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11111111-1111-1111-1111-111111111111}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11111111-1111-1111-1111-111111111111}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E0F1003A-31EB-42B8-8684-F82D4D7B9108} + EndGlobalSection +EndGlobal diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.sln.txt new file mode 100644 index 00000000..0ce6ccc5 --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.sln.txt @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35819.311 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicateProjectId", "DuplicateProjectId.csproj", "{8BADBEEF-1111-2222-3333-444444444444}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DuplicateProjectIdOpposite", "DuplicateProjectIdOpposite.csproj", "{8BADBEEF-1111-2222-3333-444444444444}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8BADBEEF-1111-2222-3333-444444444444}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Release|Any CPU.Build.0 = Release|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Debug|Any CPU.Build.0 = Release|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {8BADBEEF-1111-2222-3333-444444444444}.Release|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E0F1003A-31EB-42B8-8684-F82D4D7B9108} + EndGlobalSection +EndGlobal diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.slnx.xml b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.slnx.xml new file mode 100644 index 00000000..5f6baea4 --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/DuplicateProjectId.slnx.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/InvalidProjectType.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/InvalidProjectType.sln.txt new file mode 100644 index 00000000..0d26d91d --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Invalid/InvalidProjectType.sln.txt @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35819.311 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("NotAGuid") = "InvalidProjectType", "InvalidProjectType.csproj", "{8A1FD751-4BAA-467E-A9FA-77239CA44A61}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CFB61351-9264-45B3-BBE0-BAC5D49C87CE} + EndGlobalSection +EndGlobal diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnAssets.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnAssets.cs index 9aef8f25..093f5ad5 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnAssets.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnAssets.cs @@ -13,6 +13,8 @@ internal static class SlnAssets public static ResourceName[] ClassicSlnFiles => GetAllSampleFiles(".sln").ToArray(); + public static ResourceName[] XmlSlnxFiles => GetAllSampleFiles(".slnx").ToArray(); + #region Sample Classic Sln // Empty VS Solution template. ASCII encoding. @@ -97,8 +99,6 @@ internal static class SlnAssets // A solution with missing configurations. public static ResourceStream XmlSlnxMissingConfigurations => LoadResource("Configurations/MissingConfigurations.slnx"); - public static ResourceName[] XmlSlnxFiles => GetAllSampleFiles(".slnx").ToArray(); - #endregion #region Test result Slnx diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnTestHelper.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnTestHelper.cs index ec1d182e..5497e8ae 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnTestHelper.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Utilities/SlnTestHelper.cs @@ -11,15 +11,6 @@ namespace Utilities; /// internal static class SlnTestHelper { - /// - /// We do not support mono, but xunit testing tries to run the .NET Framework tests on mono when running on Linux/Mac. - /// -#if NETFRAMEWORK - internal static bool IsMono = Environment.OSVersion.Platform != PlatformID.Win32NT; -#else - internal static bool IsMono = false; -#endif - /// /// Converts the model to it's file contents using the specified serializer. /// From 872e8e848d35f38aab5075bb7c7c701237bb9cd6 Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Fri, 28 Feb 2025 12:58:40 -0800 Subject: [PATCH 108/109] Don't report error reading invalid project type guid in .sln files. --- .../Errors.Designer.cs | 9 --------- .../Errors.resx | 4 ---- .../SlnV12/SlnFileV12Serializer.Reader.cs | 6 +++++- .../Serialization/InvalidSolutions.cs | 15 +++++++++------ 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs index 95ecaeaf..d4a76b4d 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.Designer.cs @@ -226,15 +226,6 @@ internal static string InvalidProjectReference_Args1 { } } - /// - /// Looks up a localized string similar to Missing or invalid project type guid.. - /// - internal static string InvalidProjectType { - get { - return ResourceManager.GetString("InvalidProjectType", resourceCulture); - } - } - /// /// Looks up a localized string similar to ProjectType '{0}' not found.. /// diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx index fb39ab19..9b902f9e 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Errors.resx @@ -129,10 +129,6 @@ Missing or invalid scope. Error message - - Missing or invalid project type guid. - Error message - Syntax error. Error message diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs index be070214..9643bfab 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnFileV12Serializer.Reader.cs @@ -525,7 +525,11 @@ private SolutionItemModel ReadProjectInfo(SolutionModel solution, ref StringToke StringSpan projectType = tokenizer.NextToken(SlnConstants.ProjectSeparators); // but it must end with [sep]) ... checked later. - this.SolutionAssert(Guid.TryParse(projectType.ToString(), out Guid projectTypeId), Errors.InvalidProjectType); + if (!Guid.TryParse(projectType.ToString(), out Guid projectTypeId)) + { + projectTypeId = Guid.Empty; + this.tarnished = true; + } // this just skips up to Display's name "App1" first quote, position at 'A". The TrimStart is extension to allow spaces before ')'; // and yes, any characters are allowed for example // Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App1", valid bad format :P "App1\App1.csproj", diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs index 6a36ff37..39a344a9 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/InvalidSolutions.cs @@ -307,16 +307,19 @@ public async Task DuplicateProjectIdSlnxAsync() } /// - /// Checks that an error is thrown if the solution contains an invalid project type id. + /// Verifies that a malformed project type id is loaded as an empty guid without errors, and + /// the solution is marked as tarnished. /// [Fact] public async Task InvalidProjectTypeSlnAsync() { ResourceStream invalidProjectType = SlnAssets.LoadResource("Invalid/InvalidProjectType.sln"); - SolutionException ex = await Assert.ThrowsAsync( - async () => _ = await SolutionSerializers.SlnFileV12.OpenAsync(invalidProjectType.Stream, CancellationToken.None)); - Assert.StartsWith(Errors.InvalidProjectType, ex.Message); - Assert.Equal(5, ex.Line); - Assert.Null(ex.Column); + SolutionModel solution = await SolutionSerializers.SlnFileV12.OpenAsync(invalidProjectType.Stream, CancellationToken.None); + Assert.NotNull(solution.SerializerExtension); + Assert.True(solution.SerializerExtension.Tarnished); + + SolutionProjectModel? project = solution.FindProject("InvalidProjectType.csproj"); + Assert.NotNull(project); + Assert.Equal(Guid.Empty, project.TypeId); } } From 6c4ef88828f0c17febae588353653075d244cc8a Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Fri, 28 Feb 2025 14:52:01 -0800 Subject: [PATCH 109/109] Support for project types with no platforms. --- .../Model/ConfigurationRuleFollower.cs | 2 +- .../Model/ModelHelper.cs | 5 ++ .../Model/PlatformNames.cs | 8 +++ .../Model/ProjectType.cs | 6 +-- .../Model/ProjectTypeTable.BuiltInTypes.cs | 3 ++ .../Model/StringTable.cs | 6 +++ .../Serializer/SlnV12/SlnV12Extensions.cs | 25 +++++---- .../Serializer/Xml/Keywords.cs | 4 ++ .../Serializer/Xml/Slnx.xsd | 9 ++-- .../Serializer/Xml/SlnxSerializerSettings.cs | 4 +- .../Serializer/Xml/XmlDecorators/SlnxFile.cs | 2 +- .../XmlDecorators/XmlContainer.ApplyModel.cs | 2 +- .../Xml/XmlDecorators/XmlContainer.cs | 2 +- .../Xml/XmlDecorators/XmlProjectType.cs | 52 ++++++++++++++++++- .../Serialization/RoundTripClassicSln.cs | 3 ++ .../RoundTripClassicSlnThruSlnxStream.cs | 3 ++ .../Serialization/RoundTripXmlSlnx.cs | 3 ++ .../RoundTripXmlSlnxThruModelCopy.cs | 3 ++ .../Serialization/StringTests.cs | 38 ++++++++++++-- .../BuiltInProjectTypes.slnx.xml | 1 + .../MissingConfigurations.sln.txt | 2 +- .../SlnAssets/Report Project.sln.txt | 30 +++++++++++ .../SlnAssets/Report Project.slnx.xml | 12 +++++ 23 files changed, 194 insertions(+), 31 deletions(-) create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.sln.txt create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.slnx.xml diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/ConfigurationRuleFollower.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/ConfigurationRuleFollower.cs index 6d65615a..cf13facd 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/ConfigurationRuleFollower.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/ConfigurationRuleFollower.cs @@ -30,7 +30,7 @@ internal readonly ref struct ConfigurationRuleFollower(IReadOnlyList All, Missing => Missing, + Default => Default, + AnyCPU => AnyCPU, AnySpaceCPU => AnySpaceCPU, Win32 => Win32, x64 => x64, diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectType.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectType.cs index c4ac27aa..dfbb3d13 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectType.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectType.cs @@ -32,7 +32,7 @@ public sealed class ProjectType(Guid projectTypeId, IReadOnlyList /// - /// If a project type should not build, it should have a single rule with Build set to false. + /// If a project type should not build, it should have a single rule with Build set to . /// public IReadOnlyList ConfigurationRules { get; } = rules; @@ -51,8 +51,8 @@ public sealed class ProjectType(Guid projectTypeId, IReadOnlyList - /// Gets references a base project type to inherit its configuration rules and project type id. - /// This uses the Name or Extension of the base project type to find it. + /// Gets a references to a base project type to inherit its configuration rules and project type id. + /// This uses the or of the base project type to find it. /// public string? BasedOn { get; init; } } diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectTypeTable.BuiltInTypes.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectTypeTable.BuiltInTypes.cs index 4f58937e..fc66fc31 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectTypeTable.BuiltInTypes.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/ProjectTypeTable.BuiltInTypes.cs @@ -8,6 +8,8 @@ internal sealed partial class ProjectTypeTable { internal static readonly ConfigurationRule[] NoBuildRules = [ModelHelper.CreateNoBuildRule()]; + internal static readonly ConfigurationRule NoPlatformsRule = ModelHelper.CreateNoPlatformsRule(); + internal static readonly Guid VCXProj = new Guid("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"); internal static readonly Guid SolutionFolder = new Guid("2150E333-8FDC-42A3-9474-1A3956D46DE8"); @@ -87,6 +89,7 @@ internal sealed partial class ProjectTypeTable new ProjectType(new Guid("00D1A9C2-B5F0-4AF3-8072-F6C62B433612"), NoBuildRules) { Name = "SQL", Extension = ".sqlproj" }, new ProjectType(new Guid("0C603C2C-620A-423B-A800-4F3E2F6281F1"), NoBuildRules) { Name = "U-SQL-DB", Extension = ".usqldbproj" }, new ProjectType(new Guid("182E2583-ECAD-465B-BB50-91101D7C24CE"), NoBuildRules) { Name = "U-SQL", Extension = ".usqlproj" }, + new ProjectType(new Guid("F14B399A-7131-4C87-9E4B-1186C45EF12D"), [NoPlatformsRule]) { Name = "SSRS", Extension = ".rptproj" }, // Azure project types new ProjectType(new Guid("A07B5EB6-E848-4116-A8D0-A826331D98C6"), NoBuildRules) { Name = "Fabric", Extension = ".sfproj" }, diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/StringTable.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/StringTable.cs index b2aa68cb..bfcdadbe 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/StringTable.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/StringTable.cs @@ -69,4 +69,10 @@ internal void AddString(string str) { _ = this.GetString(str); } + + // Used to test the string table. + internal bool Contains(string str) + { + return this.strings.Contains(str); + } } diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnV12Extensions.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnV12Extensions.cs index 055f2b5e..fd58f775 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnV12Extensions.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/SlnV12/SlnV12Extensions.cs @@ -253,9 +253,10 @@ static void SetProjectConfigurationPlatforms(SolutionModel solution, SolutionPro project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.BuildType, buildType, platform, BuildTypeNames.Missing)); project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.Platform, buildType, platform, PlatformNames.Missing)); - // In the old .sln file the default configuration is not to build unless there is a build line. - // This rule will get overwritten by the build line if it exists. + // In the old .sln file the default configuration is not to build/deploy unless there is a build/deploy line. + // This rule will get overwritten by the build/deploy line if it exists. project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.Build, buildType, platform, bool.FalseString)); + project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.Deploy, buildType, platform, bool.FalseString)); } } } @@ -336,6 +337,11 @@ void ParseProjectConfigLine(SolutionModel solutionModel, string name, string val projectModel.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.BuildType, solutionBuildType, solutionPlatform, projectBuildType)); projectModel.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.Platform, solutionBuildType, solutionPlatform, projectPlatform)); } + else if (!value.IsNullOrEmpty()) + { + // If the project configuration does not have a platform, just set the build type. + projectModel.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.BuildType, solutionBuildType, solutionPlatform, value)); + } break; case ConfigLineType.Build: @@ -454,18 +460,15 @@ not SectionName.ExtensibilityGlobals and continue; } - bool isMissing = mapping.BuildType == BuildTypeNames.Missing || mapping.Platform == PlatformNames.Missing; - // Default project mapping in SLN was to use "Any CPU" - string platform = mapping.Platform; - if (platform == PlatformNames.AnyCPU) - { - platform = PlatformNames.AnySpaceCPU; - } + string platform = + mapping.Platform == PlatformNames.AnyCPU ? PlatformNames.AnySpaceCPU : + mapping.Platform; - string prjCfgPlatString = $"{mapping.BuildType}|{platform}"; + // If just the platform is missing, the project doesn't support platforms and only the build type should be written. + string prjCfgPlatString = platform == PlatformNames.Missing ? mapping.BuildType : $"{mapping.BuildType}|{platform}"; - if (!isMissing) + if (mapping.BuildType != BuildTypeNames.Missing) { WriteProperty(propertyBag, projectId, entry.SlnKey, ActiveCfgSuffix, prjCfgPlatString); } diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Keywords.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Keywords.cs index 98ff5040..76d21286 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Keywords.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Keywords.cs @@ -37,6 +37,7 @@ internal enum Keyword Extension, BasedOn, IsBuildable, + SupportsPlatform, // Configuration properties Configuration, @@ -87,6 +88,7 @@ static Keywords() new(nameof(Keyword.Extension), Keyword.Extension), new(nameof(Keyword.BasedOn), Keyword.BasedOn), new(nameof(Keyword.IsBuildable), Keyword.IsBuildable), + new(nameof(Keyword.SupportsPlatform), Keyword.SupportsPlatform), new(nameof(Keyword.Configuration), Keyword.Configuration), new(nameof(Keyword.Dimension), Keyword.Dimension), new(nameof(Keyword.BuildType), Keyword.BuildType), @@ -125,6 +127,8 @@ internal static StringTable WithSolutionConstants(this StringTable stringTable) stringTable.AddString(BuildTypeNames.Debug); stringTable.AddString(BuildTypeNames.Release); stringTable.AddString(PlatformNames.All); + stringTable.AddString(PlatformNames.Missing); + stringTable.AddString(PlatformNames.Default); stringTable.AddString(PlatformNames.AnyCPU); stringTable.AddString(PlatformNames.AnySpaceCPU); stringTable.AddString(PlatformNames.Win32); diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Slnx.xsd b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Slnx.xsd index e395847f..399bf6ed 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Slnx.xsd +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/Slnx.xsd @@ -7,10 +7,8 @@ - - - - + + @@ -38,7 +36,8 @@ - + + diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/SlnxSerializerSettings.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/SlnxSerializerSettings.cs index 0b24b591..d8b38890 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/SlnxSerializerSettings.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/SlnxSerializerSettings.cs @@ -15,8 +15,8 @@ public readonly struct SlnxSerializerSettings(SlnxSerializerSettings settings) { /// /// Gets a value indicating whether to keep whitespace when writing the solution file. - /// If this is true, the solution file will be written with the same whitespace as the original file. - /// Default is true. + /// If this is , the solution file will be written with the same whitespace as the original file. + /// Default is . /// public bool? PreserveWhitespace { get; init; } = settings.PreserveWhitespace; diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/SlnxFile.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/SlnxFile.cs index 02a14020..96a7a6c6 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/SlnxFile.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/SlnxFile.cs @@ -86,7 +86,7 @@ internal string ConvertToUserPath(string projectPath) /// Update the Xml DOM with changes from the model. /// /// - /// true if any changes were made to the XML. + /// if any changes were made to the XML. /// internal bool ApplyModel(SolutionModel model) { diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.ApplyModel.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.ApplyModel.cs index 34fdccd7..d5543ae2 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.ApplyModel.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.ApplyModel.cs @@ -57,7 +57,7 @@ internal List DebugChildNodes /// The list of existing decorator items in the XML. /// The element name for the decorator, can be dynamic by using getDecoratorElementName. /// Applies the model item changes to the decorator. - /// true if the XML was changed. + /// if the XML was changed. internal bool ApplyModelItemsToXml( List<(string ItemRef, TModelItem Item)>? modelItems, ref ItemRefList decoratorItems, diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.cs index 6de22d84..543d66f9 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlContainer.cs @@ -50,7 +50,7 @@ internal override void UpdateFromXml() /// /// Wraps the given element with a new decorator and adds it to the cache. - /// If this is a new element, pass itemRef and validateItemRef to true. + /// If this is a new element, pass itemRef and validateItemRef to . /// private XmlDecorator? CreateChildDecorator(XmlElement xmlElement, string? itemRef = null, bool validateItemRef = false) { diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlProjectType.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlProjectType.cs index 30d2154d..5ad61b6b 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlProjectType.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Serializer/Xml/XmlDecorators/XmlProjectType.cs @@ -18,36 +18,61 @@ internal sealed class XmlProjectType(SlnxFile root, XmlElement element) : public Keyword ItemRefAttribute => Keyword.TypeId; + /// internal Guid TypeId { get => this.GetXmlAttributeGuid(Keyword.TypeId); set => this.UpdateXmlAttributeGuid(Keyword.TypeId, value); } + /// internal string? Name { get => this.GetXmlAttribute(Keyword.Name); set => this.UpdateXmlAttribute(Keyword.Name, value); } + /// internal string? Extension { get => this.GetXmlAttribute(Keyword.Extension); set => this.UpdateXmlAttribute(Keyword.Extension, value); } + /// internal string? BasedOn { get => this.GetXmlAttribute(Keyword.BasedOn); set => this.UpdateXmlAttribute(Keyword.BasedOn, value); } + /// + /// Gets or sets a value indicating whether the project type is buildable. + /// + /// + /// Default is . + /// When automatically sets configuration rules to never build. + /// internal bool IsBuildable { get => this.GetXmlAttributeBool(Keyword.IsBuildable, defaultValue: true); set => this.UpdateXmlAttributeBool(Keyword.IsBuildable, value, defaultValue: true); } + /// + /// Gets or sets a value indicating whether the project type supports platform configurations. + /// + /// + /// Default is . + /// When automatically adds configuration rule to remove platform mappings. + /// This setting is ignored if is . + /// + internal bool SupportsPlatform + { + get => this.GetXmlAttributeBool(Keyword.SupportsPlatform, defaultValue: true); + set => this.UpdateXmlAttributeBool(Keyword.SupportsPlatform, value, defaultValue: true); + } + private protected override bool AllowEmptyItemRef => true; /// @@ -124,7 +149,10 @@ internal override bool IsValid() internal ProjectType ToModel() { - ConfigurationRule[] rules = this.IsBuildable ? [.. this.configurationRules.ToModel()] : ProjectTypeTable.NoBuildRules; + ConfigurationRule[] rules = + !this.IsBuildable ? ProjectTypeTable.NoBuildRules : + !this.SupportsPlatform ? [ProjectTypeTable.NoPlatformsRule, .. this.configurationRules.ToModel()] : + /*default*/ [.. this.configurationRules.ToModel()]; return new ProjectType(this.TypeId, rules) { @@ -164,6 +192,7 @@ internal bool ApplyModelToXml(ProjectType modelProjectType) ConfigurationRuleFollower rules = new ConfigurationRuleFollower(modelProjectType.ConfigurationRules); bool isBuildable = rules.GetIsBuildable() ?? true; + bool supportsPlatform = rules.GetProjectPlatform() != PlatformNames.Missing; if (this.IsBuildable != isBuildable) { @@ -171,7 +200,26 @@ internal bool ApplyModelToXml(ProjectType modelProjectType) modified = true; } - modified |= this.configurationRules.ApplyModelToXml(this, isBuildable ? modelProjectType.ConfigurationRules : []); + if (this.SupportsPlatform != supportsPlatform) + { + this.SupportsPlatform = supportsPlatform; + modified = true; + } + + // Determine which rules to serizlize. Remove rules implied by IsBuildable and SupportsPlatform. + IReadOnlyList? rulesToApply = + !isBuildable ? [] : + !supportsPlatform ? RemovePlatformRules(modelProjectType.ConfigurationRules) : + modelProjectType.ConfigurationRules; + + modified |= this.configurationRules.ApplyModelToXml(this, rulesToApply); return modified; + + // Remove any platform rules from the list. + static List RemovePlatformRules(IReadOnlyList rules) => + rules.WhereToList( + predicate: static (rule, _) => rule.Dimension != BuildDimension.Platform, + selector: static (rule, _) => rule, + (object?)null); } } diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs index 5c495e30..5676fd5f 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs @@ -42,6 +42,9 @@ public class RoundTripClassicSln [Fact] public Task FolderIdAsync() => TestRoundTripSerializerAsync(SlnAssets.LoadResource("FolderId.sln")); + [Fact] + public Task ReportProjectAsync() => TestRoundTripSerializerAsync(SlnAssets.LoadResource("Report Project.sln")); + [Theory] [MemberData(nameof(ClassicSlnFiles))] public Task AllClassicSolutionAsync(ResourceName sampleFile) diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs index 4580cd11..bcc0143f 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSlnThruSlnxStream.cs @@ -36,6 +36,9 @@ public class RoundTripClassicSlnThruSlnxStream [Fact] public Task MissingConfigurationsThruSlnxStreamAsync() => TestRoundTripSerializerAsync(SlnAssets.ClassicSlnMissingConfigurations, SlnAssets.XmlSlnxMissingConfigurations); + [Fact] + public Task ReportProjectThruSlnxStreamAsync() => TestRoundTripSerializerAsync(SlnAssets.LoadResource("Report Project.sln"), SlnAssets.LoadResource("Report Project.slnx")); + /// /// Round trip a .SLN file through the slnx serializer. /// diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs index 6a588175..8ffc0e62 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnx.cs @@ -51,6 +51,9 @@ public class RoundTripXmlSlnx [Fact] public Task VersionMinAsync() => TestRoundTripSerializerAsync(SlnAssets.XmlSlnxVersionMin); + [Fact] + public Task ReportProject() => TestRoundTripSerializerAsync(SlnAssets.LoadResource("Report Project.slnx")); + [Theory] [MemberData(nameof(XmlSlnxFiles))] public Task AllXmlSolutionAsync(ResourceName sampleFile) diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs index 1f79e3e3..2aa1d02e 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripXmlSlnxThruModelCopy.cs @@ -49,6 +49,9 @@ public Task CommentsAsync() [Fact] public Task TraditionalAsync() => TestRoundTripSerializerAsync(SlnAssets.XmlSlnxTraditional); + [Fact] + public Task ReportProjectAsync() => TestRoundTripSerializerAsync(SlnAssets.LoadResource("Report Project.slnx")); + private static async Task TestRoundTripSerializerAsync(ResourceStream slnStream) { // Open the Model from stream. diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/StringTests.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/StringTests.cs index eed39ab4..124a036d 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/StringTests.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/StringTests.cs @@ -1,6 +1,7 @@ ๏ปฟ// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Reflection; using Microsoft.VisualStudio.SolutionPersistence.Serializer.Xml; namespace Serialization; @@ -10,6 +11,8 @@ namespace Serialization; /// public sealed class StringTests { + private readonly StringTable stringTable = new StringTable().WithSolutionConstants(); + /// /// Make sure all keywords have a string representation. /// @@ -19,11 +22,40 @@ public void KeywordStrings() // Validate that if any new keywords are added to the enum, they are in the mapping tables. foreach (Keyword keyword in Enum.GetValues(typeof(Keyword))) { - if (keyword is not Keyword.Unknown and not < 0 and not >= Keyword.MaxProp && - keyword.ToXmlString() is null) + if (keyword is not Keyword.Unknown and not < 0 and not >= Keyword.MaxProp) { - Assert.Fail($"Keyword {keyword} does not have a string representation."); + string keywordStr = keyword.ToXmlString(); + Assert.True(keywordStr is not null, $"Keyword {keyword} does not have a string representation."); + Assert.True(this.stringTable.Contains(keywordStr), $"StringTable missing {keyword.ToXmlString()}"); } } } + + /// + /// Make sure all build type names have a string representation. + /// + [Fact] + public void BuildTypeNamesTest() + { + foreach (FieldInfo fieldInfo in typeof(BuildTypeNames).GetFields(BindingFlags.NonPublic | BindingFlags.Static)) + { + string value = fieldInfo.GetValue(null) as string ?? string.Empty; + Assert.True(BuildTypeNames.TryGetKnown(value.AsSpan(), out string? str), $"BuildType lookup missing {value}"); + Assert.True(this.stringTable.Contains(str), $"StringTable missing {str}"); + } + } + + /// + /// Make sure all platform names have a string representation. + /// + [Fact] + public void PlatformNamesTest() + { + foreach (FieldInfo fieldInfo in typeof(PlatformNames).GetFields(BindingFlags.NonPublic | BindingFlags.Static)) + { + string value = fieldInfo.GetValue(null) as string ?? string.Empty; + Assert.True(PlatformNames.TryGetKnown(value.AsSpan(), out string? str), $"Platform lookup missing {value}"); + Assert.True(this.stringTable.Contains(str), $"StringTable missing {str}"); + } + } } diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/BuiltInProjectTypes.slnx.xml b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/BuiltInProjectTypes.slnx.xml index 88022ce4..eb00b37f 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/BuiltInProjectTypes.slnx.xml +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/BuiltInProjectTypes.slnx.xml @@ -32,6 +32,7 @@ + diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/MissingConfigurations.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/MissingConfigurations.sln.txt index 7cd290b1..c6e986fb 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/MissingConfigurations.sln.txt +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Configurations/MissingConfigurations.sln.txt @@ -25,7 +25,7 @@ Global {B0C8586B-AD06-484D-A425-78449EEB0AFA}.Release|x64.Build.0 = Release|x64 {B0C8586B-AD06-484D-A425-78449EEB0AFA}.Release|x86.ActiveCfg = Release|Win32 {B0C8586B-AD06-484D-A425-78449EEB0AFA}.Release|x86.Build.0 = Release|Win32 - {D53DB013-AEE1-48D8-874F-509000819E30}.Debug|x86.Build.0 = ?|? + {D53DB013-AEE1-48D8-874F-509000819E30}.Debug|x86.Build.0 = ? {D53DB013-AEE1-48D8-874F-509000819E30}.Release|x64.ActiveCfg = Release|x64 {D53DB013-AEE1-48D8-874F-509000819E30}.Release|x64.Build.0 = Release|x64 EndGlobalSection diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.sln.txt new file mode 100644 index 00000000..d3281505 --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.sln.txt @@ -0,0 +1,30 @@ +๏ปฟ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35821.254 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F14B399A-7131-4C87-9E4B-1186C45EF12D}") = "Report Project", "Report Project.rptproj", "{5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Default = Debug|Default + DebugLocal|Default = DebugLocal|Default + Release|Default = Release|Default + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.Debug|Default.ActiveCfg = Debug + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.Debug|Default.Build.0 = Debug + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.Debug|Default.Deploy.0 = Debug + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.DebugLocal|Default.ActiveCfg = DebugLocal + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.DebugLocal|Default.Build.0 = DebugLocal + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.Release|Default.ActiveCfg = Release + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.Release|Default.Build.0 = Release + {5F864A61-8A8B-9ED2-A92E-9ABB172CC8D7}.Release|Default.Deploy.0 = Release + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AB744758-6EDA-4264-84B6-7396FCA3E003} + EndGlobalSection +EndGlobal diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.slnx.xml b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.slnx.xml new file mode 100644 index 00000000..25e0f20a --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/Report Project.slnx.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + +