culvert-async 0.2.0

Async typed access to the HDMI 2.1 SCDC register map
Documentation
name: CI

on:
  push:
    branches: [main, develop]
  # Not main: the only PRs into main are release-tag's release-promote/* PRs,
  # whose content already passed CI on develop. Opened by github-actions[bot],
  # their runs would be held for approval and end as action_required/failure.
  pull_request:
    branches: [develop]

env:
  CARGO_TERM_COLOR: always
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install stable toolchain
        uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
        with:
          toolchain: stable
          components: rustfmt, clippy
          targets: thumbv7em-none-eabi

      - name: Cache
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: ${{ runner.os }}-cargo-

      - name: Format check
        run: cargo fmt --check

      - name: Clippy
        run: cargo clippy --locked --all-features -- -D warnings

      - name: Docs
        run: cargo rustdoc --locked --all-features -- -D missing_docs

      - name: Test
        run: cargo test --locked

      - name: Test (plumbob-async feature)
        run: cargo test --locked --features plumbob-async

      - name: Run the example
        run: cargo run --locked --example scdc

      - name: Build (no_std)
        run: cargo build --locked --no-default-features --target thumbv7em-none-eabi

      - name: Build (no_std, plumbob-async feature)
        run: cargo build --locked --no-default-features --features plumbob-async --target thumbv7em-none-eabi

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install stable toolchain
        uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
        with:
          toolchain: stable
          components: llvm-tools-preview

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@1168f6810a3cb30a3514bf5756a3b7f0422c6df8 # v2.87.28
        with:
          tool: cargo-llvm-cov

      - name: Cache
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-coverage-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: ${{ runner.os }}-coverage-

      - name: Measure coverage
        run: |
          cargo llvm-cov clean --workspace
          cargo llvm-cov --no-report --locked
          # The `plumbob-async` adapter is only compiled with its feature; measure it too, so
          # the baseline covers it. The two runs are merged into one report.
          cargo llvm-cov --no-report --locked --features plumbob-async
          LINES=$(cargo llvm-cov report --json --summary-only \
            | python3 -c "import sys,json; d=json.load(sys.stdin); print(round(d['data'][0]['totals']['lines']['percent'], 2))")
          echo "COVERAGE=${LINES}" >> "$GITHUB_ENV"

      - name: Check coverage
        run: |
          BASELINE=$(cat .coverage-baseline)
          echo "Coverage: ${COVERAGE}%  Baseline: ${BASELINE}%"
          python3 -c "import sys; sys.exit(0 if float('${COVERAGE}') >= float('${BASELINE}') - 0.1 else 1)" \
            || { echo "Coverage dropped below baseline"; exit 1; }

      - name: Update baseline if improved
        if: github.event_name == 'push'
        run: |
          BASELINE=$(cat .coverage-baseline)
          if awk "BEGIN { exit !(${COVERAGE} > ${BASELINE}) }"; then
            LC_NUMERIC=C printf '%.2f\n' "${COVERAGE}" > .coverage-baseline
            echo "Baseline updated: ${BASELINE} -> ${COVERAGE}"
          else
            echo "No update needed (${COVERAGE} <= ${BASELINE})"
          fi

      - name: Open PR if baseline changed
        if: github.event_name == 'push'
        uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          branch: ci/coverage-ratchet
          commit-message: "ci: ratchet coverage baseline to ${{ env.COVERAGE }}%"
          title: "ci: ratchet coverage baseline to ${{ env.COVERAGE }}%"
          body: |
            Coverage improved to `${{ env.COVERAGE }}%`. Updated `.coverage-baseline`.

            *Opened automatically by the coverage CI job.*
          add-paths: .coverage-baseline