diff --git a/.github/workflows/platform_quality.yaml b/.github/workflows/platform_quality.yaml new file mode 100644 index 000000000..97cff3d33 --- /dev/null +++ b/.github/workflows/platform_quality.yaml @@ -0,0 +1,23 @@ +name: Platform SDK quality gate (C#) + +on: + pull_request: + paths: + - platform/** + - .github/workflows/platform_quality.yaml + - .github/workflows/sdk_quality.yaml + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: platform-quality-${{ github.ref }} + cancel-in-progress: true + +jobs: + quality: + uses: ./.github/workflows/sdk_quality.yaml + with: + target: platform + artifact_name: platform-quality diff --git a/.github/workflows/sdk_quality.yaml b/.github/workflows/sdk_quality.yaml new file mode 100644 index 000000000..910dc9da0 --- /dev/null +++ b/.github/workflows/sdk_quality.yaml @@ -0,0 +1,39 @@ +name: SDK quality (reusable) + +on: + workflow_call: + inputs: + target: + description: SDK target directory (e.g. platform) + required: true + type: string + artifact_name: + description: Name for the uploaded results artifact + required: true + type: string + +permissions: + contents: read + +jobs: + sdk-quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4 + with: + dotnet-version: 8.0.x + + - name: Check (build + test) + run: pwsh ./check.ps1 -Target ${{ inputs.target }} + + - name: Publish results + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: ${{ inputs.artifact_name }} + path: | + **/*.received.txt + **/test-results/** + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index ccd534821..5b6056421 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ # Ignore Speakeasy regen change logs .speakeasy/logs/changes/ + +# Local test run output (uploaded as a CI artifact, never committed) +**/test-results/ diff --git a/check.ps1 b/check.ps1 new file mode 100644 index 000000000..4c4219608 --- /dev/null +++ b/check.ps1 @@ -0,0 +1,44 @@ +#requires -Version 7 +[CmdletBinding()] +param( + [string]$Target = '' +) + +$ErrorActionPreference = 'Stop' +$repoRoot = $PSScriptRoot + +$testProjects = Get-ChildItem -Path $repoRoot -Recurse -Filter '*.csproj' | + Where-Object { $_.FullName -match '[\\/]tests[\\/]' } + +if ($Target) { + $prefix = (Join-Path $repoRoot $Target) + $testProjects = $testProjects | Where-Object { $_.FullName.StartsWith($prefix, [System.StringComparison]::OrdinalIgnoreCase) } +} + +if (-not $testProjects) { + Write-Error "No test projects found$(if ($Target) { " for target '$Target'" })." + exit 1 +} + +$failed = @() + +foreach ($proj in $testProjects) { + Write-Host "==> $($proj.FullName)" -ForegroundColor Cyan + + dotnet build $proj.FullName -c Release --nologo + if ($LASTEXITCODE -ne 0) { $failed += "build: $($proj.Name)"; continue } + + $env:DiffEngine_Disabled = 'true' + $env:CI = 'true' + dotnet test $proj.FullName -c Release --no-build ` + --logger 'trx;LogFileName=results.trx' ` + --results-directory (Join-Path $proj.Directory.FullName 'test-results') + if ($LASTEXITCODE -ne 0) { $failed += "test: $($proj.Name)" } +} + +if ($failed) { + Write-Host "FAILED: $($failed -join ', ')" -ForegroundColor Red + exit 1 +} + +Write-Host 'OK' -ForegroundColor Green