Skip to content

Tutorial Validate In CI

Marko Koljancic edited this page May 28, 2026 · 5 revisions

Home

Tutorial: Validate in CI

You're a pipeline engineer at a studio where artists keep occasionally checking in assets that bust the runtime budget or ship with bad UVs. You want to gate pull requests on asset quality so problems get caught before merge, not at cook time. This tutorial wires solarxy-cli into a GitHub Actions workflow that runs on every PR touching assets/ and annotates the PR inline with findings.

By the end you'll have a solarxy.toml that defines your studio's gates, a local repro that runs the same check on your laptop, and a working CI job that fails the PR when a bad asset slips in.

Goal

Make CI fail a pull request when it adds an asset that violates the project's validation policy, with the findings visible inline in the PR.

Setup

You need:

  • A GitHub repository with an assets/ directory of .glb or .gltf files.
  • A local Solarxy install with solarxy-cli on PATH (verify with solarxy-cli --about).
  • Permission to enable GitHub Actions on the repo.

Step 1: Author a starter solarxy.toml

At the repo root, create a solarxy.toml. Start small - one or two triangle budget categories and a default - then iterate as you learn what your assets actually look like.

#:schema https://raw.githubusercontent.com/marko-koljancic/solarxy/main/schemas/solarxy-config.v1.json

format_version = 1

[budgets]
hero    = 100000
prop    = 20000
default = 30000

[[filenames.rules]]
pattern  = "^hero_"
category = "hero"

[[filenames.rules]]
pattern  = "^prop_"
category = "prop"

Defaults take effect for every section you omit; [validation] toggles all nine checks on except allow_open_mesh. For per-toggle tuning, see Tutorial: Build a custom validation policy.

Add the #:schema line as the first non-blank line so VS Code with Even Better TOML or any JetBrains IDE gives you autocomplete and field-level validation while editing.

Step 2: Run batch validation locally

flowchart TD
    classDef start fill:#33415E,stroke:#FFC44C,color:#FFC44C
    classDef gui fill:#1F2430,stroke:#7FD962,color:#7FD962
    classDef analyze fill:#1F2430,stroke:#78A0EE,color:#78A0EE
    classDef batch fill:#1F2430,stroke:#FFC44C,color:#FFC44C
    classDef exit fill:#1F2430,stroke:#FF3333,color:#FF3333

    Start[solarxy-cli with args]:::start
    Start --> Mode{--mode?}
    Mode -->|view default| GUI[Launch solarxy GUI<br/>--paths ignored]:::gui
    Mode -->|analyze| Paths{--paths<br/>present?}
    Paths -->|no| Single[Single-file analyzer<br/>TUI or JSON]:::analyze
    Paths -->|yes| Batch[Batch validator<br/>via solarxy-validate]:::batch
    Batch --> FailOn{--fail-on}
    FailOn -->|error default| E1[Exit nonzero<br/>on errors]:::exit
    FailOn -->|warning| E2[Exit nonzero<br/>on errors or warnings]:::exit
    FailOn -->|never| E0[Always exit 0]:::gui
Loading

solarxy-cli dispatch. --mode analyze plus --paths is what flips dispatch to batch validation; either alone falls back to the GUI or single-file analyzer.

Before pushing, run the same command CI will run:

solarxy-cli --mode analyze \
  --paths "assets/**/*.glb" "assets/**/*.gltf" \
  --config solarxy.toml \
  --adapter generic \
  --adapter-format json \
  --fail-on error

--mode analyze is required for --paths. The default mode is view, which just launches the GUI and ignores --paths. This is the most-cited footgun in the wiki - see CLI Reference → Batch validation.

The command prints JSON to stdout (or to a file with --output report.json) and exits non-zero if any asset has validation errors. Quote your glob patterns so the shell doesn't expand ** before solarxy-cli sees it.

If you'd rather see findings interactively for a single file, drop --paths and use -m:

solarxy-cli --mode analyze -m assets/prop_barrel_01.glb

This opens the four-tab Analyze TUI.

The local Analyze TUI showing findings

Step 3: Add the GitHub Actions workflow

Create .github/workflows/validate-assets.yml:

name: Validate Assets
on:
  pull_request:
    paths:
      - "assets/**"
      - "solarxy.toml"

jobs:
  validate:
    runs-on: ubuntu-latest
    container: ghcr.io/marko-koljancic/solarxy-cli:0.6
    steps:
      - uses: actions/checkout@v4
      - name: Validate assets
        run: |
          solarxy-cli --mode analyze \
            --paths "assets/**/*.glb" "assets/**/*.gltf" \
            --config solarxy.toml \
            --adapter github-actions \
            --fail-on error

The github-actions adapter's default output format is gha-commands - GitHub Actions workflow commands that surface findings as inline PR annotations. The paths: filter under pull_request: skips the job for code-only PRs that don't touch assets, so artists waiting on PR checks aren't blocked by unrelated CI noise.

The Docker tag :0.6 follows the 0.6.x line and picks up patch fixes without breaking changes. For a fully reproducible pin, use :0.6.0. For the full image reference and mirroring instructions, see CI/CD Integration → The Docker image.

Step 4: Open a PR and observe annotations

Commit the workflow and the solarxy.toml. Push a PR that adds a deliberately bad asset (e.g. a prop_* file with 200000 triangles when the prop budget is 20000).

When the action runs you'll see:

  • A red status check on the PR: "Validate Assets / validate (failed)".
  • Inline annotations on the files-changed view, each pointing at the asset file with the validation message ("Triangle budget exceeded: 198432 / 20000 (prop), tolerance band 24000").

Fix the asset (reduce triangle count or re-categorize), push again, and watch the status turn green.

Step 5: Switch to SARIF for Code Scanning

To surface findings in the repository's Security → Code scanning tab in addition to the PR annotations, emit SARIF and upload it via GitHub's official action. Append a second step to the workflow:

      - name: Validate assets (SARIF)
        run: |
          solarxy-cli --mode analyze \
            --paths "assets/**/*.glb" "assets/**/*.gltf" \
            --config solarxy.toml \
            --adapter github-actions --adapter-format sarif \
            --output solarxy.sarif \
            --fail-on never
      - name: Upload SARIF
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: solarxy.sarif

Two deliberate differences from the gating step:

  • --fail-on never keeps this step green so the upload always runs. The earlier step (with --fail-on error) is still what gates the PR.
  • if: always() on the upload makes it survive a failing earlier step.

Code Scanning surfaces and tracks findings across commits, so trends become visible across the repo over time.

Verify

Open a PR that adds a bad asset. You should observe:

  • Files changed view: inline annotations on the bad assets.
  • PR status check: red, "Validate Assets / validate (failed)".
  • Security → Code scanning: new alerts (if you added the SARIF step).

Fix the asset, push, and confirm green.

What you learned

  • --mode analyze flips dispatch. The same solarxy-cli binary opens the GUI by default; the explicit mode is what makes --paths and the batch validator kick in.
  • The adapter shapes the output for the CI ecosystem. github-actions emits workflow commands by default (PR annotations); generic emits JSON / Text / TAP / JUnit for any other system. Not every format is supported on every adapter - see CI/CD Integration → Adapters and formats.
  • --fail-on controls exit codes. error (default) fails on errors; warning fails on either; never always exits 0 (useful for the SARIF-upload pattern).
  • Config discovery is bounded. For --paths runs, discovery starts in the current working directory, not each asset's directory. Run CI from the repo root or pass --config explicitly. See Configuration → Discovery order.

Where to go next

See also: CI/CD Integration · CLI Reference · Configuration · Tutorial: Build a custom validation policy

Clone this wiki locally