Skip to content

Commit dd163a0

Browse files
authored
Merge pull request #35 from the-dev-tools/feat/graphql-delta-fix
Feat/graphql delta fix
2 parents 2848ee5 + a63342c commit dd163a0

141 files changed

Lines changed: 16143 additions & 161 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/check.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ jobs:
5252
path: '*/*/dist/go-test.json'
5353
retention-days: 1
5454

55+
cli-integration:
56+
name: CLI Integration Tests
57+
runs-on: ubuntu-latest
58+
needs: check
59+
steps:
60+
- uses: actions/checkout@v4
61+
62+
- name: Setup runner environment
63+
uses: ./.github/actions/setup
64+
65+
- name: Run CLI integration tests
66+
run: pnpm nx run cli:test:integration
67+
5568
go-test-summary:
5669
name: Test
5770
runs-on: ubuntu-latest

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ storybook-static
2828
tmp/
2929
tsconfig.tsbuildinfo
3030
tsp-output
31+
.bench/
32+
.ralph/
33+
.ralphrc
3134

3235
# Coverage files
3336
*.out

apps/cli/cmd/flow.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/the-dev-tools/dev-tools/packages/db/pkg/sqlitemem"
1515
"github.com/the-dev-tools/dev-tools/packages/server/pkg/expression"
1616
"github.com/the-dev-tools/dev-tools/packages/server/pkg/flow/flowbuilder"
17+
gqlresolver "github.com/the-dev-tools/dev-tools/packages/server/pkg/graphql/resolver"
1718
"github.com/the-dev-tools/dev-tools/packages/server/pkg/http/resolver"
1819
"github.com/the-dev-tools/dev-tools/packages/server/pkg/idwrap"
1920
"github.com/the-dev-tools/dev-tools/packages/server/pkg/ioworkspace"
@@ -153,7 +154,7 @@ var yamlflowRunCmd = &cobra.Command{
153154
return fmt.Errorf("failed to convert YAML using v2: %w", err)
154155
}
155156

156-
resolver := resolver.NewStandardResolver(
157+
httpResolver := resolver.NewStandardResolver(
157158
&services.HTTP,
158159
&services.HTTPHeader,
159160
services.HTTPSearchParam,
@@ -163,6 +164,12 @@ var yamlflowRunCmd = &cobra.Command{
163164
services.HTTPAssert,
164165
)
165166

167+
graphqlResolver := gqlresolver.NewStandardResolver(
168+
services.GraphQL.Reader(),
169+
&services.GraphQLHeader,
170+
&services.GraphQLAssert,
171+
)
172+
166173
// Create LLM provider factory for AI nodes
167174
llmFactory := scredential.NewLLMProviderFactory(&services.Credential)
168175

@@ -176,10 +183,14 @@ var yamlflowRunCmd = &cobra.Command{
176183
&services.NodeAI,
177184
&services.NodeAiProvider,
178185
&services.NodeMemory,
186+
&services.NodeGraphQL,
187+
&services.GraphQL,
188+
&services.GraphQLHeader,
179189
&services.Workspace,
180190
&services.Variable,
181191
&services.FlowVariable,
182-
resolver,
192+
httpResolver,
193+
graphqlResolver,
183194
services.Logger,
184195
llmFactory,
185196
)

apps/cli/internal/common/services.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/scredential"
1111
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/senv"
1212
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/sflow"
13+
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/sgraphql"
1314
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/shttp"
1415
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/sworkspace"
1516
)
@@ -40,6 +41,12 @@ type Services struct {
4041
NodeAI sflow.NodeAIService
4142
NodeAiProvider sflow.NodeAiProviderService
4243
NodeMemory sflow.NodeMemoryService
44+
NodeGraphQL sflow.NodeGraphQLService
45+
46+
// GraphQL
47+
GraphQL sgraphql.GraphQLService
48+
GraphQLHeader sgraphql.GraphQLHeaderService
49+
GraphQLAssert sgraphql.GraphQLAssertService
4350

4451
// Credentials
4552
Credential scredential.CredentialService
@@ -87,6 +94,12 @@ func CreateServices(ctx context.Context, db *sql.DB, logger *slog.Logger) (*Serv
8794
NodeAI: sflow.NewNodeAIService(queries),
8895
NodeAiProvider: sflow.NewNodeAiProviderService(queries),
8996
NodeMemory: sflow.NewNodeMemoryService(queries),
97+
NodeGraphQL: sflow.NewNodeGraphQLService(queries),
98+
99+
// GraphQL
100+
GraphQL: sgraphql.New(queries, logger),
101+
GraphQLHeader: sgraphql.NewGraphQLHeaderService(queries),
102+
GraphQLAssert: sgraphql.NewGraphQLAssertService(queries),
90103

91104
// Credentials
92105
Credential: scredential.NewCredentialService(queries),

apps/cli/internal/runner/runner.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/the-dev-tools/dev-tools/apps/cli/internal/reporter"
1414

1515
"github.com/the-dev-tools/dev-tools/packages/server/pkg/flow/node"
16+
"github.com/the-dev-tools/dev-tools/packages/server/pkg/flow/node/ngraphql"
1617
"github.com/the-dev-tools/dev-tools/packages/server/pkg/flow/node/nrequest"
1718
"github.com/the-dev-tools/dev-tools/packages/server/pkg/flow/runner"
1819
"github.com/the-dev-tools/dev-tools/packages/server/pkg/flow/runner/flowlocalrunner"
@@ -251,6 +252,17 @@ func RunFlow(ctx context.Context, flowPtr *mflow.Flow, services RunnerServices,
251252
}()
252253
defer close(requestRespChan)
253254

255+
// Initialize GraphQL response channel
256+
gqlRespChan := make(chan ngraphql.NodeGraphQLSideResp, requestBufferSize)
257+
go func() {
258+
for resp := range gqlRespChan {
259+
if resp.Done != nil {
260+
close(resp.Done)
261+
}
262+
}
263+
}()
264+
defer close(gqlRespChan)
265+
254266
// Build flow node map using flowbuilder
255267
flowNodeMap, startNodeID, err := services.Builder.BuildNodes(
256268
ctx,
@@ -259,6 +271,7 @@ func RunFlow(ctx context.Context, flowPtr *mflow.Flow, services RunnerServices,
259271
nodeTimeout,
260272
httpClient,
261273
requestRespChan,
274+
gqlRespChan,
262275
services.JSClient,
263276
)
264277
if err != nil {

apps/cli/internal/runner/runner_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,14 @@ func newFlowTestFixture(t *testing.T) *flowTestFixture {
113113
nil, // NodeAIService - not needed for CLI tests
114114
nil, // NodeAiProviderService - not needed for CLI tests
115115
nil, // NodeMemoryService - not needed for CLI tests
116+
nil, // NodeGraphQLService - not needed for CLI tests
117+
nil, // GraphQLService - not needed for CLI tests
118+
nil, // GraphQLHeaderService - not needed for CLI tests
116119
&workspaceService,
117120
&varService,
118121
&flowVariableService,
119122
res,
123+
nil, // GraphQLResolver - not needed for CLI tests
120124
logger,
121125
nil, // LLMProviderFactory - not needed for CLI tests
122126
)

apps/cli/project.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,21 @@
6060
},
6161
"dependsOn": ["copy-worker"]
6262
},
63+
"test:integration": {
64+
"executor": "nx:run-commands",
65+
"options": {
66+
"cwd": "{projectRoot}",
67+
"parallel": false,
68+
"commands": [
69+
"go build -tags cli -o dist/devtools-cli-test .",
70+
"RUN_CLI_INTEGRATION=true DEVTOOLS_CLI_BIN=$(pwd)/dist/devtools-cli-test go test -tags cli_integration ./test/yamlflow/ -v -timeout 120s"
71+
],
72+
"env": {
73+
"DEVTOOLS_MODE": "cli"
74+
}
75+
},
76+
"dependsOn": ["copy-worker"]
77+
},
6378
"lint": {
6479
"executor": "nx:run-commands",
6580
"options": {

apps/cli/test/yamlflow/example_run_yamlflow.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ flows:
8383
depends_on: RequestB
8484
- if:
8585
name: CheckPostCount
86-
condition: RequestB.response.body.length > 10
86+
condition: len(RequestB.response.body) > 10
8787
then: LogManyPosts
8888
else: LogFewPosts
8989
depends_on: RequestB
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
workspace_name: GraphQL Run Example
2+
run:
3+
- flow: QueryAndLookup
4+
graphql_requests:
5+
- name: ListCountries
6+
url: https://countries.trevorblades.com/graphql
7+
query: |-
8+
query {
9+
countries {
10+
code
11+
name
12+
capital
13+
}
14+
}
15+
variables: '{}'
16+
assertions:
17+
- response.status == 200
18+
- response.body.data.countries != nil
19+
- name: GetCountry
20+
url: https://countries.trevorblades.com/graphql
21+
query: |-
22+
query GetCountry($code: ID!) {
23+
country(code: $code) {
24+
name
25+
capital
26+
currency
27+
languages {
28+
name
29+
}
30+
}
31+
}
32+
variables: '{}'
33+
assertions:
34+
- response.status == 200
35+
flows:
36+
- name: QueryAndLookup
37+
steps:
38+
- manual_start:
39+
name: Start
40+
position_x: 0
41+
position_y: 0
42+
- graphql:
43+
name: ListCountries
44+
depends_on: Start
45+
position_x: 300
46+
position_y: 0
47+
use_request: ListCountries
48+
- js:
49+
name: PickCountry
50+
depends_on: ListCountries
51+
position_x: 600
52+
position_y: 0
53+
code: |-
54+
export default function(ctx) {
55+
const countries = ctx.ListCountries.response.body.data.countries;
56+
const country = countries[0];
57+
return { code: country.code, name: country.name };
58+
}
59+
- graphql:
60+
name: GetCountry
61+
depends_on: PickCountry
62+
position_x: 900
63+
position_y: 0
64+
use_request: GetCountry
65+
variables: '{"code": "{{PickCountry.code}}"}'
66+
assertions:
67+
- response.body.data.country.name != nil
68+
environments:
69+
- name: default
70+
variables: {}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//go:build cli_integration
2+
3+
package yamlflow_test
4+
5+
import (
6+
"os"
7+
"os/exec"
8+
"path/filepath"
9+
"testing"
10+
)
11+
12+
// TestMain builds the CLI binary once for all tests in this package.
13+
// If DEVTOOLS_CLI_BIN is already set, it skips the build step.
14+
func TestMain(m *testing.M) {
15+
if os.Getenv("RUN_CLI_INTEGRATION") != "true" {
16+
os.Exit(0)
17+
}
18+
19+
binPath := os.Getenv("DEVTOOLS_CLI_BIN")
20+
cleanUp := false
21+
if binPath == "" {
22+
// Build CLI binary with cli tag
23+
binPath = filepath.Join(os.TempDir(), "devtools-cli-test")
24+
cmd := exec.Command("go", "build", "-tags", "cli", "-o", binPath, "../../.")
25+
cmd.Stdout = os.Stdout
26+
cmd.Stderr = os.Stderr
27+
if err := cmd.Run(); err != nil {
28+
panic("failed to build CLI binary: " + err.Error())
29+
}
30+
os.Setenv("DEVTOOLS_CLI_BIN", binPath)
31+
cleanUp = true
32+
}
33+
34+
code := m.Run()
35+
36+
if cleanUp {
37+
os.Remove(binPath)
38+
}
39+
os.Exit(code)
40+
}
41+
42+
func runCLI(t *testing.T, yamlFile string) {
43+
t.Helper()
44+
45+
binPath := os.Getenv("DEVTOOLS_CLI_BIN")
46+
if binPath == "" {
47+
t.Fatal("DEVTOOLS_CLI_BIN not set")
48+
}
49+
50+
cmd := exec.Command(binPath, "flow", "run", yamlFile)
51+
cmd.Env = append(os.Environ(), "DEVTOOLS_MODE=cli")
52+
out, err := cmd.CombinedOutput()
53+
if err != nil {
54+
t.Fatalf("CLI failed for %s:\n%s", filepath.Base(yamlFile), string(out))
55+
}
56+
57+
t.Logf("CLI output for %s:\n%s", filepath.Base(yamlFile), string(out))
58+
}
59+
60+
func TestYAMLFlow_SimpleRun(t *testing.T) {
61+
runCLI(t, "simple_run_example.yaml")
62+
}
63+
64+
func TestYAMLFlow_MultiFlowRun(t *testing.T) {
65+
runCLI(t, "multi_flow_run_example.yaml")
66+
}
67+
68+
func TestYAMLFlow_ExampleRun(t *testing.T) {
69+
runCLI(t, "example_run_yamlflow.yaml")
70+
}
71+
72+
func TestYAMLFlow_TestRunField(t *testing.T) {
73+
runCLI(t, "test_run_field.yaml")
74+
}
75+
76+
func TestYAMLFlow_GraphQLRun(t *testing.T) {
77+
runCLI(t, "graphql_run_example.yaml")
78+
}

0 commit comments

Comments
 (0)