Skip to content

Commit

Permalink
pkg/workflows/sdk: add WorkflowSpec.FormatChart for mermaid flowcharts
Browse files Browse the repository at this point in the history
  • Loading branch information
jmank88 committed Oct 7, 2024
1 parent dd59341 commit 7c3e9ff
Show file tree
Hide file tree
Showing 17 changed files with 840 additions and 87 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@ lint-workspace:

lint:
@./script/lint.sh $(GOLANGCI_LINT_VERSION) "$(GOLANGCI_LINT_COMMON_OPTS)" $(GOLANGCI_LINT_DIRECTORY) "--new-from-rev=origin/main"

.PHONY: test-quiet
test-quiet:
go test ./... | grep -v "\[no test files\]" | grep -v "\(cached\)"
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module github.com/smartcontractkit/chainlink-common

go 1.22.0

toolchain go1.22.7
go 1.23

require (
github.com/andybalholm/brotli v1.1.0
Expand Down
21 changes: 21 additions & 0 deletions pkg/capabilities/capabilities.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package capabilities

import (
"cmp"
"context"
"fmt"
"regexp"
Expand Down Expand Up @@ -53,6 +54,26 @@ func (c CapabilityType) IsValid() error {
return fmt.Errorf("invalid capability type: %s", c)
}

func (c CapabilityType) cmpOrder() int {
switch c {
case CapabilityTypeTrigger:
return 0
case CapabilityTypeAction:
return 1
case CapabilityTypeConsensus:
return 2
case CapabilityTypeTarget:
return 3
case CapabilityTypeUnknown:
return 4
default:
return 5
}
}
func (c CapabilityType) Compare(c2 CapabilityType) int {
return cmp.Compare(c.cmpOrder(), c2.cmpOrder())
}

// CapabilityResponse is a struct for the Execute response of a capability.
type CapabilityResponse struct {
Value *values.Map
Expand Down
2 changes: 1 addition & 1 deletion pkg/workflows/dependency_graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func BuildDependencyGraph(spec sdk.WorkflowSpec) (*DependencyGraph, error) {
Graph: g,
Triggers: triggerSteps,
}
return wf, err
return wf, nil
}

var (
Expand Down
63 changes: 63 additions & 0 deletions pkg/workflows/dependency_graph_chart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package workflows

import (
"cmp"
"slices"
"strings"
"text/template"

"github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk"
)

func (g *DependencyGraph) FormatChart() (string, error) {
var sb strings.Builder
steps := slices.Clone(g.Spec.Triggers)
steps = append(steps, g.Spec.Steps()...)
slices.SortFunc(steps, func(a, b sdk.StepDefinition) int {
return cmp.Or(
a.CapabilityType.Compare(b.CapabilityType),
cmp.Compare(a.Ref, b.Ref),
cmp.Compare(a.ID, b.ID),
)
})
err := tmpl.Execute(&sb, steps)
if err != nil {
return "", err
}
return sb.String(), nil
}

var tmpl = template.Must(template.New("").Funcs(map[string]any{
"replace": strings.ReplaceAll,
}).Parse(`flowchart
{{ range $i, $step := . }}
{{ $ref := .Ref -}}
{{ $id := replace .ID "@" "[at]" -}}
{{ $name := printf "%s<br><i>(%s)</i>" .CapabilityType $id -}}
{{ if .Ref -}}
{{ $name = printf "<b>%s</b><br>%s" .Ref $name -}}
{{ else -}}
{{ $ref = printf "%s%d" "unnamed" $i -}}
{{ end -}}
{{ if eq .CapabilityType "trigger" -}}
{{ $ref }}[\"{{$name}}"/]
{{ else if eq .CapabilityType "consensus" -}}
{{ $ref }}[["{{$name}}"]]
{{ else if eq .CapabilityType "target" -}}
{{ $ref }}[/"{{$name}}"\]
{{ else -}}
{{ $ref }}["{{$name}}"]
{{ end -}}
{{ if .Inputs.OutputRef -}}
{{ .Inputs.OutputRef }} --> {{ $step.Ref }}
{{ else -}}
{{ range $out := .Inputs.Outputs -}}
{{ if $out.Name -}}
{{ $out.Ref }} -- {{ $out.Name }} --> {{ $ref}}
{{ else -}}
{{ $out.Ref }} --> {{ $ref}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
`))
Loading

0 comments on commit 7c3e9ff

Please sign in to comment.