Skip to content

Commit 9d370e5

Browse files
jameshcorbettCamStan
authored andcommitted
ci: add generate_matrix script for CI
Problem: a script is needed to generate the GitHub CI matrix. Add a script, copying it over from flux-core with modifications.
1 parent c18b403 commit 9d370e5

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

src/test/generate_matrix.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Generate a build matrix for use with github workflows
4+
#
5+
6+
from copy import deepcopy
7+
import json
8+
import os
9+
import re
10+
import pathlib
11+
12+
docker_run_checks = pathlib.Path("src/test/docker/docker-run-checks.sh")
13+
14+
default_args = ""
15+
16+
DOCKER_REPO = "libscr/scr"
17+
18+
19+
def on_master_or_tag(matrix):
20+
return matrix.branch == "master" or matrix.tag
21+
22+
23+
DEFAULT_MULTIARCH_PLATFORMS = {
24+
"linux/arm64": {
25+
"when": lambda _: True,
26+
"suffix": " - arm64",
27+
"timeout_minutes": 90,
28+
"runner": "ubuntu-24.04-arm",
29+
},
30+
"linux/amd64": {"when": lambda _: True, "suffix": " - amd64", "runner": "ubuntu-latest"},
31+
}
32+
33+
34+
class BuildMatrix:
35+
def __init__(self):
36+
self.matrix = []
37+
self.branch = None
38+
self.tag = None
39+
40+
# Set self.branch or self.tag based on GITHUB_REF
41+
if "GITHUB_REF" in os.environ:
42+
self.ref = os.environ["GITHUB_REF"]
43+
match = re.search("^refs/heads/(.*)", self.ref)
44+
if match:
45+
self.branch = match.group(1)
46+
match = re.search("^refs/tags/(.*)", self.ref)
47+
if match:
48+
self.tag = match.group(1)
49+
50+
def create_docker_tag(self, image, env, command, platform):
51+
"""Create docker tag string if this is master branch or a tag"""
52+
if self.branch == "master" or self.tag:
53+
tag = f"{DOCKER_REPO}:{image}"
54+
if self.tag:
55+
tag += f"-{self.tag}"
56+
if platform is not None:
57+
tag += "-" + platform.split("/")[1]
58+
env["DOCKER_TAG"] = tag
59+
command += f" --tag={tag}"
60+
return True, command
61+
62+
return False, command
63+
64+
def add_build(
65+
self,
66+
name=None,
67+
image=None,
68+
args=default_args,
69+
jobs=6,
70+
env=None,
71+
docker_tag=False,
72+
platform=None,
73+
command_args="",
74+
timeout_minutes=60,
75+
runner="ubuntu-latest",
76+
):
77+
"""Add a build to the matrix.include array"""
78+
79+
# Extra environment to add to this command:
80+
# NOTE: ensure we copy the dict rather than modify, re-used dicts can cause
81+
# overwriting
82+
env = dict(env) if env is not None else {}
83+
84+
needs_buildx = False
85+
if platform:
86+
command_args += f"--platform={platform}"
87+
needs_buildx = True
88+
89+
# The command to run:
90+
command = f"{docker_run_checks} -j{jobs} --image={image} {command_args}"
91+
92+
if docker_tag:
93+
# Only export docker_tag if this is main branch or a tag:
94+
docker_tag, command = self.create_docker_tag(image, env, command, platform)
95+
96+
create_release = False
97+
if self.tag and "DISTCHECK" in env:
98+
create_release = True
99+
100+
command += f" -- {args}"
101+
102+
self.matrix.append(
103+
{
104+
"name": name,
105+
"env": env,
106+
"command": command,
107+
"image": image,
108+
"runner": runner,
109+
"tag": self.tag,
110+
"branch": self.branch,
111+
"docker_tag": docker_tag,
112+
"needs_buildx": needs_buildx,
113+
"create_release": create_release,
114+
"timeout_minutes": timeout_minutes,
115+
}
116+
)
117+
118+
def add_multiarch_build(
119+
self,
120+
name: str,
121+
platforms=DEFAULT_MULTIARCH_PLATFORMS,
122+
default_suffix="",
123+
image=None,
124+
docker_tag=True,
125+
**kwargs,
126+
):
127+
for p, args in platforms.items():
128+
if args["when"](self):
129+
suffix = args.get("suffix", default_suffix)
130+
self.add_build(
131+
name + suffix,
132+
platform=p,
133+
docker_tag=docker_tag,
134+
image=image if image is not None else name,
135+
command_args=args.get("command_args", ""),
136+
timeout_minutes=args.get("timeout_minutes", 30),
137+
runner=args["runner"],
138+
**kwargs,
139+
)
140+
141+
def __str__(self):
142+
"""Return compact JSON representation of matrix"""
143+
return json.dumps(
144+
{"include": self.matrix}, skipkeys=True, separators=(",", ":")
145+
)
146+
147+
148+
matrix = BuildMatrix()
149+
150+
151+
for name in ("bookworm", "alpine", "fedora40"):
152+
matrix.add_multiarch_build(name=name)
153+
154+
matrix.add_build(
155+
name="el9 - arm64",
156+
image="el9",
157+
platform="linux/arm64",
158+
runner="ubuntu-24.04-arm",
159+
docker_tag=True
160+
)
161+
162+
163+
print(matrix)

0 commit comments

Comments
 (0)