feat: Add castle build command

Added castle build [project] command following the same pattern as castle test and castle lint. Stack handlers already had build methods — this just wires up the CLI to expose them.

Supports building a single project or all projects, providing feature parity with existing project-level commands.
This commit is contained in:
2026-04-27 20:48:35 -07:00
parent 529ca53242
commit b720a96c6e
2 changed files with 37 additions and 4 deletions

View File

@@ -1,4 +1,4 @@
"""castle test / castle lint - run dev commands across projects.""" """castle build / castle test / castle lint - run dev commands across projects."""
from __future__ import annotations from __future__ import annotations
@@ -98,3 +98,29 @@ def run_lint(args: argparse.Namespace) -> int:
else: else:
print("\nSome lint checks failed.") print("\nSome lint checks failed.")
return 0 if all_passed else 1 return 0 if all_passed else 1
def run_build(args: argparse.Namespace) -> int:
"""Run build for one or all projects."""
config = load_config()
if args.project:
success = _run_action(config, args.project, "build")
return 0 if success else 1
# Run all buildable projects
all_passed = True
for name, comp in config.programs.items():
if not comp.source:
continue
handler = get_handler(comp.stack)
if handler is None:
continue
if not _run_action(config, name, "build"):
all_passed = False
if all_passed:
print("\nAll builds succeeded.")
else:
print("\nSome builds failed.")
return 0 if all_passed else 1

View File

@@ -55,6 +55,10 @@ def build_parser() -> argparse.ArgumentParser:
lint_parser = subparsers.add_parser("lint", help="Run linter") lint_parser = subparsers.add_parser("lint", help="Run linter")
lint_parser.add_argument("project", nargs="?", help="Project to lint (default: all)") lint_parser.add_argument("project", nargs="?", help="Project to lint (default: all)")
# castle build
build_parser = subparsers.add_parser("build", help="Build projects")
build_parser.add_argument("project", nargs="?", help="Project to build (default: all)")
# castle sync # castle sync
subparsers.add_parser("sync", help="Sync submodules and install dependencies") subparsers.add_parser("sync", help="Sync submodules and install dependencies")
@@ -106,9 +110,7 @@ def build_parser() -> argparse.ArgumentParser:
) )
# castle deploy # castle deploy
deploy_parser = subparsers.add_parser( deploy_parser = subparsers.add_parser("deploy", help="Deploy to ~/.castle/ (spec → runtime)")
"deploy", help="Deploy to ~/.castle/ (spec → runtime)"
)
deploy_parser.add_argument("name", nargs="?", help="Service or job to deploy (default: all)") deploy_parser.add_argument("name", nargs="?", help="Service or job to deploy (default: all)")
# castle tool # castle tool
@@ -156,6 +158,11 @@ def main() -> int:
return run_lint(args) return run_lint(args)
elif args.command == "build":
from castle_cli.commands.dev import run_build
return run_build(args)
elif args.command == "sync": elif args.command == "sync":
from castle_cli.commands.sync import run_sync from castle_cli.commands.sync import run_sync