refactor: reduce CRAP scores in router/workflow/notification
ci / test (push) Successful in 3m42s

- llm_router.go: Extract getStringFromMap, firstNonEmpty, paramResolver
  - buildCronSpec: 12 → 4 complexity
  - buildParameters: 9 → 5 complexity

- routing_workflow.go: Extract stateMachine, stateResult types
  - RoutingWorkflow: 11 → 6 complexity
  - Separate executeTask/executePass/executeFail

- notification.go: Extract checker interface pattern
  - DeploymentPreCheckActivity: 10 → 5 complexity
  - goCheckers() returns language-specific checkers

- Added 7 new test cases for helper functions
- Coverage: internal/routing 63.6% → 66.0%
This commit is contained in:
Test
2026-09-03 08:50:21 -07:00
parent a0e64224a7
commit 1c16869126
6 changed files with 487 additions and 169 deletions
+76 -31
View File
@@ -203,6 +203,70 @@ type DeploymentPreCheckOutput struct {
Warnings []string `json:"warnings"` Warnings []string `json:"warnings"`
} }
// checker defines a deployment check
type checker struct {
name string
types []string // which checkTypes trigger this checker
isWarning bool // if true, failure goes to warnings not failures
run func(ctx context.Context, path string) (string, error)
}
// shouldRun checks if this checker should run for given checkType
func (c *checker) shouldRun(checkType string) bool {
for _, t := range c.types {
if t == checkType {
return true
}
}
return false
}
// goCheckers returns checkers for Go projects
func goCheckers() []*checker {
return []*checker{
{
name: "build",
types: []string{"all", "build"},
run: func(ctx context.Context, path string) (string, error) {
cmd := exec.CommandContext(ctx, "go", "build", "./...")
cmd.Dir = path
out, err := cmd.CombinedOutput()
return string(out), err
},
},
{
name: "test",
types: []string{"all", "test"},
run: func(ctx context.Context, path string) (string, error) {
cmd := exec.CommandContext(ctx, "go", "test", "-short", "./...")
cmd.Dir = path
out, err := cmd.CombinedOutput()
return string(out), err
},
},
{
name: "lint",
types: []string{"all", "lint"},
isWarning: true,
run: func(ctx context.Context, path string) (string, error) {
cmd := exec.CommandContext(ctx, "go", "vet", "./...")
cmd.Dir = path
out, err := cmd.CombinedOutput()
return string(out), err
},
},
}
}
// detectProjectCheckers returns checkers based on project type
func detectProjectCheckers(path string) []*checker {
if _, err := os.Stat(fmt.Sprintf("%s/go.mod", path)); err == nil {
return goCheckers()
}
// Add more project types here (Node, Python, etc.)
return nil
}
// DeploymentPreCheckActivity validates deployment readiness // DeploymentPreCheckActivity validates deployment readiness
func DeploymentPreCheckActivity(ctx context.Context, in DeploymentPreCheckInput) (DeploymentPreCheckOutput, error) { func DeploymentPreCheckActivity(ctx context.Context, in DeploymentPreCheckInput) (DeploymentPreCheckOutput, error) {
logger := newActivityLogger(ctx) logger := newActivityLogger(ctx)
@@ -226,38 +290,19 @@ func DeploymentPreCheckActivity(ctx context.Context, in DeploymentPreCheckInput)
return output, nil return output, nil
} }
// Check for Go project // Run applicable checkers
isGo := false for _, c := range detectProjectCheckers(in.Path) {
if _, err := os.Stat(fmt.Sprintf("%s/go.mod", in.Path)); err == nil { if !c.shouldRun(checkType) {
isGo = true continue
}
if isGo && (checkType == "all" || checkType == "build") {
// Try go build
cmd := exec.CommandContext(ctx, "go", "build", "./...")
cmd.Dir = in.Path
if buildOut, err := cmd.CombinedOutput(); err != nil {
output.Passed = false
output.Failures = append(output.Failures, fmt.Sprintf("build failed: %s", string(buildOut)))
} }
} if out, err := c.run(ctx, in.Path); err != nil {
msg := fmt.Sprintf("%s failed: %s", c.name, out)
if isGo && (checkType == "all" || checkType == "test") { if c.isWarning {
// Try go test output.Warnings = append(output.Warnings, msg)
cmd := exec.CommandContext(ctx, "go", "test", "-short", "./...") } else {
cmd.Dir = in.Path output.Passed = false
if testOut, err := cmd.CombinedOutput(); err != nil { output.Failures = append(output.Failures, msg)
output.Passed = false }
output.Failures = append(output.Failures, fmt.Sprintf("tests failed: %s", string(testOut)))
}
}
if isGo && (checkType == "all" || checkType == "lint") {
// Try go vet
cmd := exec.CommandContext(ctx, "go", "vet", "./...")
cmd.Dir = in.Path
if vetOut, err := cmd.CombinedOutput(); err != nil {
output.Warnings = append(output.Warnings, fmt.Sprintf("vet issues: %s", string(vetOut)))
} }
} }
+111 -64
View File
@@ -324,44 +324,52 @@ func (r *LLMRouter) buildSpec(intent *Intent, input LLMRouterInput) (*WorkflowSp
}, nil }, nil
} }
// getStringFromMap safely extracts a string from a map
func getStringFromMap(m map[string]interface{}, key string) string {
if m == nil {
return ""
}
if v, ok := m[key].(string); ok {
return v
}
return ""
}
// firstNonEmpty returns the first non-empty string from the list
func firstNonEmpty(values ...string) string {
for _, v := range values {
if v != "" {
return v
}
}
return ""
}
// buildCronSpec creates CronWorkflowSpec from intent // buildCronSpec creates CronWorkflowSpec from intent
func (r *LLMRouter) buildCronSpec(intent *Intent, input LLMRouterInput) (*CronWorkflowSpec, error) { func (r *LLMRouter) buildCronSpec(intent *Intent, input LLMRouterInput) (*CronWorkflowSpec, error) {
// First build regular spec
spec, err := r.buildSpec(intent, input) spec, err := r.buildSpec(intent, input)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Get schedule - check both intent and parameters (LLM sometimes puts it in parameters) // Extract schedule from multiple sources
schedule := intent.CronSchedule schedule := firstNonEmpty(
if schedule == "" { intent.CronSchedule,
if sched, ok := intent.Parameters["cronSchedule"].(string); ok { getStringFromMap(intent.Parameters, "cronSchedule"),
schedule = sched getStringFromMap(spec.Input, "cronSchedule"),
} )
}
if schedule == "" {
if sched, ok := spec.Input["cronSchedule"].(string); ok {
schedule = sched
delete(spec.Input, "cronSchedule") // Remove from input
}
}
// Get timezone // Extract timezone from multiple sources, default to UTC
timezone := intent.CronTimezone timezone := firstNonEmpty(
if timezone == "" { intent.CronTimezone,
if tz, ok := intent.Parameters["cronTimezone"].(string); ok { getStringFromMap(intent.Parameters, "cronTimezone"),
timezone = tz getStringFromMap(spec.Input, "cronTimezone"),
} "UTC",
} )
if timezone == "" {
if tz, ok := spec.Input["cronTimezone"].(string); ok { // Clean cron fields from input
timezone = tz delete(spec.Input, "cronSchedule")
delete(spec.Input, "cronTimezone") // Remove from input delete(spec.Input, "cronTimezone")
}
}
if timezone == "" {
timezone = "UTC"
}
return &CronWorkflowSpec{ return &CronWorkflowSpec{
Name: spec.Name, Name: spec.Name,
@@ -376,44 +384,83 @@ func (r *LLMRouter) buildCronSpec(intent *Intent, input LLMRouterInput) (*CronWo
}, nil }, nil
} }
// buildParameters creates parameter map for activity // isCommonInputField checks if field name is a common workflow input
func (r *LLMRouter) buildParameters(act *ActivityMetadata, intent *Intent, stateIndex int) map[string]interface{} { func isCommonInputField(name string) bool {
params := make(map[string]interface{}) switch name {
case "repo", "path", "branch":
return true
}
return false
}
for inputName, inputDef := range act.Inputs { // paramResolver resolves activity parameters from multiple sources
// Check if parameter was extracted from intent type paramResolver struct {
if val, ok := intent.Parameters[inputName]; ok { intent *Intent
params[inputName] = val kb *KnowledgeBase
continue prevState string
} }
// Check for JSONPath reference from previous state // resolve finds parameter value from intent, previous output, default, or input ref
if stateIndex > 0 { func (r *paramResolver) resolve(inputName string, inputDef InputField) interface{} {
prevAct := intent.Activities[stateIndex-1] // 1. From intent parameters
prevActDef := r.knowledgeBase.GetActivity(prevAct) if val, ok := r.intent.Parameters[inputName]; ok {
return val
// Look for matching output from previous activity
for outName := range prevActDef.Outputs {
if outName == inputName || strings.EqualFold(outName, inputName) {
params[inputName] = fmt.Sprintf("${%s.output.%s}", prevAct, outName)
break
}
}
}
// Use default if available
if params[inputName] == nil && inputDef.Default != nil {
params[inputName] = inputDef.Default
}
// Use input reference for common fields
if params[inputName] == nil {
if inputName == "repo" || inputName == "path" || inputName == "branch" {
params[inputName] = fmt.Sprintf("${input.%s}", inputName)
}
}
} }
// 2. From previous state output
if val := r.fromPrevOutput(inputName); val != nil {
return val
}
// 3. Default value
if inputDef.Default != nil {
return inputDef.Default
}
// 4. Input reference for common fields
if isCommonInputField(inputName) {
return fmt.Sprintf("${input.%s}", inputName)
}
return nil
}
// fromPrevOutput checks if previous activity has matching output
func (r *paramResolver) fromPrevOutput(inputName string) interface{} {
if r.prevState == "" {
return nil
}
prevActDef := r.kb.GetActivity(r.prevState)
if prevActDef == nil {
return nil
}
for outName := range prevActDef.Outputs {
if outName == inputName || strings.EqualFold(outName, inputName) {
return fmt.Sprintf("${%s.output.%s}", r.prevState, outName)
}
}
return nil
}
// buildParameters creates parameter map for activity
func (r *LLMRouter) buildParameters(act *ActivityMetadata, intent *Intent, stateIndex int) map[string]interface{} {
var prevState string
if stateIndex > 0 {
prevState = intent.Activities[stateIndex-1]
}
resolver := &paramResolver{
intent: intent,
kb: r.knowledgeBase,
prevState: prevState,
}
params := make(map[string]interface{})
for name, def := range act.Inputs {
if val := resolver.resolve(name, def); val != nil {
params[name] = val
}
}
return params return params
} }
+187
View File
@@ -278,6 +278,193 @@ func TestBuildRetryPolicy(t *testing.T) {
} }
} }
func TestGetStringFromMap(t *testing.T) {
tests := []struct {
name string
m map[string]interface{}
key string
expected string
}{
{"nil map", nil, "key", ""},
{"missing key", map[string]interface{}{"a": "b"}, "key", ""},
{"found string", map[string]interface{}{"key": "value"}, "key", "value"},
{"non-string value", map[string]interface{}{"key": 123}, "key", ""},
{"empty string", map[string]interface{}{"key": ""}, "key", ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := getStringFromMap(tt.m, tt.key)
if got != tt.expected {
t.Errorf("getStringFromMap() = %q, want %q", got, tt.expected)
}
})
}
}
func TestFirstNonEmpty(t *testing.T) {
tests := []struct {
name string
values []string
expected string
}{
{"all empty", []string{"", "", ""}, ""},
{"first non-empty", []string{"first", "second"}, "first"},
{"second non-empty", []string{"", "second", "third"}, "second"},
{"last non-empty", []string{"", "", "last"}, "last"},
{"no values", []string{}, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := firstNonEmpty(tt.values...)
if got != tt.expected {
t.Errorf("firstNonEmpty() = %q, want %q", got, tt.expected)
}
})
}
}
func TestIsCommonInputField(t *testing.T) {
tests := []struct {
name string
expected bool
}{
{"repo", true},
{"path", true},
{"branch", true},
{"unknown", false},
{"Repository", false}, // case-sensitive
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := isCommonInputField(tt.name)
if got != tt.expected {
t.Errorf("isCommonInputField(%q) = %v, want %v", tt.name, got, tt.expected)
}
})
}
}
func TestBuildCronSpecScheduleSources(t *testing.T) {
kb, err := LoadKnowledgeBaseFromDefaultPath()
if err != nil {
t.Fatalf("failed to load knowledge base: %v", err)
}
router := &LLMRouter{knowledgeBase: kb}
tests := []struct {
name string
intentSchedule string
intentTimezone string
paramSchedule string
paramTimezone string
wantSchedule string
wantTimezone string
}{
{
name: "from intent",
intentSchedule: "0 2 * * *",
intentTimezone: "PST",
wantSchedule: "0 2 * * *",
wantTimezone: "PST",
},
{
name: "from params",
paramSchedule: "0 3 * * *",
paramTimezone: "EST",
wantSchedule: "0 3 * * *",
wantTimezone: "EST",
},
{
name: "default UTC",
wantSchedule: "",
wantTimezone: "UTC",
},
{
name: "intent priority",
intentSchedule: "0 1 * * *",
intentTimezone: "UTC",
paramSchedule: "0 2 * * *",
paramTimezone: "PST",
wantSchedule: "0 1 * * *",
wantTimezone: "UTC",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
intent := &Intent{
Activities: []string{"CloneRepoActivity"},
Parameters: map[string]interface{}{},
IsCron: true,
CronSchedule: tt.intentSchedule,
CronTimezone: tt.intentTimezone,
WorkflowName: "test",
}
if tt.paramSchedule != "" {
intent.Parameters["cronSchedule"] = tt.paramSchedule
}
if tt.paramTimezone != "" {
intent.Parameters["cronTimezone"] = tt.paramTimezone
}
input := LLMRouterInput{Message: "test"}
spec, err := router.buildCronSpec(intent, input)
if err != nil {
t.Fatalf("buildCronSpec failed: %v", err)
}
if spec.Schedule != tt.wantSchedule {
t.Errorf("schedule = %q, want %q", spec.Schedule, tt.wantSchedule)
}
if spec.Timezone != tt.wantTimezone {
t.Errorf("timezone = %q, want %q", spec.Timezone, tt.wantTimezone)
}
})
}
}
func TestParamResolverFromPrevOutput(t *testing.T) {
kb, err := LoadKnowledgeBaseFromDefaultPath()
if err != nil {
t.Fatalf("failed to load knowledge base: %v", err)
}
resolver := &paramResolver{
intent: &Intent{
Activities: []string{"CloneRepoActivity", "AnalyzeCodeActivity"},
Parameters: map[string]interface{}{},
},
kb: kb,
prevState: "CloneRepoActivity",
}
// Should find matching output from CloneRepoActivity
got := resolver.fromPrevOutput("path")
if got == nil {
t.Error("expected to find path from prev output")
}
if got != "${CloneRepoActivity.output.path}" {
t.Errorf("got %v, want ${CloneRepoActivity.output.path}", got)
}
// Should not find non-existent output
got = resolver.fromPrevOutput("nonexistent")
if got != nil {
t.Errorf("expected nil for nonexistent, got %v", got)
}
// Empty prevState should return nil
resolver.prevState = ""
got = resolver.fromPrevOutput("path")
if got != nil {
t.Errorf("expected nil for empty prevState, got %v", got)
}
}
func TestIntentJSONMarshal(t *testing.T) { func TestIntentJSONMarshal(t *testing.T) {
intent := &Intent{ intent := &Intent{
Activities: []string{"CloneRepoActivity"}, Activities: []string{"CloneRepoActivity"},
+2 -2
View File
@@ -9,6 +9,6 @@ metadata:
app.kubernetes.io/name: poimen app.kubernetes.io/name: poimen
app.kubernetes.io/component: orchestrator app.kubernetes.io/component: orchestrator
data: data:
GIT_COMMIT: "303e78f7" # Updated automatically by CI/CD GIT_COMMIT: "e82600c1" # Updated automatically by CI/CD
GIT_BRANCH: "main" GIT_BRANCH: "main"
DEPLOYMENT_DATE: "2026-09-02" DEPLOYMENT_DATE: "2026-09-03"
+2 -2
View File
@@ -13,8 +13,8 @@ spec:
labels: labels:
app: poimen-worker app: poimen-worker
annotations: annotations:
git-commit: "303e78f7" # ✅ Updated on each push, triggers rolling restart git-commit: "e82600c1" # ✅ Updated on each push, triggers rolling restart
deployment-date: "2026-09-02" deployment-date: "2026-09-03"
spec: spec:
containers: containers:
- name: worker - name: worker
+109 -70
View File
@@ -23,98 +23,137 @@ type RoutingWorkflowOutput struct {
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
} }
// stateResult holds the result of executing a state
type stateResult struct {
result interface{}
nextState string
isDone bool
err error
}
// stateMachine manages workflow state execution
type stateMachine struct {
spec *routing.WorkflowSpec
stateIndex map[string]*routing.State
execCtx *routing.ExecutionContext
output *RoutingWorkflowOutput
current string
}
// newStateMachine creates a state machine from spec
func newStateMachine(spec *routing.WorkflowSpec) *stateMachine {
idx := make(map[string]*routing.State)
for i := range spec.States {
idx[spec.States[i].Name] = &spec.States[i]
}
return &stateMachine{
spec: spec,
stateIndex: idx,
execCtx: &routing.ExecutionContext{
Input: spec.Input,
StepResults: make(map[string]interface{}),
},
output: &RoutingWorkflowOutput{
Status: "FAILED",
StepResults: make(map[string]interface{}),
},
current: spec.States[0].Name,
}
}
func (m *stateMachine) currentState() *routing.State {
return m.stateIndex[m.current]
}
func (m *stateMachine) recordResult(name string, result interface{}) {
wrapped := map[string]interface{}{"output": result}
m.execCtx.StepResults[name] = wrapped
m.output.StepResults[name] = result
}
func (m *stateMachine) complete(result interface{}) RoutingWorkflowOutput {
m.output.Status = "COMPLETED"
m.output.FinalOutput = result
return *m.output
}
func (m *stateMachine) fail(errMsg string) RoutingWorkflowOutput {
m.output.Error = errMsg
return *m.output
}
// executeTask runs a Task state
func executeTask(ctx workflow.Context, state *routing.State, execCtx *routing.ExecutionContext, logger log.Logger) stateResult {
result, nextState, err := executeTaskState(ctx, state, execCtx, logger)
if err != nil {
if nextState != "" {
return stateResult{nextState: nextState} // Caught, continue to error handler
}
return stateResult{err: err}
}
return stateResult{result: result, nextState: state.Next, isDone: state.End}
}
// executePass runs a Pass state
func executePass(state *routing.State) stateResult {
return stateResult{result: state.Result, nextState: state.Next, isDone: state.End}
}
// executeFail runs a Fail state
func executeFail(state *routing.State) stateResult {
return stateResult{err: fmt.Errorf("%s: %s", state.Error, state.Cause)}
}
// RoutingWorkflow executes any WorkflowSpec generated by llm-router // RoutingWorkflow executes any WorkflowSpec generated by llm-router
func RoutingWorkflow(ctx workflow.Context, input RoutingWorkflowInput) (RoutingWorkflowOutput, error) { func RoutingWorkflow(ctx workflow.Context, input RoutingWorkflowInput) (RoutingWorkflowOutput, error) {
logger := workflow.GetLogger(ctx) logger := workflow.GetLogger(ctx)
output := RoutingWorkflowOutput{
Status: "FAILED",
StepResults: make(map[string]interface{}),
}
if input.Spec == nil || len(input.Spec.States) == 0 { if input.Spec == nil || len(input.Spec.States) == 0 {
output.Error = "empty workflow spec" return RoutingWorkflowOutput{Status: "FAILED", Error: "empty workflow spec", StepResults: map[string]interface{}{}}, nil
return output, nil
} }
logger.Info("RoutingWorkflow started", "name", input.Spec.Name, "stateCount", len(input.Spec.States)) logger.Info("RoutingWorkflow started", "name", input.Spec.Name, "stateCount", len(input.Spec.States))
// Build execution context m := newStateMachine(input.Spec)
execCtx := &routing.ExecutionContext{
Input: input.Spec.Input,
StepResults: make(map[string]interface{}),
}
// Build state index for fast lookup
stateIndex := make(map[string]*routing.State)
for i := range input.Spec.States {
stateIndex[input.Spec.States[i].Name] = &input.Spec.States[i]
}
// Find first state (first in array)
currentStateName := input.Spec.States[0].Name
// State machine loop
for { for {
state, ok := stateIndex[currentStateName] state := m.currentState()
if !ok { if state == nil {
output.Error = fmt.Sprintf("state not found: %s", currentStateName) return m.fail(fmt.Sprintf("state not found: %s", m.current)), nil
return output, nil
} }
logger.Info("executing state", "state", currentStateName, "type", state.Type) logger.Info("executing state", "state", m.current, "type", state.Type)
var res stateResult
switch state.Type { switch state.Type {
case routing.StateTypeTask: case routing.StateTypeTask:
result, nextState, err := executeTaskState(ctx, state, execCtx, logger) res = executeTask(ctx, state, m.execCtx, logger)
if err != nil {
// Check for catch clause
if nextState != "" {
currentStateName = nextState
continue
}
output.Error = fmt.Sprintf("state %s failed: %v", currentStateName, err)
return output, nil
}
// Wrap result in output key for JSONPath compatibility (e.g., ${Clone.output.path})
wrappedResult := map[string]interface{}{"output": result}
execCtx.StepResults[state.Name] = wrappedResult
output.StepResults[state.Name] = result // Keep original for output
if state.End {
output.Status = "COMPLETED"
output.FinalOutput = result
logger.Info("RoutingWorkflow completed", "name", input.Spec.Name)
return output, nil
}
currentStateName = state.Next
case routing.StateTypePass: case routing.StateTypePass:
execCtx.StepResults[state.Name] = state.Result res = executePass(state)
output.StepResults[state.Name] = state.Result
if state.End {
output.Status = "COMPLETED"
output.FinalOutput = state.Result
return output, nil
}
currentStateName = state.Next
case routing.StateTypeFail: case routing.StateTypeFail:
output.Error = fmt.Sprintf("%s: %s", state.Error, state.Cause) res = executeFail(state)
logger.Error("RoutingWorkflow failed at Fail state", "state", currentStateName, "error", state.Error)
return output, nil
default: default:
output.Error = fmt.Sprintf("unknown state type: %s", state.Type) return m.fail(fmt.Sprintf("unknown state type: %s", state.Type)), nil
return output, nil
} }
// Safety check if res.err != nil {
if currentStateName == "" { logger.Error("state failed", "state", m.current, "error", res.err)
output.Error = "no next state and not end" return m.fail(fmt.Sprintf("state %s failed: %v", m.current, res.err)), nil
return output, nil
} }
if res.result != nil {
m.recordResult(state.Name, res.result)
}
if res.isDone {
logger.Info("RoutingWorkflow completed", "name", input.Spec.Name)
return m.complete(res.result), nil
}
if res.nextState == "" {
return m.fail("no next state and not end"), nil
}
m.current = res.nextState
} }
} }