Skip to content

Commit 8aa0078

Browse files
authored
fix(github): trim whitespace from action references (#4)
Fixes issue where action references with trailing newlines or other whitespace characters would fail with URL parsing errors. The ParseActionRef function now trims all leading and trailing whitespace (spaces, tabs, newlines) before parsing the action reference. Added comprehensive unit tests covering: - Trailing newlines - Leading and trailing whitespace - Tabs and newlines - Edge cases (empty strings, whitespace-only strings)
1 parent 47a4232 commit 8aa0078

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

internal/github/actions.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type ActionRef struct {
3434
// - "actions/checkout@v5" -> {Owner: "actions", Repo: "checkout", Version: "v5"}
3535
// - "actions/setup-node@v4" -> {Owner: "actions", Repo: "setup-node", Version: "v4"}
3636
func ParseActionRef(ref string) (*ActionRef, error) {
37+
// Trim whitespace (including newlines, spaces, tabs)
38+
ref = strings.TrimSpace(ref)
39+
3740
if ref == "" {
3841
return nil, fmt.Errorf("action reference cannot be empty")
3942
}

internal/github/actions_test.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package github
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestParseActionRef(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
input string
11+
wantOwner string
12+
wantRepo string
13+
wantVersion string
14+
wantErr bool
15+
}{
16+
{
17+
name: "valid action reference",
18+
input: "actions/checkout@v5",
19+
wantOwner: "actions",
20+
wantRepo: "checkout",
21+
wantVersion: "v5",
22+
wantErr: false,
23+
},
24+
{
25+
name: "valid action with trailing newline",
26+
input: "actions/checkout@v5\n",
27+
wantOwner: "actions",
28+
wantRepo: "checkout",
29+
wantVersion: "v5",
30+
wantErr: false,
31+
},
32+
{
33+
name: "valid action with leading and trailing whitespace",
34+
input: " actions/checkout@v5 ",
35+
wantOwner: "actions",
36+
wantRepo: "checkout",
37+
wantVersion: "v5",
38+
wantErr: false,
39+
},
40+
{
41+
name: "valid action with tabs and newlines",
42+
input: "\t\nactions/checkout@v5\n\t",
43+
wantOwner: "actions",
44+
wantRepo: "checkout",
45+
wantVersion: "v5",
46+
wantErr: false,
47+
},
48+
{
49+
name: "complex action reference with whitespace",
50+
input: "kula-app/wait-for-services-action@v1\n",
51+
wantOwner: "kula-app",
52+
wantRepo: "wait-for-services-action",
53+
wantVersion: "v1",
54+
wantErr: false,
55+
},
56+
{
57+
name: "empty string",
58+
input: "",
59+
wantErr: true,
60+
},
61+
{
62+
name: "only whitespace",
63+
input: " \n\t ",
64+
wantErr: true,
65+
},
66+
{
67+
name: "missing version",
68+
input: "actions/checkout",
69+
wantErr: true,
70+
},
71+
{
72+
name: "missing repo",
73+
input: "actions@v5",
74+
wantErr: true,
75+
},
76+
{
77+
name: "invalid format - too many slashes",
78+
input: "actions/github/checkout@v5",
79+
wantErr: true,
80+
},
81+
}
82+
83+
for _, tt := range tests {
84+
t.Run(tt.name, func(t *testing.T) {
85+
got, err := ParseActionRef(tt.input)
86+
87+
if tt.wantErr {
88+
if err == nil {
89+
t.Errorf("ParseActionRef() expected error but got none")
90+
}
91+
return
92+
}
93+
94+
if err != nil {
95+
t.Errorf("ParseActionRef() unexpected error: %v", err)
96+
return
97+
}
98+
99+
if got.Owner != tt.wantOwner {
100+
t.Errorf("ParseActionRef() Owner = %v, want %v", got.Owner, tt.wantOwner)
101+
}
102+
if got.Repo != tt.wantRepo {
103+
t.Errorf("ParseActionRef() Repo = %v, want %v", got.Repo, tt.wantRepo)
104+
}
105+
if got.Version != tt.wantVersion {
106+
t.Errorf("ParseActionRef() Version = %v, want %v", got.Version, tt.wantVersion)
107+
}
108+
})
109+
}
110+
}

0 commit comments

Comments
 (0)