Files

81 lines
2.5 KiB
Python

import argparse
import os
import re
import subprocess
import sys
from pathlib import Path
try:
import tomllib # Python 3.11+
except ModuleNotFoundError: # pragma: no cover
import tomli as tomllib
def _run_step(
title: str,
command: list[str],
cwd: Path,
env_overrides: dict[str, str] | None = None,
) -> None:
print(f"[release-gate] {title}: {' '.join(command)}")
env = os.environ.copy()
if env_overrides:
env.update(env_overrides)
subprocess.run(command, cwd=str(cwd), check=True, env=env)
def _read_project_version(pyproject_path: Path) -> str:
data = tomllib.loads(pyproject_path.read_text(encoding="utf-8"))
project = data.get("project", {})
version = str(project.get("version", "")).strip()
if not version:
raise RuntimeError("project.version is missing in pyproject.toml")
return version
def _ensure_changelog_contains_version(changelog_path: Path, version: str) -> None:
content = changelog_path.read_text(encoding="utf-8")
pattern = rf"^## \[{re.escape(version)}\] - "
if not re.search(pattern, content, flags=re.MULTILINE):
raise RuntimeError(
f"CHANGELOG.md missing release heading for version {version}. "
f"Expected: '## [{version}] - YYYY-MM-DD'"
)
def main() -> int:
parser = argparse.ArgumentParser(description="Release quality gate: lint/test/version check")
parser.add_argument("--skip-lint", action="store_true", help="Skip lint check")
parser.add_argument("--skip-tests", action="store_true", help="Skip tests")
parser.add_argument(
"--skip-version-check", action="store_true", help="Skip pyproject/changelog version check"
)
args = parser.parse_args()
root = Path(__file__).resolve().parents[1]
pyproject_path = root / "pyproject.toml"
changelog_path = root / "CHANGELOG.md"
if not args.skip_version_check:
version = _read_project_version(pyproject_path)
_ensure_changelog_contains_version(changelog_path, version)
print(f"[release-gate] version-check: OK ({version})")
if not args.skip_lint:
_run_step("lint", [sys.executable, "-m", "ruff", "check", "."], cwd=root)
if not args.skip_tests:
_run_step(
"tests-core",
[sys.executable, "-m", "pytest", "tests/core", "-q", "-m", "core"],
cwd=root,
env_overrides={"SIMPLE_ITERATOR_SKIP_NODE_IMPORT": "1"},
)
print("[release-gate] all checks passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())