Skip to content

Commit b602b12

Browse files
authored
fix: validate file input before network calls in jtk and cfl (#86)
jtk auto update: move file read and JSON validation before opts.APIClient() so bad input fails fast without needing network access or config. Same fix applied to auto create in 2cef041. cfl page create/edit: add early file existence check before config loading and API client creation when --file is provided. Add jtk update_test.go with invalid JSON and file-not-found test cases.
1 parent 9d36f1c commit b602b12

4 files changed

Lines changed: 69 additions & 7 deletions

File tree

tools/cfl/internal/cmd/page/create.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ Content format:
9292
}
9393

9494
func runCreate(opts *createOptions) error {
95+
// Validate file exists before making any network calls so we fail
96+
// fast on bad input without needing config or API access.
97+
if opts.file != "" {
98+
if _, err := os.Stat(opts.file); err != nil {
99+
return fmt.Errorf("failed to read file: %w", err)
100+
}
101+
}
102+
95103
cfg, err := opts.Config()
96104
if err != nil {
97105
return err

tools/cfl/internal/cmd/page/edit.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ Content format:
9292
}
9393

9494
func runEdit(opts *editOptions) error {
95+
// Validate file exists before making any network calls so we fail
96+
// fast on bad input without needing config or API access.
97+
if opts.file != "" {
98+
if _, err := os.Stat(opts.file); err != nil {
99+
return fmt.Errorf("failed to read file: %w", err)
100+
}
101+
}
102+
95103
cfg, err := opts.Config()
96104
if err != nil {
97105
return err

tools/jtk/internal/cmd/automation/update.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,22 @@ field mappings and workflow configuration.`,
4949
func runUpdate(opts *root.Options, ruleID, filePath string) error {
5050
v := opts.View()
5151

52-
client, err := opts.APIClient()
53-
if err != nil {
54-
return err
55-
}
56-
57-
// Read the JSON file
52+
// Read and validate file before creating the API client so we fail
53+
// fast on bad input without needing network access.
5854
data, err := os.ReadFile(filePath)
5955
if err != nil {
6056
return fmt.Errorf("failed to read file %s: %w", filePath, err)
6157
}
6258

63-
// Validate it's valid JSON
6459
if !json.Valid(data) {
6560
return fmt.Errorf("file %s does not contain valid JSON", filePath)
6661
}
6762

63+
client, err := opts.APIClient()
64+
if err != nil {
65+
return err
66+
}
67+
6868
// Fetch current rule to show what we're updating
6969
current, err := client.GetAutomationRule(ruleID)
7070
if err != nil {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package automation
2+
3+
import (
4+
"bytes"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
12+
"github.com/open-cli-collective/jira-ticket-cli/internal/cmd/root"
13+
)
14+
15+
func TestRunUpdate(t *testing.T) {
16+
t.Run("invalid JSON file", func(t *testing.T) {
17+
dir := t.TempDir()
18+
filePath := filepath.Join(dir, "bad.json")
19+
err := os.WriteFile(filePath, []byte(`not valid json`), 0644)
20+
require.NoError(t, err)
21+
22+
var stdout, stderr bytes.Buffer
23+
opts := &root.Options{
24+
Output: "table",
25+
Stdout: &stdout,
26+
Stderr: &stderr,
27+
}
28+
29+
err = runUpdate(opts, "12345", filePath)
30+
require.Error(t, err)
31+
assert.Contains(t, err.Error(), "does not contain valid JSON")
32+
})
33+
34+
t.Run("file not found", func(t *testing.T) {
35+
var stdout, stderr bytes.Buffer
36+
opts := &root.Options{
37+
Output: "table",
38+
Stdout: &stdout,
39+
Stderr: &stderr,
40+
}
41+
42+
err := runUpdate(opts, "12345", "/nonexistent/path/rule.json")
43+
require.Error(t, err)
44+
assert.Contains(t, err.Error(), "failed to read file")
45+
})
46+
}

0 commit comments

Comments
 (0)