# IMPORTANT: Run this manually shortly before a new Rust stable release
# is expected. This job should be kept the same as ci.yml, except for the
# following changes:
#
# * All instances of `stable` should be replaced with `beta`.
# * All jobs that require Rust `nightly` should be deleted.

name: Preflight with Rust beta

on:
  workflow_dispatch:
  push:
    branches:
      - beta-preflight

jobs:
  get-features:
    name: Get features
    runs-on: ubuntu-latest
    outputs:
      features: ${{ steps.get-features.outputs.features }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: stable

      - name: Get all features (excluding experimental)
        id: get-features
        run: |
          # Union of every workspace feature except `default` and experimental
          # (`unstable_`) features, so this preflight mirrors a full build
          # without pulling in experimental code. Experimental features are
          # exercised only by the non-blocking experimental-features.yml; see
          # docs/experimental-features.md.
          FEATURES=$(cargo metadata --format-version=1 --no-deps | jq -r '[.packages[] | .features | keys[]] | unique | map(select(. != "default" and (startswith("unstable_") | not))) | join(" ")')
          echo "features=$FEATURES" >> "$GITHUB_OUTPUT"

  tests:
    name: Unit tests
    needs: get-features

    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]
        rust_version: [beta]

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: ${{ matrix.rust_version }}
          components: llvm-tools-preview

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@4684b8405694ae9dd42c9f39ba901a70ae83f4a3 # v2.82.9
        with:
          tool: cargo-llvm-cov

      - name: Generate code coverage
        env:
          RUST_BACKTRACE: "1"
        run: cargo llvm-cov --lib --features "${{ needs.get-features.outputs.features }}" --lcov --output-path lcov.info

  tests-cli:
    name: Unit tests (c2patool)
    needs: get-features
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]
        rust_version: [beta]

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: ${{ matrix.rust_version }}
          components: llvm-tools-preview

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@4684b8405694ae9dd42c9f39ba901a70ae83f4a3 # v2.82.9
        with:
          tool: cargo-llvm-cov

      - name: Generate code coverage
        env:
          RUST_BACKTRACE: "1"
        run: cargo llvm-cov --bins --features "${{ needs.get-features.outputs.features }}" --lcov --output-path lcov.info

  doc-tests:
    name: Doc tests (requires nightly Rust)
    needs: get-features
    # TODO: Remove this once cargo-llvm-cov can run doc tests and generate
    # coverage. (This requires a bug fix that is only available in nightly Rust.)
    # Watch https://github.com/taiki-e/cargo-llvm-cov/issues/2
    # for progress.

    runs-on: ${{ matrix.os }}

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

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: beta
      # - name: Install Rust toolchain
      #   uses: dtolnay/rust-toolchain@nightly
      #   with:
      #     components: llvm-tools-preview

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@4684b8405694ae9dd42c9f39ba901a70ae83f4a3 # v2.82.9
        with:
          tool: cargo-llvm-cov

      # Disabling code coverage for doc tests due to a new bug in Rust nightly
      # as of 2025-01-08. Will investigate later to see if there's a repro case.
      # Meanwhile, simply run the tests so we know if there are any failing
      # doc tests.

      - name: Run doc tests (COVERAGE DISABLED)
        run: cargo test --workspace --features "${{ needs.get-features.outputs.features }}" --doc

      # - name: Generate code coverage
      #   env:
      #     RUST_BACKTRACE: "1"
      #   run: cargo llvm-cov --workspace --all-features --lcov --doctests --output-path lcov.info

      # Tokens aren't available for PRs originating from forks,
      # so we don't attempt to upload code coverage in that case.
      # - name: Upload code coverage results
      #   if: |
      #     github.event_name != 'pull_request' ||
      #     github.event.pull_request.author_association == 'COLLABORATOR' ||
      #     github.event.pull_request.author_association == 'MEMBER' ||
      #     github.event.pull_request.user.login == 'dependabot[bot]'
      #   uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
      #   with:
      #     token: ${{ secrets.CODECOV_TOKEN }}
      #     fail_ci_if_error: true
      #     verbose: true

  cargo-check:
    name: Default features build
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: beta

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: "`cargo check` with default features"
        run: cargo check

  tests-cross:
    name: Unit tests
    needs: get-features
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        target: [aarch64-unknown-linux-gnu]
        rust_version: [beta]

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: ${{ matrix.rust_version }}
          targets: ${{ matrix.target }}

      - name: Install cross-compilation toolset
        run: cargo install cross

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      # Note that we do not run code coverage because
      # it isn't readily accessible from cross-compilation
      # environment. (A PR to fix this would be welcomed!)

      # Integration tests are excluded because they require executing
      # the compiled binary, which isn't reliably possible when cross-compiling,
      # due to architecture mismatch.
      - name: Run unit tests (cross build)
        run: cross test --lib --bins --features "${{ needs.get-features.outputs.features }}" --target ${{ matrix.target }}

  tests-wasm:
    name: Unit tests (WASM)
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: beta

      - name: Add wasm web target
        run: rustup target add wasm32-unknown-unknown

      - name: Install cargo-binstall
        uses: cargo-bins/cargo-binstall@732870f031d2fb36309d0deaf36abcc704a7be65 # v1.20.1

      - name: Extract wasm-bindgen version from Cargo.lock
        id: wasm-bindgen-version
        run: |
          VERSION=$(cargo metadata --format-version 1 --locked | jq -r '.packages[] | select(.name == "wasm-bindgen") | .version')
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Using wasm-bindgen version: $VERSION"

      - name: Install wasm-bindgen-cli
        run: cargo binstall -y wasm-bindgen-cli --version ${{ steps.wasm-bindgen-version.outputs.version }}

      - name: Run Wasm tests
        run: cargo test -p c2pa --no-default-features --features rust_native_crypto,fetch_remote_manifests --target wasm32-unknown-unknown
        env:
          CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER: wasm-bindgen-test-runner
          GECKODRIVER: geckodriver
          WASM_BINDGEN_TEST_TIMEOUT: 60

  clippy_check:
    name: Clippy
    needs: get-features
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master@2026-06-30
        with:
          toolchain: beta
          components: clippy

      - name: Cache Rust dependencies
        uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1

      - name: Run Clippy
        run: cargo clippy --features "${{ needs.get-features.outputs.features }}" --all-targets -- -Dwarnings
