-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathupdate.py
144 lines (112 loc) · 4.88 KB
/
update.py
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
139
140
141
142
143
144
"""
Run within a kick_tuxsuite_foo job.
Analyze the outputted builds.json and update our cache accordingly.
If _all_ builds passed we can safely update our cache with a "pass" build_status.
However, if any build fails or times out, we will mark it as either "fail" or
"badtux", respectively.
To clarify "badtux", it just means Tuxsuite had an issue outside of just building
its targets; something like a timeout or instance crash. In these instances,
"badtux" (or any non "pass" or "fail") build status signifies to our caching
system to not cache. The idea being that we want to rerun these jobs and not have
a caching system stop us from doing so -- even if sha and version match.
"""
import json
import os
import sys
import re
import urllib.request
from pathlib import Path
from utils import get_patches_hash, get_workflow_name_to_var_name, update_repository_variable
if "GITHUB_WORKFLOW" not in os.environ:
print("Couldn't find GITHUB_WORKFLOW in env. Not in a GitHub Workflow?")
sys.exit(1)
MOCK = "MOCK" in os.environ
def update_cache(status: str, git_sha: str, clang_version: str,
patches_hash: str):
print(f"Trying to update cache with status: {status}")
cache_entry_key = get_workflow_name_to_var_name(
os.environ["GITHUB_WORKFLOW"])
if "REPO_SCOPED_PAT" not in os.environ:
print(
"Couldn't find REPO_SCOPED_PAT in env. Not in a GitHub Workflow?")
sys.exit(1)
headers = {"Authorization": f"Bearer {os.environ['REPO_SCOPED_PAT']}"}
update_repository_variable(
cache_entry_key,
http_headers=headers,
build_status=status,
sha=git_sha,
clang_version=clang_version,
patches_hash=patches_hash,
# prevent overriding a 'fail' to a 'pass'
allow_fail_to_pass=False,
)
def main():
builds_json = Path(("mock." if MOCK else "") + "builds.json")
print(f"Reading {builds_json}")
raw = builds_json.read_text(encoding="utf-8")
builds = json.loads(raw)["builds"]
if len(builds) == 0:
print("No builds present. Did Tuxsuite run?")
sys.exit(1)
# let's grab sha and version info as Tuxsuite has the most up-to-date info
builds_that_are_missing_metadata = []
git_sha = None
clang_version = None
for entry, build in builds.items():
try:
git_sha = build["git_sha"]
clang_version = build["tuxmake_metadata"]["compiler"][
"version_full"]
break
except KeyError:
builds_that_are_missing_metadata.append(entry)
# some builds may be missing metadata due to patches failing to apply
for build_id in builds_that_are_missing_metadata:
build = builds[build_id]
if "Unable to apply kernel patch" not in build["status_message"]:
continue
req = urllib.request.Request(build["download_url"] + "build.log")
build_log_raw = ""
with urllib.request.urlopen(req) as response:
build_log_raw = response.read().decode()
failed_pattern = (
r"(?<=Apply patch set FAILED\s)[0-9A-Za-z._:/\-\s]*?(?=\serror: )")
failed_matches = re.findall(failed_pattern, build_log_raw)
if len(failed_matches) == 0:
print(
f"No patches failed to apply yet the build status stated there were: {build['status_message']}"
)
sys.exit(
0) # Not sure how we got here but continue the action anyways
patches_that_failed_to_apply = failed_matches[0].split('\n')
print(
f"Error: Some patches failed to apply.\n{patches_that_failed_to_apply}\n"
)
sys.exit(1)
if len(builds_that_are_missing_metadata) == len(builds):
raise RuntimeError(
f"Could not find a suitable git sha or compiler version in any build\n"
f"Here's the build.json:\n{raw}")
if len(builds_that_are_missing_metadata) > 0:
print(
"Warning: Some of the builds in builds.json are malformed and missing "
"some metadata.\n"
f"Here's a list: {builds_that_are_missing_metadata}\n"
f"Here's the build.json in question:\n{raw}")
assert git_sha and clang_version
tree_name = os.environ["GITHUB_WORKFLOW"].split(' ', 1)[0]
patches_hash = get_patches_hash(tree_name)
print(f"Tuxsuite {git_sha = } | {clang_version = } | {patches_hash = }")
for _, info in builds.items():
if info["tuxbuild_status"] != "complete":
update_cache("badtux", git_sha, clang_version, patches_hash)
sys.exit(0)
if (status := info["build_status"]) != "pass":
update_cache(status, git_sha, clang_version, patches_hash)
sys.exit(0)
# only if all builds completed and passed will we set this status
update_cache("pass", git_sha, clang_version, patches_hash)
sys.exit(0)
if __name__ == "__main__":
main()