feat(gate): add bd gate check for GitHub gate evaluation (bd-oos3)
Implement Phase 3 of gate evaluation: GitHub gates (gh:run and gh:pr). ## Changes - Add `bd gate check` command to evaluate open gates - Support --type=gh to check all GitHub gates - Support --type=gh:run for GitHub Actions workflow run gates - Support --type=gh:pr for pull request merge status gates - Add --dry-run flag to preview gate resolution without closing - Auto-close gates when conditions are met: - gh:run: workflow completed with success - gh:pr: PR merged - Escalate when conditions fail: - gh:run: workflow failed or cancelled - gh:pr: PR closed without merging - Add unit tests for shouldCheckGate filtering Note: mol-refinery-patrol.formula.toml updated in gastown rig to include check-github-gates step (version 4). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
54
cmd/bd/gate_test.go
Normal file
54
cmd/bd/gate_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
)
|
||||
|
||||
func TestShouldCheckGate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
awaitType string
|
||||
typeFilter string
|
||||
want bool
|
||||
}{
|
||||
// Empty filter matches all
|
||||
{"empty filter matches gh:run", "gh:run", "", true},
|
||||
{"empty filter matches gh:pr", "gh:pr", "", true},
|
||||
{"empty filter matches timer", "timer", "", true},
|
||||
{"empty filter matches human", "human", "", true},
|
||||
|
||||
// "all" filter matches all
|
||||
{"all filter matches gh:run", "gh:run", "all", true},
|
||||
{"all filter matches gh:pr", "gh:pr", "all", true},
|
||||
{"all filter matches timer", "timer", "all", true},
|
||||
|
||||
// "gh" filter matches all GitHub types
|
||||
{"gh filter matches gh:run", "gh:run", "gh", true},
|
||||
{"gh filter matches gh:pr", "gh:pr", "gh", true},
|
||||
{"gh filter does not match timer", "timer", "gh", false},
|
||||
{"gh filter does not match human", "human", "gh", false},
|
||||
|
||||
// Exact type filters
|
||||
{"gh:run filter matches gh:run", "gh:run", "gh:run", true},
|
||||
{"gh:run filter does not match gh:pr", "gh:pr", "gh:run", false},
|
||||
{"gh:pr filter matches gh:pr", "gh:pr", "gh:pr", true},
|
||||
{"gh:pr filter does not match gh:run", "gh:run", "gh:pr", false},
|
||||
{"timer filter matches timer", "timer", "timer", true},
|
||||
{"timer filter does not match gh:run", "gh:run", "timer", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gate := &types.Issue{
|
||||
AwaitType: tt.awaitType,
|
||||
}
|
||||
got := shouldCheckGate(gate, tt.typeFilter)
|
||||
if got != tt.want {
|
||||
t.Errorf("shouldCheckGate(%q, %q) = %v, want %v",
|
||||
tt.awaitType, tt.typeFilter, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user