feat: wire configured harness execution
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user