From 3e39dff0d35a02e65e62f8825d7782353fe427d9 Mon Sep 17 00:00:00 2001 From: Callum Sykes Date: Tue, 26 May 2026 18:35:13 -0700 Subject: [PATCH 1/5] Created a build samples action --- .github/workflows/build-samples.yml | 140 ++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 .github/workflows/build-samples.yml diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml new file mode 100644 index 00000000..b8139e0f --- /dev/null +++ b/.github/workflows/build-samples.yml @@ -0,0 +1,140 @@ +name: Build Samples + +on: + pull_request: + paths: + - 'rhinocommon/**' + - 'rhino3dm/**' + - 'grasshopper/**' + - 'compute/**' + - 'rhino.inside/**' + - '.github/workflows/build-samples.yml' + workflow_dispatch: + +permissions: + contents: read + +# Cancel an in-progress run when newer commits land on the same PR/ref. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build ${{ matrix.category }} (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + # Keep every category running even if one fails - we want full coverage. + fail-fast: false + matrix: + include: + # net48 + net9.0-windows -> needs Windows. + - category: rhinocommon + path: rhinocommon + os: windows-latest + # net7.0 + Rhino3dm NuGet (native libs for win/mac/linux) -> build on all three. + - category: rhino3dm + path: rhino3dm + os: ubuntu-latest + - category: rhino3dm + path: rhino3dm + os: macos-latest + - category: rhino3dm + path: rhino3dm + os: windows-latest + # Grasshopper/RhinoCommon NuGet, mostly net48 -> Windows. + - category: grasshopper + path: grasshopper + os: windows-latest + # RhinoCommon/Compute NuGet, net48 -> Windows. + - category: compute + path: compute + os: windows-latest + # Rhino.Inside NuGet, mixed net48/*-windows -> Windows. + - category: rhino.inside + path: rhino.inside + os: windows-latest + + steps: + - uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: 9.0.x + + - name: Cache NuGet packages + uses: actions/cache@v5 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles(format('{0}/**/*.csproj', matrix.path)) }} + restore-keys: ${{ runner.os }}-nuget- + + - name: Build all projects + shell: pwsh + env: + CATEGORY: ${{ matrix.category }} + SEARCH_PATH: ${{ matrix.path }} + run: | + $projects = Get-ChildItem -Path $env:SEARCH_PATH -Filter *.csproj -Recurse -File | Sort-Object FullName + $summaryHeader = "## $env:CATEGORY build results" + + if ($projects.Count -eq 0) { + Write-Host "No .csproj files found under $env:SEARCH_PATH" + "$summaryHeader`n`nNo projects found under ``$env:SEARCH_PATH``." | + Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append + exit 0 + } + + $results = @() + foreach ($proj in $projects) { + $rel = (Resolve-Path -Relative $proj.FullName) -replace '\\', '/' + Write-Host "::group::Building $rel" + dotnet build $proj.FullName -c Release --nologo + $code = $LASTEXITCODE + Write-Host "::endgroup::" + if ($code -eq 0) { + Write-Host "::notice title=Build passed::$rel" + $results += [pscustomobject]@{ Project = $rel; Status = 'pass' } + } else { + Write-Host "::error title=Build failed::$rel (exit code $code)" + $results += [pscustomobject]@{ Project = $rel; Status = 'FAILED' } + } + } + + $passed = ($results | Where-Object Status -eq 'pass').Count + $failed = ($results | Where-Object Status -eq 'FAILED').Count + + $lines = @() + $lines += $summaryHeader + $lines += "" + $lines += "**$passed passed, $failed failed** of $($results.Count) project(s)." + $lines += "" + $lines += "| Project | Result |" + $lines += "| --- | --- |" + foreach ($r in $results) { + $lines += "| $($r.Project) | $($r.Status) |" + } + ($lines -join "`n") | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append + + Write-Host "$env:CATEGORY: $passed passed, $failed failed." + # Hard gate: any failed project fails the job. + if ($failed -gt 0) { exit 1 } + exit 0 + + # Single check that is green only when every category job succeeded. + gate: + name: Build gate + needs: build + if: always() + runs-on: ubuntu-latest + steps: + - name: Verify all category builds passed + run: | + echo "build matrix result: ${{ needs.build.result }}" + if [ "${{ needs.build.result }}" != "success" ]; then + echo "One or more category builds failed." + exit 1 + fi + echo "All category builds passed." From 02f1e69292a2e7265fbb63ef1d21861f6a46bdd3 Mon Sep 17 00:00:00 2001 From: Callum Sykes Date: Tue, 26 May 2026 18:47:10 -0700 Subject: [PATCH 2/5] Added a global net9.0 SDK json --- .github/workflows/build-samples.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml index b8139e0f..08f832fd 100644 --- a/.github/workflows/build-samples.yml +++ b/.github/workflows/build-samples.yml @@ -64,6 +64,21 @@ jobs: with: dotnet-version: 9.0.x + # Runners ship a newer SDK (e.g. 10.x); without this, dotnet picks the + # highest installed SDK. Pin to 9.x for the whole repo during CI only. + - name: Pin .NET SDK (CI only) + shell: pwsh + run: | + @' + { + "sdk": { + "version": "9.0.100", + "rollForward": "latestFeature" + } + } + '@ | Set-Content -Path global.json + dotnet --version + - name: Cache NuGet packages uses: actions/cache@v5 with: From 9fbd001dff7ffc47a3f3dcaeb6f99b629d379f5d Mon Sep 17 00:00:00 2001 From: Callum Sykes Date: Tue, 26 May 2026 18:47:22 -0700 Subject: [PATCH 3/5] Added a skip for legacy net45 projects --- .github/workflows/build-samples.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml index 08f832fd..e6505698 100644 --- a/.github/workflows/build-samples.yml +++ b/.github/workflows/build-samples.yml @@ -105,6 +105,16 @@ jobs: $results = @() foreach ($proj in $projects) { $rel = (Resolve-Path -Relative $proj.FullName) -replace '\\', '/' + + # Skip legacy non-SDK projects: they need msbuild + nuget restore + # and/or an installed Rhino, so they are not built in CI for now. + $isSdkStyle = (Get-Content $proj.FullName -Raw) -match ' Date: Tue, 26 May 2026 18:52:38 -0700 Subject: [PATCH 4/5] Added extensions nuget --- rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj b/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj index 540bff92..1110e5d1 100644 --- a/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj +++ b/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj @@ -31,6 +31,7 @@ + From 7518be2dc116b31bd258fa422d3992b8a4960140 Mon Sep 17 00:00:00 2001 From: Callum Sykes Date: Tue, 26 May 2026 18:55:42 -0700 Subject: [PATCH 5/5] GenerateResourceUsePreserializedResources --- rhinocommon/cs/SampleCsEto/SampleCsEto.csproj | 1 + rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/rhinocommon/cs/SampleCsEto/SampleCsEto.csproj b/rhinocommon/cs/SampleCsEto/SampleCsEto.csproj index 4a091f1e..809f2fab 100755 --- a/rhinocommon/cs/SampleCsEto/SampleCsEto.csproj +++ b/rhinocommon/cs/SampleCsEto/SampleCsEto.csproj @@ -10,6 +10,7 @@ Copyright © 2024, Robert McNeel & Associates .rhp NU1701 + true diff --git a/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj b/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj index 1110e5d1..f3522175 100644 --- a/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj +++ b/rhinocommon/cs/SampleCsWpf/SampleCsWpf.csproj @@ -11,6 +11,7 @@ SampleCsWpf Sample WPF Plug-in 8.0.0 + true 1701;1702;NU1701