Jon Chery
c3819dde12
feat(P06): task groups — multi-process services, multiple systemd units per alloc
...
P06 — Task groups (PRD §9.1: multiple systemd units per alloc).
Parser (internal/jobspec/markdown.go):
- TaskGroupTask type (Name, Runtime, Env, Command). Tasks []TaskGroupTask on
WorkloadSpec. Parses tasks: frontmatter block (array of task objects).
Tasks without their own runtime inherit the top-level Runtime as default.
Backward compat: no tasks -> single-process (existing runtime block).
Systemd emitter (internal/emitter/systemd.go):
- Task group renders one systemd unit per task (orca-v1-alloc-<id>-<task>
.service) plus a grouping target unit (orca-v1-alloc-<id>.target). Each
per-task unit carries PartOf=<target> and WantedBy=multi-user.target.
Single-process case unchanged (backward compat).
Schema (internal/spec/schema/schema.go):
- TaskGroup validation: unique task names, resolvable command (own or
inherited). JobValidator/ServiceValidator/DaemonSetValidator all accept
task groups.
Tests: 9 task-group tests in schema_test.go, lifecycle + target-unit tests
in systemd_test.go, parser tests in markdown_test.go. 22 packages pass.
Fix: 3 Service task-group test fixtures missing Count:1 (ServiceValidator
requires count>=1; a task-group Service still has >=1 replica).
---ci---
project: orca
phase: P06
milestone: v0.9
status: execute
---/ci---
2026-08-05 18:20:05 +00:00
Jon Chery
ae6eb5a27b
feat(P03,P04,P08): update stanza + lifecycle hooks + socket plumbing
...
P03 — Update stanza (rolling/canary/blue-green):
- internal/spec/schema/update.go: UpdateValidator (strategy enum, max_parallel
1..count, duration parsing, canary int/% forms, auto_promote). 98.2% cov.
- internal/emitter/update.go: RenderUpdatePlan computes the step sequence
(rolling batches, canary 1+promote+rest, blue-green all+cutover). Pure plan,
no execution (v0.10-P10 is transactional). 73.7-100% cov.
P04 — Lifecycle hooks (systemd ExecStop semantics):
- Extended internal/emitter/systemd.go: post_start -> ExecStartPost=,
pre_stop -> ExecStop=. Order: ExecStart -> ExecStartPost -> ExecStop ->
socket lines. 8 lifecycle tests. 100% cov on systemd.go.
P08 — Socket plumbing (R-007):
- internal/emitter/socket.go: SocketEmitter renders RuntimeDirectory=orca/
alloc-<id> per port (mode 0750, orca:orca). ExecStartPre TCP-bind marker
when service.bind=127.0.0.1. SocketPath(allocID,portName) helper. 100% cov.
- Alloc-id is spec.Name placeholder; real id assigned by scheduler at submit.
22 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P03/P04/P08
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:55:11 +00:00
Jon Chery
436641782c
feat(P02): Service block + Traefik emitter + atomic reload (REQ-077, gate C-10)
...
P02 — Traefik dynamic config generation + atomic reload protocol.
Parser (internal/jobspec/markdown.go):
- Extended WorkloadSpec with Health, Constraints, Affinity, Lifecycle
fields. Parsed restart/update/service/health/lifecycle/affinity/
constraints blocks. HealthBlock, AffinityRule, LifecycleBlock types.
Schema (internal/spec/schema/schema.go):
- ServiceValidator: restart.mode enum (service/on-failure/never),
update.strategy enum (rolling/canary/blue-green), health required,
service.bind IP validation (R-007 loopback opt-in). 98.5% coverage.
Traefik emitter (internal/emitter/traefik.go, REQ-077):
- TraefikEmitter renders /etc/traefik/dynamic/orca-<name>.yaml with
http.routers, http.services (servers = R-007 socket paths), TLS
(certResolver=orca, trust domain), healthCheck. RenderDrain sets
weight:0 per backend. RegisterTraefik wires process/podman/wasm.
Atomic reload (internal/emitter/traefik_atomic.go, gate C-10):
- WriteTraefikDynamic: write to path.tmp via WriteFileIdempotent, then
mv -f path.tmp path (atomic POSIX rename, Traefik fsnotify observes
IN_MOVED_TO). Traefik holds-last-good on malformed config. C-10 PASS.
22 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
Coverage: emitter 96.5%, jobspec 88.8%, schema 98.5%, sshpush 93.0%.
---ci---
project: orca
phase: P02
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:48:04 +00:00
Jon Chery
60b0357eb6
feat(P0c): Job/Service/DaemonSet schemas + emitter interface + systemd stub (REQ-074)
...
P0c — Kind-specific schema validators + Layer 4 emitter interface.
Schemas (internal/spec/schema/schema.go, REQ-074):
- Validator interface with JobValidator, ServiceValidator, DaemonSetValidator.
JobValidator: count=1, no service block, optional schedule/timeout.
ServiceValidator: ports required, count>=1, restart+update+runtime required.
DaemonSetValidator: schedule mode required, no ports (D-175), no count.
ValidatorFor(kind) dispatcher. 96.2% coverage.
Emitter interface (internal/emitter/emitter.go, REQ-074, I-B-002):
- File{Path,Content,Mode}, Emitter interface { Render(spec,node) []File },
Registry keyed by kind:runtime, Register + Render lookup. 100% coverage.
Systemd stub (internal/emitter/systemd.go):
- SystemdEmitter for process runtime. Renders minimal [Service] unit at
/etc/systemd/system/orca-v1-alloc-<name>.service (orca-v1- prefix per
dual-write window REQ-090 — no overlap with v0.8 daemon's orca-<job>).
Flock test fix: TestFlock_concurrentBlocks rewritten to use non-blocking
tryFlockEx (LOCK_NB) instead of a leaked blocking goroutine. Eliminates
the temp-dir cleanup race.
20 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P0c
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:17:02 +00:00