73da2f04dd
parity-main runs the vanilla harnesses on every push to main, one run at a time: merges that land during a run wait in one pending run, which checks every merge since main's last green parity-main (tools/parity_main.py base, then parity.py --changed). A failure is bisected over the batch's first-parent merges, running only the failing harnesses, and the breaking merge's pull request gets a comment. Game releases ship only a commit both checks and parity-main passed on (release_train.py; release.yml also starts when parity-main finishes; a forced release doesn't wait). The per-PR parity job now runs only for a PR that changes a harness, an oracle, a probe or the runner, or carries run-parity. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
44 lines
2.2 KiB
Python
44 lines
2.2 KiB
Python
"""tools/parity_main.py: the base of a parity-main run, and the bisect after a failure."""
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
from tools import parity_main
|
|
|
|
|
|
class ParityMainTests(unittest.TestCase):
|
|
def test_first_bad_finds_the_first_failing_merge(self):
|
|
commits = list("abcdefgh") # h failed; the base before a passed
|
|
for culprit in commits:
|
|
tried = []
|
|
fails = lambda commit: tried.append(commit) or commit >= culprit
|
|
self.assertEqual(parity_main.first_bad(commits, fails), culprit)
|
|
self.assertLessEqual(len(tried), 3, "log2 of 8 merges")
|
|
self.assertEqual(parity_main.first_bad(["a"], lambda commit: self.fail("nothing to try")), "a")
|
|
|
|
def test_base_is_the_newest_green_run_head_contains(self):
|
|
with tempfile.TemporaryDirectory() as tmp, mock.patch.object(parity_main, "ROOT", Path(tmp)):
|
|
git = lambda *arguments: parity_main.git(*arguments).stdout.strip()
|
|
git("init", "-q")
|
|
for n in range(3):
|
|
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", str(n))
|
|
head, parent, grandparent = git("rev-parse", "HEAD"), git("rev-parse", "HEAD^1"), git("rev-parse", "HEAD~2")
|
|
git("checkout", "-q", "-b", "side", grandparent)
|
|
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", "side")
|
|
side = git("rev-parse", "HEAD")
|
|
git("checkout", "-q", head)
|
|
self.assertEqual(parity_main.base(runs=[side, grandparent, parent]), grandparent,
|
|
"a run on a commit HEAD doesn't contain is skipped")
|
|
self.assertEqual(parity_main.base(runs=[]), parent, "no green run yet: the last merge")
|
|
self.assertEqual(parity_main.base(runs=[head]), head)
|
|
|
|
def test_a_harness_a_commit_does_not_have_cannot_fail_there(self):
|
|
with mock.patch.object(parity_main.subprocess, "run") as run:
|
|
self.assertFalse(parity_main.run_harnesses(["not_a_harness_yet"], 60))
|
|
run.assert_not_called()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|