bsv-tracker 0.4.1

A transaction evidence state machine with host supplied headers, proofs, hints and time
Documentation
name: ci

# The machine gate. The job ids below are the status-check contexts that branch
# protection on main requires (test, fmt, clippy, vectors, wasm32); renaming a
# job removes its context and blocks every PR until the protection is updated.
# The lint bar's jobs (msrv, machete, secrets, actionlint) are not required
# contexts until the keeper adds them; machete stays non-blocking.
# Every action is pinned by commit sha; the tag it was read at is in the comment.
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
  # release.yml runs the same jobs on a tag before it publishes.
  workflow_call:

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

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

defaults:
  run:
    shell: bash

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: stable

      # Cargo.lock is tracked, so the key follows the lock and every job is --locked.
      - name: Cache cargo
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ubuntu-test-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            ubuntu-test-

      - name: Run the tests
        run: cargo test --locked

      - name: Build the documentation
        run: cargo doc --locked --no-deps
        env:
          RUSTDOCFLAGS: -Dwarnings

  fmt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: stable
          components: rustfmt

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

  clippy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: stable
          components: clippy

      - name: Cache cargo
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ubuntu-clippy-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            ubuntu-clippy-

      - name: Run Clippy
        run: cargo clippy --locked --all-targets -- -D warnings

  # The wire witnesses, by name. Each step counts its passes, so a renamed or
  # removed test turns the job red and never leaves a green check that ran nothing.
  vectors:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: stable

      - name: Cache cargo
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ubuntu-vectors-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            ubuntu-vectors-

      # tests/vectors/chain_events/{tip,fork,reorg,invalidated,frozen,tip_age}.json (v1)
      # and {split,split_resolved}.json (v2)
      - name: The eight chain-event envelope vectors
        run: |
          cargo test --locked --test chain_events -- --exact \
            pinned_tip_round_trip \
            pinned_fork_round_trip \
            pinned_reorg_round_trip \
            pinned_invalidated_round_trip \
            pinned_frozen_round_trip \
            pinned_tip_age_round_trip \
            pinned_split_round_trip \
            pinned_split_resolved_round_trip | tee chain_events.out
          grep -q '^test result: ok. 8 passed; 0 failed; 0 ignored' chain_events.out

      # tests/vectors/arc_tx_status_verdicts.json
      - name: The ARC status vector
        run: |
          cargo test --locked --test verdicts -- --exact \
            arc_p0_2_twenty_bodies_are_only_hints | tee verdicts.out
          grep -q '^test result: ok. 1 passed; 0 failed; 0 ignored' verdicts.out

  # The wallet, the overlay engine and the app layer host this crate in wasm.
  wasm32:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: stable
          targets: wasm32-unknown-unknown

      - name: Cache cargo
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ubuntu-wasm32-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            ubuntu-wasm32-

      - name: Build for wasm32-unknown-unknown
        run: cargo build --locked --target wasm32-unknown-unknown --features wasm

  # The declared rust-version builds (bsv-stack-lean #139). Keep the toolchain
  # equal to rust-version in Cargo.toml; a move of one moves the other.
  msrv:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: "1.88"

      - name: Cache cargo
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ubuntu-msrv-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            ubuntu-msrv-

      - name: The declared rust-version is the toolchain
        run: |
          declared=$(cargo metadata --locked --no-deps --format-version 1 | jq -r '.packages[0].rust_version')
          if [ "$declared" != "1.88" ]; then
            echo "::error::rust-version $declared differs from the msrv job's toolchain 1.88"
            exit 1
          fi

      - name: Check at the MSRV
        run: cargo check --locked --all-targets

  # Unused dependencies (bsv-stack-lean #137). Non-blocking until the keeper
  # makes it a required check; the tool is pinned by version and its lock.
  machete:
    runs-on: ubuntu-latest
    continue-on-error: true
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f # master
        with:
          toolchain: stable

      - name: Install cargo-machete
        run: cargo install cargo-machete --version 0.9.2 --locked --root "$RUNNER_TEMP/tools"

      - name: Find unused dependencies
        run: '"$RUNNER_TEMP/tools/bin/cargo-machete" --with-metadata'

  # The secrets scan (bsv-stack-lean #140): every commit of the history,
  # findings redacted. gitleaks 8.28.0 is built from its release source,
  # pinned by the tarball's sha256 (the Homebrew formula's pin of 8.28.0).
  secrets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
        with:
          fetch-depth: 0

      - name: Install gitleaks 8.28.0
        run: |
          curl -sSfL -o "$RUNNER_TEMP/gitleaks.tar.gz" \
            https://github.com/gitleaks/gitleaks/archive/refs/tags/v8.28.0.tar.gz
          echo "c681af8aeacacf9d14f7ad97d534cf087f6d2d6fbd50dd02020b0f929b7a1c41  $RUNNER_TEMP/gitleaks.tar.gz" | sha256sum -c -
          tar -xzf "$RUNNER_TEMP/gitleaks.tar.gz" -C "$RUNNER_TEMP"
          cd "$RUNNER_TEMP/gitleaks-8.28.0"
          go build -o "$RUNNER_TEMP/tools/gitleaks" .

      - name: Scan the history
        run: '"$RUNNER_TEMP/tools/gitleaks" git --redact --no-banner --exit-code 1 .'

  # The workflows linted (bsv-stack-lean #145). actionlint 1.7.12 is built
  # from its release source, pinned by the tarball's sha256 (the Homebrew
  # formula's pin of 1.7.12); it runs shellcheck on every run step.
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

      - name: Install actionlint 1.7.12
        run: |
          curl -sSfL -o "$RUNNER_TEMP/actionlint.tar.gz" \
            https://github.com/rhysd/actionlint/archive/refs/tags/v1.7.12.tar.gz
          echo "454800bd4f854592bcfe79b161f71d56e35940eb7016e48a26dd356adc9d400a  $RUNNER_TEMP/actionlint.tar.gz" | sha256sum -c -
          tar -xzf "$RUNNER_TEMP/actionlint.tar.gz" -C "$RUNNER_TEMP"
          cd "$RUNNER_TEMP/actionlint-1.7.12"
          go build -o "$RUNNER_TEMP/tools/actionlint" ./cmd/actionlint

      - name: Lint the workflows
        run: '"$RUNNER_TEMP/tools/actionlint" -color'