Skip to content

fix: repair pull request ci#2148

Open
banteg wants to merge 26 commits into
eth-brownie:masterfrom
banteg:feat/fix-pr-ci
Open

fix: repair pull request ci#2148
banteg wants to merge 26 commits into
eth-brownie:masterfrom
banteg:feat/fix-pr-ci

Conversation

@banteg
Copy link
Copy Markdown
Collaborator

@banteg banteg commented May 9, 2026

Summary

This PR repairs the fork-PR CI path and moves the default local development backend from Ganache to Anvil. The CI failures were not one single issue; after the initial fork-permission fixes, the Anvil migration exposed several Brownie assumptions that had been hidden by Ganache. I kept the fixes separated by commit so each failure mode is reviewable on its own.

CI workflow fixes

  • Skip auto-mutating workflows on fork PRs where github-actions[bot] cannot push back to the contributor branch.
  • Remove stale lint tox config and format the files that Brownie's pinned Black check expects.
  • Update JavaScript actions for the GitHub Node 20 deprecation:
    • actions/checkout@v6
    • actions/cache@v5
    • actions/setup-python@v6
    • actions/download-artifact@v8
  • Keep CI coverage on supported Python lanes and drop the free-threaded 3.14 core Ganache lane, which currently fails in dependencies before reaching Brownie tests.
  • Expand the evm-latest matrix to cover the current hardfork set through prague, then compact older lanes so CI still finishes in a reasonable time.

Default development RPC

  • Change Brownie's default development network from Ganache to Anvil.
  • Add explicit anvil and anvil-fork network entries.
  • Use launchable Anvil defaults:
    • quiet logs
    • fixed CI/dev port
    • base fee disabled by default to preserve legacy test assumptions
    • step tracing enabled where Brownie needs source/revert/coverage tracing
  • Move PR RPC jobs off Ganache and update Ganache-shaped tests to use Anvil where the test is exercising Brownie's local RPC behavior rather than Ganache compatibility.
  • Keep Ganache support code in place. This PR changes the default and CI target; it does not remove Ganache as a backend.

Web3, compiler, and version compatibility

  • Handle web3.py 7 behavior changes around RPC reverts and event lookup during test collection.
  • Keep Brownie compiler versions as semantic_version.Version internally, while passing string versions to py-solc-x 2.x APIs that no longer accept the old object directly.
  • Pin the Vyper EVM default test to Vyper 0.2.4, because CI now has bundled vyper==0.4.3 and current active Vyper maps to newer defaults such as prague.
  • Fix source-package metadata typing failures surfaced by the mypyc wheel build.

Anvil trace, revert, and coverage fixes

  • Normalize Anvil trace memory words that may be prefixed.
  • Avoid full Anvil traces for simple return-value decoding.
  • Preserve dev revert lookup after revert data has already been decoded.
  • Recover dev comments from source/traceback when recent solc and Anvil source maps report broader ranges than Ganache did.
  • Narrow broad Solidity source ranges to the active function before scanning for // dev: comments, so a later function's comment is not selected accidentally.
  • Keep sourced first_revert steps when they already point at the real revert, instead of replacing them with an unsourced jump step.
  • Enable step tracing for plugin tests that need coverage/revert information.
  • Use Anvil snapshots to roll back coverage calls and chain isolation state.
  • Serialize chain isolation snapshot handling to avoid snapshot races.
  • Always release confirmed receipts so isolation cleanup does not retain stale state.

Why the revert fixes are in this PR

The remaining evm-latest failures reproduced on this CI branch without the versioning PR. They came from the new Anvil/default-dev setup plus newer bundled compiler tooling, not from release-version metadata.

The final failures were all in tests/network/transaction/test_revert_msg.py:

  • broad source ranges from recent solc/Anvil caused Brownie to select the wrong // dev: comment (dev: foobar instead of dev: great job);
  • optimized final reverts after a preceding require(...) had source on the REVERT instruction, but Brownie's old first_revert adjustment replaced it with an unsourced jump step, losing the // dev: comment and returning an empty revert message.

Those are Brownie trace-decoding issues, so fixing them here keeps #2148 green on its own.

Validation

Local focused validation:

  • git diff --check
  • uv run black brownie/network/transaction.py
  • uv run --with flake8==7.0.0 flake8 brownie/network/transaction.py
  • uv run python -m py_compile brownie/network/transaction.py
  • HOME=/private/tmp/brownie-ci-home .tox/plugintest/bin/python pytest_patched.py tests/network/transaction/test_revert_msg.py::test_solidity_revert_msg --evm latest prague 0 -q
  • HOME=/private/tmp/brownie-ci-home .tox/plugintest/bin/python pytest_patched.py tests/network/transaction/test_revert_msg.py::test_final_stmt_revert_no_input_no_msg --evm latest prague 0 -q
  • HOME=/private/tmp/brownie-ci-home .tox/plugintest/bin/python pytest_patched.py tests/network/transaction/test_revert_msg.py::test_final_stmt_revert_input_no_msg --evm latest paris 0 -q
  • HOME=/private/tmp/brownie-ci-home .tox/plugintest/bin/python pytest_patched.py tests/network/transaction/test_revert_msg.py::test_revert_msg_via_jump -q
  • HOME=/private/tmp/brownie-ci-home .tox/plugintest/bin/python pytest_patched.py tests/test/plugin/test_coverage.py::test_coverage_tx --target plugin -v

