feat: wire configured harness execution

This commit is contained in:
kami
2026-07-26 20:06:44 +04:00
parent 5d45351613
commit dc3cebebf8
5 changed files with 71 additions and 3 deletions
+40
View File
@@ -10,6 +10,9 @@ import (
"orchestra/internal/domain"
"orchestra/internal/herdr"
"orchestra/internal/store"
"os"
"os/exec"
"path/filepath"
"sync"
)
@@ -20,6 +23,43 @@ type Adapters interface {
Adapter(string) (herdr.Adapter, error)
}
// GitWorktrees creates one isolated checkout per task. The root is expected
// to be a clone containing the project's remote; callers may set a separate
// root per deployment.
type GitWorktrees struct {
Root string
Repo string
}
func (w GitWorktrees) Create(ctx context.Context, t domain.Task) (string, error) {
if w.Root == "" || w.Repo == "" {
return "", fmt.Errorf("worktree: root and repo required")
}
if err := os.MkdirAll(w.Root, 0755); err != nil {
return "", err
}
p := filepath.Join(w.Root, t.ID)
if _, err := os.Stat(p); err == nil {
return p, nil
}
branch := "orchestra/" + t.ID
cmd := exec.CommandContext(ctx, "git", "-C", w.Repo, "worktree", "add", "-b", branch, p, "HEAD")
if out, err := cmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("%s: %w", string(out), err)
}
return p, nil
}
type AdapterFactory struct{ Herdrs map[string]herdr.Adapter }
func (f AdapterFactory) Adapter(id string) (herdr.Adapter, error) {
a, ok := f.Herdrs[id]
if !ok {
return nil, fmt.Errorf("adapter %q not registered", id)
}
return a, nil
}
type Coordinator struct {
Store *store.Store
Worktrees Worktrees
+9 -1
View File
@@ -109,7 +109,15 @@ func putID[T any](m map[string]T, id, kind string) error {
func (r Registry) Project(id string) (Project, bool) { p, ok := r.projects[id]; return p, ok }
func (r Registry) Machine(id string) (Machine, bool) { m, ok := r.machines[id]; return m, ok }
func (r Registry) Herdr(id string) (Herdr, bool) { h, ok := r.herdrs[id]; return h, ok }
func (r Registry) Projects() []Project { return projects(r.projects) }
func (r Registry) Herdrs() []Herdr {
out := make([]Herdr, 0, len(r.herdrs))
for _, h := range r.herdrs {
out = append(out, h)
}
sort.Slice(out, func(i, j int) bool { return out[i].ID < out[j].ID })
return out
}
func (r Registry) Projects() []Project { return projects(r.projects) }
func projects(m map[string]Project) []Project {
out := make([]Project, 0, len(m))
for _, v := range m {
+6
View File
@@ -31,6 +31,7 @@ type Router struct {
Now func() time.Time
backoff map[string]time.Time
attempts map[string]int
OnLease func(domain.Event) error
}
func (r *Router) init() {
@@ -99,6 +100,11 @@ func (r *Router) AssignPending() ([]domain.Event, error) {
}
r.attempts[t.ID]++
out = append(out, e)
if r.OnLease != nil {
if err := r.OnLease(e); err != nil {
return out, err
}
}
break
}
}