metadata-gen 0.0.8

A powerful Rust library for extracting, validating, and processing metadata in YAML, TOML, and JSON formats from any content or data file.
Documentation
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
# The gates the repository standard requires that `ci.yml` does not
# cover: coverage threshold, Miri, fuzz corpus replay, docs lint,
# cargo-vet provenance, version consistency, examples and benches.
#
# Kept separate from ci.yml so the shared `rust-ci.yml` call there stays
# a straight upgrade path when the pipelines repo changes.

name: Quality

on:
  push:
    branches: [main, "feat/**"]
  pull_request:
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

jobs:
  coverage-gate:
    name: coverage (98% lines)
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: nightly
          components: llvm-tools-preview
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 # v2.87.22, installs cargo-llvm-cov
        with:
          tool: cargo-llvm-cov
      # The threshold and its rationale live in DEVELOPMENT.md. A number
      # chosen once and defended beats chasing 100%.
      - run: cargo llvm-cov --all-features --locked --fail-under-lines 98

  miri:
    name: miri
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: nightly
          components: miri
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      # The crate forbids unsafe, so this checks the interaction with
      # dependencies that use it internally. Filesystem tests are
      # skipped by #[cfg_attr(miri, ignore)] — isolation forbids open().
      - run: cargo +nightly miri test --lib

  fuzz-replay:
    name: fuzz build + corpus replay
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: nightly
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
        with:
          workspaces: fuzz
      # From source, deliberately. The prebuilt binary taiki-e ships is
      # a musl build and mis-infers the fuzz target triple, so it emits
      # sanitized fuzzers for x86_64-unknown-linux-musl and dies on
      # "sanitizer is incompatible with statically linked libc".
      - run: cargo install --locked cargo-fuzz
      # -runs=0 replays the committed inputs without generating new
      # ones: the seeds prove the targets still build and run, and
      # fuzz/regressions/ proves a fixed crash cannot come back.
      - name: Build every target and replay the corpus
        working-directory: fuzz
        run: |
          set -euo pipefail
          cargo +nightly fuzz build
          for target in $(cargo +nightly fuzz list); do
            echo "== $target"
            dirs=("corpus/$target")
            [ -d "regressions/$target" ] && dirs+=("regressions/$target")
            cargo +nightly fuzz run "$target" -- -runs=0 "${dirs[@]}"
          done

  proptest:
    name: proptest property verification
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      - run: cargo test --test test_proptest -- --nocapture

  loom:
    name: loom concurrency check
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      - run: RUSTFLAGS="--cfg loom" cargo test --test loom_smoke --release

  docs-lint:
    name: docs lint (markdownlint, codespell, REUSE)
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
      - run: npx --yes markdownlint-cli2 "**/*.md" "!target/**" "!fuzz/target/**"
      - run: uvx codespell
      - run: uvx --with chardet reuse lint

  cargo-vet:
    name: cargo-vet
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          # Pinned by SHA, the action cannot read the toolchain from the
          # ref, so it is named here.
          toolchain: stable
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      # Pinned: releases before 0.10 reject a `[[trusted.*]]` entry that
      # names a `trusted-publisher` instead of a `user-id`, which is how
      # a crates.io Trusted Publishing release is attested.
      - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 # v2.87.22, installs cargo-vet
        with:
          tool: cargo-vet@0.10.2
      - run: cargo vet --locked
      # Exemptions may shrink, never grow. A new dependency arrives with
      # an audit or a trust entry, not with another exemption.
      - name: Exemption ratchet
        run: |
          set -euo pipefail
          baseline="$(tr -d '[:space:]' < supply-chain/exemptions-baseline.txt)"
          current="$(cargo vet --locked 2>&1 | grep -oE '[0-9]+ exempted' | grep -oE '[0-9]+')"
          echo "exempted: $current (baseline $baseline)"
          if [ "$current" -gt "$baseline" ]; then
            echo "::error::exemptions grew from $baseline to $current"
            exit 1
          fi

  release-hygiene:
    name: versions, examples, benches
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          # Pinned by SHA, the action cannot read the toolchain from the
          # ref, so it is named here.
          toolchain: stable
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      # Every version-bearing file must agree with Cargo.toml before a
      # tag exists, not after the release workflow rejects the tag.
      - run: ./scripts/verify-release-versions.sh
      # Docs that run: an example that stops working fails the build.
      - run: make examples
      # Benches stay compiling and runnable; no measurement is asserted.
      - run: cargo bench --all-features -- --test
      - name: rustdoc with warnings denied
        env:
          RUSTDOCFLAGS: -D warnings
        run: cargo doc --no-deps --all-features --locked

  msrv:
    name: MSRV (1.88.0)
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          # `rust-version` in Cargo.toml. A dependency or syntax that
          # needs a newer compiler fails here, not on a user's machine.
          toolchain: 1.88.0
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      - run: cargo check --all-features --all-targets --locked

  semver-checks:
    name: API breakage (cargo-semver-checks)
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 # v2.87.22, installs cargo-semver-checks
        with:
          tool: cargo-semver-checks
      # Compares the public API against the last crates.io release. While
      # the crate is 0.0.x every release is a major bump under semver, so
      # today this proves the version moved; the lints bite from 0.1.0.
      - run: cargo semver-checks check-release --all-features

  feature-powerset:
    name: feature powerset (cargo-hack)
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: stable
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      - uses: taiki-e/install-action@83ac0ad63c0167e6f06796fab0fce28db1bf3db0 # v2.87.22, installs cargo-hack
        with:
          tool: cargo-hack
      - run: cargo hack check --feature-powerset --all-targets --locked

  no-std:
    name: no_std + alloc (thumbv7em-none-eabihf)
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: stable
          targets: thumbv7em-none-eabihf
      - uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2
      # A target with no `std` at all: the build fails if anything in the
      # tree names `std` without the `std` feature (ADR-0005).
      - run: cargo build --lib --locked --no-default-features --features yaml,toml,json --target thumbv7em-none-eabihf
      # A format that is compiled out must report UnsupportedFormatError.
      - run: cargo test --lib --locked --no-default-features --features yaml

  complexity:
    name: complexity (per-function ceilings)
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
        with:
          toolchain: stable
      - uses: taiki-e/cache-cargo-install-action@9ee83daaa7b96a6fab930949ecf1122bba04a389 # v3.0.8
        with:
          tool: rust-code-analysis-cli@0.0.25
      # Ceilings and the (empty) baseline are in scripts/complexity_check.py
      # and complexity-baseline.txt. The baseline may only shrink.
      - run: python3 -I scripts/complexity_check.py

  links:
    name: links (lychee)
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
        with:
          args: --config lychee.toml './**/*.md'
          fail: true
          token: ${{ secrets.GITHUB_TOKEN }}