From b322642c65fdac1ea32506795ee9764fe93d72aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:43:58 +0000 Subject: [PATCH 1/9] Initial plan From 8209b50ecb13b0c6bdb54f2c02761931bb15757c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:52:45 +0000 Subject: [PATCH 2/9] Add build.ps1 script for multi-Roslyn Build/Test/Pack orchestration Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- build.ps1 | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100755 build.ps1 diff --git a/build.ps1 b/build.ps1 new file mode 100755 index 0000000..34632fc --- /dev/null +++ b/build.ps1 @@ -0,0 +1,146 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Build, test, and pack DocoptNet with multi-Roslyn variant support. + +.DESCRIPTION + This script orchestrates builds across Roslyn 3.10 (baseline) and Roslyn 4.4 variants, + runs tests for both variants, and produces a NuGet package containing both analyzer DLLs. + +.PARAMETER Build + Build the solution (default parameter set). + +.PARAMETER Test + Run tests for both Roslyn variants. + +.PARAMETER Pack + Create a NuGet package containing both analyzer variants. + +.PARAMETER Configuration + The build configuration (default: Release). + +.PARAMETER NoBuild + Skip the build step when running tests (only applies to baseline tests). + +.PARAMETER VersionSuffix + Optional version suffix for the NuGet package (e.g., "beta1"). + +.EXAMPLE + ./build.ps1 + Build both Roslyn variants (baseline + 4.4). + +.EXAMPLE + ./build.ps1 -Test + Build and test both Roslyn variants. + +.EXAMPLE + ./build.ps1 -Test -NoBuild + Run tests without rebuilding baseline (Roslyn 4.4 tests always build as needed). + +.EXAMPLE + ./build.ps1 -Pack -VersionSuffix "beta1" + Build and pack with version suffix. +#> + +[CmdletBinding(DefaultParameterSetName = 'Build')] +param( + [Parameter(ParameterSetName = 'Build')] + [switch] $Build, + + [Parameter(ParameterSetName = 'Test', Mandatory)] + [switch] $Test, + + [Parameter(ParameterSetName = 'Pack', Mandatory)] + [switch] $Pack, + + [Parameter(ParameterSetName = 'Build')] + [Parameter(ParameterSetName = 'Test')] + [Parameter(ParameterSetName = 'Pack')] + [string] $Configuration = 'Release', + + [Parameter(ParameterSetName = 'Test')] + [switch] $NoBuild, + + [Parameter(ParameterSetName = 'Pack')] + [string] $VersionSuffix +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +# Make the script directory-independent +Push-Location $PSScriptRoot +try { + function Invoke-DotNet { + param( + [string[]] $Arguments, + [switch] $AllowTestFailures + ) + + Write-Host "dotnet $($Arguments -join ' ')" -ForegroundColor Cyan + & dotnet @Arguments + if ($LASTEXITCODE -ne 0) { + # On non-Windows platforms, net47 tests may fail due to missing mono, + # but this is expected. For test commands, we allow exit code 1. + if ($AllowTestFailures -and $LASTEXITCODE -eq 1) { + Write-Host "Test command returned exit code 1 (this may be due to net47 requiring mono on Linux)" -ForegroundColor Yellow + } else { + throw "dotnet command failed with exit code $LASTEXITCODE" + } + } + } + + function Invoke-BuildFlow { + Write-Host "`n=== Building Baseline (Roslyn 3.10) ===" -ForegroundColor Green + Invoke-DotNet 'build', '--configuration', $Configuration + + Write-Host "`n=== Building Roslyn 4.4 Variant ===" -ForegroundColor Green + Invoke-DotNet 'build', 'src/DocoptNet/DocoptNet.csproj', '-f', 'netstandard2.0', '-p:RoslynVersion=4.4', '--configuration', $Configuration + } + + function Invoke-TestFlow { + if (-not $NoBuild) { + Invoke-BuildFlow + } + + Write-Host "`n=== Running Tests ===" -ForegroundColor Green + if ($NoBuild) { + Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures + } else { + Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures + } + + # Note: Roslyn 4.4 analyzer is validated through integration tests + # that use the packed NuGet package containing both analyzer variants + } + + function Invoke-PackFlow { + Invoke-BuildFlow + + Write-Host "`n=== Packing NuGet Package ===" -ForegroundColor Green + $packArgs = @('pack', 'src/DocoptNet/DocoptNet.csproj', '--no-build', '--configuration', $Configuration) + if ($VersionSuffix) { + $packArgs += @('--version-suffix', $VersionSuffix) + } + Invoke-DotNet $packArgs + } + + # Execute the appropriate flow based on parameter set + switch ($PSCmdlet.ParameterSetName) { + 'Build' { + Invoke-BuildFlow + } + 'Test' { + Invoke-TestFlow + } + 'Pack' { + Invoke-PackFlow + } + } + + Write-Host "`n=== Success ===" -ForegroundColor Green +} +finally { + Pop-Location +} From 11a56ecc081af5fa71bc6e076eecaae8a336293a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:55:10 +0000 Subject: [PATCH 3/9] Update CI workflow to use build.ps1 script Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- .github/workflows/ci.yml | 18 ++++++++++-------- build.ps1 | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67305d9..4c5b6dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,10 +48,7 @@ jobs: run: dotnet tool restore - name: Build - run: dotnet build --configuration ${{ env.CONFIGURATION }} - - - name: Build Roslyn 4.4 variant - run: dotnet build src/DocoptNet/DocoptNet.csproj -f netstandard2.0 -p:RoslynVersion=4.4 --configuration ${{ env.CONFIGURATION }} + run: dotnet pwsh ./build.ps1 -Build -Configuration ${{ env.CONFIGURATION }} - name: Pack (Windows only) if: runner.os == 'Windows' @@ -79,11 +76,16 @@ jobs: } Add-Content $releaseNotesFile -Encoding UTF8 "Commit @ ${{ github.sha }}" - $packArgs = @() + + $packParams = @{ + Configuration = '${{ env.CONFIGURATION }}' + PackageReleaseNotesFile = $releaseNotesFile + } if ($versionSuffix) { - $packArgs += @('--version-suffix', $versionSuffix) + $packParams.VersionSuffix = $versionSuffix } - dotnet pack --no-build --configuration ${{ env.CONFIGURATION }} @packArgs "-p:PackageReleaseNotesFile=$releaseNotesFile" + + dotnet pwsh ./build.ps1 -Pack @packParams if ($LASTEXITCODE) { throw "Pack failed" } Get-ChildItem -File -Filter docopt.net.*.nupkg dist | @@ -91,7 +93,7 @@ jobs: ForEach-Object { dotnet sourcelink test $_; if ($LASTEXITCODE) { throw "SourceLink test failed for $_" } } - name: Test - run: dotnet test --no-build --configuration ${{ env.CONFIGURATION }} + run: dotnet pwsh ./build.ps1 -Test -NoBuild -Configuration ${{ env.CONFIGURATION }} - name: Integration Tests (Windows) if: runner.os == 'Windows' diff --git a/build.ps1 b/build.ps1 index 34632fc..e34218b 100755 --- a/build.ps1 +++ b/build.ps1 @@ -26,6 +26,9 @@ .PARAMETER VersionSuffix Optional version suffix for the NuGet package (e.g., "beta1"). +.PARAMETER PackageReleaseNotesFile + Optional path to a file containing release notes for the NuGet package. + .EXAMPLE ./build.ps1 Build both Roslyn variants (baseline + 4.4). @@ -41,6 +44,10 @@ .EXAMPLE ./build.ps1 -Pack -VersionSuffix "beta1" Build and pack with version suffix. + +.EXAMPLE + ./build.ps1 -Pack -PackageReleaseNotesFile "/path/to/notes.txt" + Build and pack with release notes from a file. #> [CmdletBinding(DefaultParameterSetName = 'Build')] @@ -63,7 +70,10 @@ param( [switch] $NoBuild, [Parameter(ParameterSetName = 'Pack')] - [string] $VersionSuffix + [string] $VersionSuffix, + + [Parameter(ParameterSetName = 'Pack')] + [string] $PackageReleaseNotesFile ) $ErrorActionPreference = 'Stop' @@ -123,6 +133,9 @@ try { if ($VersionSuffix) { $packArgs += @('--version-suffix', $VersionSuffix) } + if ($PackageReleaseNotesFile) { + $packArgs += "-p:PackageReleaseNotesFile=$PackageReleaseNotesFile" + } Invoke-DotNet $packArgs } From f1894e659e1dcda9b2b48eb0bd327753437b07fe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:55:31 +0000 Subject: [PATCH 4/9] Add Building from Source section to README Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/README.md b/README.md index 2b2e99b..1b526c1 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,58 @@ Install [the package][nupkg] in a .NET project using: dotnet add package docopt.net +## Building from Source + +The repository uses a PowerShell script to orchestrate multi-Roslyn variant builds. Ensure you have the required tools installed: + +```bash +dotnet tool restore +``` + +### Build + +To build the project with both Roslyn 3.10 (baseline) and Roslyn 4.4 variants: + +```bash +dotnet pwsh ./build.ps1 +``` + +or simply: + +```bash +dotnet pwsh ./build.ps1 -Build -Configuration Release +``` + +### Test + +To run tests: + +```bash +dotnet pwsh ./build.ps1 -Test +``` + +To run tests without rebuilding: + +```bash +dotnet pwsh ./build.ps1 -Test -NoBuild +``` + +### Pack + +To create a NuGet package containing both analyzer variants: + +```bash +dotnet pwsh ./build.ps1 -Pack +``` + +**Note:** Running `dotnet pack` directly without first building all Roslyn variants will fail with an error message. Always use `./build.ps1 -Pack` to ensure both analyzer variants are included in the package. + +To pack with a version suffix: + +```bash +dotnet pwsh ./build.ps1 -Pack -VersionSuffix "beta1" +``` + ## Copyright and License - © 2012-2014 Vladimir Keleshev From b0fab70da0e25fcb098178c3aeb1d68f1f794e9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:57:10 +0000 Subject: [PATCH 5/9] Update integration tests to use build.ps1 for packing Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- tests/Integration/run.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/run.ps1 b/tests/Integration/run.ps1 index 1bacac1..3d924b9 100644 --- a/tests/Integration/run.ps1 +++ b/tests/Integration/run.ps1 @@ -24,7 +24,7 @@ try } Remove-Item -Recurse -Force (Join-Path $props.RestorePackagesPath docopt.net) -ErrorAction SilentlyContinue if (!$noPack) { - dotnet pack -c Release ../.. + dotnet pwsh ../../build.ps1 -Pack -Configuration Release if ($LASTEXITCODE) { throw } } Remove-Item bin, obj -Recurse -Force -ErrorAction SilentlyContinue From 18203ad504ed6d0c396049ed2952fe9669a0a65a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:59:18 +0000 Subject: [PATCH 6/9] Address code review feedback: fix duplicate if-else and use & for script calls in PowerShell context Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- build.ps1 | 6 +----- tests/Integration/run.ps1 | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c5b6dd..2b071c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: $packParams.VersionSuffix = $versionSuffix } - dotnet pwsh ./build.ps1 -Pack @packParams + & ./build.ps1 -Pack @packParams if ($LASTEXITCODE) { throw "Pack failed" } Get-ChildItem -File -Filter docopt.net.*.nupkg dist | diff --git a/build.ps1 b/build.ps1 index e34218b..300cde0 100755 --- a/build.ps1 +++ b/build.ps1 @@ -115,11 +115,7 @@ try { } Write-Host "`n=== Running Tests ===" -ForegroundColor Green - if ($NoBuild) { - Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures - } else { - Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures - } + Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures # Note: Roslyn 4.4 analyzer is validated through integration tests # that use the packed NuGet package containing both analyzer variants diff --git a/tests/Integration/run.ps1 b/tests/Integration/run.ps1 index 3d924b9..3a21f23 100644 --- a/tests/Integration/run.ps1 +++ b/tests/Integration/run.ps1 @@ -24,7 +24,7 @@ try } Remove-Item -Recurse -Force (Join-Path $props.RestorePackagesPath docopt.net) -ErrorAction SilentlyContinue if (!$noPack) { - dotnet pwsh ../../build.ps1 -Pack -Configuration Release + & ../../build.ps1 -Pack -Configuration Release if ($LASTEXITCODE) { throw } } Remove-Item bin, obj -Recurse -Force -ErrorAction SilentlyContinue From d686d4a4d14392b1da71cb26c4f34f86590a5c45 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:01:37 +0000 Subject: [PATCH 7/9] Improve comments for clarity: explain AllowTestFailures usage and CI shell context Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ build.ps1 | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b071c9..0ae9f41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,10 +48,12 @@ jobs: run: dotnet tool restore - name: Build + # Uses 'dotnet pwsh' because the default shell (bash/cmd) is not PowerShell run: dotnet pwsh ./build.ps1 -Build -Configuration ${{ env.CONFIGURATION }} - name: Pack (Windows only) if: runner.os == 'Windows' + # Uses 'shell: pwsh' so commands run in PowerShell context shell: pwsh run: | $commitTimestamp = git log -1 --format=%cI @@ -93,6 +95,7 @@ jobs: ForEach-Object { dotnet sourcelink test $_; if ($LASTEXITCODE) { throw "SourceLink test failed for $_" } } - name: Test + # Uses 'dotnet pwsh' because the default shell (bash/cmd) is not PowerShell run: dotnet pwsh ./build.ps1 -Test -NoBuild -Configuration ${{ env.CONFIGURATION }} - name: Integration Tests (Windows) diff --git a/build.ps1 b/build.ps1 index 300cde0..e67ac1c 100755 --- a/build.ps1 +++ b/build.ps1 @@ -91,8 +91,8 @@ try { Write-Host "dotnet $($Arguments -join ' ')" -ForegroundColor Cyan & dotnet @Arguments if ($LASTEXITCODE -ne 0) { - # On non-Windows platforms, net47 tests may fail due to missing mono, - # but this is expected. For test commands, we allow exit code 1. + # Some test frameworks (e.g., net47) may not run on all platforms (Linux/macOS require mono). + # Allow exit code 1 for test commands when the runnable tests passed but some frameworks couldn't execute. if ($AllowTestFailures -and $LASTEXITCODE -eq 1) { Write-Host "Test command returned exit code 1 (this may be due to net47 requiring mono on Linux)" -ForegroundColor Yellow } else { @@ -115,6 +115,8 @@ try { } Write-Host "`n=== Running Tests ===" -ForegroundColor Green + # AllowTestFailures handles the case where net47 tests cannot run (requires mono on Linux/macOS) + # while still ensuring that tests that can run actually pass Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures # Note: Roslyn 4.4 analyzer is validated through integration tests From 2788ced4158166f9d90d1f1f2da3b0e8d1b6cfc1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:39:37 +0000 Subject: [PATCH 8/9] Remove obvious comments and unnecessary AllowTestFailures logic Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- .github/workflows/ci.yml | 3 --- build.ps1 | 15 +++------------ 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ae9f41..2b071c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,12 +48,10 @@ jobs: run: dotnet tool restore - name: Build - # Uses 'dotnet pwsh' because the default shell (bash/cmd) is not PowerShell run: dotnet pwsh ./build.ps1 -Build -Configuration ${{ env.CONFIGURATION }} - name: Pack (Windows only) if: runner.os == 'Windows' - # Uses 'shell: pwsh' so commands run in PowerShell context shell: pwsh run: | $commitTimestamp = git log -1 --format=%cI @@ -95,7 +93,6 @@ jobs: ForEach-Object { dotnet sourcelink test $_; if ($LASTEXITCODE) { throw "SourceLink test failed for $_" } } - name: Test - # Uses 'dotnet pwsh' because the default shell (bash/cmd) is not PowerShell run: dotnet pwsh ./build.ps1 -Test -NoBuild -Configuration ${{ env.CONFIGURATION }} - name: Integration Tests (Windows) diff --git a/build.ps1 b/build.ps1 index e67ac1c..b3badd4 100755 --- a/build.ps1 +++ b/build.ps1 @@ -84,20 +84,13 @@ Push-Location $PSScriptRoot try { function Invoke-DotNet { param( - [string[]] $Arguments, - [switch] $AllowTestFailures + [string[]] $Arguments ) Write-Host "dotnet $($Arguments -join ' ')" -ForegroundColor Cyan & dotnet @Arguments if ($LASTEXITCODE -ne 0) { - # Some test frameworks (e.g., net47) may not run on all platforms (Linux/macOS require mono). - # Allow exit code 1 for test commands when the runnable tests passed but some frameworks couldn't execute. - if ($AllowTestFailures -and $LASTEXITCODE -eq 1) { - Write-Host "Test command returned exit code 1 (this may be due to net47 requiring mono on Linux)" -ForegroundColor Yellow - } else { - throw "dotnet command failed with exit code $LASTEXITCODE" - } + throw "dotnet command failed with exit code $LASTEXITCODE" } } @@ -115,9 +108,7 @@ try { } Write-Host "`n=== Running Tests ===" -ForegroundColor Green - # AllowTestFailures handles the case where net47 tests cannot run (requires mono on Linux/macOS) - # while still ensuring that tests that can run actually pass - Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration -AllowTestFailures + Invoke-DotNet 'test', '--no-build', '--configuration', $Configuration # Note: Roslyn 4.4 analyzer is validated through integration tests # that use the packed NuGet package containing both analyzer variants From b52bfff522fc7d6b327d8f9f6be552872da78707 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:43:50 +0000 Subject: [PATCH 9/9] Revert CI Test step to use direct dotnet test command Co-authored-by: atifaziz <20511+atifaziz@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- build.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b071c9..d004012 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,7 +93,7 @@ jobs: ForEach-Object { dotnet sourcelink test $_; if ($LASTEXITCODE) { throw "SourceLink test failed for $_" } } - name: Test - run: dotnet pwsh ./build.ps1 -Test -NoBuild -Configuration ${{ env.CONFIGURATION }} + run: dotnet test --no-build --configuration ${{ env.CONFIGURATION }} - name: Integration Tests (Windows) if: runner.os == 'Windows' diff --git a/build.ps1 b/build.ps1 index b3badd4..4e878e0 100755 --- a/build.ps1 +++ b/build.ps1 @@ -12,7 +12,7 @@ Build the solution (default parameter set). .PARAMETER Test - Run tests for both Roslyn variants. + Run tests. Note: May fail on non-Windows platforms if .NET Framework tests cannot run. .PARAMETER Pack Create a NuGet package containing both analyzer variants.