86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
"""
|
|
Build endpoint — kicks off a pipeline run for a BuildSpec.
|
|
|
|
NOTE: This is the thin API wrapper. The real scheduling + execution
|
|
lives in backend/pipeline/engine.py and backend/scheduler/.
|
|
"""
|
|
|
|
from backend.api.build_spec import BuildSpec
|
|
from backend.pipeline.engine import PipelineEngine
|
|
from backend.graph.build_graph import BuildGraph
|
|
from backend.api.api import bus, registry # singletons
|
|
|
|
|
|
async def build_endpoint(spec, nodes, cluster=None, intelligence=None):
|
|
"""
|
|
Build a project.
|
|
|
|
`spec` may be:
|
|
- a BuildSpec instance
|
|
- a dict (will be coerced via BuildSpec.from_request)
|
|
- a raw dict matching the legacy BuildGraph constructor (with `target`/`output_mode`)
|
|
|
|
`nodes`, `cluster`, `intelligence` are accepted for backward-compat but
|
|
only `nodes` is actually used (the engine has its own node registry).
|
|
"""
|
|
# Coerce spec into something BuildGraph can consume.
|
|
# BuildGraph reads spec.arch, spec.target, spec.toolchain, spec.output_mode.
|
|
# BuildSpec (the dataclass) doesn't have target/output_mode, so we adapt.
|
|
if isinstance(spec, BuildSpec):
|
|
bs = spec
|
|
elif isinstance(spec, dict):
|
|
# If caller passed a raw dict with `target`/`output_mode`, wrap it
|
|
# in a tiny shim object so BuildGraph's attribute access works.
|
|
if "target" in spec or "output_mode" in spec:
|
|
bs = _ShimSpec(spec)
|
|
else:
|
|
try:
|
|
bs = BuildSpec.from_request(spec)
|
|
except KeyError:
|
|
bs = _ShimSpec(spec)
|
|
else:
|
|
# Already a shim or has the attributes BuildGraph expects
|
|
bs = spec
|
|
|
|
# Generate the DAG
|
|
try:
|
|
graph = BuildGraph(bs).generate()
|
|
except Exception as e:
|
|
# In production we'd log this; for now bubble up a structured error
|
|
return {"status": "error", "error": f"build_graph_failed: {e}"}
|
|
|
|
# Run the pipeline
|
|
engine = PipelineEngine(nodes, registry, bus)
|
|
try:
|
|
results = await engine.run(bs)
|
|
except Exception as e:
|
|
return {"status": "error", "error": f"pipeline_failed: {e}"}
|
|
|
|
return {
|
|
"status": "complete",
|
|
"actions": [{"name": n, "state": s} for n, s in results],
|
|
"graph_size": len(graph),
|
|
}
|
|
|
|
|
|
class _ShimSpec:
|
|
"""Adapter that exposes attribute access over a dict, so BuildGraph
|
|
can read spec.target / spec.output_mode / spec.arch / spec.toolchain
|
|
regardless of which shape the caller supplied."""
|
|
|
|
def __init__(self, d: dict):
|
|
self._d = d
|
|
|
|
def __getattr__(self, name):
|
|
if name in self._d:
|
|
return self._d[name]
|
|
# Sensible defaults for fields BuildGraph reads
|
|
defaults = {
|
|
"arch": "x86_64",
|
|
"target": "linux-gnu",
|
|
"toolchain": "gcc",
|
|
"output_mode": "tar",
|
|
"project": "unknown",
|
|
}
|
|
return defaults.get(name)
|