1919CI_EXTRA_SKIP_LABELS = ["documentation" ]
2020CI_MATRIX_SIZE_LIMIT = 256 # The maximum size of a matrix in GitHub Actions
2121
22+ # Docker images for building toolchains and dependencies
23+ DOCKER_BUILD_IMAGES = [
24+ {"name" : "build" , "platform" : "linux64" },
25+ {"name" : "build.cross" , "platform" : "linux64" },
26+ {"name" : "build.cross-riscv64" , "platform" : "linux64" },
27+ {"name" : "gcc" , "platform" : "linux64" },
28+ ]
29+
2230
2331def meets_conditional_version (version : str , min_version : str ) -> bool :
2432 return Version (version ) >= Version (min_version )
@@ -89,26 +97,51 @@ def should_include_entry(entry: dict[str, str], filters: dict[str, set[str]]) ->
8997 return True
9098
9199
92- def generate_matrix_entries (
100+ def generate_docker_matrix_entries (
101+ runners : dict [str , Any ],
102+ platform_filter : Optional [str ] = None ,
103+ ) -> list [dict [str , str ]]:
104+ """Generate matrix entries for docker image builds."""
105+ if platform_filter and platform_filter != "linux" :
106+ return []
107+
108+ matrix_entries = []
109+ for image in DOCKER_BUILD_IMAGES :
110+ # Find appropriate runner based on platform
111+ platform_arch = "aarch64" if image ["platform" ] == "linux_aarch64" else "x86_64"
112+ runner = find_runner (runners , "linux" , platform_arch )
113+
114+ entry = {
115+ "name" : image ["name" ],
116+ "platform" : image ["platform" ],
117+ "runner" : runner ,
118+ }
119+ matrix_entries .append (entry )
120+
121+ return matrix_entries
122+
123+
124+ def generate_python_build_matrix_entries (
93125 config : dict [str , Any ],
94126 runners : dict [str , Any ],
95127 platform_filter : Optional [str ] = None ,
96128 label_filters : Optional [dict [str , set [str ]]] = None ,
97129) -> list [dict [str , str ]]:
130+ """Generate matrix entries for python builds."""
98131 matrix_entries = []
99132
100133 for platform , platform_config in config .items ():
101134 if platform_filter and platform != platform_filter :
102135 continue
103136
104137 for target_triple , target_config in platform_config .items ():
105- add_matrix_entries_for_config (
138+ add_python_build_entries_for_config (
106139 matrix_entries ,
107140 target_triple ,
108141 target_config ,
109142 platform ,
110143 runners ,
111- label_filters .get ("directives" , set ()),
144+ label_filters .get ("directives" , set ()) if label_filters else set () ,
112145 )
113146
114147 # Apply label filters if present
@@ -144,14 +177,15 @@ def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str:
144177 raise RuntimeError (f"No runner found for platform { platform !r} and arch { arch !r} " )
145178
146179
147- def add_matrix_entries_for_config (
180+ def add_python_build_entries_for_config (
148181 matrix_entries : list [dict [str , str ]],
149182 target_triple : str ,
150183 config : dict [str , Any ],
151184 platform : str ,
152185 runners : dict [str , Any ],
153186 directives : set [str ],
154187) -> None :
188+ """Add python build matrix entries for a specific target configuration."""
155189 python_versions = config ["python_versions" ]
156190 build_options = config ["build_options" ]
157191 arch = config ["arch" ]
@@ -233,6 +267,12 @@ def parse_args() -> argparse.Namespace:
233267 action = "store_true" ,
234268 help = "If only free runners should be used." ,
235269 )
270+ parser .add_argument (
271+ "--matrix-type" ,
272+ choices = ["python-build" , "docker-build" , "all" ],
273+ default = "all" ,
274+ help = "Which matrix types to generate (default: all)" ,
275+ )
236276 return parser .parse_args ()
237277
238278
@@ -254,36 +294,59 @@ def main() -> None:
254294 if runner_config .get ("free" )
255295 }
256296
257- entries = generate_matrix_entries (
258- config ,
259- runners ,
260- args .platform ,
261- labels ,
262- )
263-
264- if args .max_shards :
265- matrix = {}
266- shards = (len (entries ) // CI_MATRIX_SIZE_LIMIT ) + 1
267- if shards > args .max_shards :
268- print (
269- f"error: matrix of size { len (entries )} requires { shards } shards, but the maximum is { args .max_shards } ; consider increasing `--max-shards`" ,
270- file = sys .stderr ,
271- )
272- sys .exit (1 )
273- for shard in range (args .max_shards ):
274- shard_entries = entries [
275- shard * CI_MATRIX_SIZE_LIMIT : (shard + 1 ) * CI_MATRIX_SIZE_LIMIT
276- ]
277- matrix [str (shard )] = {"include" : shard_entries }
278- else :
279- if len (entries ) > CI_MATRIX_SIZE_LIMIT :
280- print (
281- f"warning: matrix of size { len (entries )} exceeds limit of { CI_MATRIX_SIZE_LIMIT } but sharding is not enabled; consider setting `--max-shards`" ,
282- file = sys .stderr ,
297+ result = {}
298+
299+ # Generate python-build matrix if requested
300+ python_entries = []
301+ if args .matrix_type in ["python-build" , "all" ]:
302+ python_entries = generate_python_build_matrix_entries (
303+ config ,
304+ runners ,
305+ args .platform ,
306+ labels ,
307+ )
308+
309+ if args .max_shards :
310+ python_build_matrix = {}
311+ shards = (len (python_entries ) // CI_MATRIX_SIZE_LIMIT ) + 1
312+ if shards > args .max_shards :
313+ print (
314+ f"error: python-build matrix of size { len (python_entries )} requires { shards } shards, but the maximum is { args .max_shards } ; consider increasing `--max-shards`" ,
315+ file = sys .stderr ,
316+ )
317+ sys .exit (1 )
318+ for shard in range (args .max_shards ):
319+ shard_entries = python_entries [
320+ shard * CI_MATRIX_SIZE_LIMIT : (shard + 1 ) * CI_MATRIX_SIZE_LIMIT
321+ ]
322+ python_build_matrix [str (shard )] = {"include" : shard_entries }
323+ result ["python-build" ] = python_build_matrix
324+ else :
325+ if len (python_entries ) > CI_MATRIX_SIZE_LIMIT :
326+ print (
327+ f"warning: python-build matrix of size { len (python_entries )} exceeds limit of { CI_MATRIX_SIZE_LIMIT } but sharding is not enabled; consider setting `--max-shards`" ,
328+ file = sys .stderr ,
329+ )
330+ result ["python-build" ] = {"include" : python_entries }
331+
332+ # Generate docker-build matrix if requested
333+ # Only include docker builds if there are Linux python builds
334+ if args .matrix_type in ["docker-build" , "all" ]:
335+ # Check if we have any Linux python builds
336+ has_linux_builds = any (
337+ entry .get ("platform" ) == "linux" for entry in python_entries
338+ )
339+
340+ # If no platform filter or explicitly requesting docker-build only, include docker builds
341+ # Otherwise, only include if there are Linux python builds
342+ if args .matrix_type == "docker-build" or has_linux_builds :
343+ docker_entries = generate_docker_matrix_entries (
344+ runners ,
345+ args .platform ,
283346 )
284- matrix = {"include" : entries }
347+ result [ "docker-build" ] = {"include" : docker_entries }
285348
286- print (json .dumps (matrix ))
349+ print (json .dumps (result ))
287350
288351
289352if __name__ == "__main__" :
0 commit comments