131 lines
4.5 KiB
Python
131 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from collections.abc import Sequence
|
|
from pathlib import Path
|
|
|
|
from engine.devops_agent.compiler import compile_workflow
|
|
from engine.devops_agent.providers.gitea import GiteaProvider
|
|
from engine.devops_agent.runtime import run_issue_comment_workflow
|
|
from engine.devops_agent.spec import load_workflow_spec
|
|
from engine.devops_agent.validator import validate_workflow_spec
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
parser = argparse.ArgumentParser(
|
|
prog="devops-agent",
|
|
description="CLI for the agentic DevOps runtime.",
|
|
)
|
|
parser.add_argument(
|
|
"--version",
|
|
action="store_true",
|
|
help="Print the runtime version and exit.",
|
|
)
|
|
subparsers = parser.add_subparsers(dest="command")
|
|
|
|
compile_parser = subparsers.add_parser("compile")
|
|
compile_parser.add_argument("spec_path")
|
|
compile_parser.add_argument("--output", required=True)
|
|
|
|
validate_parser = subparsers.add_parser("validate")
|
|
validate_parser.add_argument("spec_path")
|
|
|
|
run_parser = subparsers.add_parser("run")
|
|
run_parser.add_argument("spec_path")
|
|
run_parser.add_argument("--event-payload", required=True)
|
|
run_parser.add_argument("--output-dir", required=True)
|
|
run_parser.add_argument("--base-url", required=True)
|
|
run_parser.add_argument("--token", required=True)
|
|
|
|
acceptance_parser = subparsers.add_parser("acceptance")
|
|
acceptance_parser.add_argument("spec_path")
|
|
acceptance_parser.add_argument("--base-url", required=True)
|
|
acceptance_parser.add_argument("--repo", required=True)
|
|
acceptance_parser.add_argument("--token", required=True)
|
|
acceptance_parser.add_argument("--issue-number", required=True)
|
|
acceptance_parser.add_argument("--output-dir", required=True)
|
|
acceptance_parser.add_argument(
|
|
"--comment-body",
|
|
default="@devops-agent acceptance run",
|
|
)
|
|
return parser
|
|
|
|
|
|
def _load_compile_and_validate(spec_path: str) -> tuple[dict[str, object], list[str]]:
|
|
spec = load_workflow_spec(spec_path)
|
|
errors = validate_workflow_spec(spec)
|
|
return compile_workflow(spec), errors
|
|
|
|
|
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
parser = build_parser()
|
|
args = parser.parse_args(argv)
|
|
if args.version:
|
|
from engine.devops_agent import __version__
|
|
|
|
print(__version__)
|
|
return 0
|
|
if not getattr(args, "command", None):
|
|
parser.print_help()
|
|
return 0
|
|
|
|
if args.command == "compile":
|
|
lock, errors = _load_compile_and_validate(args.spec_path)
|
|
if errors:
|
|
print(json.dumps({"errors": errors}, ensure_ascii=False, indent=2))
|
|
return 1
|
|
output_path = Path(args.output)
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(json.dumps(lock, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
return 0
|
|
|
|
if args.command == "validate":
|
|
_, errors = _load_compile_and_validate(args.spec_path)
|
|
if errors:
|
|
print(json.dumps({"errors": errors}, ensure_ascii=False, indent=2))
|
|
return 1
|
|
print("workflow is valid")
|
|
return 0
|
|
|
|
if args.command == "run":
|
|
lock, errors = _load_compile_and_validate(args.spec_path)
|
|
if errors:
|
|
print(json.dumps({"errors": errors}, ensure_ascii=False, indent=2))
|
|
return 1
|
|
provider = GiteaProvider(base_url=args.base_url, token=args.token)
|
|
payload = json.loads(Path(args.event_payload).read_text(encoding="utf-8"))
|
|
run_issue_comment_workflow(
|
|
lock=lock,
|
|
provider=provider,
|
|
event_payload=payload,
|
|
output_dir=args.output_dir,
|
|
)
|
|
return 0
|
|
|
|
if args.command == "acceptance":
|
|
lock, errors = _load_compile_and_validate(args.spec_path)
|
|
if errors:
|
|
print(json.dumps({"errors": errors}, ensure_ascii=False, indent=2))
|
|
return 1
|
|
provider = GiteaProvider(base_url=args.base_url, token=args.token)
|
|
payload = {
|
|
"repository": {"full_name": args.repo},
|
|
"issue": {"number": int(args.issue_number)},
|
|
"comment": {"body": args.comment_body},
|
|
}
|
|
run_issue_comment_workflow(
|
|
lock=lock,
|
|
provider=provider,
|
|
event_payload=payload,
|
|
output_dir=args.output_dir,
|
|
)
|
|
return 0
|
|
|
|
parser.error(f"unsupported command: {args.command}")
|
|
return 2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|