2626CPYTHONS = ["3.9" , "3.10" , "3.11" , "3.12" , "3.13" ]
2727PYPYS = ["pypy3.9" , "pypy3.10" ]
2828ALL_PYTHONS = CPYTHONS + PYPYS
29+ MIN_MAX_PYTHON = [CPYTHONS [0 ], CPYTHONS [- 1 ]]
2930BATCHTIME_WEEK = 10080
31+ AUTH_SSLS = [("auth" , "ssl" ), ("noauth" , "ssl" ), ("noauth" , "nossl" )]
32+ TOPOLOGIES = ["standalone" , "replica_set" , "sharded_cluster" ]
33+ SYNCS = ["sync" , "async" ]
34+ DISPLAY_LOOKUP = dict (
35+ ssl = dict (ssl = "SSL" , nossl = "NoSSL" ),
36+ auth = dict (auth = "Auth" , noauth = "NoAuth" ),
37+ test_suites = dict (default = "Sync" , default_async = "Async" ),
38+ coverage = dict (coverage = "cov" ),
39+ )
3040HOSTS = dict ()
3141
3242
@@ -35,11 +45,18 @@ class Host:
3545 name : str
3646 run_on : str
3747 display_name : str
48+ expansions : dict [str , str ]
3849
3950
40- HOSTS ["rhel8" ] = Host ("rhel8" , "rhel87-small" , "RHEL8" )
41- HOSTS ["win64" ] = Host ("win64" , "windows-64-vsMulti-small" , "Win64" )
42- HOSTS ["macos" ] = Host ("macos" , "macos-14" , "macOS" )
51+ _macos_expansions = dict ( # CSOT tests are unreliable on slow hosts.
52+ SKIP_CSOT_TESTS = "true"
53+ )
54+
55+ HOSTS ["rhel8" ] = Host ("rhel8" , "rhel87-small" , "RHEL8" , dict ())
56+ HOSTS ["win64" ] = Host ("win64" , "windows-64-vsMulti-small" , "Win64" , _macos_expansions )
57+ HOSTS ["win32" ] = Host ("win32" , "windows-64-vsMulti-small" , "Win32" , _macos_expansions )
58+ HOSTS ["macos" ] = Host ("macos" , "macos-14" , "macOS" , _macos_expansions )
59+ HOSTS ["macos-arm64" ] = Host ("macos-arm64" , "macos-14-arm64" , "macOS Arm64" , _macos_expansions )
4360
4461
4562##############
@@ -67,6 +84,7 @@ def create_variant(
6784 expansions ["PYTHON_BINARY" ] = get_python_binary (python , host )
6885 if version :
6986 expansions ["VERSION" ] = version
87+ expansions .update (HOSTS [host ].expansions )
7088 expansions = expansions or None
7189 return BuildVariant (
7290 name = name ,
@@ -80,10 +98,8 @@ def create_variant(
8098
8199def get_python_binary (python : str , host : str ) -> str :
82100 """Get the appropriate python binary given a python version and host."""
83- if host == "win64" :
84- is_32 = python .startswith ("32-bit" )
85- if is_32 :
86- _ , python = python .split ()
101+ if host in ["win64" , "win32" ]:
102+ if host == "win32" :
87103 base = "C:/python/32"
88104 else :
89105 base = "C:/python"
@@ -93,19 +109,29 @@ def get_python_binary(python: str, host: str) -> str:
93109 if host == "rhel8" :
94110 return f"/opt/python/{ python } /bin/python3"
95111
96- if host == "macos" :
112+ if host in [ "macos" , "macos-arm64" ] :
97113 return f"/Library/Frameworks/Python.Framework/Versions/{ python } /bin/python3"
98114
99115 raise ValueError (f"no match found for python { python } on { host } " )
100116
101117
102- def get_display_name (base : str , host : str , version : str , python : str ) -> str :
118+ def get_display_name (base : str , host : str , ** kwargs ) -> str :
103119 """Get the display name of a variant."""
104- if version not in ["rapid" , "latest" ]:
105- version = f"v{ version } "
106- if not python .startswith ("pypy" ):
107- python = f"py{ python } "
108- return f"{ base } { HOSTS [host ].display_name } { version } { python } "
120+ display_name = f"{ base } { HOSTS [host ].display_name } "
121+ for key , value in kwargs .items ():
122+ name = value
123+ if key == "version" :
124+ if value not in ["rapid" , "latest" ]:
125+ name = f"v{ value } "
126+ elif key == "python" :
127+ if not value .startswith ("pypy" ):
128+ name = f"py{ value } "
129+ elif key .lower () in DISPLAY_LOOKUP :
130+ name = DISPLAY_LOOKUP [key .lower ()][value ]
131+ else :
132+ raise ValueError (f"Missing display handling for { key } " )
133+ display_name = f"{ display_name } { name } "
134+ return display_name
109135
110136
111137def zip_cycle (* iterables , empty_default = None ):
@@ -115,6 +141,15 @@ def zip_cycle(*iterables, empty_default=None):
115141 yield tuple (next (i , empty_default ) for i in cycles )
116142
117143
144+ def generate_yaml (tasks = None , variants = None ):
145+ """Generate the yaml for a given set of tasks and variants."""
146+ project = EvgProject (tasks = tasks , buildvariants = variants )
147+ out = ShrubService .generate_yaml (project )
148+ # Dedent by two spaces to match what we use in config.yml
149+ lines = [line [2 :] for line in out .splitlines ()]
150+ print ("\n " .join (lines )) # noqa: T201
151+
152+
118153##############
119154# Variants
120155##############
@@ -159,9 +194,63 @@ def create_ocsp_variants() -> list[BuildVariant]:
159194 return variants
160195
161196
197+ def create_server_variants () -> list [BuildVariant ]:
198+ variants = []
199+
200+ # Run the full matrix on linux with min and max CPython, and latest pypy.
201+ host = "rhel8"
202+ for python , (auth , ssl ) in product ([* MIN_MAX_PYTHON , PYPYS [- 1 ]], AUTH_SSLS ):
203+ display_name = f"Test { host } "
204+ expansions = dict (AUTH = auth , SSL = ssl , COVERAGE = "coverage" )
205+ display_name = get_display_name ("Test" , host , python = python , ** expansions )
206+ variant = create_variant (
207+ [f".{ t } " for t in TOPOLOGIES ],
208+ display_name ,
209+ python = python ,
210+ host = host ,
211+ tags = ["coverage_tag" ],
212+ expansions = expansions ,
213+ )
214+ variants .append (variant )
215+
216+ # Test the rest of the pythons on linux.
217+ for python , (auth , ssl ), topology in zip_cycle (
218+ CPYTHONS [1 :- 1 ] + PYPYS [:- 1 ], AUTH_SSLS , TOPOLOGIES
219+ ):
220+ display_name = f"Test { host } "
221+ expansions = dict (AUTH = auth , SSL = ssl )
222+ display_name = get_display_name ("Test" , host , python = python , ** expansions )
223+ variant = create_variant (
224+ [f".{ topology } " ],
225+ display_name ,
226+ python = python ,
227+ host = host ,
228+ expansions = expansions ,
229+ )
230+ variants .append (variant )
231+
232+ # Test a subset on each of the other platforms.
233+ for host in ("macos" , "macos-arm64" , "win64" , "win32" ):
234+ for (python , (auth , ssl ), topology ), sync in product (
235+ zip_cycle (MIN_MAX_PYTHON , AUTH_SSLS , TOPOLOGIES ), SYNCS
236+ ):
237+ test_suite = "default" if sync == "sync" else "default_async"
238+ expansions = dict (AUTH = auth , SSL = ssl , TEST_SUITES = test_suite )
239+ display_name = get_display_name ("Test" , host , python = python , ** expansions )
240+ variant = create_variant (
241+ [f".{ topology } " ],
242+ display_name ,
243+ python = python ,
244+ host = host ,
245+ expansions = expansions ,
246+ )
247+ variants .append (variant )
248+
249+ return variants
250+
251+
162252##################
163253# Generate Config
164254##################
165255
166- project = EvgProject (tasks = None , buildvariants = create_ocsp_variants ())
167- print (ShrubService .generate_yaml (project )) # noqa: T201
256+ generate_yaml (variants = create_server_variants ())
0 commit comments