README + CONTRIBUTING + gate SVG output through librsvg/Inkscape #8
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| # Cancel superseded runs on the same PR/branch — saves minutes when pushing fixups. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-test: | |
| runs-on: ubuntu-latest | |
| env: | |
| DOTNET_NOLOGO: true | |
| DOTNET_CLI_TELEMETRY_OPTOUT: true | |
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | |
| # Belt-and-braces: the snapshot suite already refuses UPDATE_SNAPSHOTS when | |
| # CI is detected, but pin it off explicitly so a stray env var on the agent | |
| # can't auto-accept baselines. | |
| UPDATE_SNAPSHOTS: '0' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| # Reads global.json for the resolved version; cache keys off the CPM lock. | |
| global-json-file: global.json | |
| cache: true | |
| cache-dependency-path: Directory.Packages.props | |
| - name: Restore | |
| run: dotnet restore DiagramForge.slnx | |
| - name: Build | |
| run: dotnet build DiagramForge.slnx --no-restore --configuration Release | |
| - name: Test | |
| run: > | |
| dotnet test DiagramForge.slnx | |
| --no-build | |
| --configuration Release | |
| --logger "trx;LogFilePrefix=results" | |
| --results-directory TestResults | |
| # Gate the "Real SVG" claim: every rendered fixture must pass through | |
| # a non-browser renderer. librsvg has no HTML engine — <foreignObject> | |
| # with XHTML guts becomes an empty box, and anything relying on CSS | |
| # cascade or <style> blocks falls apart. If this step is green, the | |
| # output renders in GNOME thumbnails, GIMP import, and ImageMagick's | |
| # SVG delegate. | |
| # | |
| # Runs even when the snapshot-diff step above fails: artifacts are | |
| # written before assertions, and "the new output differs" and "the new | |
| # output is unrenderable" are independent facts worth knowing separately. | |
| - name: Verify SVGs render in librsvg | |
| if: always() | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update -qq | |
| sudo apt-get install -y --no-install-recommends librsvg2-bin | |
| rsvg-convert --version | |
| shopt -s nullglob | |
| files=(artifacts/test-results/snapshots/*.actual.svg) | |
| if (( ${#files[@]} == 0 )); then | |
| echo "::warning::No .actual.svg artifacts found — tests may not have produced output" | |
| exit 0 | |
| fi | |
| echo "Checking ${#files[@]} rendered SVG(s)" | |
| failed=() | |
| for f in "${files[@]}"; do | |
| if ! rsvg-convert "$f" -o /dev/null 2>&1; then | |
| failed+=("$f") | |
| echo "::error file=$f::librsvg failed to render" | |
| fi | |
| done | |
| if (( ${#failed[@]} > 0 )); then | |
| echo "${#failed[@]} file(s) failed librsvg rendering" | |
| exit 1 | |
| fi | |
| echo "All ${#files[@]} files rendered cleanly" | |
| # Upload the snapshot .actual.svg gallery even (especially) when tests fail — | |
| # that's when you most want to eyeball the rendered output. | |
| - name: Upload rendered snapshots | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: snapshots | |
| path: artifacts/test-results/snapshots/ | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results | |
| path: TestResults/ | |
| if-no-files-found: warn | |
| retention-days: 7 |