name: CI

permissions:
  contents: read

on:
  push:
    branches: [main]
  pull_request:

env:
  CARGO_TERM_COLOR: always
  RUSTC_WRAPPER: "sccache"

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  matrices:
    name: build matrices
    runs-on: ubuntu-latest
    timeout-minutes: 5
    permissions:
      contents: read
    outputs:
      test-matrix: ${{ steps.gen.outputs.test-matrix }}
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
        with:
          python-version: "3.14"
      - name: Generate matrices
        id: gen
        shell: bash
        run: |
          output=$(python3 .github/scripts/matrices.py)
          printf '::debug::test-matrix=%s\n' "$output"
          printf 'test-matrix=%s\n' "$output" >> "$GITHUB_OUTPUT"

  test:
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.runner_label }}
    needs: matrices
    timeout-minutes: 30
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.matrices.outputs.test-matrix) }}

    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - name: Install LLVM
        if: ${{ matrix.os == 'ubuntu' }}
        run: .github/scripts/install_llvm.sh ubuntu
      - name: Install LLVM
        if: ${{ matrix.os == 'macos' }}
        run: .github/scripts/install_llvm.sh macos
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        if: ${{ !matrix.target }}
        with:
          toolchain: ${{ matrix.rust }}
      - uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537 # master
        if: ${{ matrix.target }}
        with:
          toolchain: ${{ matrix.rust }}
          targets: ${{ matrix.target }}
      - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1
        if: runner.os == 'Linux'
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          cache-on-failure: true
          cache-bin: false
      - uses: taiki-e/install-action@41049aa56687c35e0afa74eed4f09cec4f9afabf # v2.85.2
        if: ${{ !matrix.command || matrix.command == 'nextest' }}
        with:
          tool: nextest
      - uses: taiki-e/install-action@41049aa56687c35e0afa74eed4f09cec4f9afabf # v2.85.2
        if: ${{ matrix.command == 'cross-test' }}
        with:
          tool: cross
      - uses: taiki-e/install-action@41049aa56687c35e0afa74eed4f09cec4f9afabf # v2.85.2
        if: ${{ matrix.command == 'wasm-test' }}
        with:
          tool: wasmtime
      - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
        if: ${{ matrix.kind == 'eest' }}
      - name: Download EEST fixtures
        if: ${{ matrix.kind == 'eest' }}
        shell: bash
        run: |
          if [[ "${{ matrix.fixture }}" == "devnet" ]]; then
            export DEVNET_VERSION="tests-glamsterdam-devnet%40v7.2.0"
            export DEVNET_TAR="fixtures_glamsterdam-devnet.tar.gz"
            export EVM2_STATETEST_DEVNET_ONLY=1
          fi
          ./scripts/setup_test_fixtures.py
      - name: ${{ matrix.kind }}
        if: ${{ !matrix.command || matrix.command == 'nextest' }}
        shell: bash
        run: |
          package_flags=(--workspace)
          if [[ -n "${{ matrix.cxx }}" ]]; then
            export CXX="${{ matrix.cxx }}"
            cargo clean -p mcl_rust
          fi
          extra_flags=()
          if [[ "${{ matrix.kind }}" == "eest" ]]; then
            package_flags=(-p evm2-eest)
            extra_flags+=(--ignore-default-filter)
            extra_flags+=(-E 'not test(/::(?:jit|aot)(?:$|::)/)')
          elif [[ "${{ matrix.os }}" == "windows" ]]; then
            package_flags+=(
              --exclude evm2-jit
              --exclude evm2-jit-*
            )
          fi
          if [[ "${{ matrix.fixture }}" == "devnet" ]]; then
            export EVM2_STATETEST_ROOT="test-fixtures/devnet/state_tests"
            export EVM2_BLOCKCHAINTEST_ROOT="test-fixtures/devnet/blockchain_tests"
          fi
          cargo nextest --profile ci run "${package_flags[@]}" --no-fail-fast ${{ matrix.flags }} "${extra_flags[@]}"
      - name: cross test
        if: ${{ matrix.command == 'cross-test' }}
        shell: bash
        run: |
          if [[ -n "${{ matrix.cxx }}" ]]; then
            export CXX="${{ matrix.cxx }}"
          fi
          cross test --workspace --exclude evm2-eest --target ${{ matrix.target }} --no-fail-fast --lib --bins --tests ${{ matrix.flags }}
      - name: wasm build
        if: ${{ matrix.command == 'build' }}
        shell: bash
        run: |
          if [[ -n "${{ matrix.cxx }}" ]]; then
            export CXX="${{ matrix.cxx }}"
          fi
          cargo build -p evm2 --target ${{ matrix.target }} ${{ matrix.flags }}
      - name: wasm test
        if: ${{ matrix.command == 'wasm-test' }}
        env:
          CARGO_TARGET_WASM32_WASIP1_RUNNER: wasmtime
          RUSTFLAGS: ${{ matrix.rustflags }}
        run: cargo test -p evm2 --target ${{ matrix.target }} --no-fail-fast --lib --tests ${{ matrix.flags }}
      - name: doctest
        if: ${{ matrix.kind == 'test' && !matrix.target }}
        run: cargo test --workspace ${{ matrix.flags }} --doc

  jit:
    name: jit ${{ matrix.os }} ${{ matrix.mode }}
    runs-on: ${{ matrix.runner_label }}
    timeout-minutes: 120
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu
            runner_label: depot-ubuntu-latest-4
            mode: jit
            subset: all
            filter: test(statetests::jit)
          - os: ubuntu
            runner_label: depot-ubuntu-latest-4
            mode: aot
            subset: ci-aot
            filter: test(statetests::aot)
          - os: macos
            runner_label: depot-macos-latest
            mode: jit
            subset: ci-smoke
            filter: test(statetests::jit)
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - name: Install LLVM
        if: ${{ matrix.os == 'ubuntu' }}
        run: .github/scripts/install_llvm.sh ubuntu
      - name: Install LLVM
        if: ${{ matrix.os == 'macos' }}
        run: .github/scripts/install_llvm.sh macos
      - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1
        with:
          toolchain: stable
      - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1
        if: runner.os == 'Linux'
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
        with:
          cache-on-failure: true
          cache-bin: false
      - uses: taiki-e/install-action@41049aa56687c35e0afa74eed4f09cec4f9afabf # v2.85.2
        with:
          tool: nextest
      - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      - name: Download EEST fixtures
        run: ./scripts/setup_test_fixtures.py
      - name: eest ${{ matrix.mode }}
        env:
          EVM2_COMPILED_EEST_SUBSET: ${{ matrix.subset }}
        run: |
          cargo nextest --profile ci run -p evm2-eest --features jit --test eest \
            --ignore-default-filter --no-fail-fast -E "${{ matrix.filter }}"

  no-std:
    name: no_std ${{ matrix.target }}
    runs-on: depot-ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        target: ["riscv32imac-unknown-none-elf", "riscv64imac-unknown-none-elf"]
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
        with:
          targets: ${{ matrix.target }}
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          cache-on-failure: true
          cache-bin: false
      - name: check
        run: cargo build -p evm2 --target ${{ matrix.target }} --no-default-features

  feature-checks:
    name: features ${{ matrix.flags }}
    runs-on: depot-ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        flags: ["", "--all-targets"]
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - name: Install LLVM
        run: .github/scripts/install_llvm.sh ubuntu
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
      - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1
      - uses: taiki-e/install-action@41049aa56687c35e0afa74eed4f09cec4f9afabf # v2.85.2
        with:
          tool: cargo-hack
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          cache-on-failure: true
          cache-bin: false
      - name: cargo hack
        run: cargo hack check --workspace --each-feature --skip nightly ${{ matrix.flags }}

  feature-propagation:
    runs-on: depot-ubuntu-latest
    timeout-minutes: 20
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
      - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 # v3.0.7
        with:
          tool: zepter
      - name: Eagerly pull dependencies
        run: cargo generate-lockfile
      - run: zepter run check

  examples:
    runs-on: depot-ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          cache-on-failure: true
          cache-bin: false
      - name: Check examples
        run: cargo build --workspace --examples

  typos:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: crate-ci/typos@bee27e3a4fd1ea2111cf90ab89cd076c870fce14 # v1.48.0

  clippy:
    runs-on: depot-ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - name: Install LLVM
        run: .github/scripts/install_llvm.sh ubuntu
      - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly
        with:
          components: clippy
      - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          cache-on-failure: true
          cache-bin: false
      - run: cargo clippy --workspace --all-targets --all-features
        env:
          RUSTFLAGS: -Dwarnings

  docs:
    runs-on: depot-ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - name: Install LLVM
        run: .github/scripts/install_llvm.sh ubuntu
      - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly
      - uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1
      - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          cache-on-failure: true
          cache-bin: false
      - name: Build documentation
        run: cargo doc --workspace --all-features --no-deps --document-private-items
        env:
          RUSTFLAGS: -Dwarnings

  fmt:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly
        with:
          components: rustfmt
      - run: cargo fmt --all --check

  deny:
    permissions:
      contents: read
    uses: tempoxyz/ci/.github/workflows/deny.yml@934b6a6317ac26272eaecf0d265472f4105c99d6 # 2026.05.09

  ci-success:
    name: ci success
    runs-on: ubuntu-latest
    if: always()
    permissions:
      contents: read
    needs:
      - matrices
      - test
      - jit
      - no-std
      - feature-checks
      - feature-propagation
      - examples
      - typos
      - clippy
      - docs
      - fmt
      - deny
    steps:
      - name: Decide whether the needed jobs succeeded or failed
        uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
        with:
          jobs: ${{ toJSON(needs) }}
