From 638a9be3e26e44deceb0ec29d5231fc223d1c352 Mon Sep 17 00:00:00 2001 From: Alister Date: Mon, 2 Nov 2026 13:28:18 -0800 Subject: [PATCH 1/2] Treat an identical compatibility update after pull as a no-op When two PRs merge close together, their "Build and upload packages" runs both commit the same compatibility-data update. The second run's `git pull` brings in the first run's identical commit, leaves nothing staged, and `git commit` fails with "nothing to commit", which fails the job and cancels the other platforms before they upload. Re-check the staged diff after pulling and return successfully when it is empty, while still failing on an unexpected diff-index error. Adds integration tests against a local bare remote, run in pre-commit. The fix and tests are from @Str-Gen's earlier PR, which was closed before landing. --- .github/workflows/pre-commit.yml | 3 ++ scripts/common.py | 9 ++++ tests/test_commit_changes.py | 88 ++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 tests/test_commit_changes.py diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 4ade24a9..4be2d265 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -20,3 +20,6 @@ jobs: - name: Run pre-commit run: pixi run lint + + - name: Test compatibility commits + run: pixi run python -m unittest discover -s tests -v diff --git a/scripts/common.py b/scripts/common.py index 314cc2ac..ca2b248d 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -54,6 +54,15 @@ def commit_push_changes(message: str, branch_name: str) -> None: # Commit, pull and push the changes run_command(["git", "pull", "origin", branch_name]) + # Another runner may already have pushed the same generated changes. + # Pulling that commit leaves nothing staged, which is a successful no-op. + result = run_command_unchecked(["git", "diff-index", "--cached", "--quiet", "HEAD"]) + if result.returncode == 0: + eprint("No changes to commit after pulling.") + return + if result.returncode != 1: + sys.exit(result.returncode) + run_command(["git", "commit", "--message", message, "--no-verify"]) run_command(["git", "push", "--set-upstream", "origin", branch_name]) diff --git a/tests/test_commit_changes.py b/tests/test_commit_changes.py new file mode 100644 index 00000000..55d06b3c --- /dev/null +++ b/tests/test_commit_changes.py @@ -0,0 +1,88 @@ +"""Exercise compatibility commits against a local Git remote.""" + +import os +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + + +ROOT = Path(__file__).resolve().parents[1] + + +class CommitChangesTest(unittest.TestCase): + def setUp(self) -> None: + self.temp = tempfile.TemporaryDirectory() + self.addCleanup(self.temp.cleanup) + self.root = Path(self.temp.name) + self.remote = self.root / "remote.git" + self.writer = self.root / "writer" + self.runner = self.root / "runner" + self.git(self.root, "init", "--bare", str(self.remote)) + self.git(self.root, "clone", str(self.remote), str(self.writer)) + self.configure(self.writer) + self.git(self.writer, "checkout", "-b", "main") + (self.writer / "compatibility.json").write_text("{}\n") + self.git(self.writer, "add", ".") + self.git(self.writer, "commit", "-m", "Initial data") + self.git(self.writer, "push", "origin", "main") + self.git( + self.root, "clone", "--branch", "main", str(self.remote), str(self.runner) + ) + self.configure(self.runner) + + def git(self, cwd: Path, *args: str) -> str: + return subprocess.run( + ["git", *args], cwd=cwd, check=True, capture_output=True, text=True + ).stdout.strip() + + def configure(self, cwd: Path) -> None: + self.git(cwd, "config", "user.name", "Test") + self.git(cwd, "config", "user.email", "test@example.invalid") + self.git(cwd, "config", "pull.rebase", "false") + self.git(cwd, "config", "commit.gpgsign", "false") + + def run_script(self) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [sys.executable, "-m", "scripts.commit-changes", "compatibility.json"], + cwd=self.runner, + env={**os.environ, "PYTHONPATH": str(ROOT)}, + capture_output=True, + text=True, + ) + + def test_remote_already_has_generated_update(self) -> None: + update = '{"example": {"failed_at": "2026-10-18"}}\n' + (self.runner / "compatibility.json").write_text(update) + (self.writer / "compatibility.json").write_text(update) + self.git(self.writer, "add", ".") + self.git(self.writer, "commit", "-m", "Concurrent update") + self.git(self.writer, "push", "origin", "main") + result = self.run_script() + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertEqual(self.git(self.runner, "status", "--porcelain"), "") + self.assertEqual( + self.git(self.runner, "rev-parse", "HEAD"), + self.git(self.writer, "rev-parse", "HEAD"), + ) + + def test_new_update_is_committed_and_pushed(self) -> None: + (self.runner / "compatibility.json").write_text('{"new": {}}\n') + result = self.run_script() + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertEqual(self.git(self.runner, "status", "--porcelain"), "") + self.assertEqual( + self.git(self.runner, "rev-parse", "HEAD"), + self.git(self.root, "--git-dir", str(self.remote), "rev-parse", "main"), + ) + + def test_unchanged_data_is_a_successful_noop(self) -> None: + before = self.git(self.runner, "rev-parse", "HEAD") + result = self.run_script() + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertEqual(self.git(self.runner, "rev-parse", "HEAD"), before) + + +if __name__ == "__main__": + unittest.main() From bab95174f998487fa7eb9e39a3fb7b28731f1796 Mon Sep 17 00:00:00 2001 From: Alister Date: Tue, 3 Nov 2026 16:45:32 -0800 Subject: [PATCH 2/2] Drop the compatibility commit integration tests --- .github/workflows/pre-commit.yml | 3 -- tests/test_commit_changes.py | 88 -------------------------------- 2 files changed, 91 deletions(-) delete mode 100644 tests/test_commit_changes.py diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 4be2d265..4ade24a9 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -20,6 +20,3 @@ jobs: - name: Run pre-commit run: pixi run lint - - - name: Test compatibility commits - run: pixi run python -m unittest discover -s tests -v diff --git a/tests/test_commit_changes.py b/tests/test_commit_changes.py deleted file mode 100644 index 55d06b3c..00000000 --- a/tests/test_commit_changes.py +++ /dev/null @@ -1,88 +0,0 @@ -"""Exercise compatibility commits against a local Git remote.""" - -import os -from pathlib import Path -import subprocess -import sys -import tempfile -import unittest - - -ROOT = Path(__file__).resolve().parents[1] - - -class CommitChangesTest(unittest.TestCase): - def setUp(self) -> None: - self.temp = tempfile.TemporaryDirectory() - self.addCleanup(self.temp.cleanup) - self.root = Path(self.temp.name) - self.remote = self.root / "remote.git" - self.writer = self.root / "writer" - self.runner = self.root / "runner" - self.git(self.root, "init", "--bare", str(self.remote)) - self.git(self.root, "clone", str(self.remote), str(self.writer)) - self.configure(self.writer) - self.git(self.writer, "checkout", "-b", "main") - (self.writer / "compatibility.json").write_text("{}\n") - self.git(self.writer, "add", ".") - self.git(self.writer, "commit", "-m", "Initial data") - self.git(self.writer, "push", "origin", "main") - self.git( - self.root, "clone", "--branch", "main", str(self.remote), str(self.runner) - ) - self.configure(self.runner) - - def git(self, cwd: Path, *args: str) -> str: - return subprocess.run( - ["git", *args], cwd=cwd, check=True, capture_output=True, text=True - ).stdout.strip() - - def configure(self, cwd: Path) -> None: - self.git(cwd, "config", "user.name", "Test") - self.git(cwd, "config", "user.email", "test@example.invalid") - self.git(cwd, "config", "pull.rebase", "false") - self.git(cwd, "config", "commit.gpgsign", "false") - - def run_script(self) -> subprocess.CompletedProcess[str]: - return subprocess.run( - [sys.executable, "-m", "scripts.commit-changes", "compatibility.json"], - cwd=self.runner, - env={**os.environ, "PYTHONPATH": str(ROOT)}, - capture_output=True, - text=True, - ) - - def test_remote_already_has_generated_update(self) -> None: - update = '{"example": {"failed_at": "2026-10-18"}}\n' - (self.runner / "compatibility.json").write_text(update) - (self.writer / "compatibility.json").write_text(update) - self.git(self.writer, "add", ".") - self.git(self.writer, "commit", "-m", "Concurrent update") - self.git(self.writer, "push", "origin", "main") - result = self.run_script() - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertEqual(self.git(self.runner, "status", "--porcelain"), "") - self.assertEqual( - self.git(self.runner, "rev-parse", "HEAD"), - self.git(self.writer, "rev-parse", "HEAD"), - ) - - def test_new_update_is_committed_and_pushed(self) -> None: - (self.runner / "compatibility.json").write_text('{"new": {}}\n') - result = self.run_script() - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertEqual(self.git(self.runner, "status", "--porcelain"), "") - self.assertEqual( - self.git(self.runner, "rev-parse", "HEAD"), - self.git(self.root, "--git-dir", str(self.remote), "rev-parse", "main"), - ) - - def test_unchanged_data_is_a_successful_noop(self) -> None: - before = self.git(self.runner, "rev-parse", "HEAD") - result = self.run_script() - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - self.assertEqual(self.git(self.runner, "rev-parse", "HEAD"), before) - - -if __name__ == "__main__": - unittest.main()