@@ -150,14 +150,14 @@ func TestPlanWorkflow_PartialResolutionFailure(t *testing.T) {
150150
151151 goodSHA := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
152152
153- // Both refs fold into one batched query: a0=good /action resolves,
153+ // Both refs fold into one batched query: a0=old /action redirects and resolves,
154154 // a1=bad/private is null (repo not found).
155155 reg .Register (
156- httpmock .GraphQLForRepo ("good " , "action" ),
156+ httpmock .GraphQLForRepo ("old " , "action" ),
157157 httpmock .JSONResponse (map [string ]any {
158158 "data" : map [string ]any {
159159 "a0" : map [string ]any {
160- "nameWithOwner" : "good /action" ,
160+ "nameWithOwner" : "new /action" ,
161161 "object" : map [string ]any {
162162 "oid" : goodSHA ,
163163 "file" : map [string ]any {"object" : map [string ]any {"text" : "name: Good\n runs:\n using: node20\n " }},
@@ -176,7 +176,7 @@ func TestPlanWorkflow_PartialResolutionFailure(t *testing.T) {
176176 Path : ".github/workflows/test.yml" ,
177177 Findings : []checks.Finding {
178178 {
179- ActionRef : & parserlock.ActionRef {Owner : "good " , Repo : "action" , Ref : "v1" },
179+ ActionRef : & parserlock.ActionRef {Owner : "old " , Repo : "action" , Ref : "v1" },
180180 Category : "unpinned" ,
181181 Severity : checks .SeverityWarning ,
182182 Confidence : checks .ConfidenceHigh ,
@@ -189,7 +189,7 @@ func TestPlanWorkflow_PartialResolutionFailure(t *testing.T) {
189189 },
190190 },
191191 ActionRefs : []parserlock.ActionRef {
192- {Owner : "good " , Repo : "action" , Ref : "v1" },
192+ {Owner : "old " , Repo : "action" , Ref : "v1" },
193193 {Owner : "bad" , Repo : "private" , Ref : "main" },
194194 },
195195 }
@@ -219,12 +219,31 @@ func TestPlanWorkflow_PartialResolutionFailure(t *testing.T) {
219219 assert .Equal (t , "main" , unresolved [0 ].Ref )
220220 assert .Contains (t , unresolved [0 ].Reason , "not found" )
221221
222- // good/action must be pinned (not poisoned by the bad ref).
222+ // The redirected action must be pinned under its canonical NWO, not
223+ // misclassified as unresolved because the sibling failed.
223224 require .Len (t , pinned , 1 , "expected exactly one pinned entry" )
224- assert .Equal (t , "good /action" , pinned [0 ].NWO )
225+ assert .Equal (t , "new /action" , pinned [0 ].NWO )
225226 assert .Equal (t , goodSHA , pinned [0 ].SHA )
226227}
227228
229+ func TestUnresolvedEntriesPreservesRefCase (t * testing.T ) {
230+ resolvedRef := parserlock.ActionRef {Owner : "old" , Repo : "action" , Ref : "Release" }
231+ failedRef := parserlock.ActionRef {Owner : "old" , Repo : "action" , Ref : "release" }
232+ wr := checks.WorkflowReport {Findings : []checks.Finding {
233+ {ActionRef : & resolvedRef , Category : checks .NotPinned },
234+ {ActionRef : & failedRef , Category : checks .NotPinned },
235+ }}
236+
237+ got := unresolvedEntries (wr , []parserlock.ActionRef {resolvedRef , failedRef }, []dep.Dependency {{
238+ NWO : "new/action" ,
239+ Ref : resolvedRef .Ref ,
240+ OriginalRefs : []parserlock.ActionRef {resolvedRef },
241+ }}, assert .AnError )
242+
243+ require .Len (t , got , 1 )
244+ assert .Equal (t , failedRef .Ref , got [0 ].Ref )
245+ }
246+
228247// TestPlanWorkflow_AllResolutionsFail verifies that when ALL refs in a
229248// workflow fail resolution, every finding is marked Unresolved and no
230249// reachability is attempted.
0 commit comments