Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/scripts/check-desktop-prod-promotion-policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
return triggers


def main() -> int:

Check warning on line 48 in .github/scripts/check-desktop-prod-promotion-policy.py

View workflow job for this annotation

GitHub Actions / Hygiene

Long function

main is 163 lines; consider extracting focused helpers over 150 lines.
text = WORKFLOW.read_text()
triggers = workflow_triggers(text)

Expand All @@ -54,6 +54,7 @@
fail(f"prod promotion must allow only workflow_dispatch, got: {', '.join(triggers) or '<none>'}")
require("release_tag:", text, "manual promotion must require an explicit release tag")
require("confirm:", text, "manual promotion must require an explicit confirmation input")
require("python_backend_sha:", text, "manual promotion must require an explicit compatible python backend SHA")
require("promote-stable", text, "manual promotion confirmation phrase must remain explicit")
if "\n force:" in text or "inputs.force" in text:
fail("prod promotion must stay roll-forward only; do not expose a force rollback input")
Expand All @@ -70,6 +71,26 @@
fail(f"desktop backend prod promotion must not use automatic trigger {trigger.strip()}")

require("check-desktop-release-promotion.py", text, "workflow must run pre-release sanity checks")
require(
"check-desktop-python-backend-coupling.py",
text,
"workflow must validate attested python-backend coupling via the extracted checker",
)
require("--desktop-target-sha", text, "workflow must pass the desktop target SHA to the coupling checker")
require("--python-backend-sha", text, "workflow must pass the attested python-backend SHA to the coupling checker")
require(
"python-backend-bless-${PYTHON_BACKEND_SHA}",
text,
"workflow must look up the explicit python-backend attestation",
)
require("--tag-sha", text, "workflow must verify the python-backend attestation tag points to the explicit SHA")
require(
"backend/scripts/bless-python-backend.sh",
text,
"workflow must tell operators how to create python-backend attestation",
)
require("COUPLING_CHECK_ARGS=(", text, "workflow must keep coupling-check args populated under set -u")
require("live_prod_check: NOT_RUN", text, "workflow must honestly report that live prod SHA matching is not run")
require("--break-glass", text, "workflow must expose an audited emergency bypass")
require("--break-glass-confirm", text, "workflow must require typed break-glass confirmation")
require("--break-glass-reason", text, "workflow must require a break-glass audit rationale")
Expand All @@ -81,6 +102,12 @@
text,
"workflow must keep promotion-check arguments populated when break glass is disabled under set -u",
)
if "I-ACCEPT-UNBLESSED-PROD-RISK" in text:
fail("desktop prod promotion must not hardcode the python-backend unblessed override phrase")
if "--override-unblessed" in text:
fail("desktop prod promotion must not call check-python-backend-blessing.py with override flags")
if "git fetch --depth=1" in text:
fail("desktop prod promotion must not shallow-fetch the attested python-backend SHA")
if "BREAK_GLASS_ARGS=()" in text:
fail("normal stable promotion must not expand an empty optional array under set -u")
require(
Expand Down
155 changes: 155 additions & 0 deletions .github/scripts/check-desktop-python-backend-coupling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""Validate desktop stable promotion against an attested python-backend SHA.

Happy path: require a full 40-char attested SHA, validate the matching
python-backend-bless-<sha> release via check-python-backend-blessing.py (no
override flags), then require that SHA is a git ancestor of the desktop target.

Break-glass: when the desktop stable-promotion risk phrase and a single-line
reason are present, skip the entire coupling gate. Do not bridge to the
python-backend unblessed override phrase.
"""

from __future__ import annotations

import argparse
import re
import subprocess
import sys
from pathlib import Path

BREAK_GLASS_CONFIRM = "I-ACCEPT-STABLE-PROMOTION-RISK"
SHA_RE = re.compile(r"^[0-9a-f]{40}$")
SCRIPT_DIR = Path(__file__).resolve().parent
BLESSING_CHECKER = SCRIPT_DIR / "check-python-backend-blessing.py"


def fail(message: str) -> None:
raise SystemExit(f"FAIL: {message}")


def write_github_output(path: str | None, values: dict[str, str]) -> None:
if not path:
return
with Path(path).open("a", encoding="utf-8") as output:
for key, value in values.items():
print(f"{key}={value}", file=output)


def parse_break_glass(args: argparse.Namespace) -> bool:
break_glass_reason = args.break_glass_reason.strip()
break_glass = (
args.break_glass
and args.break_glass_confirm == BREAK_GLASS_CONFIRM
and bool(break_glass_reason)
and "\n" not in break_glass_reason
and "\r" not in break_glass_reason
)
if args.break_glass and not break_glass:
fail(
f"--break-glass requires --break-glass-confirm {BREAK_GLASS_CONFIRM} "
"and a non-empty --break-glass-reason"
)
return break_glass


def is_ancestor(python_sha: str, desktop_sha: str, test_is_ancestor: str | None) -> bool:
if test_is_ancestor is not None:
return test_is_ancestor == "true"
result = subprocess.run(
["git", "merge-base", "--is-ancestor", python_sha, desktop_sha],
check=False,
capture_output=True,
text=True,
)
return result.returncode == 0


def validate_attestation(release_json: str, python_sha: str, tag_sha: str | None) -> None:
if not release_json:
fail("--release-json is required when validating python-backend coupling")
cmd = [
sys.executable,
str(BLESSING_CHECKER),
"--release-json",
release_json,
"--target-sha",
python_sha,
]
if tag_sha:
cmd.extend(["--tag-sha", tag_sha])
result = subprocess.run(cmd, check=False, capture_output=True, text=True)
if result.returncode != 0:
detail = (result.stderr or result.stdout or "python-backend blessing check failed").strip()
fail(detail)


def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--desktop-target-sha", required=True)
parser.add_argument("--python-backend-sha", default="")
parser.add_argument("--release-json", default="")
parser.add_argument("--tag-sha", default="")
parser.add_argument("--github-output")
parser.add_argument(
"--break-glass",
action="store_true",
help="DANGER: skip the entire python-backend coupling gate",
)
parser.add_argument(
"--break-glass-confirm",
default="",
help=f"Must be {BREAK_GLASS_CONFIRM} when --break-glass is set",
)
parser.add_argument("--break-glass-reason", default="", help="Required audit rationale for --break-glass")
parser.add_argument(
"--test-is-ancestor",
choices=("true", "false"),
help="Test-only ancestor override; if unset, call real git merge-base",
)
args = parser.parse_args()

if parse_break_glass(args):
message = (
"python-backend coupling skipped by audited desktop break-glass "
f"({BREAK_GLASS_CONFIRM}): {args.break_glass_reason.strip()}"
)
print(message)
write_github_output(
args.github_output,
{"python_backend_coupling": "skipped_break_glass"},
)
return 0

python_sha = args.python_backend_sha.strip()
if not python_sha:
fail(
"python_backend_sha is required for desktop stable promotion. "
"Provide the full 40-char SHA from python-backend-bless-<sha>, "
"or enable audited break glass."
)
if not SHA_RE.match(python_sha):
fail("--python-backend-sha must be a full 40-char lowercase git SHA")

desktop_sha = args.desktop_target_sha.strip()
if not SHA_RE.match(desktop_sha):
fail("--desktop-target-sha must be a full 40-char lowercase git SHA")

validate_attestation(args.release_json.strip(), python_sha, args.tag_sha.strip() or None)

if not is_ancestor(python_sha, desktop_sha, args.test_is_ancestor):
fail(f"python_backend_sha ({python_sha}) is not an ancestor of desktop target ({desktop_sha})")

write_github_output(
args.github_output,
{
"python_backend_attested_sha": python_sha,
"python_backend_coupling": "ok",
},
)
print(f"python-backend coupling OK: attested {python_sha} is ancestor of {desktop_sha}")
return 0


if __name__ == "__main__":
raise SystemExit(main())
15 changes: 14 additions & 1 deletion .github/scripts/check-desktop-release-terminology.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,27 @@
"web/admin/app/(protected)/dashboard/releases/page.tsx",
)

# Protocol IDs for the python-backend attestation surface may appear on operator
# surfaces without a "legacy" disclaimer. Desktop beta qualification still must
# not use bare bless/blessed/blessing wording.
PROTOCOL_ALLOWLIST = (
"python-backend-bless-",
"bless-python-backend.sh",
"check-python-backend-blessing.py",
)


def _is_protocol_mention(line: str) -> bool:
return any(token in line for token in PROTOCOL_ALLOWLIST)


def main() -> int:
failures: list[str] = []
legacy_term = re.compile(r"\bbless(?:ed|ing)?\b", re.IGNORECASE)
for relative in OPERATOR_SURFACES:
path = ROOT / relative
for line_number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
if legacy_term.search(line) and "legacy" not in line.lower():
if legacy_term.search(line) and "legacy" not in line.lower() and not _is_protocol_mention(line):
failures.append(f"{relative}:{line_number}: desktop beta qualification uses legacy terminology")

canonical_script = ROOT / "desktop/macos/scripts/qualify-desktop-beta.sh"
Expand Down
Loading
Loading