relay-flow 0.2.10-alpha → 0.3.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/cmd/relay-flow/main.go +114 -19
- package/cmd/relay-flow/observability_test.go +118 -6
- package/internal/execution/goworkflows/activities.go +11 -6
- package/internal/execution/goworkflows/engine_test.go +52 -0
- package/internal/execution/goworkflows/fakes_test.go +14 -7
- package/internal/execution/goworkflows/interpreter.go +11 -7
- package/internal/execution/goworkflows/node_runtime_test.go +8 -8
- package/internal/execution/temporal/activities.go +11 -6
- package/internal/execution/temporal/end_cleanup_order_test.go +147 -0
- package/internal/execution/temporal/interpreter.go +11 -7
- package/internal/harness/opencode/opencode_test.go +1 -1
- package/internal/harness/opencode/repo_setup.go +1 -1
- package/internal/harness/pi/pi.go +18 -8
- package/internal/harness/pi/pi_test.go +1 -1
- package/internal/harness/pi/prompt_test.go +2 -2
- package/internal/runner/clean.go +38 -0
- package/internal/runner/clean_test.go +84 -0
- package/internal/runner/herdr/herdr.go +24 -10
- package/internal/runner/herdr/herdr_test.go +66 -0
- package/internal/runner/orca/orca.go +16 -2
- package/internal/runner/orca/orca_test.go +103 -1
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ package orca
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
5
|
"errors"
|
|
6
|
+
"os"
|
|
6
7
|
"os/exec"
|
|
7
8
|
"strings"
|
|
8
9
|
"testing"
|
|
@@ -404,7 +405,7 @@ func TestCloseTerminalsContinuesAfterStaleHandle(t *testing.T) {
|
|
|
404
405
|
func TestCleanupRunDeletesWorktreeAfterStaleHandle(t *testing.T) {
|
|
405
406
|
fx := &fakeCLI{
|
|
406
407
|
repos: []orcacli.Repo{{ID: "r1", DisplayName: "app", Path: "/srv/app"}},
|
|
407
|
-
worktrees: []orcacli.Worktree{{ID: "wt-PAY-1", RepoID: "r1", DisplayName: "PAY-1"}},
|
|
408
|
+
worktrees: []orcacli.Worktree{{ID: "wt-PAY-1", RepoID: "r1", DisplayName: "PAY-1", Path: "/wt/PAY-1"}},
|
|
408
409
|
listedTerminals: []orcacli.Terminal{{Handle: "term-stale", Title: "PAY-1:implement", Connected: true}},
|
|
409
410
|
closeErrors: map[string]error{"term-stale": orcacli.ErrTerminalUnavailable},
|
|
410
411
|
}
|
|
@@ -422,6 +423,107 @@ func TestCleanupRunDeletesWorktreeAfterStaleHandle(t *testing.T) {
|
|
|
422
423
|
}
|
|
423
424
|
}
|
|
424
425
|
|
|
426
|
+
func TestCleanupRunBlocksDirtyCheckoutBeforeResourceCleanup(t *testing.T) {
|
|
427
|
+
repo := newOrcaCleanCheckout(t)
|
|
428
|
+
if err := os.WriteFile(repo+"/dirty.txt", []byte("uncommitted\n"), 0o644); err != nil {
|
|
429
|
+
t.Fatal(err)
|
|
430
|
+
}
|
|
431
|
+
fx := &fakeCLI{
|
|
432
|
+
repos: []orcacli.Repo{{ID: "r1", DisplayName: "app", Path: repo}},
|
|
433
|
+
worktrees: []orcacli.Worktree{{ID: "wt-PAY-1", RepoID: "r1", DisplayName: "PAY-1", Path: repo}},
|
|
434
|
+
listedTerminals: []orcacli.Terminal{{Handle: "term-live", Title: "PAY-1:implement", Connected: true}},
|
|
435
|
+
}
|
|
436
|
+
a, err := New(fx, config.RawValues{})
|
|
437
|
+
if err != nil {
|
|
438
|
+
t.Fatal(err)
|
|
439
|
+
}
|
|
440
|
+
err = a.CleanupRun(context.Background(), runner.RunSpec{RepoName: "app", RepoPath: repo, TicketKey: "PAY-1"})
|
|
441
|
+
if err == nil || !strings.Contains(err.Error(), "commit required") {
|
|
442
|
+
t.Fatalf("CleanupRun error = %v, want commit-required dirty-check error", err)
|
|
443
|
+
}
|
|
444
|
+
if len(fx.closedHandles) != 0 || len(fx.deletedWorktrees) != 0 {
|
|
445
|
+
t.Fatalf("dirty cleanup touched runner resources: closed=%v deleted=%v", fx.closedHandles, fx.deletedWorktrees)
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
func TestCleanupRunAllowsCleanCheckoutAndLaterRetry(t *testing.T) {
|
|
450
|
+
repo := newOrcaCleanCheckout(t)
|
|
451
|
+
dirty := repo + "/dirty.txt"
|
|
452
|
+
if err := os.WriteFile(dirty, []byte("uncommitted\n"), 0o644); err != nil {
|
|
453
|
+
t.Fatal(err)
|
|
454
|
+
}
|
|
455
|
+
fx := &fakeCLI{
|
|
456
|
+
repos: []orcacli.Repo{{ID: "r1", DisplayName: "app", Path: repo}},
|
|
457
|
+
worktrees: []orcacli.Worktree{{ID: "wt-PAY-1", RepoID: "r1", DisplayName: "PAY-1", Path: repo}},
|
|
458
|
+
listedTerminals: []orcacli.Terminal{{Handle: "term-live", Title: "PAY-1:implement", Connected: true}},
|
|
459
|
+
}
|
|
460
|
+
a, err := New(fx, config.RawValues{})
|
|
461
|
+
if err != nil {
|
|
462
|
+
t.Fatal(err)
|
|
463
|
+
}
|
|
464
|
+
spec := runner.RunSpec{RepoName: "app", RepoPath: repo, TicketKey: "PAY-1"}
|
|
465
|
+
if err := a.CleanupRun(context.Background(), spec); err == nil {
|
|
466
|
+
t.Fatal("dirty CleanupRun succeeded")
|
|
467
|
+
}
|
|
468
|
+
if err := os.Remove(dirty); err != nil {
|
|
469
|
+
t.Fatal(err)
|
|
470
|
+
}
|
|
471
|
+
if err := a.CleanupRun(context.Background(), spec); err != nil {
|
|
472
|
+
t.Fatalf("clean retry CleanupRun = %v", err)
|
|
473
|
+
}
|
|
474
|
+
if len(fx.closedHandles) != 1 || len(fx.deletedWorktrees) != 1 {
|
|
475
|
+
t.Fatalf("clean retry resources: closed=%v deleted=%v", fx.closedHandles, fx.deletedWorktrees)
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
func TestCleanupRunPropagatesGitStatusFailureBeforeResourceCleanup(t *testing.T) {
|
|
480
|
+
repo := t.TempDir()
|
|
481
|
+
fx := &fakeCLI{
|
|
482
|
+
repos: []orcacli.Repo{{ID: "r1", DisplayName: "app", Path: repo}},
|
|
483
|
+
worktrees: []orcacli.Worktree{{ID: "wt-PAY-1", RepoID: "r1", DisplayName: "PAY-1", Path: repo}},
|
|
484
|
+
}
|
|
485
|
+
a, err := New(fx, config.RawValues{})
|
|
486
|
+
if err != nil {
|
|
487
|
+
t.Fatal(err)
|
|
488
|
+
}
|
|
489
|
+
if err := a.CleanupRun(context.Background(), runner.RunSpec{RepoName: "app", RepoPath: repo, TicketKey: "PAY-1"}); err == nil {
|
|
490
|
+
t.Fatal("CleanupRun treated Git status failure as clean")
|
|
491
|
+
}
|
|
492
|
+
if len(fx.closedHandles) != 0 || len(fx.deletedWorktrees) != 0 {
|
|
493
|
+
t.Fatalf("Git status failure touched runner resources: closed=%v deleted=%v", fx.closedHandles, fx.deletedWorktrees)
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
func newOrcaCleanCheckout(t *testing.T) string {
|
|
498
|
+
t.Helper()
|
|
499
|
+
repo := t.TempDir()
|
|
500
|
+
for _, args := range [][]string{
|
|
501
|
+
{"init", "-q", "-b", "main"},
|
|
502
|
+
{"config", "user.email", "relay-flow@example.invalid"},
|
|
503
|
+
{"config", "user.name", "Relay Flow"},
|
|
504
|
+
} {
|
|
505
|
+
cmd := exec.Command("git", args...)
|
|
506
|
+
cmd.Dir = repo
|
|
507
|
+
if output, err := cmd.CombinedOutput(); err != nil {
|
|
508
|
+
t.Fatalf("git %v: %v: %s", args, err, output)
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if err := os.WriteFile(repo+"/tracked.txt", []byte("clean\n"), 0o644); err != nil {
|
|
512
|
+
t.Fatal(err)
|
|
513
|
+
}
|
|
514
|
+
cmd := exec.Command("git", "add", "tracked.txt")
|
|
515
|
+
cmd.Dir = repo
|
|
516
|
+
if output, err := cmd.CombinedOutput(); err != nil {
|
|
517
|
+
t.Fatalf("git add: %v: %s", err, output)
|
|
518
|
+
}
|
|
519
|
+
cmd = exec.Command("git", "commit", "-qm", "initial")
|
|
520
|
+
cmd.Dir = repo
|
|
521
|
+
if output, err := cmd.CombinedOutput(); err != nil {
|
|
522
|
+
t.Fatalf("git commit: %v: %s", err, output)
|
|
523
|
+
}
|
|
524
|
+
return repo
|
|
525
|
+
}
|
|
526
|
+
|
|
425
527
|
// An existing ticket branch must win even over a configured baseRef. Passing
|
|
426
528
|
// any other base would make Orca hit its branch-name collision behavior.
|
|
427
529
|
func TestEnsureEnvironment_ExistingTicketBranchAvoidsCollision(t *testing.T) {
|