forked from carbon-language/carbon-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtarget_determinator.py
executable file
·108 lines (90 loc) · 3.03 KB
/
target_determinator.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
#!/usr/bin/env python3
"""Computes the potentially differing rules from some git commit.
Wraps the "target-determinator" Go program here:
https://github.com/bazel-contrib/target-determinator
The purpose is to compute the potentially impacted set of targets from some
provided Git commit to the current checkout.
This script will ensure a cached version of the latest release is available, and
then forward a limited set of flags to it. This script also filters the
resulting targets using `bazel query` to make it the most relevant list for
continuous integration.
"""
__copyright__ = """
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
import subprocess
import argparse
import tempfile
import sys
from pathlib import Path
import scripts_utils
def log(s: str) -> None:
print(s, file=sys.stderr)
def filter_targets(bazel: Path, targets: str) -> str:
with tempfile.NamedTemporaryFile(mode="w+") as tmp:
query = (
f"let t = set({targets}) in "
"kind(rule, $t) except attr(tags, manual, $t)\n"
)
query_lines = query.splitlines()
if len(query_lines) <= 10:
query_snippet = "\n".join(query_lines)
else:
query_snippet = "\n".join(
query_lines[:5] + ["..."] + query_lines[-5:]
)
log(f"Bazel query snippet:\n```\n{query_snippet}\n```")
tmp.write(query)
tmp.flush()
try:
p = subprocess.run(
[str(bazel), "query", f"--query_file={tmp.name}"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
encoding="utf-8",
)
return p.stdout
except subprocess.CalledProcessError as err:
log(err.stderr)
log("Full query file:\n```")
with open(tmp.name) as f:
log(f.read())
log("```")
raise
def main() -> None:
parser = argparse.ArgumentParser(__doc__)
parser.add_argument(
"baseline", nargs=1, help="Git commit of the diff baseline."
)
parser.add_argument(
"args",
nargs="*",
help="Remaining args to forward to the underlying tool.",
)
parsed_args = parser.parse_args()
scripts_utils.chdir_repo_root()
bazel = Path(scripts_utils.locate_bazel())
target_determinator = scripts_utils.get_release(
scripts_utils.Release.TARGET_DETERMINATOR
)
p = subprocess.run(
[
target_determinator,
f"--bazel={bazel}",
parsed_args.baseline[0],
]
+ parsed_args.args,
check=True,
stdout=subprocess.PIPE,
encoding="utf-8",
)
targets = p.stdout
if targets.strip() != "":
targets = filter_targets(bazel, targets)
log(f"Found {len(targets.splitlines())} impacted targets!")
print(targets.rstrip())
if __name__ == "__main__":
main()