diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/preview.py | 38 | ||||
| -rw-r--r-- | scripts/test_preview.py | 79 |
2 files changed, 114 insertions, 3 deletions
diff --git a/scripts/preview.py b/scripts/preview.py index 746a157a..e173f865 100644 --- a/scripts/preview.py +++ b/scripts/preview.py @@ -20,7 +20,6 @@ EXPECTED_ASSET_NAMES = { "windows-x86_64": "herdr-windows-x86_64.exe", } HIDDEN_SUBJECTS = ( - "release:", "docs: update website manifest", "docs: update preview manifest", "chore: approve contributor", @@ -48,8 +47,21 @@ def normalize_version(version: str) -> str: return version.strip().removeprefix("v") -def latest_stable_tag() -> str: - return run_git(["describe", "--tags", "--match", "v[0-9]*", "--abbrev=0"]) +def latest_stable_tag(ref: str | None = None) -> str: + args = ["describe", "--tags", "--match", "v[0-9]*", "--abbrev=0"] + if ref: + args.append(ref) + return run_git(args) + + +def git_is_ancestor(ancestor: str, descendant: str) -> bool: + result = subprocess.run( + ["git", "merge-base", "--is-ancestor", ancestor, descendant], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=False, + ) + return result.returncode == 0 def read_json(path: Path) -> dict[str, Any] | None: @@ -95,6 +107,16 @@ def commit_subjects(previous: str, commit: str) -> list[str]: return subjects +def preview_range_base(previous: str, commit: str) -> str: + try: + stable = latest_stable_tag(commit) + except subprocess.CalledProcessError: + return previous + if git_is_ancestor(previous, stable) and git_is_ancestor(stable, commit): + return stable + return previous + + def humanize_subject(subject: str) -> tuple[str, str]: match = COMMIT_RE.match(subject) if not match: @@ -258,6 +280,11 @@ def cmd_select_commit(args: argparse.Namespace) -> int: return 0 +def cmd_range_base(args: argparse.Namespace) -> int: + print(preview_range_base(args.previous, args.commit)) + return 0 + + def main() -> int: parser = argparse.ArgumentParser(description="Preview channel release helpers") sub = parser.add_subparsers(required=True) @@ -294,6 +321,11 @@ def main() -> int: select.add_argument("--ref", default="origin/master") select.set_defaults(func=cmd_select_commit) + range_base = sub.add_parser("range-base") + range_base.add_argument("--previous", required=True) + range_base.add_argument("--commit", required=True) + range_base.set_defaults(func=cmd_range_base) + args = parser.parse_args() return args.func(args) diff --git a/scripts/test_preview.py b/scripts/test_preview.py index 5cd5be93..db80b1a7 100644 --- a/scripts/test_preview.py +++ b/scripts/test_preview.py @@ -1,7 +1,9 @@ import json +import os import subprocess import tempfile import unittest +from unittest import mock from pathlib import Path import scripts.conventional_commits as conventional_commits @@ -55,8 +57,85 @@ class PreviewNotesTests(unittest.TestCase): def test_hidden_subjects_include_preview_manifest_commits(self): self.assertTrue(preview.hidden_subject("docs: update preview manifest")) + self.assertTrue(preview.hidden_subject("docs: update website manifest")) + self.assertFalse(preview.hidden_subject("release: v0.7.0")) self.assertFalse(preview.hidden_subject("fix: repair preview manifest")) + def test_latest_publishable_commit_keeps_release_commits(self): + output = "\n".join( + [ + "manifest\x00docs: update website manifest for v0.7.0", + "release\x00release: v0.7.0", + "feature\x00feat: add plugin v1 system", + ] + ) + with mock.patch.object(preview, "run_git", return_value=output): + self.assertEqual(preview.latest_publishable_commit("origin/master"), "release") + + def test_preview_range_base_advances_to_stable_tag(self): + with ( + mock.patch.object(preview, "latest_stable_tag", return_value="v0.7.0"), + mock.patch.object(preview, "git_is_ancestor", return_value=True), + ): + self.assertEqual( + preview.preview_range_base("previous-preview", "release"), + "v0.7.0", + ) + + def test_preview_range_base_keeps_previous_preview_for_unreleased_work(self): + def is_ancestor(ancestor: str, descendant: str) -> bool: + return (ancestor, descendant) == ("v0.7.0", "new-feature") + + with ( + mock.patch.object(preview, "latest_stable_tag", return_value="v0.7.0"), + mock.patch.object(preview, "git_is_ancestor", side_effect=is_ancestor), + ): + self.assertEqual( + preview.preview_range_base("previous-preview", "new-feature"), + "previous-preview", + ) + + def test_post_stable_history_selects_release_and_bases_range_on_stable_tag(self): + with tempfile.TemporaryDirectory() as tmp: + repo = Path(tmp) + + def git(*args: str) -> str: + return subprocess.check_output( + ["git", *args], + cwd=repo, + text=True, + stderr=subprocess.DEVNULL, + ).strip() + + git("init") + git("config", "user.email", "test@example.com") + git("config", "user.name", "Test User") + + marker = repo / "marker.txt" + marker.write_text("preview\n", encoding="utf-8") + git("add", "marker.txt") + git("commit", "-m", "feat: previous preview") + previous_preview = git("rev-parse", "HEAD") + + marker.write_text("release\n", encoding="utf-8") + git("commit", "-am", "release: v0.7.0") + release = git("rev-parse", "HEAD") + git("tag", "v0.7.0") + + marker.write_text("manifest\n", encoding="utf-8") + git("commit", "-am", "docs: update website manifest for v0.7.0") + + original_cwd = os.getcwd() + try: + os.chdir(repo) + self.assertEqual(preview.latest_publishable_commit("HEAD"), release) + self.assertEqual( + preview.preview_range_base(previous_preview, release), + "v0.7.0", + ) + finally: + os.chdir(original_cwd) + def test_preview_docs_rewrite_links_to_preview_namespace(self): source = """--- title: Install Herdr |
