87 lines
3.2 KiB
Python
Executable file
87 lines
3.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""xo-gen-ci - generate a forgejo cmake pipeline from an xo subsystem-list.
|
|
|
|
The repetitive middle of a cmake CI workflow is one identical step per
|
|
subsystem, in build order. Maintaining that by hand drifts: as of 2026-09-07
|
|
.forgejo/workflows/ci-cmake.yaml named 41 subsystems where subsystem-list had
|
|
70, so 28 -- including every python binding module -- were not built by CI at
|
|
all, with nothing to say so.
|
|
|
|
Membership and order come from the same file xo-build reads, so a subsystem
|
|
added there is built by CI without a second edit. subsystem-list is a valid
|
|
topological order (verified against subsystem-edges: 226 edges, 0 violations),
|
|
which is what makes it safe to drive a sequential pipeline.
|
|
|
|
The generated step runs `xo-build --utest`, not a bare `ctest`: a subsystem
|
|
with no tests then reports 'no-tests' rather than exiting 0 and reading as a
|
|
pass, so the template needs no per-subsystem conditionals.
|
|
|
|
TEMPLATE. jinja2, like genfacet (xo-facet/codegen/*.j2), with the same
|
|
Environment settings. NB DELIMITERS ARE NOT THE DEFAULTS:
|
|
|
|
expression [[ sub ]] (jinja default {{ }} collides with
|
|
statement <% for ... %> Actions' own ${{ matrix.cc }} -- rendering
|
|
the workflow head raises
|
|
UndefinedError: 'matrix' is undefined)
|
|
|
|
Use:
|
|
xo-gen-ci <template.j2> <subsystem-list> [--exclude SUB]... [-o OUTPUT]
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from jinja2 import Environment, FileSystemLoader
|
|
|
|
|
|
def subsystems(path, exclude):
|
|
"""subsystem names from `path`, in file order, minus `exclude`"""
|
|
out = []
|
|
with open(path) as f:
|
|
for line in f:
|
|
name = line.strip()
|
|
if name and not name.startswith("#") and name not in exclude:
|
|
out.append(name)
|
|
return out
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
p.add_argument("template", help="jinja2 workflow template (.j2)")
|
|
p.add_argument("subsystem_list")
|
|
p.add_argument("--exclude", action="append", default=[], metavar="SUB",
|
|
help="omit this subsystem (e.g. the xo-cmake bootstrap)")
|
|
p.add_argument("-o", "--output", help="write here rather than to stdout")
|
|
args = p.parse_args()
|
|
|
|
template_path = Path(args.template)
|
|
|
|
env = Environment(loader=FileSystemLoader(template_path.parent),
|
|
variable_start_string="[[",
|
|
variable_end_string="]]",
|
|
block_start_string="<%",
|
|
block_end_string="%>",
|
|
trim_blocks=True,
|
|
lstrip_blocks=True,
|
|
keep_trailing_newline=True)
|
|
|
|
subs = subsystems(args.subsystem_list, set(args.exclude))
|
|
|
|
text = env.get_template(template_path.name).render(
|
|
subsystems=subs,
|
|
template_name=template_path.name,
|
|
subsystem_list=args.subsystem_list)
|
|
|
|
if args.output:
|
|
Path(args.output).write_text(text)
|
|
print(f"xo-gen-ci: wrote {args.output} ({len(subs)} subsystems)",
|
|
file=sys.stderr)
|
|
else:
|
|
sys.stdout.write(text)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|