Skip to content

Commit c120f90

Browse files
authored
Merge pull request #62 from grafana/use-input-from-stdin
Use input from stdin
2 parents eaaf865 + 7719e36 commit c120f90

File tree

4 files changed

+137
-53
lines changed

4 files changed

+137
-53
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ Analyze the k6 test script and extract the extensions that the script depends on
136136

137137
Dependencies can come from three sources: k6 test script, manifest file, `K6_DEPENDENCIES` environment variable. Instead of these three sources, a k6 archive can also be specified, which can contain all three sources (currently two actually, because the manifest file is not yet included in the k6 archive).
138138

139+
The name of k6 test script or archive can be specified as the positional argument in the command invocation. Alternatively, the content can be provided in the stdin. If stdin is used, the input format ('js' for script of or 'tar' for archive) must be specified using the `--input` parameter.
140+
139141
Primarily, the k6 test script is the source of dependencies. The test script and the local and remote JavaScript modules it uses are recursively analyzed. The extensions used by the test script are collected. In addition to the require function and import expression, the `"use k6 ..."` directive can be used to specify additional extension dependencies. If necessary, the `"use k6 ..."` directive can also be used to specify version constraints.
140142

141143
"use k6 > 0.54";
@@ -189,6 +191,7 @@ k6deps [flags] [script-file]
189191
--ignore-manifest disable package.json detection and processing
190192
--ignore-script disable script processing
191193
--ingnore-env ignore K6_DEPENDENCIES environment variable processing
194+
-i, --input string input format ('js' or 'tar' for archives)
192195
--manifest string manifest file to analyze (default 'package.json' nearest to script-file)
193196
-o, --output string write output to file (default stdout)
194197
```

cmd/cmd.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package cmd
33

44
import (
5+
"bytes"
56
_ "embed"
67
"encoding/json"
78
"fmt"
@@ -36,6 +37,7 @@ const (
3637

3738
type options struct {
3839
k6deps.Options
40+
input string
3941
format format
4042
output string
4143
}
@@ -69,11 +71,13 @@ func New() *cobra.Command {
6971
"ignore "+k6deps.EnvDependencies+" environment variable processing")
7072
flags.BoolVar(&opts.Manifest.Ignore, "ignore-manifest", false, "disable package.json detection and processing")
7173
flags.BoolVar(&opts.Script.Ignore, "ignore-script", false, "disable script processing")
72-
74+
flags.StringVarP(&opts.input, "input", "i", "", "input format ('js' or 'tar' for archives)")
7375
return cmd
7476
}
7577

7678
func deps(opts *options, args []string) error {
79+
var ignoreStdin bool
80+
7781
if len(args) > 0 {
7882
filename := args[0]
7983
switch filepath.Ext(filename) {
@@ -84,6 +88,23 @@ func deps(opts *options, args []string) error {
8488
default:
8589
return fmt.Errorf("unsupported file extension: %s", filepath.Ext(filename))
8690
}
91+
ignoreStdin = true
92+
}
93+
94+
if opts.input != "" && !ignoreStdin {
95+
buffer := &bytes.Buffer{}
96+
buffer.ReadFrom(os.Stdin) //nolint:errcheck,forbidigo,gosec
97+
98+
switch opts.input {
99+
case "js":
100+
opts.Script.Name = "stdin"
101+
opts.Script.Contents = buffer.Bytes()
102+
case "tar":
103+
opts.Archive.Name = "stdin"
104+
opts.Archive.Contents = buffer.Bytes()
105+
default:
106+
return fmt.Errorf("unsupported input format: %s", opts.input)
107+
}
87108
}
88109

89110
var out io.Writer

cmd/cmd_test.go

+110-52
Original file line numberDiff line numberDiff line change
@@ -10,63 +10,121 @@ import (
1010
)
1111

1212
//nolint:forbidigo
13-
func Test_New(t *testing.T) {
13+
func Test_Root(t *testing.T) {
1414
t.Parallel()
1515

16-
root := cmd.New()
17-
require.Equal(t, "k6deps [flags] [script-file]", root.Use)
16+
t.Run("New", func(t *testing.T) {
17+
t.Parallel()
1818

19-
dir := t.TempDir()
19+
root := cmd.New()
20+
require.Equal(t, "k6deps [flags] [script-file]", root.Use)
21+
})
2022

2123
scriptfile := filepath.Join("testdata", "script.js")
2224
archive := filepath.Join("testdata", "archive.tar")
2325

24-
out := filepath.Clean(filepath.Join(dir, "output"))
25-
26-
root = cmd.New()
27-
root.SetArgs([]string{"--ingnore-env", "--ignore-manifest", "-o", out, scriptfile})
28-
err := root.Execute()
29-
require.NoError(t, err)
30-
31-
contents, err := os.ReadFile(out)
32-
require.NoError(t, err)
33-
require.Equal(t, `{"k6/x/faker":">v0.3.0","xk6-top":"*"}`+"\n", string(contents))
34-
35-
root = cmd.New()
36-
root.SetArgs([]string{"--ingnore-env", "--ignore-manifest", "-o", out, archive})
37-
err = root.Execute()
38-
require.NoError(t, err)
39-
40-
contents, err = os.ReadFile(out)
41-
require.NoError(t, err)
42-
require.Equal(t, `{"k6":">0.54","k6/x/faker":">0.4.0","k6/x/sql":">=1.0.1","k6/x/sql/driver/ramsql":"*"}`+"\n", string(contents))
43-
44-
root = cmd.New()
45-
root.SetArgs([]string{"--ingnore-env", "--ignore-manifest", "--format", "json", "-o", out, scriptfile})
46-
err = root.Execute()
47-
require.NoError(t, err)
48-
49-
contents, err = os.ReadFile(out)
50-
require.NoError(t, err)
51-
require.Equal(t, `{"k6/x/faker":">v0.3.0","xk6-top":"*"}`+"\n", string(contents))
52-
53-
root = cmd.New()
54-
root.SetArgs([]string{"--ingnore-env", "--ignore-manifest", "--format", "text", "-o", out, scriptfile})
55-
err = root.Execute()
56-
require.NoError(t, err)
57-
58-
contents, err = os.ReadFile(out)
59-
require.NoError(t, err)
60-
require.Equal(t, `k6/x/faker>v0.3.0;xk6-top*`+"\n", string(contents))
61-
62-
root = cmd.New()
63-
root.SetArgs([]string{"--ingnore-env", "--ignore-manifest", "--format", "js", "-o", out, scriptfile})
64-
err = root.Execute()
65-
require.NoError(t, err)
66-
67-
contents, err = os.ReadFile(out)
68-
require.NoError(t, err)
69-
require.Equal(t, `"use k6 with k6/x/faker>v0.3.0";
70-
"use k6 with xk6-top*";
71-
`, string(contents))
26+
testCases := []struct {
27+
name string
28+
args []string
29+
source string
30+
expected string
31+
}{
32+
{
33+
name: "script default format",
34+
args: []string{"--ingnore-env", "--ignore-manifest"},
35+
source: scriptfile,
36+
expected: `{"k6/x/faker":">v0.3.0","xk6-top":"*"}` + "\n",
37+
},
38+
{
39+
name: "script json format",
40+
args: []string{"--ingnore-env", "--ignore-manifest", "--format", "json"},
41+
source: scriptfile,
42+
expected: `{"k6/x/faker":">v0.3.0","xk6-top":"*"}` + "\n",
43+
},
44+
{
45+
name: "script text format",
46+
args: []string{"--ingnore-env", "--ignore-manifest", "--format", "text"},
47+
source: scriptfile,
48+
expected: `k6/x/faker>v0.3.0;xk6-top*` + "\n",
49+
},
50+
{
51+
name: "script js format",
52+
args: []string{"--ingnore-env", "--ignore-manifest", "--format", "js"},
53+
source: scriptfile,
54+
expected: `"use k6 with k6/x/faker>v0.3.0";` + "\n" + `"use k6 with xk6-top*";` + "\n",
55+
},
56+
{
57+
name: "archive",
58+
args: []string{"--ingnore-env", "--ignore-manifest"},
59+
source: archive,
60+
expected: `{"k6":">0.54","k6/x/faker":">0.4.0","k6/x/sql":">=1.0.1","k6/x/sql/driver/ramsql":"*"}` + "\n",
61+
},
62+
}
63+
64+
for _, tc := range testCases {
65+
t.Run(tc.name, func(t *testing.T) {
66+
t.Parallel()
67+
out := filepath.Clean(filepath.Join(t.TempDir(), "output"))
68+
69+
root := cmd.New()
70+
args := tc.args
71+
args = append(args, "-o", out, tc.source)
72+
root.SetArgs(args)
73+
err := root.Execute()
74+
require.NoError(t, err)
75+
76+
contents, err := os.ReadFile(out)
77+
require.NoError(t, err)
78+
require.Equal(t, tc.expected, string(contents))
79+
})
80+
}
81+
82+
t.Run("using input", func(t *testing.T) {
83+
t.Parallel()
84+
85+
testCases := []struct {
86+
name string
87+
source string
88+
input string
89+
expected string
90+
}{
91+
{
92+
name: "script",
93+
input: "js",
94+
source: scriptfile,
95+
expected: `{"k6/x/faker":">v0.3.0","xk6-top":"*"}` + "\n",
96+
},
97+
{
98+
name: "archive",
99+
input: "tar",
100+
source: archive,
101+
expected: `{"k6":">0.54","k6/x/faker":">0.4.0","k6/x/sql":">=1.0.1","k6/x/sql/driver/ramsql":"*"}` + "\n",
102+
},
103+
}
104+
105+
// the following tests cannot be executed in parallel because they modify the stdin
106+
for _, tc := range testCases {
107+
t.Run(tc.name, func(t *testing.T) {
108+
var err error
109+
stdin := os.Stdin
110+
t.Cleanup(func() { os.Stdin = stdin })
111+
112+
out := filepath.Clean(filepath.Join(t.TempDir(), "output"))
113+
114+
root := cmd.New()
115+
os.Stdin, err = os.Open(tc.source)
116+
if err != nil {
117+
t.Fatal(err)
118+
}
119+
root.SetArgs([]string{"--ingnore-env", "--ignore-manifest", "--input", tc.input, "--format", "json", "-o", out})
120+
err = root.Execute()
121+
122+
require.NoError(t, err)
123+
124+
contents, err := os.ReadFile(out)
125+
require.NoError(t, err)
126+
require.Equal(t, tc.expected, string(contents))
127+
})
128+
}
129+
})
72130
}

cmd/help.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Analyze the k6 test script and extract the extensions that the script depends on
44

55
Dependencies can come from three sources: k6 test script, manifest file, `K6_DEPENDENCIES` environment variable. Instead of these three sources, a k6 archive can also be specified, which can contain all three sources (currently two actually, because the manifest file is not yet included in the k6 archive).
66

7+
The name of k6 test script or archive can be specified as the positional argument in the command invocation. Alternatively, the content can be provided in the stdin. If stdin is used, the input format ('js' for script of or 'tar' for archive) must be specified using the `--input` parameter.
8+
79
Primarily, the k6 test script is the source of dependencies. The test script and the local and remote JavaScript modules it uses are recursively analyzed. The extensions used by the test script are collected. In addition to the require function and import expression, the `"use k6 ..."` directive can be used to specify additional extension dependencies. If necessary, the `"use k6 ..."` directive can also be used to specify version constraints.
810

911
"use k6 > 0.54";

0 commit comments

Comments
 (0)