Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
417 commits
Select commit Hold shift + click to select a range
c8fb112
Update
shoumikhin Aug 15, 2026
ca072ae
Update
shoumikhin Aug 15, 2026
0f3fe8c
Update
shoumikhin Aug 15, 2026
8b07750
Update
shoumikhin Aug 15, 2026
a08fb9f
Update
shoumikhin Aug 15, 2026
4c049da
Update
shoumikhin Aug 15, 2026
a0cc20a
Update
shoumikhin Aug 15, 2026
c0fda39
Update
shoumikhin Aug 15, 2026
faf9c0f
Update
shoumikhin Aug 15, 2026
207926a
Update
shoumikhin Aug 15, 2026
1edbb75
Update
shoumikhin Aug 15, 2026
8a2f27e
Update
shoumikhin Aug 15, 2026
09d8f2d
Update
shoumikhin Aug 15, 2026
90ad462
Update
shoumikhin Aug 16, 2026
deda54e
Update
shoumikhin Aug 16, 2026
69f23e9
Update
shoumikhin Aug 16, 2026
79e264b
Update
shoumikhin Aug 16, 2026
239b534
Update
shoumikhin Aug 16, 2026
dcda51d
Update
shoumikhin Aug 16, 2026
4ad455a
Update
shoumikhin Aug 16, 2026
64a8c6f
Update
shoumikhin Aug 16, 2026
e7e3d16
Update
shoumikhin Aug 16, 2026
6389a12
Update
shoumikhin Aug 16, 2026
2f93e19
Update
shoumikhin Aug 16, 2026
6311d11
Update
shoumikhin Aug 16, 2026
b2e20c0
Update
shoumikhin Aug 16, 2026
4c410cd
Update
shoumikhin Aug 16, 2026
e956483
Update
shoumikhin Aug 16, 2026
9336d31
Update
shoumikhin Aug 16, 2026
95c838f
Update
shoumikhin Aug 16, 2026
ff5e447
Update
shoumikhin Aug 16, 2026
c27bbce
Update
shoumikhin Aug 16, 2026
abc987c
Update
shoumikhin Aug 16, 2026
b242cce
Update
shoumikhin Aug 16, 2026
e38d2dc
Update
shoumikhin Aug 16, 2026
dba35de
Update
shoumikhin Aug 16, 2026
029785c
Update
shoumikhin Aug 16, 2026
7697369
Update
shoumikhin Aug 16, 2026
3f66522
Update
shoumikhin Aug 16, 2026
4553641
Update
shoumikhin Aug 16, 2026
57a0b50
Update
shoumikhin Aug 16, 2026
9ef0082
Update
shoumikhin Aug 16, 2026
c0cfda7
Update
shoumikhin Aug 16, 2026
217f439
Update
shoumikhin Aug 16, 2026
b877122
Update
shoumikhin Aug 16, 2026
12a62ba
Update
shoumikhin Aug 16, 2026
208d4d7
Update
shoumikhin Aug 16, 2026
751b387
Update
shoumikhin Aug 16, 2026
f5e31f8
Update
shoumikhin Aug 16, 2026
71cc17d
Update
shoumikhin Aug 16, 2026
04c3e79
Update
shoumikhin Aug 16, 2026
53402ea
Update
shoumikhin Aug 16, 2026
8aae779
Update
shoumikhin Aug 16, 2026
0e4c9ff
Update
shoumikhin Aug 16, 2026
1d62fbd
Update
shoumikhin Aug 16, 2026
013867d
Update
shoumikhin Aug 16, 2026
0926f33
Update
shoumikhin Aug 16, 2026
8153c90
Update
shoumikhin Aug 16, 2026
cd685bb
Update
shoumikhin Aug 16, 2026
2ca2429
Update
shoumikhin Aug 16, 2026
e9d986d
Update
shoumikhin Aug 16, 2026
667c2a0
Update
shoumikhin Aug 16, 2026
997d129
Update
shoumikhin Aug 16, 2026
57df58b
Update
shoumikhin Aug 16, 2026
1cf432a
Update
shoumikhin Aug 17, 2026
97136c3
Update
shoumikhin Aug 17, 2026
c06e924
Update
shoumikhin Aug 17, 2026
19e2901
Update
shoumikhin Aug 17, 2026
796877f
Update
shoumikhin Aug 17, 2026
0958811
Update
shoumikhin Aug 17, 2026
3b683b2
Update
shoumikhin Aug 17, 2026
6086b9b
Update
shoumikhin Aug 17, 2026
791f5cd
Update
shoumikhin Aug 17, 2026
42bf1a2
Update
shoumikhin Aug 17, 2026
2f483ba
Update
shoumikhin Aug 17, 2026
fafc231
Update
shoumikhin Aug 17, 2026
fad6f63
Update
shoumikhin Aug 17, 2026
e9e7192
Update
shoumikhin Aug 17, 2026
820eea8
Update
shoumikhin Aug 17, 2026
fd874ca
Update
shoumikhin Aug 17, 2026
1ddfe57
Update
shoumikhin Aug 17, 2026
a74be37
Update
shoumikhin Aug 17, 2026
1950b86
Update
shoumikhin Aug 17, 2026
bbf273d
Update
shoumikhin Aug 17, 2026
64683d3
Update
shoumikhin Aug 17, 2026
17d9f0b
Update
shoumikhin Aug 17, 2026
527a6f5
Update
shoumikhin Aug 17, 2026
0aebe4e
Update
shoumikhin Aug 17, 2026
df38602
Update
shoumikhin Aug 17, 2026
7483dd9
Update
shoumikhin Aug 17, 2026
58a6f64
Update
shoumikhin Aug 17, 2026
c169bcc
Update
shoumikhin Aug 17, 2026
b14202e
Update
shoumikhin Aug 17, 2026
e26ead1
Update
shoumikhin Aug 17, 2026
5a6389e
Update
shoumikhin Aug 17, 2026
455cb2c
Update
shoumikhin Aug 17, 2026
6aea4ec
Update
shoumikhin Aug 17, 2026
1c02585
Update
shoumikhin Aug 17, 2026
d240af6
Update
shoumikhin Aug 17, 2026
a54c84f
Update
shoumikhin Aug 17, 2026
70a1c5f
Update
shoumikhin Aug 17, 2026
e9a410f
Update
shoumikhin Aug 17, 2026
e095c57
Update
shoumikhin Aug 17, 2026
d4c76a1
Update
shoumikhin Aug 17, 2026
e90c122
Update
shoumikhin Aug 17, 2026
4a41acb
Update
shoumikhin Aug 17, 2026
0830b54
Update
shoumikhin Aug 17, 2026
84edf54
Update
shoumikhin Aug 17, 2026
f5ae389
Update
shoumikhin Aug 17, 2026
5d760b0
Update
shoumikhin Aug 17, 2026
3b068e6
Update
shoumikhin Aug 17, 2026
8d5164b
Update
shoumikhin Aug 17, 2026
58adddc
Update
shoumikhin Aug 17, 2026
6f67011
Update
shoumikhin Aug 17, 2026
0458d41
Update
shoumikhin Aug 17, 2026
e0d5be0
Update
shoumikhin Aug 17, 2026
55785f7
Update
shoumikhin Aug 17, 2026
6f962f9
Update
shoumikhin Aug 17, 2026
7fde9c6
Update
shoumikhin Aug 17, 2026
4017168
Update
shoumikhin Aug 17, 2026
76f35fd
Update
shoumikhin Aug 17, 2026
a87494b
Update
shoumikhin Aug 17, 2026
c5cc47b
Update
shoumikhin Aug 17, 2026
c8ccf79
Update
shoumikhin Aug 17, 2026
75c520f
Update
shoumikhin Aug 17, 2026
76ed9f8
Update
shoumikhin Aug 17, 2026
b87d66a
Update
shoumikhin Aug 17, 2026
a7a7958
Update
shoumikhin Aug 17, 2026
f945d1c
Update
shoumikhin Aug 17, 2026
d2e7fe8
Update
shoumikhin Aug 17, 2026
de531bf
Update
shoumikhin Aug 17, 2026
9c0e747
Update
shoumikhin Aug 17, 2026
efc3e3b
Update
shoumikhin Aug 17, 2026
cedf860
Update
shoumikhin Aug 17, 2026
56ca0d2
Update
shoumikhin Aug 17, 2026
dbf799a
Update
shoumikhin Aug 17, 2026
b7e7e9c
Update
shoumikhin Aug 17, 2026
cad10ee
Update
shoumikhin Aug 17, 2026
0e87b5d
Update
shoumikhin Aug 17, 2026
55a00ff
Update
shoumikhin Aug 18, 2026
ce4b0ef
Update
shoumikhin Aug 18, 2026
e04d0e0
Update
shoumikhin Aug 18, 2026
5440c27
Update
shoumikhin Aug 18, 2026
5e1d927
Update
shoumikhin Aug 18, 2026
1573e0b
Update
shoumikhin Aug 18, 2026
aa1bb51
Update
shoumikhin Aug 18, 2026
48c5e9b
Update
shoumikhin Aug 18, 2026
b19544b
Update
shoumikhin Aug 18, 2026
548bddf
Update
shoumikhin Aug 18, 2026
038e36c
Update
shoumikhin Aug 18, 2026
bb43581
Update
shoumikhin Aug 18, 2026
ac6a665
Update
shoumikhin Aug 18, 2026
c71ced0
Update
shoumikhin Aug 18, 2026
6a2ce9f
Update
shoumikhin Aug 18, 2026
65e3621
Update
shoumikhin Aug 18, 2026
cc4d013
Update
shoumikhin Aug 18, 2026
2af0c80
Update
shoumikhin Aug 18, 2026
dc5cb10
Update
shoumikhin Aug 18, 2026
be9caec
Update
shoumikhin Aug 18, 2026
d6ec909
Update
shoumikhin Aug 18, 2026
d2ddb04
Update
shoumikhin Aug 18, 2026
39e3a30
Update
shoumikhin Aug 18, 2026
a75e7f2
Update
shoumikhin Aug 18, 2026
bdfee64
Update
shoumikhin Aug 18, 2026
1b58553
Update
shoumikhin Aug 19, 2026
1f90586
Update
shoumikhin Aug 19, 2026
50c329a
Update
shoumikhin Aug 19, 2026
e62a93d
Update
shoumikhin Aug 19, 2026
17b84d9
Update
shoumikhin Aug 19, 2026
34a39b0
Update
shoumikhin Aug 19, 2026
2b886e2
Update
shoumikhin Aug 19, 2026
2dd1a16
Update
shoumikhin Aug 19, 2026
2e8f1b5
Update
shoumikhin Aug 19, 2026
6c5de5d
Update
shoumikhin Aug 19, 2026
636d433
Update
shoumikhin Aug 19, 2026
12e101b
Update
shoumikhin Aug 19, 2026
537d0e7
Update
shoumikhin Aug 19, 2026
97cc7c9
Update
shoumikhin Aug 19, 2026
1a07c5d
Update
shoumikhin Aug 19, 2026
cacb83f
Update
shoumikhin Aug 19, 2026
c439310
Update
shoumikhin Aug 19, 2026
b7b109a
Update
shoumikhin Aug 19, 2026
4af3062
Update
shoumikhin Aug 19, 2026
601ea70
Update
shoumikhin Aug 19, 2026
762afb5
Update
shoumikhin Aug 19, 2026
8d43cd1
Update
shoumikhin Aug 19, 2026
37058f6
Update
shoumikhin Aug 19, 2026
fdc827d
Update
shoumikhin Aug 19, 2026
fb42f27
Update
shoumikhin Aug 19, 2026
688310d
Update
shoumikhin Aug 19, 2026
33abafa
Update
shoumikhin Aug 19, 2026
c686c3f
Update
shoumikhin Aug 19, 2026
b30dad3
Update
shoumikhin Aug 19, 2026
5ca10de
Update
shoumikhin Aug 19, 2026
6b4ab76
Update
shoumikhin Aug 19, 2026
eb1aa7a
Update
shoumikhin Aug 19, 2026
d663a16
Update
shoumikhin Aug 19, 2026
946557b
Update
shoumikhin Aug 19, 2026
9502898
Update
shoumikhin Aug 19, 2026
154a20a
Update
shoumikhin Aug 19, 2026
ccaa0be
Update
shoumikhin Aug 19, 2026
7439020
Update
shoumikhin Aug 19, 2026
bbb264d
Update
shoumikhin Aug 19, 2026
04696ce
Update
shoumikhin Aug 19, 2026
72778d3
Update
shoumikhin Aug 19, 2026
c8b2dff
Update
shoumikhin Aug 19, 2026
1d06139
Update
shoumikhin Aug 19, 2026
2e09096
Update
shoumikhin Aug 19, 2026
ae991df
Update
shoumikhin Aug 19, 2026
f6ec683
Update
shoumikhin Aug 19, 2026
4978509
Update
shoumikhin Aug 19, 2026
d8b5901
Update
shoumikhin Aug 19, 2026
5b6fe07
Update
shoumikhin Aug 19, 2026
053b207
Update
shoumikhin Aug 19, 2026
6df56df
Update
shoumikhin Aug 19, 2026
5437d2d
Update
shoumikhin Aug 19, 2026
8fedf97
Update
shoumikhin Aug 19, 2026
0e2f70e
Update
shoumikhin Aug 19, 2026
d64c0d0
Update
shoumikhin Aug 19, 2026
c213052
Update
shoumikhin Aug 19, 2026
d3e208b
Update
shoumikhin Aug 19, 2026
61824d2
Update
shoumikhin Aug 20, 2026
4b4e231
Update
shoumikhin Aug 20, 2026
78efab9
Update
shoumikhin Aug 20, 2026
30bc80c
Update
shoumikhin Aug 20, 2026
93cb6df
Update
shoumikhin Aug 20, 2026
f736168
Update
shoumikhin Aug 20, 2026
ed9732b
Update
shoumikhin Aug 20, 2026
e847aaf
Update
shoumikhin Aug 20, 2026
3a2908b
Update
shoumikhin Aug 20, 2026
6f8d6ce
Update
shoumikhin Aug 20, 2026
31b5943
Update
shoumikhin Aug 20, 2026
9756431
Update
shoumikhin Aug 20, 2026
c5f5746
Update
shoumikhin Aug 20, 2026
b886d96
Update
shoumikhin Aug 20, 2026
0f78a5b
Update
shoumikhin Aug 20, 2026
fd63222
Update
shoumikhin Aug 20, 2026
b6c3c8a
Update
shoumikhin Aug 20, 2026
1aa2410
Update
shoumikhin Aug 20, 2026
2620efe
Update
shoumikhin Aug 20, 2026
9f02f69
Update
shoumikhin Aug 20, 2026
36db138
Update
shoumikhin Aug 20, 2026
7e72e28
Update
shoumikhin Aug 20, 2026
cea2a23
Update
shoumikhin Aug 20, 2026
1149045
Update
shoumikhin Aug 20, 2026
90b0004
Update
shoumikhin Aug 20, 2026
293ce61
Update
shoumikhin Aug 20, 2026
9e062cf
Update
shoumikhin Aug 20, 2026
e9242c1
Update
shoumikhin Aug 20, 2026
b457905
Update
shoumikhin Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 301 additions & 0 deletions .ci/scripts/tests/test_filter_cuda_matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# Tests for the CUDA release matrix filter.
#
# The filter decides which wheel rows a release builds and exits non-zero when its inputs disagree
# with what the project can publish. Two of its comments record past bugs it now guards against, and
# a regression in any of them would surface only as a broken release, so each gate is pinned here.

