Skip to content

Commit f0e5c2c

Browse files
committed
Add bin script for joining buildkite logs
1 parent aa3fa8a commit f0e5c2c

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

bin/combine-buildkite

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import asyncio
5+
import os
6+
import re
7+
import requests
8+
9+
_API_TOKEN = os.environ["BUILDKITE_API_TOKEN"]
10+
_BASE_URL = "https://api.buildkite.com/v2/organizations/"
11+
_BUILDKITE_AUTH_HEADERS = {"Authorization": f"Bearer {_API_TOKEN}"}
12+
13+
ansi_escape_8bit = re.compile(
14+
r"(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])"
15+
)
16+
17+
18+
def _build_parser() -> argparse.ArgumentParser:
19+
parser = argparse.ArgumentParser(description="Combine buildkite logs")
20+
parser.add_argument(
21+
"pipeline", help="Pipeline to combine logs for, ex: bazelbuild/bazel"
22+
)
23+
parser.add_argument(
24+
"build_number", help="Build number to combine logs for"
25+
)
26+
return parser
27+
28+
29+
def _get_job_log(
30+
org: str, pipeline: str, build_number: str, job_id: str
31+
) -> str:
32+
response = requests.get(
33+
f"{_BASE_URL}/{org}/pipelines/{pipeline}/builds/{build_number}/jobs/{job_id}/log",
34+
headers=_BUILDKITE_AUTH_HEADERS,
35+
)
36+
response.raise_for_status()
37+
return ansi_escape_8bit.sub("", response.json()["content"]).replace(
38+
"\r", ""
39+
)
40+
41+
42+
async def _main(org: str, pipeline: str, build_number: str) -> None:
43+
response = requests.get(
44+
f"{_BASE_URL}/{org}/pipelines/{pipeline}/builds/{build_number}",
45+
headers=_BUILDKITE_AUTH_HEADERS,
46+
)
47+
response.raise_for_status()
48+
49+
combined_log = ""
50+
build = response.json()
51+
loop = asyncio.get_event_loop()
52+
futures = []
53+
54+
for job in build["jobs"]:
55+
job_id = str(job["id"])
56+
futures.append(
57+
loop.run_in_executor(
58+
None, _get_job_log, org, pipeline, build_number, job_id
59+
)
60+
)
61+
62+
for future in futures:
63+
combined_log += await future
64+
combined_log += "\n"
65+
66+
with open(f"buildkite-build-{build_number}.log", "w") as f:
67+
f.write(combined_log)
68+
f.write("\n")
69+
70+
71+
if __name__ == "__main__":
72+
args = _build_parser().parse_args()
73+
org, pipeline = args.pipeline.split("/", 1)
74+
loop = asyncio.get_event_loop()
75+
loop.run_until_complete(_main(org, pipeline, args.build_number))

0 commit comments

Comments
 (0)