gitlink-cli/shortcuts/workflow/engine/steps.go

107 lines
2.5 KiB
Go

package engine
import (
"encoding/json"
"fmt"
"os/exec"
"strings"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
wf "github.com/gitlink-org/gitlink-cli/shortcuts/workflow"
"github.com/gitlink-org/gitlink-cli/shortcuts/workflow/snapshot"
)
// ExecuteStep dispatches a step to the right executor based on its Type.
func ExecuteStep(ctx *common.RuntimeContext, step wf.StepDef, dryRun bool) *wf.StepResult {
sr := &wf.StepResult{
Step: step.Name,
Purpose: step.Purpose,
Type: step.Type,
}
switch step.Type {
case wf.StepTypeAPI:
executeAPIStep(ctx, step, sr)
case wf.StepTypeCommand:
executeCommandStep(ctx, step, sr)
case wf.StepTypeSkill:
executeSkillStep(ctx, step, sr, dryRun)
default:
sr.OK = false
sr.Error = fmt.Sprintf("unknown step type: %q", step.Type)
}
return sr
}
func executeAPIStep(ctx *common.RuntimeContext, step wf.StepDef, sr *wf.StepResult) {
path := wf.ResolvePath(step.Target, ctx.Owner, ctx.Repo)
env, err := ctx.CallAPIWithQuery(step.Method, path, step.Query)
if err != nil {
sr.OK = false
sr.Error = err.Error()
} else {
sr.OK = env.OK
sr.Data = env.Data
}
}
func executeCommandStep(ctx *common.RuntimeContext, step wf.StepDef, sr *wf.StepResult) {
if strings.HasPrefix(step.Target, "workflow-internal:") {
executeInternalCommandStep(ctx, step, sr)
return
}
parts := wf.ParseCommandTarget(step.Target)
if len(parts) == 0 {
sr.OK = false
sr.Error = fmt.Sprintf("empty command target: %q", step.Target)
return
}
bin := wf.ResolveCLIBinary()
args := append(parts, "--format", "json")
if ctx.Owner != "" {
args = append(args, "--owner", ctx.Owner)
}
if ctx.Repo != "" {
args = append(args, "--repo", ctx.Repo)
}
cmd := exec.Command(bin, args...)
cmd.Stderr = nil
out, err := cmd.Output()
if err != nil {
sr.OK = false
sr.Error = fmt.Sprintf("command failed: %v", err)
return
}
var data interface{}
if err := json.Unmarshal(out, &data); err != nil {
sr.OK = true
sr.Data = strings.TrimSpace(string(out))
} else {
sr.OK = true
sr.Data = data
}
}
func executeInternalCommandStep(ctx *common.RuntimeContext, step wf.StepDef, sr *wf.StepResult) {
switch strings.TrimPrefix(step.Target, "workflow-internal:") {
case "multi-repo-snapshot":
snap, err := snapshot.BuildMultiRepoSnapshot(ctx)
if err != nil {
sr.OK = false
sr.Error = err.Error()
return
}
sr.OK = true
sr.Data = snap
default:
sr.OK = false
sr.Error = fmt.Sprintf("unknown internal workflow command: %q", step.Target)
}
}