splicer 2.0.1

Plan and generate middleware splice operations for WebAssembly component composition graphs.
Documentation
name: CI

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

env:
  CARGO_TERM_COLOR: always
  # Pinned tool versions shared across all jobs. Bump here once and
  # every install step picks it up.
  WAC_VERSION: "0.10.0"
  WASM_TOOLS_VERSION: "1.247.0"
  CVIZ_VERSION: "2.0.2"
  WKG_VERSION: "0.13.0"

jobs:
  # Figure out whether the PR / push touched code the fuzz harness
  # depends on. Downstream fuzz jobs depend on this so we don't burn
  # CI re-fuzzing unchanged code at a pinned seed.
  changes:
    name: Detect source changes
    runs-on: ubuntu-latest
    outputs:
      fuzz_relevant: ${{ steps.filter.outputs.fuzz_relevant }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            fuzz_relevant:
              - 'src/**'
              - 'wit/**'
              - 'tests/fuzz_and_run.rs'
              - 'Cargo.toml'
              - 'Cargo.lock'
              - '.github/workflows/ci.yml'

  lint:
    name: Format + Clippy
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      # Caching to increase performance as dependency tree grows
      - uses: Swatinem/rust-cache@v2

      - name: Check formatting
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --all-features --all-targets -- -D warnings

  # Run CLI across OS targets
  build_and_test:
    name: Build + Test (${{ matrix.os }})
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - uses: dtolnay/rust-toolchain@stable

      # Caching per OS
      - uses: Swatinem/rust-cache@v2

      - name: Build
        run: cargo build --locked --verbose

      - name: Run tests
        run: cargo test --locked --all-features --verbose --all-targets

  # Integration tests using the component-interposition submodule.
  # Runs the full splicer + wac + wasmtime pipeline against real components.
  integration:
   name: Integration Tests
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v4
       with:
         submodules: recursive
     # Pin toolchain to the version run.sh's check_env expects —
     # otherwise it emits a cargo-version-mismatch WARNING every run.
     # wasm32-wasip1 target is required because run.sh's `build`
     # step compiles the component fixtures for that target.
     - uses: dtolnay/rust-toolchain@1.93.0
       with:
         targets: wasm32-wasip1
     - uses: Swatinem/rust-cache@v2
     - uses: cargo-bins/cargo-binstall@main
     - name: Install tools
       # `cargo binstall` downloads prebuilt release binaries from
       # GitHub when the crate ships them (wac-cli, wasm-tools, cviz
       # all do), falling back to `cargo install` from source on miss.
       run: cargo binstall --no-confirm wac-cli@${{ env.WAC_VERSION }} wasm-tools@${{ env.WASM_TOOLS_VERSION }} cviz@${{ env.CVIZ_VERSION }} wkg@${{ env.WKG_VERSION }}
     - name: Install splicer from the PR-under-test tree
       # The submodule's run.sh calls whichever `splicer` is on PATH.
       # Install from the current checkout so the integration tests
       # exercise THIS PR's splicer, not a stale registry version.
       run: cargo install --path . --force
     - name: Run integration tests
       # `--nocapture` surfaces the component-interposition run.sh
       # output so failures show up in CI logs instead of exiting
       # silently with no context.
       run: cargo test --test integration -- --ignored --nocapture

  # End-to-end fuzz + run harness (tests/fuzz_and_run.rs). Scaffolds
  # provider/consumer/middleware crates in a tempdir, drives both the
  # canned catalog and the `arbitrary`-generated fuzz cases through the
  # full splicer pipeline (compose + splice for both `between` and
  # `before` rules), and invokes the output under wasmtime.
  #
  # Split into two parallel jobs so PR wall-clock is min(canned, fuzz)
  # instead of their sum. Both run on every PR so branch protection
  # can treat each as a required status check without the
  # skipped-means-failed trap that gating on path filters would create.
  fuzz_and_run_canned:
   name: Fuzz + Run (canned)
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v4
       with:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@stable
       with:
         targets: wasm32-wasip1
     - uses: Swatinem/rust-cache@v2
     - uses: cargo-bins/cargo-binstall@main
     - name: Install tools
       run: cargo binstall --no-confirm wac-cli@${{ env.WAC_VERSION }} wasm-tools@${{ env.WASM_TOOLS_VERSION }}
     - name: Canned shape catalog
       run: cargo test --test fuzz_and_run -- --ignored --nocapture test_canned

  fuzz_and_run_fuzz:
   name: Fuzz + Run (fuzz)
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v4
       with:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@stable
       with:
         targets: wasm32-wasip1
     - uses: Swatinem/rust-cache@v2
     - uses: cargo-bins/cargo-binstall@main
     - name: Install tools
       run: cargo binstall --no-confirm wac-cli@${{ env.WAC_VERSION }} wasm-tools@${{ env.WASM_TOOLS_VERSION }}
     - name: Fuzz (25 iters, depth 5)
       env:
         SPLICER_FUZZ_ITERS: "25"
         SPLICER_FUZZ_DEPTH: "5"
       run: cargo test --test fuzz_and_run -- --ignored --nocapture test_fuzz

  # Heavier fuzz run on every push to main — re-validates the merged
  # code against deeper shape trees than PR CI exercised. Gated on the
  # same path filter so a merge that doesn't touch fuzz-relevant paths
  # doesn't re-run this at the same pinned seed.
  fuzz_postmerge:
   name: Fuzz + Run (post-merge, heavy)
   runs-on: ubuntu-latest
   needs: changes
   if: github.event_name == 'push' && needs.changes.outputs.fuzz_relevant == 'true'
   steps:
     - uses: actions/checkout@v4
       with:
         submodules: recursive
     - uses: dtolnay/rust-toolchain@stable
       with:
         targets: wasm32-wasip1
     - uses: Swatinem/rust-cache@v2
     - uses: cargo-bins/cargo-binstall@main
     - name: Install tools
       run: cargo binstall --no-confirm wac-cli@${{ env.WAC_VERSION }} wasm-tools@${{ env.WASM_TOOLS_VERSION }}
     - name: Fuzz (200 iters, depth 6)
       env:
         SPLICER_FUZZ_ITERS: "200"
         SPLICER_FUZZ_DEPTH: "6"
       run: cargo test --test fuzz_and_run -- --ignored --nocapture test_fuzz