26
26
CPYTHONS = ["3.9" , "3.10" , "3.11" , "3.12" , "3.13" ]
27
27
PYPYS = ["pypy3.9" , "pypy3.10" ]
28
28
ALL_PYTHONS = CPYTHONS + PYPYS
29
+ MIN_MAX_PYTHON = [CPYTHONS [0 ], CPYTHONS [- 1 ]]
29
30
BATCHTIME_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
+ )
30
40
HOSTS = dict ()
31
41
32
42
@@ -35,11 +45,18 @@ class Host:
35
45
name : str
36
46
run_on : str
37
47
display_name : str
48
+ expansions : dict [str , str ]
38
49
39
50
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 )
43
60
44
61
45
62
##############
@@ -67,6 +84,7 @@ def create_variant(
67
84
expansions ["PYTHON_BINARY" ] = get_python_binary (python , host )
68
85
if version :
69
86
expansions ["VERSION" ] = version
87
+ expansions .update (HOSTS [host ].expansions )
70
88
expansions = expansions or None
71
89
return BuildVariant (
72
90
name = name ,
@@ -80,10 +98,8 @@ def create_variant(
80
98
81
99
def get_python_binary (python : str , host : str ) -> str :
82
100
"""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" :
87
103
base = "C:/python/32"
88
104
else :
89
105
base = "C:/python"
@@ -93,19 +109,29 @@ def get_python_binary(python: str, host: str) -> str:
93
109
if host == "rhel8" :
94
110
return f"/opt/python/{ python } /bin/python3"
95
111
96
- if host == "macos" :
112
+ if host in [ "macos" , "macos-arm64" ] :
97
113
return f"/Library/Frameworks/Python.Framework/Versions/{ python } /bin/python3"
98
114
99
115
raise ValueError (f"no match found for python { python } on { host } " )
100
116
101
117
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 :
103
119
"""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
109
135
110
136
111
137
def zip_cycle (* iterables , empty_default = None ):
@@ -115,6 +141,15 @@ def zip_cycle(*iterables, empty_default=None):
115
141
yield tuple (next (i , empty_default ) for i in cycles )
116
142
117
143
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
+
118
153
##############
119
154
# Variants
120
155
##############
@@ -159,9 +194,63 @@ def create_ocsp_variants() -> list[BuildVariant]:
159
194
return variants
160
195
161
196
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
+
162
252
##################
163
253
# Generate Config
164
254
##################
165
255
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