mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-09 10:39:46 -10:00
CI parity: test the head merged into main
A head tested alone keeps failing harnesses that main already fixed. Since 10-25 evening, 9 of 21 failed PR parity jobs failed only on such fixes: server_knockback (heads without #2114, 7 times), mob_ai's oracle heap (without #2270), save_roundtrip (without #2212). #2160 needed 4 parity runs this way. The job now merges main's current tip into the head and selects harnesses against that main commit, so only the pull request's own changes count. A branch that doesn't change the runner scripts or the selection gets main's, which replaces the two steps that copied main's vanilla-data.sh and parity.py in by hand. A head that conflicts with main is tested alone, with a warning. The job summary names the main commit, and the check is still `parity / parity` on the head. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
55a71d3502
commit
df045f1e9a
2 files changed
+36
-61
No files matched your search
@@ -26,35 +26,46 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# The commit the event names: a fork's later pushes need another run-parity label.
|
||||
# The commit the event names: a fork's later pushes need another run-parity label. The next step merges
|
||||
# main into it.
|
||||
ref: ${{ inputs.head }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
# Keeps .local/ (parity state, probe builds, oracle results) and target/ between runs.
|
||||
clean: false
|
||||
- name: The head merged into main (what merging it would land)
|
||||
id: merge
|
||||
env:
|
||||
BASE_SHA: ${{ inputs.base }}
|
||||
HEAD_SHA: ${{ inputs.head }}
|
||||
run: |
|
||||
# Harness fixes and game fixes that reached main since the branch was made then apply here too: a head
|
||||
# tested alone failed harnesses already fixed on main (server_knockback before #2114, mob_ai's heap before
|
||||
# #2270, save_roundtrip before #2212). Selection then compares with this main, so it sees only the pull
|
||||
# request's own changes. A head that conflicts with main is tested alone.
|
||||
set -euo pipefail
|
||||
git merge --abort 2>/dev/null || true
|
||||
git fetch -q --no-tags origin +refs/heads/main:refs/remotes/origin/main
|
||||
main=$(git rev-parse origin/main)
|
||||
if git -c user.name=parity -c user.email=parity@localhost merge -q --no-edit --no-ff "$main" >/dev/null 2>&1; then
|
||||
echo "base=$main" >> "$GITHUB_OUTPUT"
|
||||
echo "Tested: head ${HEAD_SHA:0:9} merged into main ${main:0:9}" | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
else
|
||||
git merge --abort
|
||||
echo "base=$BASE_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "::warning::head ${HEAD_SHA:0:9} conflicts with main ${main:0:9}: tested alone, without main's fixes"
|
||||
echo "Tested: head ${HEAD_SHA:0:9} alone (it conflicts with main ${main:0:9})" | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
fi
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Tools from the runner
|
||||
run: bash tools/ci/runner-env.sh
|
||||
- name: Vanilla data, and resources prepared by this preparer
|
||||
env:
|
||||
BASE_SHA: ${{ inputs.base }}
|
||||
run: |
|
||||
# main's script: one written before a fix to it left a real .local/horizon-client without sounds.json on
|
||||
# the runner, and every later job there failed `subtitle`. A branch that changes the script runs its own.
|
||||
set -euo pipefail
|
||||
if git rev-parse --verify -q origin/main >/dev/null \
|
||||
&& git diff --quiet "$(git merge-base "$BASE_SHA" HEAD)" HEAD -- tools/ci/vanilla-data.sh; then
|
||||
git show origin/main:tools/ci/vanilla-data.sh > "$RUNNER_TEMP/vanilla-data.sh"
|
||||
bash "$RUNNER_TEMP/vanilla-data.sh"
|
||||
else
|
||||
bash tools/ci/vanilla-data.sh
|
||||
fi
|
||||
run: bash tools/ci/vanilla-data.sh
|
||||
- name: The prepared output is the one the preparer's OUTPUT_VERSION says
|
||||
env:
|
||||
BASE_SHA: ${{ inputs.base }}
|
||||
BASE_SHA: ${{ steps.merge.outputs.base }}
|
||||
run: |
|
||||
# The job runs main's workflow on the head's files: a head made before OUTPUT_VERSION (#1947) has neither
|
||||
# the tool nor the number, so there is nothing to check.
|
||||
# A head made before OUTPUT_VERSION (#1947) that conflicts with main has neither the tool nor the number.
|
||||
if [ ! -f tools/prepare_output.py ] || ! grep -q OUTPUT_VERSION crates/horizon-prepare/src/lib.rs; then
|
||||
echo "This head's preparer has no OUTPUT_VERSION: nothing to check"
|
||||
exit 0
|
||||
@@ -65,47 +76,8 @@ jobs:
|
||||
- name: The harnesses this change can affect
|
||||
env:
|
||||
PARITY_HOSTS: ''
|
||||
BASE_SHA: ${{ inputs.base }}
|
||||
run: |
|
||||
# main's selection (tools/parity.py --changed --list with main's parity.py and parity_reach.py), so a
|
||||
# branch made before a better selection landed gets it too; the head's own runner then runs those
|
||||
# harnesses. A branch that changes the selection itself selects with its own code.
|
||||
set -euo pipefail
|
||||
own() { python3 tools/parity.py --changed "$BASE_SHA" --timeout 2400; } # world_spawn takes ~1480 s on a busy runner
|
||||
fork_point=$(git merge-base "$BASE_SHA" HEAD)
|
||||
if ! git rev-parse --verify -q origin/main >/dev/null || ! git diff --quiet "$fork_point" HEAD -- tools/parity.py tools/parity_reach.py; then
|
||||
own
|
||||
exit
|
||||
fi
|
||||
had_reach=$(git ls-files tools/parity_reach.py)
|
||||
git show origin/main:tools/parity.py > tools/parity.py
|
||||
git show origin/main:tools/parity_reach.py > tools/parity_reach.py
|
||||
status=0
|
||||
python3 tools/parity.py --changed "$BASE_SHA" --list > .local/parity-selection.txt || status=$?
|
||||
git checkout -- tools/parity.py
|
||||
if [ -n "$had_reach" ]; then git checkout -- tools/parity_reach.py; else rm -f tools/parity_reach.py; fi
|
||||
cat .local/parity-selection.txt
|
||||
if [ "$status" != 0 ]; then
|
||||
echo "main's selection failed: the head's own selection runs"
|
||||
own
|
||||
exit
|
||||
fi
|
||||
names=$(sed '$d' .local/parity-selection.txt | grep -E '^[A-Za-z0-9_#]+$' || true)
|
||||
# The summary line says how many would run: a count that doesn't match the names read (a format change)
|
||||
# must not let the job pass untested.
|
||||
expected=$(tail -1 .local/parity-selection.txt | sed -nE 's/^([0-9]+) of [0-9]+ harnesses would run$/\1/p')
|
||||
count=$(printf '%s' "$names" | grep -c . || true)
|
||||
if [ -z "$expected" ] || [ "$expected" != "$count" ]; then
|
||||
echo "main's selection listed $count names, its summary says '${expected:-?}': the head's own selection runs"
|
||||
own
|
||||
exit
|
||||
fi
|
||||
if [ "$count" = 0 ]; then
|
||||
echo "Nothing to run."
|
||||
exit 0
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
python3 tools/parity.py $names --timeout 2400
|
||||
BASE_SHA: ${{ steps.merge.outputs.base }}
|
||||
run: python3 tools/parity.py --changed "$BASE_SHA" --timeout 2400 # world_spawn takes ~1480 s on a busy runner
|
||||
- name: Logs of the failed harnesses
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -32,6 +32,12 @@ copy is: the Mac mini, his Linux desktop and playhorizon (below). Their runners
|
||||
between runs (`clean: false`), so the probes build incrementally into `.local/parity-target` and earlier passes
|
||||
stand.
|
||||
|
||||
The job tests the pull request's head merged into main's current tip, which is what merging it would land: harness
|
||||
and game fixes that reached main after the branch was made apply to it too, and an old branch runs main's runner
|
||||
scripts and selection unless it changes them. The base for the selection is that main commit, so only the pull
|
||||
request's own changes count. The job summary names the main commit. A head that conflicts with main is tested
|
||||
alone, with a warning. The check is still reported on the head.
|
||||
|
||||
1. `tools/ci/runner-env.sh` puts the machine's Python 3.13 and the JDK `research-lock.json` pins on the PATH
|
||||
(Homebrew and `java_home` on the Mac; on Linux what `linux-runner.sh` pinned, else nixpkgs), and sccache when
|
||||
the machine has it.
|
||||
@@ -50,9 +56,6 @@ stand.
|
||||
modules, Java oracles and every Rust source their probes compile) changed since the merge base, plus any
|
||||
harness nothing is recorded about yet, and runs those that have no pass for their current inputs. A change to
|
||||
`Cargo.lock` or `research-lock.json` affects every harness. Each harness has 25 minutes, the job 45.
|
||||
The selection runs with main's `tools/parity.py` and `tools/parity_reach.py` (`--changed <base> --list`), so a
|
||||
branch made before a better selection landed gets it too, and the head's own `parity.py` then runs the named
|
||||
harnesses. A branch that changes either file selects with its own code.
|
||||
|
||||
Failed harnesses' logs are uploaded as the `parity-logs` artifact.
|
||||
|
||||
|
||||
Reference in new issue
Block a user