about summary refs log tree commit diff
path: root/library/compiler-builtins/ci/ci-util.py
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2025-04-20 07:05:32 +0000
committerTrevor Gross <t.gross35@gmail.com>2025-04-20 04:24:24 -0400
commit8902f740da9566061c5b23000899e7908921370b (patch)
treea6b61bb55fa82c691d588551b9069d6a458ea2aa /library/compiler-builtins/ci/ci-util.py
parenta829d916b5555a5ef65d521e98488f32b5476d36 (diff)
downloadrust-8902f740da9566061c5b23000899e7908921370b.tar.gz
rust-8902f740da9566061c5b23000899e7908921370b.zip
ci: Skip testing libm in PRs if it did not change
Many contributions to compiler-builtins don't have any need to touch
libm, and could get by with the few minutes of CI for compiler-builtins
rather than the ~30 minutes for libm. We already have some scripts that
handle changed file detection, so expand its use to skip libm CI if it
doesn't need to run.
Diffstat (limited to 'library/compiler-builtins/ci/ci-util.py')
-rwxr-xr-xlibrary/compiler-builtins/ci/ci-util.py42
1 files changed, 31 insertions, 11 deletions
diff --git a/library/compiler-builtins/ci/ci-util.py b/library/compiler-builtins/ci/ci-util.py
index d9e402d6bd7..7486d6b4186 100755
--- a/library/compiler-builtins/ci/ci-util.py
+++ b/library/compiler-builtins/ci/ci-util.py
@@ -7,6 +7,7 @@ git history.
 
 import json
 import os
+import re
 import subprocess as sp
 import sys
 from dataclasses import dataclass
@@ -68,6 +69,10 @@ IGNORE_FILES = [
     "libm/src/math/arch/intrinsics.rs",
 ]
 
+# libm PR CI takes a long time and doesn't need to run unless relevant files have been
+# changed. Anything matching this regex pattern will trigger a run.
+TRIGGER_LIBM_PR_CI = ".*(libm|musl).*"
+
 TYPES = ["f16", "f32", "f64", "f128"]
 
 
@@ -116,7 +121,6 @@ class FunctionDef(TypedDict):
     type: str
 
 
-@dataclass
 class Context:
     gh_ref: str | None
     changed: list[Path]
@@ -142,7 +146,7 @@ class Context:
         # the PR number), and sets this as `GITHUB_REF`.
         ref = self.gh_ref
         eprint(f"using ref `{ref}`")
-        if ref is None or "merge" not in ref:
+        if not self.is_pr():
             # If the ref is not for `merge` then we are not in PR CI
             eprint("No diff available for ref")
             return
@@ -170,6 +174,10 @@ class Context:
         )
         self.changed = [Path(p) for p in textlist.splitlines()]
 
+    def is_pr(self) -> bool:
+        """Check if we are looking at a PR rather than a push."""
+        return self.gh_ref is not None and "merge" in self.gh_ref
+
     @staticmethod
     def _ignore_file(fname: str) -> bool:
         return any(fname.startswith(pfx) for pfx in IGNORE_FILES)
@@ -196,7 +204,16 @@ class Context:
 
         return ret
 
-    def make_workflow_output(self) -> str:
+    def may_skip_libm_ci(self) -> bool:
+        """If this is a PR and no libm files were changed, allow skipping libm
+        jobs."""
+
+        if self.is_pr():
+            return all(not re.match(TRIGGER_LIBM_PR_CI, str(f)) for f in self.changed)
+
+        return False
+
+    def emit_workflow_output(self):
         """Create a JSON object a list items for each type's changed files, if any
         did change, and the routines that were affected by the change.
         """
@@ -216,9 +233,10 @@ class Context:
                 eprint("Skipping all extensive tests")
 
         changed = self.changed_routines()
-        ret = []
+        matrix = []
         total_to_test = 0
 
+        # Figure out which extensive tests need to run
         for ty in TYPES:
             ty_changed = changed.get(ty, [])
             ty_to_test = [] if skip_tests else ty_changed
@@ -230,9 +248,14 @@ class Context:
                 "to_test": ",".join(ty_to_test),
             }
 
-            ret.append(item)
-        output = json.dumps({"matrix": ret}, separators=(",", ":"))
-        eprint(f"output: {output}")
+            matrix.append(item)
+
+        ext_matrix = json.dumps({"extensive_matrix": matrix}, separators=(",", ":"))
+        may_skip = str(self.may_skip_libm_ci()).lower()
+        print(f"extensive_matrix={ext_matrix}")
+        print(f"may_skip_libm_ci={may_skip}")
+        eprint(f"extensive_matrix={ext_matrix}")
+        eprint(f"may_skip_libm_ci={may_skip}")
         eprint(f"total extensive tests: {total_to_test}")
 
         if error_on_many_tests and total_to_test > MANY_EXTENSIVE_THRESHOLD:
@@ -242,8 +265,6 @@ class Context:
             )
             exit(1)
 
-        return output
-
 
 def locate_baseline(flags: list[str]) -> None:
     """Find the most recent baseline from CI, download it if specified.
@@ -398,8 +419,7 @@ def main():
     match sys.argv[1:]:
         case ["generate-matrix"]:
             ctx = Context()
-            output = ctx.make_workflow_output()
-            print(f"matrix={output}")
+            ctx.emit_workflow_output()
         case ["locate-baseline", *flags]:
             locate_baseline(flags)
         case ["check-regressions", *args]: