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 1, 2024
1 parent aded1b2 commit 1d141c0
Show file tree
Hide file tree
Showing 16 changed files with 755 additions and 154 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/models_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var transformJSON = cmp.FilterValues(func(x, y []byte) bool {
return out
}))

func TestWorkflowSpecMarshalling(t *testing.T) {
func TestWorkflowSpecYamlMarshalling(t *testing.T) {
t.Parallel()
fixtureReader := yamlFixtureReaderBytes(t, "marshalling")

Expand Down
77 changes: 1 addition & 76 deletions pkg/workflows/sdk/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/require"
"sigs.k8s.io/yaml"

"github.com/smartcontractkit/chainlink-common/pkg/capabilities"
ocr3 "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/ocr3cap"
"github.com/smartcontractkit/chainlink-common/pkg/capabilities/targets/chainwriter"
"github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers/streams"
Expand Down Expand Up @@ -205,81 +204,7 @@ func TestBuilder_ValidSpec(t *testing.T) {
actual, err := factory.Spec()
require.NoError(t, err)

expected := sdk.WorkflowSpec{
Name: "notccipethsep",
Owner: "0x00000000000000000000000000000000000000aa",
Triggers: []sdk.StepDefinition{
{
ID: "[email protected]",
Ref: "trigger",
Inputs: sdk.StepInputs{},
Config: map[string]any{"maxFrequencyMs": 5000},
CapabilityType: capabilities.CapabilityTypeTrigger,
},
},
Actions: make([]sdk.StepDefinition, 0),
Consensus: []sdk.StepDefinition{
{
ID: "[email protected]",
Ref: "data-feeds-report",
Inputs: sdk.StepInputs{
Mapping: map[string]any{"observations": []map[string]any{
{
"Metadata": map[string]any{
"MinRequiredSignatures": 1,
"Signers": []string{"$(trigger.outputs.Metadata.Signer)"},
},
"Payload": []map[string]any{
{
"BenchmarkPrice": "$(trigger.outputs.Payload.BuyPrice)",
"FeedID": anyFakeFeedID,
"FullReport": "$(trigger.outputs.Payload.FullReport)",
"ObservationTimestamp": "$(trigger.outputs.Payload.ObservationTimestamp)",
"ReportContext": "$(trigger.outputs.Payload.ReportContext)",
"Signatures": []string{"$(trigger.outputs.Payload.Signature)"},
},
},
"Timestamp": "$(trigger.outputs.Timestamp)",
},
}},
},
Config: map[string]any{
"aggregation_config": ocr3.DataFeedsConsensusConfigAggregationConfig{
AllowedPartialStaleness: "0.5",
Feeds: map[string]ocr3.FeedValue{
anyFakeFeedID: {
Deviation: "0.5",
Heartbeat: 3600,
},
},
},
"aggregation_method": "data_feeds",
"encoder": "EVM",
"encoder_config": ocr3.EncoderConfig{
"Abi": "(bytes32 FeedID, uint224 Price, uint32 Timestamp)[] Reports",
},
"report_id": "0001",
},
CapabilityType: capabilities.CapabilityTypeConsensus,
},
},
Targets: []sdk.StepDefinition{
{
ID: "[email protected]",
Inputs: sdk.StepInputs{
Mapping: map[string]any{"signed_report": "$(data-feeds-report.outputs)"},
},
Config: map[string]any{
"address": "0xE0082363396985ae2FdcC3a9F816A586Eed88416",
"deltaStage": "45s",
"schedule": "oneAtATime",
},
CapabilityType: capabilities.CapabilityTypeTarget,
},
},
}

testutils.AssertWorkflowSpec(t, expected, actual)
testutils.AssertWorkflowSpec(t, notStreamSepoliaWorkflowSpec, actual)
})

t.Run("duplicate names causes errors", func(t *testing.T) {
Expand Down
70 changes: 2 additions & 68 deletions pkg/workflows/sdk/compute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,74 +39,8 @@ func TestCompute(t *testing.T) {

spec, err2 := workflow.Spec()
require.NoError(t, err2)
expectedSpec := sdk.WorkflowSpec{
Name: "name",
Owner: "owner",
Triggers: []sdk.StepDefinition{
{
ID: "[email protected]",
Ref: "trigger",
Inputs: sdk.StepInputs{},
Config: map[string]any{"maxFrequencyMs": 5000},
CapabilityType: capabilities.CapabilityTypeTrigger,
},
},
Actions: []sdk.StepDefinition{
{
ID: "[email protected]",
Ref: "Compute",
Inputs: sdk.StepInputs{
Mapping: map[string]any{"Arg0": "$(trigger.outputs)"},
},
Config: map[string]any{
"binary": "$(ENV.binary)",
"config": "$(ENV.config)",
},
CapabilityType: capabilities.CapabilityTypeAction,
},
},
Consensus: []sdk.StepDefinition{
{
ID: "[email protected]",
Ref: "data-feeds-report",
Inputs: sdk.StepInputs{
Mapping: map[string]any{"observations": "$(Compute.outputs.Value)"},
},
Config: map[string]any{
"aggregation_config": ocr3.DataFeedsConsensusConfigAggregationConfig{
AllowedPartialStaleness: "false",
Feeds: map[string]ocr3.FeedValue{
anyFakeFeedID: {
Deviation: "0.5",
Heartbeat: 3600,
},
},
},
"aggregation_method": "data_feeds",
"encoder": ocr3.EncoderEVM,
"encoder_config": ocr3.EncoderConfig{},
"report_id": "0001",
},
CapabilityType: capabilities.CapabilityTypeConsensus,
},
},
Targets: []sdk.StepDefinition{
{
ID: "[email protected]",
Inputs: sdk.StepInputs{
Mapping: map[string]any{"signed_report": "$(data-feeds-report.outputs)"},
},
Config: map[string]any{
"address": "0xE0082363396985ae2FdcC3a9F816A586Eed88416",
"deltaStage": "45s",
"schedule": "oneAtATime",
},
CapabilityType: capabilities.CapabilityTypeTarget,
},
},
}

testutils.AssertWorkflowSpec(t, expectedSpec, spec)
testutils.AssertWorkflowSpec(t, serialWorkflowSpec, spec)
})

t.Run("compute runs the function and returns the value", func(t *testing.T) {
Expand All @@ -133,7 +67,7 @@ func TestCompute(t *testing.T) {
func createWorkflow(fn func(_ sdk.Runtime, inputFeed notstreams.Feed) ([]streams.Feed, error)) *sdk.WorkflowSpecFactory {
workflow := sdk.NewWorkflowSpecFactory(sdk.NewWorkflowParams{
Owner: "owner",
Name: "name",
Name: "serial",
})

trigger := notstreams.TriggerConfig{MaxFrequencyMs: 5000}.New(workflow)
Expand Down
14 changes: 14 additions & 0 deletions pkg/workflows/sdk/helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package sdk

import (
"testing"

"github.com/stretchr/testify/require"
)

func (w *WorkflowSpecFactory) MustSpec(t *testing.T) WorkflowSpec {
t.Helper()
s, err := w.Spec()
require.NoError(t, err)
return s
}
8 changes: 8 additions & 0 deletions pkg/workflows/sdk/testdata/fixtures/charts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# WorkflowSpec Charts

This directory contains WorkflowSpec chart golden files. They are validated against test data by TestWorkflowSpecFormatChart,
and can be regenerated by passing the `-update` flag:
```sh
go test -run=TestWorkflowSpecFormatChart ./pkg/workflows/sdk/ -update
```
You can also invoke go:generate on package sdk, which will do the same.
26 changes: 26 additions & 0 deletions pkg/workflows/sdk/testdata/fixtures/charts/builder_parallel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
```mermaid
flowchart
trigger[\"<b>trigger</b><br>trigger<br><i>(basic-test-trigger[at]1.0.0)</i>"/]
compute["<b>compute</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
get-bar -- Value --> compute
get-baz -- Value --> compute
get-foo -- Value --> compute
get-bar["<b>get-bar</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
trigger -- cool_output --> get-bar
get-baz["<b>get-baz</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
trigger -- cool_output --> get-baz
get-foo["<b>get-foo</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
trigger -- cool_output --> get-foo
consensus[["<b>consensus</b><br>consensus<br><i>(offchain_reporting[at]1.0.0)</i>"]]
compute -- Value --> consensus
unnamed6[/"target<br><i>(id)</i>"\]
consensus --> unnamed6
```
12 changes: 12 additions & 0 deletions pkg/workflows/sdk/testdata/fixtures/charts/notstreamssepolia.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```mermaid
flowchart
trigger[\"<b>trigger</b><br>trigger<br><i>(notstreams[at]1.0.0)</i>"/]
data-feeds-report[["<b>data-feeds-report</b><br>consensus<br><i>(offchain_reporting[at]1.0.0)</i>"]]
trigger -- Metadata.Signer<br>Payload.BuyPrice<br>Payload.FullReport<br>Payload.ObservationTimestamp<br>Payload.ReportContext<br>Payload.Signature<br>Timestamp --> data-feeds-report
unnamed2[/"target<br><i>(write_ethereum-testnet-sepolia[at]1.0.0)</i>"\]
data-feeds-report --> unnamed2
```
29 changes: 29 additions & 0 deletions pkg/workflows/sdk/testdata/fixtures/charts/parallel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
```mermaid
flowchart
trigger-chain-event[\"<b>trigger-chain-event</b><br>trigger<br><i>(chain_reader[at]1.0.0)</i>"/]
compute-bar["<b>compute-bar</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
get-bar --> compute-bar
compute-foo["<b>compute-foo</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
get-foo --> compute-foo
get-bar["<b>get-bar</b><br>action<br><i>(http[at]1.0.0)</i>"]
trigger-chain-event --> get-bar
get-foo["<b>get-foo</b><br>action<br><i>(http[at]1.0.0)</i>"]
trigger-chain-event --> get-foo
read-token-price["<b>read-token-price</b><br>action<br><i>(chain_reader[at]1.0.0)</i>"]
trigger-chain-event --> read-token-price
data-feeds-report[["<b>data-feeds-report</b><br>consensus<br><i>(offchain_reporting[at]1.0.0)</i>"]]
compute-bar -- Value --> data-feeds-report
compute-foo -- Value --> data-feeds-report
read-token-price -- Value --> data-feeds-report
unnamed7[/"target<br><i>(write_ethereum-testnet-sepolia[at]1.0.0)</i>"\]
data-feeds-report --> unnamed7
```
31 changes: 31 additions & 0 deletions pkg/workflows/sdk/testdata/fixtures/charts/parallel_serialized.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
```mermaid
flowchart
trigger-chain-event[\"<b>trigger-chain-event</b><br>trigger<br><i>(chain_reader[at]1.0.0)</i>"/]
compute-bar["<b>compute-bar</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
get-bar --> compute-bar
compute-foo["<b>compute-foo</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
get-foo --> compute-foo
get-bar["<b>get-bar</b><br>action<br><i>(http[at]1.0.0)</i>"]
compute-foo -..-> get-bar
trigger-chain-event --> get-bar
get-foo["<b>get-foo</b><br>action<br><i>(http[at]1.0.0)</i>"]
trigger-chain-event --> get-foo
read-token-price["<b>read-token-price</b><br>action<br><i>(chain_reader[at]1.0.0)</i>"]
compute-bar -..-> read-token-price
trigger-chain-event --> read-token-price
data-feeds-report[["<b>data-feeds-report</b><br>consensus<br><i>(offchain_reporting[at]1.0.0)</i>"]]
compute-bar -- Value --> data-feeds-report
compute-foo -- Value --> data-feeds-report
read-token-price -- Value --> data-feeds-report
unnamed7[/"target<br><i>(write_ethereum-testnet-sepolia[at]1.0.0)</i>"\]
data-feeds-report --> unnamed7
```
15 changes: 15 additions & 0 deletions pkg/workflows/sdk/testdata/fixtures/charts/serial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```mermaid
flowchart
trigger[\"<b>trigger</b><br>trigger<br><i>(notstreams[at]1.0.0)</i>"/]
Compute["<b>Compute</b><br>action<br><i>(custom_compute[at]1.0.0)</i>"]
trigger --> Compute
data-feeds-report[["<b>data-feeds-report</b><br>consensus<br><i>(offchain_reporting[at]1.0.0)</i>"]]
Compute -- Value --> data-feeds-report
unnamed3[/"target<br><i>(write_ethereum-testnet-sepolia[at]1.0.0)</i>"\]
data-feeds-report --> unnamed3
```
Loading

0 comments on commit 1d141c0

Please sign in to comment.