Skip to content

Commit 885e24c

Browse files
committed
ci: Add a way to run libm tests that would otherwise be skipped
As part of this, commonize the way to get a `PrInfo` object from environment variables.
1 parent 16d9435 commit 885e24c

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

ci/ci-util.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
# accidentally spending huge amounts of CI time.
6060
ALLOW_MANY_EXTENSIVE_DIRECTIVE = "ci: allow-many-extensive"
6161
MANY_EXTENSIVE_THRESHOLD = 20
62+
# Require tests for `libm`
63+
TEST_LIBM_DIRECTIVE = "ci: test-libm"
6264

6365
# Don't run exhaustive tests if these files change, even if they contaiin a function
6466
# definition.
@@ -90,8 +92,25 @@ class PrInfo:
9092
number: int
9193

9294
@classmethod
93-
def load(cls, pr_number: int | str) -> Self:
94-
"""For a given PR number, query the body and commit list"""
95+
def from_env(cls, gh_ref: str | None = None) -> Self | None:
96+
"""Create a PR object from the PR_NUMBER environment if set, using a ref
97+
as a fallback. Returns `None` is there is no PR found.
98+
"""
99+
pr_env = os.environ.get("PR_NUMBER")
100+
if pr_env is not None and len(pr_env) > 0:
101+
# `type(cls)` needs to be used rather than `PrInfo` to keep MyPy happy
102+
return type(cls).from_pr(pr_env)
103+
104+
if gh_ref is None:
105+
return None
106+
107+
# Split `refs/pull/1234/merge`
108+
pr_number = int(gh_ref.split("/")[2])
109+
return type(cls).from_pr(pr_number)
110+
111+
@classmethod
112+
def from_pr(cls, pr_number: int | str) -> Self:
113+
"""For a given PR number, query the body and commit list."""
95114
pr_info = sp.check_output(
96115
[
97116
"gh",
@@ -207,22 +226,31 @@ def may_skip_libm_ci(self) -> bool:
207226
"""If this is a PR and no libm files were changed, allow skipping libm
208227
jobs."""
209228

210-
if self.is_pr():
211-
return all(not re.match(TRIGGER_LIBM_PR_CI, str(f)) for f in self.changed)
229+
# Always run on merge CI
230+
if not self.is_pr():
231+
return False
232+
233+
pr = PrInfo.from_env()
234+
if pr is None:
235+
eprint("Is a PR but couldn't load PrInfo")
236+
exit(1)
237+
238+
# Allow opting in to libm tests
239+
if pr.contains_directive(TEST_LIBM_DIRECTIVE):
240+
return True
212241

213-
return False
242+
return all(not re.match(TRIGGER_LIBM_PR_CI, str(f)) for f in self.changed)
214243

215244
def emit_workflow_output(self):
216245
"""Create a JSON object a list items for each type's changed files, if any
217246
did change, and the routines that were affected by the change.
218247
"""
219248

220-
pr_number = os.environ.get("PR_NUMBER")
221249
skip_tests = False
222250
error_on_many_tests = False
223251

224-
if pr_number is not None and len(pr_number) > 0:
225-
pr = PrInfo.load(pr_number)
252+
pr = PrInfo.from_env()
253+
if pr is not None:
226254
skip_tests = pr.contains_directive(SKIP_EXTENSIVE_DIRECTIVE)
227255
error_on_many_tests = not pr.contains_directive(
228256
ALLOW_MANY_EXTENSIVE_DIRECTIVE
@@ -371,7 +399,7 @@ def handle_bench_regressions(args: list[str]):
371399
eprint(USAGE)
372400
exit(1)
373401

374-
pr = PrInfo.load(pr_number)
402+
pr = PrInfo.from_pr(pr_number)
375403
if pr.contains_directive(REGRESSION_DIRECTIVE):
376404
eprint("PR allows regressions")
377405
return

0 commit comments

Comments
 (0)