Skip to content

Commit 5c4faa8

Browse files
committed
fix(policies): split comma-separated values on each merged input line
When a policy input declared as a comma-separated value in a workflow contract was merged with a runtime value supplied via --policy-input-from-file, getInputArguments split the merged string on newlines first and returned the multi-line slice as-is, skipping the per-value comma splitting. This collapsed the contract's comma-joined segment into a single literal glob containing commas that matched nothing. Normalize consistently by splitting each line on commas as well, so a comma-separated segment is always expanded into separate values regardless of whether a runtime value was appended. Assisted-by: Claude Code Signed-off-by: Javier Rodriguez <javier@chainloop.dev> Chainloop-Trace-Sessions: 20709f88-f555-488c-a8ae-e2d60903aff5, 7c9eb197-bbea-464f-9444-cd17ac09039c
1 parent a7c7890 commit 5c4faa8

2 files changed

Lines changed: 37 additions & 13 deletions

File tree

pkg/policies/policies.go

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -773,22 +773,19 @@ func getInputArguments(inputs map[string]string) map[string]any {
773773
args := make(map[string]any)
774774

775775
for k, v := range inputs {
776-
// scan for multiple values
776+
// Normalize consistently: split on newlines first (multi-value inputs,
777+
// e.g. a comma-separated contract value merged with runtime values by
778+
// mergeRuntimeInputs), then split each line on commas. Doing both means a
779+
// comma-separated segment is always expanded into separate values,
780+
// regardless of whether it arrived as a single line or as one of several
781+
// merged lines.
777782
lines := strings.Split(strings.TrimRight(v, "\n"), "\n")
778-
value := getValue(lines)
779-
780-
if value == nil {
781-
continue
782-
}
783-
s, ok := value.(string)
784-
if !ok {
785-
// case for multivalued argument
786-
args[k] = value
783+
values := make([]string, 0, len(lines))
784+
for _, line := range lines {
785+
values = append(values, splitArgs(line)...)
787786
}
788787

789-
// Single string, let's check for CSV and escaped commas `\,`
790-
lines = splitArgs(s)
791-
value = getValue(lines)
788+
value := getValue(values)
792789
if value == nil {
793790
continue
794791
}

pkg/policies/policies_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,33 @@ func (s *testSuite) TestGetInputArguments() {
799799
inputs: map[string]string{"foo": "\n\n\nbar1\nbar2\n\nbar3\n"},
800800
expected: map[string]any{"foo": []string{"bar1", "bar2", "bar3"}},
801801
},
802+
{
803+
// A comma-separated contract value merged with runtime values (which
804+
// mergeRuntimeInputs joins with newlines) must still split the
805+
// comma-joined line into separate values instead of collapsing it into
806+
// a single literal glob containing commas.
807+
name: "multiline input where a line is comma-separated",
808+
inputs: map[string]string{"foo": "**/vendor/**,**/redist/**\nC:/a\nC:/b"},
809+
expected: map[string]any{"foo": []string{"**/vendor/**", "**/redist/**", "C:/a", "C:/b"}},
810+
},
811+
{
812+
name: "multiline input where several lines are comma-separated",
813+
inputs: map[string]string{"foo": "a,b\nc,d\ne"},
814+
expected: map[string]any{"foo": []string{"a", "b", "c", "d", "e"}},
815+
},
816+
{
817+
name: "multiline input with escaped comma on a line",
818+
inputs: map[string]string{"foo": "a\\,b,c\nd"},
819+
expected: map[string]any{"foo": []string{"a,b", "c", "d"}},
820+
},
821+
{
822+
// A multiline input that reduces to a single non-empty value after
823+
// blank-line filtering must return a plain string, not a one-element
824+
// slice, so the two-stage split never over-wraps single values.
825+
name: "multiline input collapsing to a single value",
826+
inputs: map[string]string{"foo": "\nbar\n"},
827+
expected: map[string]any{"foo": "bar"},
828+
},
802829
{
803830
name: "no input",
804831
inputs: nil,

0 commit comments

Comments
 (0)