From 252e624fb40e34f2697c3415796dd4b33276cc0d Mon Sep 17 00:00:00 2001 From: geomin12 Date: Tue, 20 Oct 2026 11:31:38 -0700 Subject: [PATCH 1/5] ci: scope multi-arch nightly tests to rocm-libraries subtrees The nightly passed `changed_projects: ''`, TheRock's "test everything" signal, so every scheduled run spent GPU runner time on ROCm system components (hip-tests, rocrtst, rocgdb, rocprofiler-*, amdsmi, rccl, ...) that no change in this repository can affect. Derive the test scope from .github/repos-config.json so the nightly resolves tests through TheRock's consumer graph, the same path presubmit already takes. Reading the config rather than hardcoding a list keeps the scope correct as subtrees are added or removed. Co-Authored-By: Claude Opus 4.6 --- .../therock-multi-arch-ci-nightly.yml | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/.github/workflows/therock-multi-arch-ci-nightly.yml b/.github/workflows/therock-multi-arch-ci-nightly.yml index b32752dbf10d..387b2840c689 100644 --- a/.github/workflows/therock-multi-arch-ci-nightly.yml +++ b/.github/workflows/therock-multi-arch-ci-nightly.yml @@ -9,6 +9,12 @@ # test hardware exists for that family yet (see amdgpu_family_matrix.py in # TheRock, family key "gfx125x": test-runs-on is empty everywhere). # +# Testing is scoped to the subtrees listed in .github/repos-config.json rather +# than to all of ROCm. A schedule run has no diff to narrow against, so TheRock +# would otherwise test every component it builds, including system components +# (hip-tests, rocrtst, rocgdb, rocprofiler-*, amdsmi, rccl, ...) that this +# repository cannot affect. +# # For manual triggering with custom GPU families, use therock-multi-arch-ci.yml. name: TheRock Multi-Arch Nightly CI @@ -33,6 +39,48 @@ concurrency: cancel-in-progress: true jobs: + configure: + name: Configure Test Scope + runs-on: ubuntu-24.04 + outputs: + test_projects: ${{ steps.scope.outputs.test_projects }} + steps: + - name: Checkout repository config + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github/repos-config.json + sparse-checkout-cone-mode: false + + - name: Collect rocm-libraries subtrees + id: scope + run: | + python3 - <<'PY' >> "$GITHUB_OUTPUT" + import json + + with open(".github/repos-config.json", encoding="utf-8") as f: + config = json.load(f) + subtrees = sorted( + f"{entry['category']}/{entry['name']}" + for entry in config["repositories"] + ) + print("test_projects=" + ",".join(subtrees)) + PY + + - name: Surface test scope + env: + TEST_PROJECTS: ${{ steps.scope.outputs.test_projects }} + run: | + { + echo "### Nightly test scope" + echo "" + echo "Testing rocm-libraries subtrees and their direct consumers only:" + echo "" + echo '```' + echo "${TEST_PROJECTS}" | tr ',' '\n' + echo '```' + } >> "$GITHUB_STEP_SUMMARY" + setup: uses: ROCm/TheRock/.github/workflows/setup_multi_arch.yml@47434387de730d51788b705e5600602dd6064997 # 2026-10-16 with: @@ -85,7 +133,7 @@ jobs: linux_build_and_test: name: Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} - needs: [setup] + needs: [configure, setup] if: >- ${{ needs.setup.outputs.linux_build_config != '' && @@ -101,8 +149,12 @@ jobs: rocm_rpm_package_version: ${{ needs.setup.outputs.rocm_rpm_package_version }} test_type: ${{ needs.setup.outputs.test_type }} external_repo_config: ${{ needs.setup.outputs.external_repo_config }} - # Empty string triggers full test run in downstream workflow - changed_projects: '' + # Scope testing to the subtrees this repository owns (plus the consumers + # TheRock's dependency graph pulls in). An empty string would mean "test + # everything", which on a schedule run spends GPU runner time on ROCm + # system components (hip-tests, rocrtst, rocgdb, rocprofiler-*, amdsmi, + # ...) that no rocm-libraries change can affect. + changed_projects: ${{ needs.configure.outputs.test_projects }} repository: ROCm/TheRock ref: 47434387de730d51788b705e5600602dd6064997 # 2026-10-16 permissions: @@ -111,7 +163,7 @@ jobs: windows_build_and_test: name: Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} - needs: [setup] + needs: [configure, setup] if: >- ${{ needs.setup.outputs.windows_build_config != '' && @@ -125,8 +177,8 @@ jobs: rocm_package_version: ${{ needs.setup.outputs.rocm_package_version }} test_type: ${{ needs.setup.outputs.test_type }} external_repo_config: ${{ needs.setup.outputs.external_repo_config }} - # Empty string triggers full test run in downstream workflow - changed_projects: '' + # See the Linux job above: scope testing to rocm-libraries-owned subtrees. + changed_projects: ${{ needs.configure.outputs.test_projects }} repository: ROCm/TheRock ref: 47434387de730d51788b705e5600602dd6064997 # 2026-10-16 permissions: @@ -137,6 +189,7 @@ jobs: name: Multi-Arch CI Summary if: always() needs: + - configure - setup - linux_build_and_test - windows_build_and_test From 2204f2c0dffbc754a3c2f9dd7ea0216731ff2af9 Mon Sep 17 00:00:00 2001 From: geomin12 Date: Mon, 26 Oct 2026 07:05:16 -0700 Subject: [PATCH 2/5] refactor(ci): extract nightly test scope into a proper script The inline heredoc-Python and shell step-summary block in the multi-arch nightly workflow were hard to read and impossible to run locally. Move the logic into .github/scripts/therock_nightly_test_scope.py, reusing the existing load_repo_config/get_valid_prefixes helpers instead of re-parsing repos-config.json ad hoc, so there is one definition of a `category/name` subtree. Output is identical to the inline version. An empty subtree list now fails the job, since TheRock reads an empty changed_projects as "test everything" -- the opposite of this job's purpose. The configure job checks out .github and sets up Python to match therock-ci-nightly.yml. --- .../tests/therock_nightly_test_scope_test.py | 81 ++++++++++++++++ .github/scripts/therock_nightly_test_scope.py | 92 +++++++++++++++++++ .../therock-multi-arch-ci-nightly.yml | 44 +++------ 3 files changed, 187 insertions(+), 30 deletions(-) create mode 100644 .github/scripts/tests/therock_nightly_test_scope_test.py create mode 100644 .github/scripts/therock_nightly_test_scope.py diff --git a/.github/scripts/tests/therock_nightly_test_scope_test.py b/.github/scripts/tests/therock_nightly_test_scope_test.py new file mode 100644 index 000000000000..cdf49649c93d --- /dev/null +++ b/.github/scripts/tests/therock_nightly_test_scope_test.py @@ -0,0 +1,81 @@ +import json +import os +import sys +import tempfile +import unittest +from pathlib import Path +from typing import List + +sys.path.insert(0, os.fspath(Path(__file__).parent.parent)) +import therock_nightly_test_scope as scope + + +def make_entry(name: str, category: str) -> dict: + return { + "name": name, + "url": f"ROCm/{name}", + "branch": "develop", + "category": category, + "auto_subtree_pull": False, + "auto_subtree_push": True, + "monorepo_source_of_truth": True, + } + + +def write_config(tmpdir: str, entries: List[dict]) -> Path: + config_path = Path(tmpdir) / "repos-config.json" + config_path.write_text(json.dumps({"repositories": entries}), encoding="utf-8") + return config_path + + +class NightlyTestScopeTest(unittest.TestCase): + def test_returns_sorted_category_name_pairs(self): + with tempfile.TemporaryDirectory() as tmpdir: + config_path = write_config( + tmpdir, + [ + make_entry("rocblas", "projects"), + make_entry("rocsparse", "projects"), + make_entry("hipblas-common", "shared"), + ], + ) + self.assertEqual( + scope.get_test_projects(config_path), + [ + "projects/rocblas", + "projects/rocsparse", + "shared/hipblas-common", + ], + ) + + def test_includes_entries_regardless_of_subtree_sync_flags(self): + # The nightly scope is "everything this repo owns", so entries are not + # filtered by the auto_subtree_pull/push flags that the sync tooling uses. + with tempfile.TemporaryDirectory() as tmpdir: + entry = make_entry("rocprim", "projects") + entry["auto_subtree_push"] = False + entry["monorepo_source_of_truth"] = False + config_path = write_config(tmpdir, [entry]) + self.assertEqual(scope.get_test_projects(config_path), ["projects/rocprim"]) + + def test_empty_config_fails_instead_of_testing_everything(self): + # An empty changed_projects means "test everything" to TheRock. + with tempfile.TemporaryDirectory() as tmpdir: + config_path = write_config(tmpdir, []) + with self.assertRaises(SystemExit): + scope.main(["--config", os.fspath(config_path)]) + + def test_real_config_is_non_empty(self): + projects = scope.get_test_projects(scope.DEFAULT_CONFIG_PATH) + self.assertTrue(projects) + for project in projects: + self.assertIn("/", project) + + def test_step_summary_lists_each_subtree_on_its_own_line(self): + summary = scope.format_step_summary(["projects/rocblas", "shared/rocroller"]) + self.assertIn("### Nightly test scope", summary) + self.assertIn("projects/rocblas\nshared/rocroller", summary) + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/scripts/therock_nightly_test_scope.py b/.github/scripts/therock_nightly_test_scope.py new file mode 100644 index 000000000000..769daa1844a9 --- /dev/null +++ b/.github/scripts/therock_nightly_test_scope.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +""" +TheRock Nightly Test Scope +-------------------------- +Computes the set of projects the multi-arch nightly CI workflow should test. + +A scheduled run has no diff to narrow testing against, so TheRock would +otherwise test every component it builds, including ROCm system components +(hip-tests, rocrtst, rocgdb, rocprofiler-*, amdsmi, rccl, ...) that no change +in this repository can affect. This script emits every subtree registered in +.github/repos-config.json in `category/name` form, which the workflow passes to +TheRock as `changed_projects` so testing stays scoped to the code this +repository owns (plus the consumers TheRock's dependency graph pulls in). + +Arguments: + --config : OPTIONAL, path to the repos-config.json file. + +Outputs: + Writes 'test_projects' to the GitHub Actions $GITHUB_OUTPUT file as a + comma-separated list of subtrees in `category/name` format, and appends a + human-readable scope listing to $GITHUB_STEP_SUMMARY. Both are printed to + stdout when run outside of GitHub Actions. + +Example Usage: + python therock_nightly_test_scope.py +""" + +import argparse +import logging +from pathlib import Path +from typing import List, Optional + +from ci_utils import append_step_summary, set_github_output +from config_loader import load_repo_config +from pr_detect_changed_subtrees import get_valid_prefixes + +logger = logging.getLogger(__name__) + +SCRIPT_DIR = Path(__file__).resolve().parent +DEFAULT_CONFIG_PATH = SCRIPT_DIR.parent / "repos-config.json" + + +def parse_arguments(argv: Optional[List[str]] = None) -> argparse.Namespace: + """Parse command-line arguments.""" + parser = argparse.ArgumentParser( + description="Compute the nightly multi-arch CI test scope." + ) + parser.add_argument( + "--config", + type=Path, + default=DEFAULT_CONFIG_PATH, + help="Path to the repos-config.json file", + ) + return parser.parse_args(argv) + + +def get_test_projects(config_path: Path) -> List[str]: + """Return every subtree in repos-config.json as a sorted `category/name` list.""" + config = load_repo_config(str(config_path)) + return sorted(get_valid_prefixes(config)) + + +def format_step_summary(test_projects: List[str]) -> str: + """Render the test scope as a markdown step summary.""" + subtree_list = "\n".join(test_projects) + return ( + "### Nightly test scope\n" + "\n" + "Testing rocm-libraries subtrees and their direct consumers only:\n" + "\n" + f"```\n{subtree_list}\n```\n" + ) + + +def main(argv: Optional[List[str]] = None) -> None: + """Emit the nightly test scope for the multi-arch CI workflow.""" + logging.basicConfig(level=logging.INFO) + args = parse_arguments(argv) + + test_projects = get_test_projects(args.config) + if not test_projects: + # TheRock reads an empty `changed_projects` as "test everything", which + # is the opposite of this job's purpose, so fail instead of emitting it. + raise SystemExit(f"No subtrees found in {args.config}") + + set_github_output({"test_projects": ",".join(test_projects)}) + append_step_summary(format_step_summary(test_projects)) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/therock-multi-arch-ci-nightly.yml b/.github/workflows/therock-multi-arch-ci-nightly.yml index 387b2840c689..6f316aeabbab 100644 --- a/.github/workflows/therock-multi-arch-ci-nightly.yml +++ b/.github/workflows/therock-multi-arch-ci-nightly.yml @@ -45,41 +45,25 @@ jobs: outputs: test_projects: ${{ steps.scope.outputs.test_projects }} steps: - - name: Checkout repository config + - name: Checkout CI config uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - sparse-checkout: | - .github/repos-config.json - sparse-checkout-cone-mode: false + sparse-checkout: .github + sparse-checkout-cone-mode: true + + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.12" + + - name: Install python dependencies + run: | + python -m pip install --upgrade pip + pip install pydantic requests - name: Collect rocm-libraries subtrees id: scope - run: | - python3 - <<'PY' >> "$GITHUB_OUTPUT" - import json - - with open(".github/repos-config.json", encoding="utf-8") as f: - config = json.load(f) - subtrees = sorted( - f"{entry['category']}/{entry['name']}" - for entry in config["repositories"] - ) - print("test_projects=" + ",".join(subtrees)) - PY - - - name: Surface test scope - env: - TEST_PROJECTS: ${{ steps.scope.outputs.test_projects }} - run: | - { - echo "### Nightly test scope" - echo "" - echo "Testing rocm-libraries subtrees and their direct consumers only:" - echo "" - echo '```' - echo "${TEST_PROJECTS}" | tr ',' '\n' - echo '```' - } >> "$GITHUB_STEP_SUMMARY" + run: python .github/scripts/therock_nightly_test_scope.py setup: uses: ROCm/TheRock/.github/workflows/setup_multi_arch.yml@47434387de730d51788b705e5600602dd6064997 # 2026-10-16 From 45d91815d90fe4c7d9ffecb1adc2fa693b7466f0 Mon Sep 17 00:00:00 2001 From: geomin12 Date: Mon, 26 Oct 2026 07:06:48 -0700 Subject: [PATCH 3/5] docs(ci): flag nightly test scope script as a temporary workaround Record why the script exists and what has to land in TheRock before it, its test, and the configure job that consumes it can be deleted. --- .github/scripts/therock_nightly_test_scope.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/scripts/therock_nightly_test_scope.py b/.github/scripts/therock_nightly_test_scope.py index 769daa1844a9..640ee19f9c09 100644 --- a/.github/scripts/therock_nightly_test_scope.py +++ b/.github/scripts/therock_nightly_test_scope.py @@ -3,6 +3,14 @@ """ TheRock Nightly Test Scope -------------------------- +TEMPORARY: this script is a workaround and is expected to be deleted. + +TheRock does not yet scope a schedule run to the components an external +repository actually owns, so rocm-libraries has to compute that scope itself +and hand it over as `changed_projects`. Once TheRock narrows schedule runs to +the calling repository's own components natively, delete this script, its test, +and the `configure` job in therock-multi-arch-ci-nightly.yml that consumes it. + Computes the set of projects the multi-arch nightly CI workflow should test. A scheduled run has no diff to narrow testing against, so TheRock would From 21f8265497819136cf2daf45e714dfd704713ca2 Mon Sep 17 00:00:00 2001 From: geomin12 Date: Mon, 26 Oct 2026 07:13:50 -0700 Subject: [PATCH 4/5] refactor(ci): condense nightly test scope script and drop setup-python Trim the module docstring to the temporary-workaround rationale and cut the tests to the three cases that carry weight: the category/name mapping, the empty-config guard, and a smoke check against the real repos-config.json. Use the runner's preinstalled python3 instead of actions/setup-python, which drops a step but needs --break-system-packages under PEP 668, as noted in .github/scripts/DEVELOPMENT.md. Move the job to ubuntu-26.04. --- .../tests/therock_nightly_test_scope_test.py | 58 ++++--------- .github/scripts/therock_nightly_test_scope.py | 85 +++++-------------- .../therock-multi-arch-ci-nightly.yml | 16 ++-- 3 files changed, 47 insertions(+), 112 deletions(-) diff --git a/.github/scripts/tests/therock_nightly_test_scope_test.py b/.github/scripts/tests/therock_nightly_test_scope_test.py index cdf49649c93d..ec317857491a 100644 --- a/.github/scripts/tests/therock_nightly_test_scope_test.py +++ b/.github/scripts/tests/therock_nightly_test_scope_test.py @@ -10,19 +10,19 @@ import therock_nightly_test_scope as scope -def make_entry(name: str, category: str) -> dict: - return { - "name": name, - "url": f"ROCm/{name}", - "branch": "develop", - "category": category, - "auto_subtree_pull": False, - "auto_subtree_push": True, - "monorepo_source_of_truth": True, - } - - -def write_config(tmpdir: str, entries: List[dict]) -> Path: +def write_config(tmpdir: str, names: List[tuple]) -> Path: + entries = [ + { + "name": name, + "url": f"ROCm/{name}", + "branch": "develop", + "category": category, + "auto_subtree_pull": False, + "auto_subtree_push": True, + "monorepo_source_of_truth": True, + } + for category, name in names + ] config_path = Path(tmpdir) / "repos-config.json" config_path.write_text(json.dumps({"repositories": entries}), encoding="utf-8") return config_path @@ -34,30 +34,16 @@ def test_returns_sorted_category_name_pairs(self): config_path = write_config( tmpdir, [ - make_entry("rocblas", "projects"), - make_entry("rocsparse", "projects"), - make_entry("hipblas-common", "shared"), + ("projects", "rocsparse"), + ("shared", "hipblas-common"), + ("projects", "rocblas"), ], ) self.assertEqual( scope.get_test_projects(config_path), - [ - "projects/rocblas", - "projects/rocsparse", - "shared/hipblas-common", - ], + ["projects/rocblas", "projects/rocsparse", "shared/hipblas-common"], ) - def test_includes_entries_regardless_of_subtree_sync_flags(self): - # The nightly scope is "everything this repo owns", so entries are not - # filtered by the auto_subtree_pull/push flags that the sync tooling uses. - with tempfile.TemporaryDirectory() as tmpdir: - entry = make_entry("rocprim", "projects") - entry["auto_subtree_push"] = False - entry["monorepo_source_of_truth"] = False - config_path = write_config(tmpdir, [entry]) - self.assertEqual(scope.get_test_projects(config_path), ["projects/rocprim"]) - def test_empty_config_fails_instead_of_testing_everything(self): # An empty changed_projects means "test everything" to TheRock. with tempfile.TemporaryDirectory() as tmpdir: @@ -66,15 +52,7 @@ def test_empty_config_fails_instead_of_testing_everything(self): scope.main(["--config", os.fspath(config_path)]) def test_real_config_is_non_empty(self): - projects = scope.get_test_projects(scope.DEFAULT_CONFIG_PATH) - self.assertTrue(projects) - for project in projects: - self.assertIn("/", project) - - def test_step_summary_lists_each_subtree_on_its_own_line(self): - summary = scope.format_step_summary(["projects/rocblas", "shared/rocroller"]) - self.assertIn("### Nightly test scope", summary) - self.assertIn("projects/rocblas\nshared/rocroller", summary) + self.assertTrue(scope.get_test_projects(scope.DEFAULT_CONFIG_PATH)) if __name__ == "__main__": diff --git a/.github/scripts/therock_nightly_test_scope.py b/.github/scripts/therock_nightly_test_scope.py index 640ee19f9c09..6cd5471307e3 100644 --- a/.github/scripts/therock_nightly_test_scope.py +++ b/.github/scripts/therock_nightly_test_scope.py @@ -1,37 +1,13 @@ #!/usr/bin/env python3 -""" -TheRock Nightly Test Scope --------------------------- -TEMPORARY: this script is a workaround and is expected to be deleted. - -TheRock does not yet scope a schedule run to the components an external -repository actually owns, so rocm-libraries has to compute that scope itself -and hand it over as `changed_projects`. Once TheRock narrows schedule runs to -the calling repository's own components natively, delete this script, its test, -and the `configure` job in therock-multi-arch-ci-nightly.yml that consumes it. - -Computes the set of projects the multi-arch nightly CI workflow should test. - -A scheduled run has no diff to narrow testing against, so TheRock would -otherwise test every component it builds, including ROCm system components -(hip-tests, rocrtst, rocgdb, rocprofiler-*, amdsmi, rccl, ...) that no change -in this repository can affect. This script emits every subtree registered in -.github/repos-config.json in `category/name` form, which the workflow passes to -TheRock as `changed_projects` so testing stays scoped to the code this -repository owns (plus the consumers TheRock's dependency graph pulls in). - -Arguments: - --config : OPTIONAL, path to the repos-config.json file. - -Outputs: - Writes 'test_projects' to the GitHub Actions $GITHUB_OUTPUT file as a - comma-separated list of subtrees in `category/name` format, and appends a - human-readable scope listing to $GITHUB_STEP_SUMMARY. Both are printed to - stdout when run outside of GitHub Actions. - -Example Usage: - python therock_nightly_test_scope.py +"""Emits the subtrees the multi-arch nightly CI should test, as `category/name`. + +TEMPORARY: a scheduled run has no diff to narrow testing against, so TheRock +tests every component it builds, including ROCm system components (hip-tests, +rocrtst, rocgdb, amdsmi, ...) that no change here can affect. Passing every +subtree in repos-config.json as `changed_projects` scopes it back to the code +this repo owns. Delete this script, its test, and the `configure` job in +therock-multi-arch-ci-nightly.yml once TheRock scopes schedule runs natively. """ import argparse @@ -43,53 +19,38 @@ from config_loader import load_repo_config from pr_detect_changed_subtrees import get_valid_prefixes -logger = logging.getLogger(__name__) - -SCRIPT_DIR = Path(__file__).resolve().parent -DEFAULT_CONFIG_PATH = SCRIPT_DIR.parent / "repos-config.json" - - -def parse_arguments(argv: Optional[List[str]] = None) -> argparse.Namespace: - """Parse command-line arguments.""" - parser = argparse.ArgumentParser( - description="Compute the nightly multi-arch CI test scope." - ) - parser.add_argument( - "--config", - type=Path, - default=DEFAULT_CONFIG_PATH, - help="Path to the repos-config.json file", - ) - return parser.parse_args(argv) +DEFAULT_CONFIG_PATH = Path(__file__).resolve().parent.parent / "repos-config.json" def get_test_projects(config_path: Path) -> List[str]: """Return every subtree in repos-config.json as a sorted `category/name` list.""" - config = load_repo_config(str(config_path)) - return sorted(get_valid_prefixes(config)) + return sorted(get_valid_prefixes(load_repo_config(str(config_path)))) def format_step_summary(test_projects: List[str]) -> str: """Render the test scope as a markdown step summary.""" - subtree_list = "\n".join(test_projects) + subtrees = "\n".join(test_projects) return ( - "### Nightly test scope\n" - "\n" - "Testing rocm-libraries subtrees and their direct consumers only:\n" - "\n" - f"```\n{subtree_list}\n```\n" + "### Nightly test scope\n\n" + "Testing rocm-libraries subtrees and their direct consumers only:\n\n" + f"```\n{subtrees}\n```\n" ) def main(argv: Optional[List[str]] = None) -> None: - """Emit the nightly test scope for the multi-arch CI workflow.""" logging.basicConfig(level=logging.INFO) - args = parse_arguments(argv) + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--config", + type=Path, + default=DEFAULT_CONFIG_PATH, + help="Path to the repos-config.json file", + ) + args = parser.parse_args(argv) test_projects = get_test_projects(args.config) if not test_projects: - # TheRock reads an empty `changed_projects` as "test everything", which - # is the opposite of this job's purpose, so fail instead of emitting it. + # TheRock reads an empty `changed_projects` as "test everything". raise SystemExit(f"No subtrees found in {args.config}") set_github_output({"test_projects": ",".join(test_projects)}) diff --git a/.github/workflows/therock-multi-arch-ci-nightly.yml b/.github/workflows/therock-multi-arch-ci-nightly.yml index 6f316aeabbab..2326bf1b8700 100644 --- a/.github/workflows/therock-multi-arch-ci-nightly.yml +++ b/.github/workflows/therock-multi-arch-ci-nightly.yml @@ -41,7 +41,7 @@ concurrency: jobs: configure: name: Configure Test Scope - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 outputs: test_projects: ${{ steps.scope.outputs.test_projects }} steps: @@ -51,19 +51,15 @@ jobs: sparse-checkout: .github sparse-checkout-cone-mode: true - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: "3.12" - + # Uses the runner's preinstalled python3 instead of actions/setup-python. + # --break-system-packages is required because the image manages its Python + # through apt and PEP 668 otherwise rejects installing into it. - name: Install python dependencies - run: | - python -m pip install --upgrade pip - pip install pydantic requests + run: python3 -m pip install --break-system-packages pydantic requests - name: Collect rocm-libraries subtrees id: scope - run: python .github/scripts/therock_nightly_test_scope.py + run: python3 .github/scripts/therock_nightly_test_scope.py setup: uses: ROCm/TheRock/.github/workflows/setup_multi_arch.yml@47434387de730d51788b705e5600602dd6064997 # 2026-10-16 From 21ff310d18553f2480d6c745bb5c6e035ba88920 Mon Sep 17 00:00:00 2001 From: geomin12 Date: Mon, 26 Oct 2026 07:16:46 -0700 Subject: [PATCH 5/5] ci: restore setup-python for the nightly test scope job Pinning the interpreter via actions/setup-python installs into a Python the action owns, so pip needs no --break-system-packages escape hatch and the job is unaffected by whatever the runner image ships. --- .github/workflows/therock-multi-arch-ci-nightly.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/therock-multi-arch-ci-nightly.yml b/.github/workflows/therock-multi-arch-ci-nightly.yml index 2326bf1b8700..9d68a6d74e47 100644 --- a/.github/workflows/therock-multi-arch-ci-nightly.yml +++ b/.github/workflows/therock-multi-arch-ci-nightly.yml @@ -51,15 +51,17 @@ jobs: sparse-checkout: .github sparse-checkout-cone-mode: true - # Uses the runner's preinstalled python3 instead of actions/setup-python. - # --break-system-packages is required because the image manages its Python - # through apt and PEP 668 otherwise rejects installing into it. + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.12" + - name: Install python dependencies - run: python3 -m pip install --break-system-packages pydantic requests + run: pip install pydantic requests - name: Collect rocm-libraries subtrees id: scope - run: python3 .github/scripts/therock_nightly_test_scope.py + run: python .github/scripts/therock_nightly_test_scope.py setup: uses: ROCm/TheRock/.github/workflows/setup_multi_arch.yml@47434387de730d51788b705e5600602dd6064997 # 2026-10-16