feat(release): admit a stable release from its claim tag
main carries 0.0.0, so comparing the tag against pyproject.toml refuses every release. Admission reads the version from the -rc claim and checks only that the commit is on main.
This commit is contained in:
@@ -24,6 +24,23 @@ SMOKE_JOBS = {
|
||||
}
|
||||
|
||||
|
||||
def admit_claim(tag: str, commit: str, *, on_main) -> dict:
|
||||
"""Admit a release from its claim tag. The checkout version is not read.
|
||||
|
||||
``main`` carries ``0.0.0`` on purpose, so the version comes from the
|
||||
``-rc`` tag and the only question about the commit is whether it is on
|
||||
``main``.
|
||||
"""
|
||||
if not isinstance(tag, str) or not tag.endswith("-rc"):
|
||||
raise ValueError(f"{tag} is not a claim tag")
|
||||
version = tag[1:-3]
|
||||
if not re.fullmatch(r"(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)", version):
|
||||
raise ValueError(f"{tag} is not a claim tag")
|
||||
if not on_main(commit):
|
||||
raise ValueError(f"{commit} is not on main")
|
||||
return {"version": version, "commit": commit}
|
||||
|
||||
|
||||
def require_stable_identity(tag: str, commit: str, ref: str) -> None:
|
||||
if not isinstance(tag, str) or not STABLE_TAG_RE.fullmatch(tag) or not SHA.fullmatch(commit or "") or ref != f"refs/tags/{tag}":
|
||||
raise ValueError("Stable release must run on its exact stable tag and commit")
|
||||
@@ -195,16 +212,19 @@ def summary(text: str, env: dict) -> None:
|
||||
|
||||
|
||||
def admit(env: dict) -> None:
|
||||
tag, commit = check_tag(env)
|
||||
with Path("pyproject.toml").open("rb") as file:
|
||||
version = tomllib.load(file)["project"]["version"]
|
||||
if f"v{version}" != tag:
|
||||
raise ValueError("Stable tag must match the project version")
|
||||
release = json.loads(output(["gh", "release", "view", tag, "--repo", env["GITHUB_REPOSITORY"], "--json", "tagName,isDraft,isPrerelease"]))
|
||||
if release["tagName"] != tag or not release["isDraft"] or release["isPrerelease"]:
|
||||
raise ValueError("Stable candidate must have a non-prerelease draft")
|
||||
emit({"tag": tag, "commit": commit}, env)
|
||||
summary(f"## Stable candidate {tag}\nCommit: {commit}\n\nDesktop Playwright E2E: deferred by owner, not passed.\nOSV findings retain the existing advisory policy.", env)
|
||||
"""Admit the claim. The checkout carries 0.0.0, so the tag is the version."""
|
||||
tag, commit = env.get("RELEASE_TAG"), env.get("GITHUB_SHA")
|
||||
admitted = admit_claim(tag, commit, on_main=lambda sha: _on_main(sha, env))
|
||||
emit({"tag": tag, "commit": admitted["commit"], "version": admitted["version"]}, env)
|
||||
summary(f"## Stable candidate {tag}\nCommit: {commit}\nVersion: {admitted['version']}\n", env)
|
||||
|
||||
|
||||
def _on_main(commit: str, env: dict) -> bool:
|
||||
try:
|
||||
output(["git", "merge-base", "--is-ancestor", commit, "origin/main"])
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def transitions(env: dict) -> None:
|
||||
|
||||
30
tests/scripts/test_stable_admission.py
Normal file
30
tests/scripts/test_stable_admission.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""Stable admission reads the version from the claim, not from the checkout.
|
||||
|
||||
``main`` carries ``0.0.0`` by design, so comparing the tag against
|
||||
``pyproject.toml`` would refuse every release. The claim tag is the version,
|
||||
and the only question about the commit is whether it is on ``main``.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
|
||||
def test_admission_reads_the_version_from_the_claim():
|
||||
from scripts.releases.stable import admit_claim
|
||||
|
||||
commit = "a" * 40
|
||||
admitted = admit_claim("v0.21.5-rc", commit, on_main=lambda sha: sha == commit)
|
||||
|
||||
assert admitted == {"version": "0.21.5", "commit": commit}
|
||||
|
||||
|
||||
def test_admission_refuses_a_claim_for_a_commit_off_main():
|
||||
from scripts.releases.stable import admit_claim
|
||||
|
||||
with pytest.raises(ValueError, match="not on main"):
|
||||
admit_claim("v0.21.5-rc", "b" * 40, on_main=lambda _sha: False)
|
||||
|
||||
|
||||
def test_admission_refuses_a_tag_that_is_not_a_claim():
|
||||
from scripts.releases.stable import admit_claim
|
||||
|
||||
with pytest.raises(ValueError, match="claim"):
|
||||
admit_claim("v0.21.5", "a" * 40, on_main=lambda _sha: True)
|
||||
Reference in New Issue
Block a user