GitHub CI on the current head is green:

  • compile
  • pip-compile
  • linting (docs-external, true)
  • linting (docs-local, false)
  • linting (lint, false)
  • functionality (pmtest)
  • functionality (plugintest)
  • evm (evm-byzantium)
  • evm (evm-petersburg)
  • evm (evm-istanbul)
  • evm (evm-latest) through byzantium,petersburg,istanbul,berlin,london,paris,shanghai,cancun,prague

lint-all-the-things is skipped by design on fork PRs because it mutates/pushes formatting changes.

@BobTheBuidler
Copy link
Copy Markdown
Collaborator

Status update on the split-out work from this PR.

Merged extractions:

  • fix: support forked pull requests in ci #2147 pulled out the fork-PR checkout / CI writeback safety work. This lets workflows check out contributor fork branches correctly, while keeping writeback behavior limited to cases where the workflow can actually push.

  • ci: guard mutating workflows on forks #2143 pulled out the mutating workflow guards. This now lives on master: mutating CI paths are guarded so fork PRs do not try to write back where they cannot.

  • ci: bump github action versions #2144 pulled out the GitHub Actions version bumps. This was intentionally mechanical: action uses: version upgrades only, with no backend migration or test-matrix behavior mixed in.

  • fix: always release confirmed receipts #2142 pulled out the receipt-confirmation safety fix. This ensures transaction confirmation waiters are released even if trace / coverage expansion or confirmation output raises.

  • fix(test): cover vyper evm default boundaries #2154 pulled out the Vyper default EVM-version test cleanup. This was improved from the original narrow pin: it now documents why legacy Vyper defaults to Istanbul and adds boundary coverage for the Vyper default EVM mapping.

Still open as a scoped PR:

  • test: include modern hardforks in test matrix #2153 contains the modern hardfork test-matrix expansion. This is no longer just a big aggregate evm-latest job; it splits the modern latest-solc hardfork checks into named jobs like evm-latest-berlin, evm-latest-london, etc., while keeping the existing historical jobs (evm-byzantium, evm-petersburg, evm-istanbul) intact. This is the one I’d like reviewed by the original contributor before merging, since it changes CI topology and naming, not just coverage contents.

The remaining #2148 diff should now be smaller and more focused on the pieces that were not yet cleanly peeled into these scoped PRs.

@BobTheBuidler
Copy link
Copy Markdown
Collaborator

Leaving the audit-derived “better shape” notes here so they do not get lost while #2148 continues shrinking.

Already split or addressed:

Better-shape candidates still worth considering before landing remaining pieces from #2148:

  • Web3/RPC revert normalization: centralize provider error normalization behind one helper, with tests for Web3RPCError, ContractLogicError, Ganache-style dictionaries, and plain ValueError payloads.
  • Ganache/plugin test brittleness: keep the test-only robustness fixes separate from the runtime ganache.py default-balance change. If the runtime default-balance change is still wanted, it should get its own PR and direct launch-behavior tests.
  • Python 3.14 pytest compatibility: prefer environment markers in package metadata / lock inputs over dynamic setup.py filtering, so tox, installers, and dependency compilation all see the same constraints.
  • Source-map ID typing: instead of only changing the field to int, use a SourceId alias plus Literal[-1] for the sentinel; longer term, replace positional source-map tuples with a named structure.
  • EVM compile config: expose a small fixture/helper for “compile with current EVM matrix settings” rather than having tests reach through private project build internals.
  • Backend migration to Anvil: keep backend selection explicit, document the migration, and preserve Ganache compatibility coverage somewhere, likely scheduled if not normal PR CI.
  • Anvil launcher defaults: add validation for backend-specific command settings, tests for 0 / True / False / None CLI rendering, and an explicit nonzero-base-fee mode for EIP-1559-specific tests.
  • Anvil logging/tracing: make verbosity configurable, and enable step tracing only when coverage, trace expansion, or dev-revert source lookup actually needs it.
  • RPC launch tests: parametrize launch coverage across Anvil and Ganache instead of only switching the tests to the new default backend.
  • Plugin child network config: keep the direct regression test that mutates a parent runtime network setting and asserts the child .brownie/network-config.yaml receives it; longer term, prefer a shared config writer or env handoff over ad hoc YAML mutation.
  • Coverage call rollback/isolation: present the final snapshot-based rollback design directly, not the intermediate undo-count / undo-by-tx-id attempts. A small internal context manager for temporary snapshot rollback would be cleaner than mutating chain internals directly from contract code.
  • Chain isolation locking: centralize locking around every mutation of current snapshot IDs and undo/redo buffers.
  • Trace memory normalization: normalize trace memory once at raw trace ingestion, then keep the downstream representation typed/consistent.
  • Dev revert lookup: keep user-facing revert messages and developer-source annotations as independent values until final display.
  • Broad source-range dev comments: move toward a reusable AST/source resolver keyed by source IDs, signatures, and node spans instead of doing function-name AST scanning inside transaction handling.
  • First-revert source preservation: add bounds checks around the jump-step lookback and a regression test where the jump candidate lacks source metadata.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants