Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
76 changes: 54 additions & 22 deletions .github/actions/generate-build-matrix/generate_matrix.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,85 @@
"""Generates a build matrix for CI based on the trigger event and user input."""
import json
import os
import re


def get_default_combinations(event_name, all_combinations):
"""Gets the default build combinations based on the GitHub event type."""
if event_name in ("push", "pull_request", "pull_request_target"):
return ["gcc/none"]
elif event_name == "issue_comment":
return ["gcc/none", "clang/none"]
elif event_name == "workflow_dispatch":
return all_combinations
else:
# Default to a minimal safe configuration for unknown events
return ["gcc/none"]


def main():
"""Generates and outputs the build matrix based on environment variables."""
all_combinations = [
"gcc/none", "gcc/asan", "gcc/tsan", "gcc/valgrind",
"clang/none", "clang/asan", "clang/tsan", "clang/valgrind"
"gcc/none",
"gcc/asan",
"gcc/tsan",
"gcc/valgrind",
"clang/none",
"clang/asan",
"clang/tsan",
"clang/valgrind",
]
default_excluded = ["clang/none", "clang/valgrind"]

user_input = os.getenv("USER_INPUT", "")
comment_body = os.getenv("COMMENT_BODY", "")
event_name = os.getenv("GITHUB_EVENT_NAME")

input_str = ""
if event_name == "workflow_dispatch":
input_str = user_input
elif event_name == "issue_comment":
default_combinations = get_default_combinations(event_name, all_combinations)

input_str = user_input
if event_name == "issue_comment":
match = re.match(r"^@phlexbot build\s*(.*)", comment_body)
if match:
input_str = match.group(1)
input_str = match.group(1).strip()

tokens = [token for token in re.split(r"[\s,]+", input_str) if token]

if not tokens:
final_combinations = [combo for combo in all_combinations if combo not in default_excluded]
# Case 3: No input. Use the trigger-specific default.
final_combinations = default_combinations
else:
is_additive = any(token == "all" or token.startswith("+") or token.startswith("-") for token in tokens)

if is_additive:
base_set = set(all_combinations if "all" in tokens else [combo for combo in all_combinations if combo not in default_excluded])
# Check for explicit (non-modifier) combinations
explicit_combos = {
t for t in tokens if not (t.startswith("+") or t.startswith("-") or t == "all")
}

for token in tokens:
if token.startswith("+"):
base_set.add(token[1:])
elif token.startswith("-"):
base_set.discard(token[1:])
final_combinations = list(base_set)
if explicit_combos:
# Case 1: Explicit list. This forms the base set, ignoring defaults.
base_set = explicit_combos
else:
final_combinations = tokens
# Case 2: Only modifiers. Determine base set from 'all' or defaults.
if "all" in tokens:
base_set = set(all_combinations)
else:
base_set = set(default_combinations)

# Apply modifiers to the determined base set
for token in tokens:
if token.startswith("+"):
base_set.add(token[1:])
elif token.startswith("-"):
base_set.discard(token[1:])

final_combinations = list(base_set)

matrix = {"include": []}
for combo in sorted(list(set(final_combinations))):
for combo in sorted(set(final_combinations)):
compiler, sanitizer = combo.split("/")
matrix["include"].append({"compiler": compiler, "sanitizer": sanitizer})

json_matrix = json.dumps(matrix)
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
print(f"matrix={json_matrix}", file=f)


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