Skip to content

Commit 92e7173

Browse files
committed
pkg/workflows/sdk: add WorkflowSpec.FormatChart for mermaid flowcharts
1 parent 62ca3f7 commit 92e7173

17 files changed

+718
-86
lines changed

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,7 @@ lint-workspace:
4747

4848
lint:
4949
@./script/lint.sh $(GOLANGCI_LINT_VERSION) "$(GOLANGCI_LINT_COMMON_OPTS)" $(GOLANGCI_LINT_DIRECTORY) "--new-from-rev=origin/main"
50+
51+
.PHONY: test-quiet
52+
test-quiet:
53+
go test ./... | grep -v "\[no test files\]" | grep -v "\(cached\)"

go.mod

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
module github.com/smartcontractkit/chainlink-common
22

3-
go 1.22.0
4-
5-
toolchain go1.22.7
3+
go 1.23
64

75
require (
86
github.com/andybalholm/brotli v1.1.0

pkg/capabilities/capabilities.go

+21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package capabilities
22

33
import (
4+
"cmp"
45
"context"
56
"fmt"
67
"regexp"
@@ -53,6 +54,26 @@ func (c CapabilityType) IsValid() error {
5354
return fmt.Errorf("invalid capability type: %s", c)
5455
}
5556

57+
func (c CapabilityType) cmpOrder() int {
58+
switch c {
59+
case CapabilityTypeTrigger:
60+
return 0
61+
case CapabilityTypeAction:
62+
return 1
63+
case CapabilityTypeConsensus:
64+
return 2
65+
case CapabilityTypeTarget:
66+
return 3
67+
case CapabilityTypeUnknown:
68+
return 4
69+
default:
70+
return 5
71+
}
72+
}
73+
func (c CapabilityType) Compare(c2 CapabilityType) int {
74+
return cmp.Compare(c.cmpOrder(), c2.cmpOrder())
75+
}
76+
5677
// CapabilityResponse is a struct for the Execute response of a capability.
5778
type CapabilityResponse struct {
5879
Value *values.Map

pkg/workflows/dependency_graph.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func BuildDependencyGraph(spec sdk.WorkflowSpec) (*DependencyGraph, error) {
129129
Graph: g,
130130
Triggers: triggerSteps,
131131
}
132-
return wf, err
132+
return wf, nil
133133
}
134134

135135
var (
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package workflows
2+
3+
import (
4+
"cmp"
5+
"fmt"
6+
"maps"
7+
"slices"
8+
"strings"
9+
"text/template"
10+
11+
"github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk"
12+
)
13+
14+
func (g *DependencyGraph) FormatChart() (string, error) {
15+
var sb strings.Builder
16+
steps := slices.Clone(g.Spec.Triggers)
17+
steps = append(steps, g.Spec.Steps()...)
18+
slices.SortFunc(steps, func(a, b sdk.StepDefinition) int {
19+
return cmp.Or(
20+
a.CapabilityType.Compare(b.CapabilityType),
21+
cmp.Compare(a.Ref, b.Ref),
22+
cmp.Compare(a.ID, b.ID),
23+
)
24+
})
25+
preds, err := g.Graph.PredecessorMap()
26+
if err != nil {
27+
return "", fmt.Errorf("failed to get graph predecessors: %w", err)
28+
}
29+
type stepAndOutput struct {
30+
Step sdk.StepDefinition
31+
Inputs []string
32+
}
33+
nodes := make([]stepAndOutput, len(steps))
34+
for i, step := range steps {
35+
nodes[i] = stepAndOutput{Step: step, Inputs: slices.Collect(maps.Keys(preds[step.Ref]))}
36+
}
37+
err = tmpl.Execute(&sb, nodes)
38+
if err != nil {
39+
return "", err
40+
}
41+
return sb.String(), nil
42+
}
43+
44+
var tmpl = template.Must(template.New("").Funcs(map[string]any{
45+
"replace": strings.ReplaceAll,
46+
}).Parse(`flowchart
47+
{{ range $i, $e := . }}
48+
{{ $ref := .Step.Ref -}}
49+
{{ $id := replace .Step.ID "@" "[at]" -}}
50+
{{ $name := printf "%s<br><i>(%s)</i>" .Step.CapabilityType $id -}}
51+
{{ if .Step.Ref -}}
52+
{{ $name = printf "<b>%s</b><br>%s" .Step.Ref $name -}}
53+
{{ else -}}
54+
{{ $ref = printf "%s%d" "unnamed" $i -}}
55+
{{ end -}}
56+
{{ if eq .Step.CapabilityType "trigger" -}}
57+
{{ $ref }}[\"{{$name}}"/]
58+
{{ else if eq .Step.CapabilityType "consensus" -}}
59+
{{ $ref }}[["{{$name}}"]]
60+
{{ else if eq .Step.CapabilityType "target" -}}
61+
{{ $ref }}[/"{{$name}}"\]
62+
{{ else -}}
63+
{{ $ref }}["{{$name}}"]
64+
{{ end -}}
65+
{{ if .Step.Inputs.OutputRef -}}
66+
{{ .Step.Inputs.OutputRef }} --> {{ .Step.Ref }}
67+
{{ else -}}
68+
{{ range $out := .Inputs -}}
69+
{{ $out }} --> {{ $ref }}
70+
{{ end -}}
71+
{{ end -}}
72+
{{ end -}}
73+
`))

0 commit comments

Comments
 (0)