Fix/v2 cpi context borrow check #8534
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Tests | |
| on: | |
| push: | |
| branches: | |
| - anchor-next | |
| paths-ignore: | |
| - "docs/**" | |
| pull_request: | |
| paths-ignore: | |
| - "docs/**" | |
| workflow_dispatch: | |
| env: | |
| SOLANA_VERSION: "3.1.10" | |
| SBF_TOOLS_VERSION: "v1.52" | |
| jobs: | |
| test-v2: | |
| name: v2 Tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| env: | |
| CARGO_INCREMENTAL: "0" | |
| steps: | |
| - uses: actions/checkout@v3 | |
| - uses: ./.github/actions/setup/ | |
| # tests-v2 runs `cargo build-sbf` on its member programs; the rest of | |
| # the v2 stack doesn't need the Solana toolchain but installing it | |
| # once for the whole job is cheaper than splitting the matrix. | |
| - uses: ./.github/actions/setup-solana/ | |
| # Cache dependency downloads, but do not cache target directories here: | |
| # coverage and debugger runs leave multi-GB artifacts behind, and saving | |
| # or restoring those archives costs more than it buys in this job. | |
| - uses: actions/cache@v4 | |
| name: Cache Cargo home | |
| with: | |
| path: | | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| key: cargo-home-${{ runner.os }}-v2-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| cargo-home-${{ runner.os }}-v2- | |
| # Install platform-tools up front so the concurrent `cargo build-sbf` | |
| # invocations fired by parallel test threads don't race on the | |
| # one-time extract-then-rename of the platform-tools directory (surfaces | |
| # in CI as `Unable to rename: No such file or directory`). | |
| # SBF_TOOLS_VERSION must match `tests-v2/src/lib.rs::build_program`. | |
| # | |
| # Cache the platform-tools directory separately from the Solana tool | |
| # suite cache. The Solana cache is keyed by CLI version and may already | |
| # be a hit before this directory exists, so it will not save platform | |
| # tools that `cargo build-sbf --install-only` downloads later in the job. | |
| - uses: actions/cache@v4 | |
| name: Cache SBF platform tools | |
| with: | |
| path: ~/.cache/solana/${{ env.SBF_TOOLS_VERSION }}/platform-tools | |
| key: solana-platform-tools-${{ runner.os }}-${{ env.SBF_TOOLS_VERSION }} | |
| - run: cargo build-sbf --tools-version "$SBF_TOOLS_VERSION" --install-only | |
| # Tools for `make coverage-v2`: | |
| # - lcov for merging sbf.lcov + host.lcov and generating the report. | |
| # - cargo-llvm-cov for host-side instrumentation coverage. | |
| # | |
| # The three direct `cargo test -p anchor-{lang,spl}-v2` / `-p tests-v2` | |
| # invocations that used to live here (including `anchor-lang-v2`'s | |
| # `--features testing` flag for the Miri-witnesses scaffold) are | |
| # subsumed by the coverage-v2 steps below — the Makefile's host | |
| # coverage targets run the same packages under instrumentation. | |
| - name: Install lcov | |
| run: sudo apt-get install -y --no-install-recommends lcov | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/install-action@cargo-llvm-cov | |
| # Run the v2 test suite with coverage enabled, split across the same SBF | |
| # and host-side coverage boundaries used by `make coverage-v2`. Each | |
| # step still fails on test failure while keeping the slowest package | |
| # boundary visible in the Actions UI. | |
| - name: v2 SBF runtime coverage | |
| run: make coverage-v2-sbf | |
| - name: Prune v2 SBF coverage scratch | |
| run: make coverage-v2-sbf-prune | |
| - name: v2 host coverage setup | |
| run: make coverage-v2-host-clean | |
| - name: v2 host coverage for anchor-lang-v2 | |
| run: make coverage-v2-host-lang | |
| - name: v2 host coverage for anchor-spl-v2 | |
| run: make coverage-v2-host-spl | |
| - name: v2 host coverage for tests-v2 | |
| env: | |
| CARGO_BUILD_JOBS: "1" | |
| run: make coverage-v2-host-tests | |
| - name: v2 host coverage for idl-build fixtures | |
| run: make coverage-v2-host-idl-build | |
| - name: Generate v2 coverage report | |
| run: | | |
| make coverage-v2-host-report | |
| make coverage-v2-report | |
| # Upload to Codecov. The action handles comment posting on PRs via | |
| # the Codecov GitHub App — including fork PRs, where the token | |
| # flows through their bot instead of our workflow's `GITHUB_TOKEN`. | |
| # | |
| # `token` is optional on public repos (Codecov supports tokenless | |
| # uploads for open-source projects) but passing the repo-scoped | |
| # secret when available speeds upload discovery and is required on | |
| # anchor-next pushes. On fork PRs the secret is empty — the action | |
| # falls through to the tokenless flow automatically. | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: target/coverage/combined.lcov | |
| flags: v2 | |
| fail_ci_if_error: false | |
| # Miri (Tree Borrows) — UB + aliasing + provenance checks on the | |
| # same integration tests above. Catches things the default cargo | |
| # test run can't: `AccountView` copy-aliasing, `Slab::header_ptr` | |
| # write provenance, `AccountCursor::next` strict-provenance walks. | |
| # Caches the nightly toolchain and miri component to avoid a | |
| # per-run rustup fetch (~200 MB). | |
| - uses: actions/cache@v4 | |
| name: Cache rustup nightly + miri | |
| with: | |
| path: | | |
| ~/.rustup/toolchains/ | |
| ~/.rustup/update-hashes/ | |
| ~/.rustup/settings.toml | |
| key: rustup-miri-${{ runner.os }}-v2-${{ hashFiles('rust-toolchain*', '**/rust-toolchain*') }} | |
| restore-keys: | | |
| rustup-miri-${{ runner.os }}-v2- | |
| - name: Install nightly + miri | |
| run: | | |
| rustup toolchain install nightly --component miri --profile minimal | |
| cargo +nightly miri setup | |
| - name: Miri (Tree Borrows) for anchor-lang-v2 + anchor-spl-v2 | |
| env: | |
| MIRIFLAGS: '-Zmiri-tree-borrows' | |
| run: cargo +nightly miri test -p anchor-lang-v2 -p anchor-spl-v2 --tests --features anchor-lang-v2/testing | |
| # Kani harnesses live in-tree under `#[cfg(kani)]` and are runnable | |
| # locally via `cargo kani -p anchor-lang-v2` / `-p anchor-spl-v2`, | |
| # but are not wired into CI: kani-verifier 0.67.0 has an | |
| # upstream-deterministic `.unwrap()` panic on CBMC `ERROR` status | |
| # lines (kani#4519, fixed on main in #4540, not yet released). | |
| # Re-enable once kani-verifier ≥ 0.68.0 ships on crates.io. | |
| # CLI: unit-test + build sanity only. No anchor-binary install, | |
| # no `anchor build`/`anchor test` flows, no tests/* integration. | |
| - name: Run CLI Tests | |
| run: cargo test -p anchor-cli | |
| # Install the `anchor` bin to `~/.cargo/bin` (already on PATH via | |
| # rustup). Shared `./target/` via `--target-dir` means the build | |
| # reuses artifacts from prior `cargo test -p anchor-cli` instead | |
| # of starting from scratch in a temp tree; `--debug` skips release | |
| # opt (smoke test — runtime speed doesn't matter). | |
| - name: Install CLI | |
| run: cargo install --path cli --locked --debug --force --target-dir ./target | |
| # `anchor debugger` smoke test. These bench crates have no | |
| # Anchor.toml, so the CLI falls into loose mode and runs the full | |
| # pipeline: `cargo build-sbf` → `cargo test --features profile` → | |
| # TUI. We wrap in `script` so crossterm can enter raw mode on a | |
| # pty (GHA stdin/stdout aren't ttys) and `timeout` kills the TUI | |
| # once it's in its event loop. | |
| # | |
| # Failure handling: each `prog` is run in its own subshell so | |
| # `cd` is scoped (no `popd` bookkeeping) and so `|| rc=$?` | |
| # captures the inner pipeline's exit status directly. Build and | |
| # TUI phases are kept distinct so a build break is reported as | |
| # such instead of bleeding into a confusing TUI failure. | |
| # | |
| # Exit-code semantics for the TUI phase: | |
| # 124 → timeout-killed (TUI was still alive — success) | |
| # 0 → clean exit (rare in CI; legal) | |
| # else → real failure; dump the pty log | |
| - name: anchor debugger TUI launches for bench anchor-v2 programs | |
| run: | | |
| set -euo pipefail | |
| fail=0 | |
| for prog in bench/programs/*/anchor-v2; do | |
| echo "::group::anchor debugger in $prog" | |
| log=$(mktemp) | |
| # Build phase — surface build breaks as a distinct error. | |
| if ! ( cd "$prog" && anchor coverage ); then | |
| echo "::error::`anchor coverage` failed in $prog" | |
| fail=1 | |
| rm -f "$log" | |
| echo "::endgroup::" | |
| continue | |
| fi | |
| # TUI phase — `|| rc=$?` captures the subshell exit cleanly | |
| # without toggling `set +e`/`set -e` around it. | |
| rc=0 | |
| ( cd "$prog" && timeout --kill-after=30 30 \ | |
| script -qec 'anchor debugger --skip-build' "$log" ) || rc=$? | |
| if [ "$rc" -ne 0 ] && [ "$rc" -ne 124 ]; then | |
| echo "::error::anchor debugger failed in $prog (exit $rc)" | |
| cat "$log" | |
| fail=1 | |
| fi | |
| rm -f "$log" | |
| echo "::endgroup::" | |
| done | |
| exit "$fail" |