Skip to content

Commit 4b489ad

Browse files
authored
Add validation for workflow intent minimum content requirements (#7852)
1 parent 24d3960 commit 4b489ad

File tree

3 files changed

+184
-1
lines changed

3 files changed

+184
-1
lines changed

pkg/cli/interactive.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ func (b *InteractiveWorkflowBuilder) promptForConfiguration() error {
213213
huh.NewGroup(
214214
huh.NewText().
215215
Title("Describe what this workflow should do:").
216-
Value(&b.Intent),
216+
Value(&b.Intent).
217+
Validate(ValidateWorkflowIntent),
217218
).
218219
Title("Instructions").
219220
Description("Describe what you want this workflow to accomplish"),

pkg/cli/validators.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cli
33
import (
44
"errors"
55
"regexp"
6+
"strings"
67
)
78

89
// workflowNameRegex validates workflow names contain only alphanumeric characters, hyphens, and underscores
@@ -19,3 +20,17 @@ func ValidateWorkflowName(s string) error {
1920
}
2021
return nil
2122
}
23+
24+
// ValidateWorkflowIntent checks if the provided workflow intent is valid.
25+
// It ensures the intent has meaningful content with at least 20 characters
26+
// and is not just whitespace.
27+
func ValidateWorkflowIntent(s string) error {
28+
trimmed := strings.TrimSpace(s)
29+
if len(trimmed) == 0 {
30+
return errors.New("workflow instructions cannot be empty")
31+
}
32+
if len(trimmed) < 20 {
33+
return errors.New("please provide at least 20 characters of instructions")
34+
}
35+
return nil
36+
}

pkg/cli/validators_test.go

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,170 @@ func TestValidateWorkflowName_EdgeCases(t *testing.T) {
245245
})
246246
}
247247
}
248+
249+
func TestValidateWorkflowIntent(t *testing.T) {
250+
tests := []struct {
251+
name string
252+
input string
253+
expectError bool
254+
errorMsg string
255+
}{
256+
{
257+
name: "valid minimal intent",
258+
input: "Create a workflow to triage issues",
259+
expectError: false,
260+
},
261+
{
262+
name: "valid long intent",
263+
input: "Create a comprehensive workflow that automatically triages GitHub issues by analyzing their content, assigning appropriate labels, and notifying relevant team members",
264+
expectError: false,
265+
},
266+
{
267+
name: "valid exactly 20 characters",
268+
input: "12345678901234567890",
269+
expectError: false,
270+
},
271+
{
272+
name: "valid with newlines",
273+
input: "Create a workflow to\ntriage issues automatically",
274+
expectError: false,
275+
},
276+
{
277+
name: "valid with leading/trailing whitespace",
278+
input: " Create a workflow to triage issues ",
279+
expectError: false,
280+
},
281+
{
282+
name: "empty string",
283+
input: "",
284+
expectError: true,
285+
errorMsg: "workflow instructions cannot be empty",
286+
},
287+
{
288+
name: "only whitespace",
289+
input: " \t\n ",
290+
expectError: true,
291+
errorMsg: "workflow instructions cannot be empty",
292+
},
293+
{
294+
name: "only spaces",
295+
input: " ",
296+
expectError: true,
297+
errorMsg: "workflow instructions cannot be empty",
298+
},
299+
{
300+
name: "only tabs",
301+
input: "\t\t\t",
302+
expectError: true,
303+
errorMsg: "workflow instructions cannot be empty",
304+
},
305+
{
306+
name: "only newlines",
307+
input: "\n\n\n",
308+
expectError: true,
309+
errorMsg: "workflow instructions cannot be empty",
310+
},
311+
{
312+
name: "too short - single character",
313+
input: "a",
314+
expectError: true,
315+
errorMsg: "please provide at least 20 characters of instructions",
316+
},
317+
{
318+
name: "too short - 5 characters",
319+
input: "hello",
320+
expectError: true,
321+
errorMsg: "please provide at least 20 characters of instructions",
322+
},
323+
{
324+
name: "too short - 19 characters",
325+
input: "1234567890123456789",
326+
expectError: true,
327+
errorMsg: "please provide at least 20 characters of instructions",
328+
},
329+
{
330+
name: "too short with whitespace padding",
331+
input: " test ",
332+
expectError: true,
333+
errorMsg: "please provide at least 20 characters of instructions",
334+
},
335+
{
336+
name: "19 chars after trim",
337+
input: " 1234567890123456789 ",
338+
expectError: true,
339+
errorMsg: "please provide at least 20 characters of instructions",
340+
},
341+
}
342+
343+
for _, tt := range tests {
344+
t.Run(tt.name, func(t *testing.T) {
345+
err := ValidateWorkflowIntent(tt.input)
346+
347+
if tt.expectError {
348+
if err == nil {
349+
t.Errorf("ValidateWorkflowIntent(%q) expected error but got nil", tt.input)
350+
return
351+
}
352+
if !strings.Contains(err.Error(), tt.errorMsg) {
353+
t.Errorf("ValidateWorkflowIntent(%q) error = %q, want error containing %q", tt.input, err.Error(), tt.errorMsg)
354+
}
355+
} else {
356+
if err != nil {
357+
t.Errorf("ValidateWorkflowIntent(%q) unexpected error: %v", tt.input, err)
358+
}
359+
}
360+
})
361+
}
362+
}
363+
364+
func TestValidateWorkflowIntent_EdgeCases(t *testing.T) {
365+
tests := []struct {
366+
name string
367+
input string
368+
expectError bool
369+
}{
370+
{
371+
name: "exactly 20 characters with spaces",
372+
input: "a b c d e f g h i j k",
373+
expectError: false,
374+
},
375+
{
376+
name: "unicode characters",
377+
input: "Create workflow with émojis 🎉🎊",
378+
expectError: false,
379+
},
380+
{
381+
name: "special characters",
382+
input: "Create workflow: @user, #123, $var!",
383+
expectError: false,
384+
},
385+
{
386+
name: "very long intent",
387+
input: strings.Repeat("a", 1000),
388+
expectError: false,
389+
},
390+
{
391+
name: "mixed whitespace",
392+
input: " \t\n Create workflow for automation \t\n ",
393+
expectError: false,
394+
},
395+
{
396+
name: "only punctuation but >= 20 chars",
397+
input: "!@#$%^&*()_+-={}[]|;",
398+
expectError: false,
399+
},
400+
}
401+
402+
for _, tt := range tests {
403+
t.Run(tt.name, func(t *testing.T) {
404+
err := ValidateWorkflowIntent(tt.input)
405+
406+
if tt.expectError && err == nil {
407+
t.Errorf("ValidateWorkflowIntent(%q) expected error but got nil", tt.input)
408+
}
409+
if !tt.expectError && err != nil {
410+
t.Errorf("ValidateWorkflowIntent(%q) unexpected error: %v", tt.input, err)
411+
}
412+
})
413+
}
414+
}

0 commit comments

Comments
 (0)