ferroni 1.6.1

Oniguruma, continued in pure Rust, with a vscode-oniguruma-compatible TextMate scanner
Documentation
name: CI

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

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

jobs:
  test:
    name: Test (${{ matrix.os }}, ${{ matrix.rust }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        rust: [stable, nightly, "1.94"]
    # rust-toolchain.toml pins the local default toolchain; RUSTUP_TOOLCHAIN
    # makes the matrix selection win over it.
    env:
      RUSTUP_TOOLCHAIN: ${{ matrix.rust }}
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: ${{ matrix.rust }}
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
      - name: Build
        run: cargo build
      - name: Test lib and api
        run: cargo test --lib --test api_test
      - name: Test opt-in match cache
        run: cargo test --locked --features match-cache --lib --test api_test --test match_cache
        env:
          RUST_MIN_STACK: "268435456"
      - name: Test doctests
        run: cargo test --doc
      - name: Test compat_syntax
        run: cargo test --test compat_syntax
      - name: Test compat_options
        run: cargo test --test compat_options
      - name: Test compat_regset
        run: cargo test --test compat_regset
      - name: Test compat_utf8
        run: cargo test --test compat_utf8 -- --test-threads=1
        env:
          RUST_MIN_STACK: "536870912"
      - name: Test compat_back
        run: cargo test --test compat_back -- --test-threads=1
        env:
          RUST_MIN_STACK: "268435456"

  fresh-resolution:
    name: Fresh dependency resolution
    runs-on: ubuntu-latest
    # Library consumers resolve the dependency graph themselves instead of
    # using our committed Cargo.lock, so one lane drops the lockfile and lets
    # Cargo pick the newest compatible versions. This is a resolution lane, not
    # the old edition-2024 manifest workaround the MSRV bump removed: it exists
    # so a dependency release that breaks a fresh build is caught here rather
    # than downstream.
    env:
      RUSTUP_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
      - name: Remove Cargo.lock for fresh resolution
        run: rm -f Cargo.lock
      - name: Build
        run: cargo build --all-targets
      - name: Test lib and api
        run: cargo test --lib --test api_test
      - name: Test doctests
        run: cargo test --doc

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    # cargo-llvm-cov needs the nightly coverage attribute; override the
    # rust-toolchain.toml default for this job.
    env:
      RUSTUP_TOOLCHAIN: nightly
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: nightly
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@94c31af3204a9f15ab40b35ad084410b905bbc73 # v2.87.17
        with:
          tool: cargo-llvm-cov
      # scripts/coverage.sh is the gate. It holds the threshold, the files
      # excluded from the measurement and the stack-heavy tests that have to be
      # skipped under instrumentation, it appends the measured number to the
      # run summary, and it exits non-zero below the threshold. The same script
      # runs locally, so CI and a developer machine cannot disagree.
      - name: Measure coverage and enforce the gate
        run: ./scripts/coverage.sh

  ffi-smoke:
    name: FFI feature smoke
    runs-on: ubuntu-latest
    # rust-toolchain.toml pins the local default toolchain; RUSTUP_TOOLCHAIN
    # keeps the toolchain this job asks for in charge.
    env:
      RUSTUP_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
      - name: Prepare Oniguruma sources
        run: ./scripts/prepare-oniguruma-sources.sh
      # --all-targets also compiles the Criterion benches that need the ffi
      # feature (battle_bench, battle_mem_onig).
      - name: Check ffi feature
        run: cargo check --features ffi --all-targets
      - name: Compare match cache with C Oniguruma
        run: cargo test --locked --features ffi,match-cache --test match_cache_differential -- --nocapture
        env:
          RUST_MIN_STACK: "268435456"
      # The original breakage only showed in the published layout (benches/
      # and scripts/ are excluded from the crate), so also check the packaged
      # artifact with the sources supplied via FERRONI_ONIGURUMA_DIR.
      - name: Check ffi feature from the packaged crate
        run: |
          cargo package --no-verify
          crate=$(ls target/package/ferroni-*.crate)
          tar -xzf "$crate" -C target/package
          pkg_dir="${crate%.crate}"
          FERRONI_ONIGURUMA_DIR="$GITHUB_WORKSPACE/.cache/upstream/oniguruma-orig" \
            cargo check --features ffi --manifest-path "$pkg_dir/Cargo.toml"

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    # rust-toolchain.toml pins the local default toolchain; RUSTUP_TOOLCHAIN
    # keeps the toolchain this job asks for in charge.
    env:
      RUSTUP_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: stable
          components: clippy
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
      # --all-features includes ffi, which compiles the upstream C sources.
      - name: Prepare Oniguruma sources
        run: ./scripts/prepare-oniguruma-sources.sh
      # The allowed lints live in the [lints] table of Cargo.toml, never on the
      # command line: command-line flags outrank the manifest, so a lint denied
      # here would silently override the table.
      - run: cargo clippy --all-targets --all-features --locked -- -D warnings

  docs:
    name: Rustdoc
    runs-on: ubuntu-latest
    # rust-toolchain.toml pins the local default toolchain; RUSTUP_TOOLCHAIN
    # keeps the toolchain this job asks for in charge.
    env:
      RUSTUP_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
      # Mirrors the docs.rs build, which does not enable the ffi feature.
      - run: cargo doc --no-deps --locked
        env:
          RUSTDOCFLAGS: -D warnings
      - run: cargo doc --no-deps --locked --features match-cache
        env:
          RUSTDOCFLAGS: -D warnings

  deny:
    name: cargo-deny
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2.1.1
        with:
          arguments: --all-features --locked

  readme-family:
    name: README themes
    runs-on: ubuntu-latest
    # Native composition checks both shared frames and the project content.
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
        with:
          version: 2026.9.12
          install_args: --locked
      - name: Check the generated README
        run: ./scripts/readme-family.sh check

  docs-format:
    name: Docs format
    runs-on: ubuntu-latest
    # The documentation site is a declared Node workspace with the org's
    # managed oxfmt configuration, so its formatting is checked here rather
    # than only on the developer's machine. Node only -- it never builds the
    # crate, which is why it stays outside the Rust matrix.
    defaults:
      run:
        working-directory: docs
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v4.4.0
        with:
          version: 10.34.5
      - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
        with:
          node-version: '24'
          cache: 'pnpm'
          cache-dependency-path: docs/pnpm-lock.yaml
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
      - name: Lint documentation
        run: pnpm lint
      - name: Typecheck documentation
        run: pnpm typecheck
      - name: Check formatting
        run: pnpm format:check
      - name: Build documentation
        run: pnpm build

  fmt:
    name: Format
    runs-on: ubuntu-latest
    # rust-toolchain.toml pins the local default toolchain; RUSTUP_TOOLCHAIN
    # keeps the toolchain this job asks for in charge.
    env:
      RUSTUP_TOOLCHAIN: stable
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
        with:
          toolchain: stable
          components: rustfmt
      - run: cargo fmt -- --check
      # The fuzz harness is its own workspace, so it needs its own invocation.
      - run: cargo fmt --manifest-path fuzz/Cargo.toml -- --check
      - name: Check that workflow actions are pinned by SHA
        run: ./scripts/check-workflow-pins.sh

  standards:
    name: standards drift
    runs-on: ubuntu-latest
    # Reports drift from @sebastian-software/standards. Node only -- it never
    # builds the crate, which is why it stays outside the Rust matrix.
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: "Guard: agent step not yet completed for this PR"
        run: test ! -f .standards/pending.json

      - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v4.4.0
        with:
          # This repository has no root package.json to read `packageManager`
          # from, so the pnpm version is spelled out here.
          version: 10.34.5
      - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
        with:
          node-version: '24'

      # A Rust-only repository has no lockfile to pin the CLI in, so the
      # version is pinned here and Renovate's regex manager in renovate.json
      # moves it. An unpinned `dlx` would execute whatever was published
      # minutes ago, with the job's token.
      #
      # minimum-release-age=0 stays: pnpm 11 defaults minimumReleaseAge to 1440
      # (24h), so without the bypass a pin that was raised on the day of a
      # standards release cannot resolve at all.
      - run: pnpm --config.minimum-release-age=0 dlx @sebastian-software/standards@0.13.0 check