-
Notifications
You must be signed in to change notification settings - Fork 367
refactor(workflow): co-locate heredoc utils and consolidate any→[]string helpers #26428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,12 @@ | |
| // - validateMountStringFormat() - Parses and validates a "source:dest:mode" mount string | ||
| // - containsTrigger() - Reports whether an 'on:' section includes a named trigger | ||
| // | ||
| // # Type Conversion Helpers (any → []string) | ||
| // | ||
| // - parseStringSliceAny() - Canonical coercion of []string/[]any to []string; skips non-strings | ||
| // - toStringSlice() - Strict variant: returns error on non-string elements; also accepts bare string | ||
| // - extractStringSliceField() - Accepts string/[]string/[]any; skips empty strings; wraps bare string | ||
| // | ||
| // # Design Rationale | ||
| // | ||
| // These helpers consolidate 76+ duplicate validation patterns identified in the | ||
|
|
@@ -189,6 +195,67 @@ func parseStringSliceAny(raw any, log *logger.Logger) []string { | |
| } | ||
| } | ||
|
|
||
| // toStringSlice converts an any value to a []string, supporting []string, []any, and string. | ||
| // Unlike parseStringSliceAny, this function returns an error when a []any element is not a string, | ||
| // and also accepts a bare string value (wrapping it in a single-element slice). | ||
| func toStringSlice(val any) ([]string, error) { | ||
| switch v := val.(type) { | ||
| case []string: | ||
| return v, nil | ||
| case []any: | ||
| result := make([]string, 0, len(v)) | ||
| for _, item := range v { | ||
| s, ok := item.(string) | ||
| if !ok { | ||
| return nil, errors.New("non-string item in list") | ||
| } | ||
| result = append(result, s) | ||
| } | ||
| return result, nil | ||
| case string: | ||
| return []string{v}, nil | ||
| default: | ||
| return nil, fmt.Errorf("unsupported type %T", val) | ||
| } | ||
| } | ||
|
|
||
| // extractStringSliceField extracts a string slice from various input formats. | ||
| // Handles: string, []string, []any (with string elements). | ||
| // Returns nil if the input is empty or invalid. | ||
| func extractStringSliceField(value any, fieldName string) []string { | ||
| switch v := value.(type) { | ||
| case string: | ||
| // Single string | ||
| if v == "" { | ||
| return nil | ||
| } | ||
| validationHelpersLog.Printf("Extracted single %s: %s", fieldName, v) | ||
| return []string{v} | ||
|
Comment on lines
+232
to
+233
|
||
| case []string: | ||
| // Already a string slice | ||
| if len(v) == 0 { | ||
| return nil | ||
| } | ||
| validationHelpersLog.Printf("Extracted %d %s: %v", len(v), fieldName, v) | ||
| return v | ||
| case []any: | ||
| // Array of any - extract strings | ||
| var result []string | ||
| for _, item := range v { | ||
| if str, ok := item.(string); ok && str != "" { | ||
| result = append(result, str) | ||
| } | ||
| } | ||
| if len(result) == 0 { | ||
| return nil | ||
| } | ||
| validationHelpersLog.Printf("Extracted %d %s from array: %v", len(result), fieldName, result) | ||
| return result | ||
| } | ||
| validationHelpersLog.Printf("No valid %s found or unsupported type: %T", fieldName, value) | ||
| return nil | ||
| } | ||
|
|
||
| // validateNoDuplicateIDs checks that all items have unique IDs extracted by idFunc. | ||
| // The onDuplicate callback creates the error to return when a duplicate is found. | ||
| func validateNoDuplicateIDs[T any](items []T, idFunc func(T) string, onDuplicate func(string) error) error { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file-level doc says
extractStringSliceField()“skips empty strings”, but the implementation only skips empty strings forstringand[]anyinputs; for[]stringit returns the slice as-is (so empty-string elements are preserved). Either update the docs to match the actual behavior, or filter empty strings from the[]stringcase as well so the documented behavior is correct.