forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreflight_public_build_config.py
More file actions
138 lines (119 loc) · 5.55 KB
/
Copy pathpreflight_public_build_config.py
File metadata and controls
138 lines (119 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python3
"""Resolve the reviewed public-build source from GitHub before a deploy builds."""
from __future__ import annotations
import argparse
import base64
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
from pathlib import Path
from typing import Any, Iterable
from check_public_build_contract import (
ROOT,
Contract,
Target,
build_args,
load_contract,
parse_values_document,
validate_values,
)
API_ROOT = "https://api.github.com"
class RemoteConfigMissing(RuntimeError):
"""The selected commit has no reviewed public-build configuration."""
class RemoteConfigUnavailable(RuntimeError):
"""The workflow token cannot read the authoritative GitHub source."""
def request_remote_values(
*, repository: str, ref: str, config_path: str, token: str
) -> dict[str, dict[str, str]]:
encoded_path = "/".join(urllib.parse.quote(segment, safe="") for segment in config_path.split("/"))
encoded_ref = urllib.parse.quote(ref, safe="")
request = urllib.request.Request(
f"{API_ROOT}/repos/{repository}/contents/{encoded_path}?ref={encoded_ref}",
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "omi-public-build-preflight",
},
)
try:
with urllib.request.urlopen(request, timeout=20) as response: # noqa: S310 - fixed GitHub API root
payload = json.loads(response.read().decode("utf-8"))
except urllib.error.HTTPError as exc:
if exc.code == 404:
raise RemoteConfigMissing("reviewed public-build configuration is missing at the deployed ref") from exc
raise RemoteConfigUnavailable(f"reviewed public-build configuration is unavailable (HTTP {exc.code})") from exc
except urllib.error.URLError as exc:
raise RemoteConfigUnavailable("reviewed public-build configuration is unavailable") from exc
if (
not isinstance(payload, dict)
or payload.get("encoding") != "base64"
or not isinstance(payload.get("content"), str)
):
raise RemoteConfigUnavailable("reviewed public-build configuration metadata is invalid")
try:
content = base64.b64decode("".join(payload["content"].split()), validate=True).decode("utf-8")
return parse_values_document(json.loads(content), source="remote reviewed public-build configuration")
except (ValueError, UnicodeDecodeError, json.JSONDecodeError) as exc:
raise RemoteConfigUnavailable("reviewed public-build configuration content is invalid") from exc
def select_targets(contract: Contract, names: Iterable[str] | None, all_targets: bool) -> list[Target]:
selected_names = sorted(contract.targets) if all_targets else list(names or [])
if not selected_names:
raise ValueError("specify --target or --all")
unknown = sorted(set(selected_names) - contract.targets.keys())
if unknown:
raise ValueError(f"unknown public-build targets: {', '.join(unknown)}")
return [contract.targets[name] for name in selected_names]
def write_github_output(path: Path, *, target: Target, values: dict[str, str]) -> None:
arguments = build_args(target, values)
with path.open("a", encoding="utf-8") as handle:
handle.write("build_args<<OMI_PUBLIC_BUILD_ARGS\n")
handle.write(f"{arguments}\n")
handle.write("OMI_PUBLIC_BUILD_ARGS\n")
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--environment", required=True)
parser.add_argument("--target", action="append")
parser.add_argument("--all", action="store_true")
parser.add_argument("--repository", default=os.environ.get("GITHUB_REPOSITORY"))
parser.add_argument("--ref", default=os.environ.get("GITHUB_SHA"))
parser.add_argument("--token", default=os.environ.get("GITHUB_TOKEN"))
parser.add_argument("--contract", type=Path, default=ROOT / "config" / "public-build-contract.json")
parser.add_argument("--github-output", type=Path)
args = parser.parse_args(argv)
if args.github_output and args.all:
print("public-build configuration preflight failed: --github-output requires one --target", file=sys.stderr)
return 1
if not args.repository or not args.ref or not args.token:
print(
"public-build configuration preflight failed: repository, ref, and read-only GitHub token are required",
file=sys.stderr,
)
return 1
try:
contract = load_contract(args.contract)
targets = select_targets(contract, args.target, args.all)
values = request_remote_values(
repository=args.repository,
ref=args.ref,
config_path=contract.config_path,
token=args.token,
)
errors = validate_values(contract, values, targets, args.environment)
if errors:
raise ValueError("; ".join(errors))
if args.github_output:
write_github_output(args.github_output, target=targets[0], values=values[args.environment])
except (OSError, ValueError, RemoteConfigMissing, RemoteConfigUnavailable, json.JSONDecodeError) as exc:
print(f"public-build configuration preflight failed: {exc}", file=sys.stderr)
return 1
print(
"public-build configuration preflight passed: "
f"source=reviewed-ref, environment={args.environment}, targets={len(targets)}"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())