diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ab08ba7204..824dd2198b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -95,3 +95,105 @@ jobs: - uses: ./.github/actions/setup-env - name: Run optimized tests run: tox -e optimized + + changed-forks: + runs-on: ubuntu-latest + needs: static + outputs: + changed-forks: ${{ steps.filter-tests.outputs.forks }} + fork-mapping: ${{ steps.filter-tests.outputs.fork_mapping }} + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install project for fork detection + run: pip install . + - name: Find changed valid forks + id: set-forks + run: | + git fetch origin ${{ github.event.pull_request.base.ref }} + VALID_FORKS=$(python -c "import json; from ethereum_spec_tools.forks import Hardfork; print(json.dumps([f.short_name for f in Hardfork.discover()]))") + CHANGED_FORKS=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }} ${{ github.sha }} -- src/ethereum/ | awk -F'/' '{print $3}' | sort -u) + readarray -t VALID_FORKS_ARR < <(echo "$VALID_FORKS" | jq -r '.[]') + FILTERED=$(for f in $CHANGED_FORKS; do for v in "${VALID_FORKS_ARR[@]}"; do [ "$f" = "$v" ] && echo $f; done; done | jq -R . | jq -s -c .) + echo "FILTERED (final forks for matrix): $FILTERED" + echo "forks=$FILTERED" >> $GITHUB_OUTPUT + - name: Filter out forks without tests + id: filter-tests + run: | + FORK_DATA=$(python -c " + import sys + sys.path.insert(0, 'tests') + from json_infra import FORKS + import json + eels_to_json = {} + for json_fork, config in FORKS.items(): + eels_to_json[config['eels_fork']] = json_fork + print(json.dumps(eels_to_json)) + ") + + AVAILABLE_EELS_FORKS=$(echo "$FORK_DATA" | jq -r 'keys[]') + FILTERED_WITH_TESTS=$(for f in $(echo '${{ steps.set-forks.outputs.forks }}' | jq -r '.[]'); do + if echo "$AVAILABLE_EELS_FORKS" | grep -q "^$f$"; then + echo $f + fi + done | jq -R . | jq -s -c .) + echo "FILTERED_WITH_TESTS: $FILTERED_WITH_TESTS" + echo "forks=$FILTERED_WITH_TESTS" >> $GITHUB_OUTPUT + echo "fork_mapping=$FORK_DATA" >> $GITHUB_OUTPUT + + mutation-test: + runs-on: [self-hosted-ghr, size-xl-x64] + needs: [static, changed-forks] + if: github.event_name == 'pull_request' + strategy: + matrix: + fork: ${{ fromJson(needs.changed-forks.outputs.changed-forks) }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install project with test dependencies + run: pip install '.[test]' + - name: Install mutmut + run: pip install git+https://github.com/souradeep-das/mutmut.git@cc99e509092ed232600712d9d77fb38be31f74ec + - name: Find changed files for fork + id: changed + run: | + git fetch origin ${{ github.event.pull_request.base.ref }} + echo "changed_files<> $GITHUB_OUTPUT + (git diff --name-only origin/${{ github.event.pull_request.base.ref }} ${{ github.sha }} -- src/ethereum/${{ matrix.fork }}/ || true) >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + - name: Display changed files + run: | + echo "Changed files:" + echo "${{ steps.changed.outputs.changed_files }}" + - name: Skip if no changes for this fork + if: steps.changed.outputs.changed_files == '' + run: echo "No changes for ${{ matrix.fork }}, skipping mutmut." + - name: Copy dependencies for mutation testing + if: steps.changed.outputs.changed_files != '' + run: | + mkdir -p mutants/src + cp -r src/* mutants/src/ + - name: Determine JSON fork name + if: steps.changed.outputs.changed_files != '' + id: json-fork + run: | + JSON_FORK=$(echo '${{ needs.changed-forks.outputs.fork-mapping }}' | jq -r '."${{ matrix.fork }}"') + echo "json_fork=$JSON_FORK" >> $GITHUB_OUTPUT + echo "Found JSON fork name: $JSON_FORK for eels fork: ${{ matrix.fork }}" + - name: Run mutmut + if: steps.changed.outputs.changed_files != '' + run: | + FILES=$(echo "${{ steps.changed.outputs.changed_files }}" | paste -sd, -) + mutmut --paths-to-mutate $FILES --tests-dir tests/json_infra/ --pytest-extra-args '-m "not slow and not angry_mutant" --ignore-glob=tests/json_infra/fixtures/* --fork ${{ steps.json-fork.outputs.json_fork }}' --debug run + - name: Show mutmut results + if: steps.changed.outputs.changed_files != '' + run: mutmut results