import importlib.util
import json
import unittest
from pathlib import Path
from unittest import mock

import yaml

ROOT = Path(__file__).resolve().parents[3]


def _load_filter():
"""Load the script by path, since .github/scripts is not an importable package."""
path = ROOT / ".github" / "scripts" / "filter_cuda_matrix.py"
spec = importlib.util.spec_from_file_location("filter_cuda_matrix", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


FILTER = _load_filter()


def _full_matrix():
"""Every supported python and CUDA pair.

The filter refuses anything less: one gate rejects a matrix that would leave a CUDA train
unpublished, another rejects a missing python and CUDA combination. Built from the module's own
lists so it cannot go stale when either grows.

That also means it shrinks when either list shrinks, and every gate keeps passing. Measured:
deleting cu132 and 3.13 from the filter left all sixteen cases here green. TestPublishedSets
below is what notices that, so this fixture does not have to.
"""
return {
"include": [
{"python_version": python, "desired_cuda": cuda}
for python in FILTER.SUPPORTED_PYTHON_VERSIONS
for cuda in FILTER.SUPPORTED_CUDA_VERSIONS
]
}


def _run(matrix, limit="false", extra=None):
argv = ["--matrix", json.dumps(matrix), "--limit-pr-builds", limit] + (extra or [])
with mock.patch("builtins.print") as printed:
FILTER.main(argv)
return printed


def _emitted(printed):
return json.loads(printed.call_args_list[-1].args[0])


class TestRanking(unittest.TestCase):
def test_prefers_the_requested_cuda_over_a_newer_one(self):
# The ranking deliberately scores a version above the requested one NEGATIVELY, so a newer
# one never outranks the one a machine here can actually run. A fixture offering only
# versions at or below the request never executes that branch.
newer = [
c for c in FILTER.SUPPORTED_CUDA_VERSIONS if c > FILTER.PR_CUDA_VERSION
]
items = [
{
"python_version": FILTER.PR_PYTHON_VERSION,
"desired_cuda": FILTER.PR_CUDA_VERSION,
}
] + [
{"python_version": FILTER.PR_PYTHON_VERSION, "desired_cuda": c}
for c in newer
]
picked = FILTER.only_pull_request_row(items)
self.assertEqual(picked[0]["desired_cuda"], FILTER.PR_CUDA_VERSION)

def test_cuda_closeness_outranks_the_python_match(self):
# Closeness is the FIRST element of the sort key, deliberately. Ranking python first is a
# recorded past bug: it picked a wheel for a CUDA version nothing on hand can execute.
other_python = next(
p for p in FILTER.SUPPORTED_PYTHON_VERSIONS if p != FILTER.PR_PYTHON_VERSION
)
other_cuda = next(
c for c in FILTER.SUPPORTED_CUDA_VERSIONS if c != FILTER.PR_CUDA_VERSION
)
items = [
{"python_version": other_python, "desired_cuda": FILTER.PR_CUDA_VERSION},
{"python_version": FILTER.PR_PYTHON_VERSION, "desired_cuda": other_cuda},
]
picked = FILTER.only_pull_request_row(items)
self.assertEqual(picked[0]["desired_cuda"], FILTER.PR_CUDA_VERSION)

def test_picks_the_requested_row(self):
items = [
{"python_version": p, "desired_cuda": c}
for p in FILTER.SUPPORTED_PYTHON_VERSIONS
for c in FILTER.SUPPORTED_CUDA_VERSIONS
]
picked = FILTER.only_pull_request_row(items)
self.assertEqual(len(picked), 1)
self.assertEqual(picked[0]["python_version"], FILTER.PR_PYTHON_VERSION)
self.assertEqual(picked[0]["desired_cuda"], FILTER.PR_CUDA_VERSION)

def test_empty_input_gives_empty_output(self):
# Raising here would break every pull request while releases kept working, which is one of
# the two failures this function records having had.
self.assertEqual(FILTER.only_pull_request_row([]), [])

def test_requested_cuda_absent_from_the_offer(self):
# The other recorded past bug: the requested version falls off the supported list, and the
# function still has to return one row rather than raise or return nothing.
items = [
{"python_version": FILTER.PR_PYTHON_VERSION, "desired_cuda": c}
for c in FILTER.SUPPORTED_CUDA_VERSIONS
if c != FILTER.PR_CUDA_VERSION
]
picked = FILTER.only_pull_request_row(items)
self.assertEqual(len(picked), 1)


class TestVersionRank(unittest.TestCase):
def test_newer_cuda_ranks_higher(self):
ordered = sorted(FILTER.SUPPORTED_CUDA_VERSIONS)
self.assertGreater(
FILTER._version_rank(ordered[-1]), FILTER._version_rank(ordered[0])
)

def test_unknown_value_ranks_below_every_real_one(self):
# A value ranking above the real ones would silently take over the pull request row.
self.assertEqual(FILTER._version_rank("not-a-version"), -1)


class TestKeep(unittest.TestCase):
def test_unsupported_python_is_dropped(self):
# The recorded bug: passing a 3.9 row returned success and emitted it.
matrix = _full_matrix()
matrix["include"].append(
{"python_version": "3.9", "desired_cuda": FILTER.SUPPORTED_CUDA_VERSIONS[0]}
)
emitted = _emitted(_run(matrix))
self.assertNotIn("3.9", [row["python_version"] for row in emitted["include"]])

def test_unsupported_cuda_is_dropped(self):
matrix = _full_matrix()
matrix["include"].append(
{
"python_version": FILTER.SUPPORTED_PYTHON_VERSIONS[0],
"desired_cuda": "cu999",
}
)
emitted = _emitted(_run(matrix))
self.assertNotIn("cu999", [row["desired_cuda"] for row in emitted["include"]])


class TestGates(unittest.TestCase):
def _exit_message(self, matrix, limit="false", extra=None):
"""The stderr text of the gate that fired, so a case can name which one it hit."""
import contextlib
import io

argv = ["--matrix", json.dumps(matrix), "--limit-pr-builds", limit] + (
extra or []
)
captured = io.StringIO()
with contextlib.redirect_stderr(captured):
with self.assertRaises(SystemExit) as raised:
FILTER.main(argv)
self.assertNotEqual(raised.exception.code, 0)
return captured.getvalue()

def _expect_exit(self, matrix, limit="false", extra=None):
with mock.patch("builtins.print"):
with self.assertRaises(SystemExit) as raised:
_run(matrix, limit=limit, extra=extra)
self.assertNotEqual(raised.exception.code, 0)

def test_unparseable_matrix_exits_nonzero(self):
argv = ["--matrix", "{not json", "--limit-pr-builds", "false"]
with mock.patch("builtins.print"):
with self.assertRaises(SystemExit) as raised:
FILTER.main(argv)
self.assertNotEqual(raised.exception.code, 0)

def test_absent_train_exits_nonzero(self):
# A supported train the generator offers nothing for would publish no wheel at all.
#
# Patching the supported list rather than deleting rows, because deleting every row for one
# train also creates missing combinations, so both gates fire and the test cannot tell which
# one it exercised. Adding an extra supported train makes it absent while every offered
# combination stays complete.
# These two gates cannot be separated by input: any matrix leaving a train absent also
# leaves every combination for that train missing, so the later gate always catches what the
# earlier one would. Measured. So each gate gets its own case, and the case asserts on the
# message rather than only on a nonzero exit, which is the only way to tell them apart.
offered = FILTER.SUPPORTED_CUDA_VERSIONS[:-1]
matrix = {
"include": [
{"python_version": python, "desired_cuda": cuda}
for python in FILTER.SUPPORTED_PYTHON_VERSIONS
for cuda in offered
]
}
message = self._exit_message(matrix)
self.assertIn("publish no wheel for that CUDA version", message)

def test_missing_combination_exits_nonzero(self):
matrix = _full_matrix()
del matrix["include"][0]
message = self._exit_message(matrix)
self.assertIn("combination(s) produced no row", message)

def test_jetpack_not_published_exits_nonzero(self):
# Refused explicitly rather than allowed to fall through to an empty result, so the reason a
# reader sees is the real one. Nothing passes this flag today, which is why it had no cover.
message = self._exit_message(_full_matrix(), extra=["--jetpack", "true"])
self.assertIn("JetPack rows are not published yet", message)

def test_empty_result_exits_nonzero(self):
self._expect_exit({"include": []})

def test_well_formed_matrix_passes_through(self):
matrix = _full_matrix()
emitted = _emitted(_run(matrix))
self.assertEqual(emitted["include"], matrix["include"])

def test_pull_request_limit_reduces_to_one_row(self):
emitted = _emitted(_run(_full_matrix(), limit="true"))
self.assertEqual(len(emitted["include"]), 1)


class TestPublishedSets(unittest.TestCase):
"""What a release publishes, pinned against something other than the filter's own lists.

Every case above builds its fixture from those lists, so shrinking one shrinks the fixture with
it and every gate still passes. The published set is a promise to users rather than an
implementation detail, so dropping a row has to be a deliberate edit here too.
"""

def test_published_cuda_versions(self):
self.assertEqual(FILTER.SUPPORTED_CUDA_VERSIONS, ["cu126", "cu130", "cu132"])

def test_published_python_versions(self):
self.assertEqual(
FILTER.SUPPORTED_PYTHON_VERSIONS, ["3.10", "3.11", "3.12", "3.13"]
)

def test_the_workflows_offer_exactly_the_published_pythons(self):
# The filter can only keep a row the generator produced, and these two workflows are what
# tell the generator which pythons to produce. A python published here but not offered
# there does trip the release gate, but only on a release run, well after the change
# landed. A python offered there and not published here is dropped without a word.
for name in (
"build-wheels-cuda-linux.yml",
"build-wheels-cuda-aarch64-linux.yml",
):
with self.subTest(workflow=name):
workflow = yaml.safe_load(
(ROOT / ".github" / "workflows" / name).read_text()
)
offered = json.loads(
workflow["jobs"]["generate-matrix"]["with"]["python-versions"]
)
self.assertEqual(offered, FILTER.SUPPORTED_PYTHON_VERSIONS)

def test_the_pull_request_row_names_a_python_a_pull_request_is_offered(self):
# A limited pull request is offered one python only, because the shared generator replaces
# the list the workflow passes with its first entry. Naming any other one here matched no
# offered row, so the row a pull request built was not the row this file names.
offered = {
"include": [
{
"python_version": FILTER.SUPPORTED_PYTHON_VERSIONS[0],
"desired_cuda": cuda,
}
for cuda in FILTER.SUPPORTED_CUDA_VERSIONS
]
}
emitted = _emitted(_run(offered, limit="true"))
self.assertEqual(
emitted["include"],
[
{
"python_version": FILTER.PR_PYTHON_VERSION,
"desired_cuda": FILTER.PR_CUDA_VERSION,
}
],
)


if __name__ == "__main__":
unittest.main()
Loading
Loading