Introduces shared seams for paginated views, D-pad reorder, media control routing, async singletons and the device method channel, then points the open-coded copies at them. Also removes unused models and duplicated provider/server plumbing, folds the twice-implemented artifact store in the server, and factors the repeated Flutter toolchain prologue in CI into a composite action.
63 lines
2.0 KiB
Python
Executable File
63 lines
2.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Require immutable commit pins for remote GitHub Actions dependencies."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import workflow_yaml
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
WORKFLOWS = ROOT / ".github" / "workflows"
|
|
ACTIONS = ROOT / ".github" / "actions"
|
|
REMOTE_RE = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+(?:/[A-Za-z0-9_./-]+)?@[0-9a-fA-F]{40}$")
|
|
|
|
|
|
def iter_action_files(directory: Path = ACTIONS):
|
|
"""Local composite actions run in the same trust boundary as the workflows."""
|
|
yield from sorted((*directory.glob("*/action.yml"), *directory.glob("*/action.yaml")))
|
|
|
|
|
|
def iter_uses_references(path: Path):
|
|
return workflow_yaml.iter_uses_references(path.read_text(encoding="utf-8"))
|
|
|
|
|
|
def validate_reference(reference: str) -> str | None:
|
|
if reference.startswith("./"):
|
|
return None
|
|
if REMOTE_RE.fullmatch(reference):
|
|
return None
|
|
return "remote actions must use a full 40-character commit SHA"
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
args = list(sys.argv[1:] if argv is None else argv)
|
|
paths = (
|
|
[Path(value) for value in args]
|
|
if args
|
|
else [*workflow_yaml.iter_workflow_files(WORKFLOWS), *iter_action_files()]
|
|
)
|
|
violations = []
|
|
for path in paths:
|
|
for line_number, reference in iter_uses_references(path):
|
|
reason = validate_reference(reference)
|
|
if reason:
|
|
try:
|
|
display_path = path.resolve().relative_to(ROOT)
|
|
except ValueError:
|
|
display_path = path
|
|
violations.append(f"{display_path}:{line_number}: {reference!r}: {reason}")
|
|
if violations:
|
|
print("Mutable or malformed GitHub Actions references:", file=sys.stderr)
|
|
for violation in violations:
|
|
print(f" {violation}", file=sys.stderr)
|
|
return 1
|
|
print(f"Workflow action pins verified ({len(paths)} files).")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|