Files
awoooi/ops/runner/select-latest-inclusive-cd-carrier.py
Your Name 0d3c3b483e
Some checks failed
CD Pipeline / select-latest-carrier (push) Successful in 48s
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m34s
CD Pipeline / revalidate-deploy-carrier (push) Successful in 26s
CD Pipeline / revalidate-post-deploy-carrier (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
fix(cd): coalesce stale carriers and harden verifiers
2026-07-18 18:54:18 +08:00

192 lines
5.9 KiB
Python

#!/usr/bin/env python3
"""Select one exact main revision as the inclusive AWOOOI CD carrier."""
from __future__ import annotations
import argparse
import json
import re
import subprocess
import time
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Sequence
SHA_RE = re.compile(r"^[0-9a-f]{40}$")
EXCLUDED_MESSAGE_MARKERS = ("[skip ci]", "cancel-stale-cd", "[metadata-only]")
@dataclass(frozen=True)
class CarrierDecision:
selected: bool
status: str
source_sha: str
latest_sha: str
main_tip_sha: str
def _git(args: Sequence[str], *, cwd: Path, check: bool = True) -> subprocess.CompletedProcess[str]:
return subprocess.run(
["git", *args],
cwd=cwd,
check=check,
capture_output=True,
text=True,
)
def _validate_sha(value: str, *, label: str) -> str:
normalized = value.strip().lower()
if not SHA_RE.fullmatch(normalized):
raise RuntimeError(f"{label}_invalid")
return normalized
def _latest_remote_sha(*, remote_url: str, branch: str, cwd: Path) -> str:
result = _git(
["ls-remote", "--heads", remote_url, f"refs/heads/{branch}"],
cwd=cwd,
)
rows = [row.split() for row in result.stdout.splitlines() if row.strip()]
if len(rows) != 1 or len(rows[0]) != 2:
raise RuntimeError("latest_main_ref_unresolved")
return _validate_sha(rows[0][0], label="latest_sha")
def _fetch_latest_history(*, remote_url: str, branch: str, cwd: Path, depth: int) -> None:
_git(
[
"fetch",
"--no-tags",
"--prune",
f"--depth={depth}",
remote_url,
f"+refs/heads/{branch}:refs/remotes/awoooi-carrier/{branch}",
],
cwd=cwd,
)
def _latest_deploy_eligible_sha(*, branch: str, cwd: Path) -> str | None:
result = _git(
[
"log",
"--format=%H%x1f%B%x1e",
f"refs/remotes/awoooi-carrier/{branch}",
],
cwd=cwd,
)
for record in result.stdout.split("\x1e"):
sha, separator, message = record.strip().partition("\x1f")
if not separator:
continue
normalized_message = message.lower()
if any(marker in normalized_message for marker in EXCLUDED_MESSAGE_MARKERS):
continue
return _validate_sha(sha, label="latest_deploy_eligible_sha")
return None
def _source_is_ancestor(*, source_sha: str, latest_sha: str, cwd: Path) -> bool:
result = _git(
["merge-base", "--is-ancestor", source_sha, latest_sha],
cwd=cwd,
check=False,
)
if result.returncode not in {0, 1}:
raise RuntimeError("carrier_lineage_check_failed")
return result.returncode == 0
def select_latest_inclusive_carrier(
*,
source_sha: str,
remote_url: str,
branch: str = "main",
cwd: Path,
debounce_seconds: float = 0,
) -> CarrierDecision:
source_sha = _validate_sha(source_sha, label="source_sha")
if debounce_seconds < 0 or debounce_seconds > 60:
raise RuntimeError("debounce_seconds_out_of_range")
if debounce_seconds:
time.sleep(debounce_seconds)
main_tip_sha = _latest_remote_sha(remote_url=remote_url, branch=branch, cwd=cwd)
_fetch_latest_history(remote_url=remote_url, branch=branch, cwd=cwd, depth=256)
latest_sha = _latest_deploy_eligible_sha(branch=branch, cwd=cwd)
if latest_sha is None:
_fetch_latest_history(remote_url=remote_url, branch=branch, cwd=cwd, depth=2048)
latest_sha = _latest_deploy_eligible_sha(branch=branch, cwd=cwd)
if latest_sha is None:
raise RuntimeError("latest_deploy_eligible_main_unresolved")
if source_sha == latest_sha:
return CarrierDecision(
selected=True,
status="selected_latest_main_carrier",
source_sha=source_sha,
latest_sha=latest_sha,
main_tip_sha=main_tip_sha,
)
if not _source_is_ancestor(source_sha=source_sha, latest_sha=latest_sha, cwd=cwd):
shallow = _git(
["rev-parse", "--is-shallow-repository"],
cwd=cwd,
).stdout.strip()
if shallow == "true":
_fetch_latest_history(remote_url=remote_url, branch=branch, cwd=cwd, depth=2048)
if not _source_is_ancestor(source_sha=source_sha, latest_sha=latest_sha, cwd=cwd):
raise RuntimeError("latest_main_does_not_include_source")
return CarrierDecision(
selected=False,
status="superseded_by_latest_inclusive_carrier",
source_sha=source_sha,
latest_sha=latest_sha,
main_tip_sha=main_tip_sha,
)
def _write_github_output(path: Path, decision: CarrierDecision) -> None:
fields = {
"selected": str(decision.selected).lower(),
"status": decision.status,
"source_sha": decision.source_sha,
"latest_sha": decision.latest_sha,
"main_tip_sha": decision.main_tip_sha,
}
with path.open("a", encoding="utf-8") as stream:
for key, value in fields.items():
stream.write(f"{key}={value}\n")
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--source-sha", required=True)
parser.add_argument("--remote-url", required=True)
parser.add_argument("--branch", default="main")
parser.add_argument("--repo", type=Path, default=Path.cwd())
parser.add_argument("--debounce-seconds", type=float, default=0)
parser.add_argument("--github-output", type=Path)
args = parser.parse_args()
decision = select_latest_inclusive_carrier(
source_sha=args.source_sha,
remote_url=args.remote_url,
branch=args.branch,
cwd=args.repo.resolve(),
debounce_seconds=args.debounce_seconds,
)
if args.github_output:
_write_github_output(args.github_output, decision)
print(json.dumps(asdict(decision), sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())