Created a build samples action #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| # 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: | |
| 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 '\\', '/' | |
| # 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 '<Project\s+Sdk=' | |
| if (-not $isSdkStyle) { | |
| Write-Host "::notice title=Skipped (legacy non-SDK)::$rel" | |
| $results += [pscustomobject]@{ Project = $rel; Status = 'skipped' } | |
| continue | |
| } | |
| 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 | |
| $skipped = ($results | Where-Object Status -eq 'skipped').Count | |
| $lines = @() | |
| $lines += $summaryHeader | |
| $lines += "" | |
| $lines += "**$passed passed, $failed failed, $skipped skipped** 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, $skipped skipped." | |
| # Hard gate: any failed project fails the job (skipped does not). | |
| 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." |