@@ -584,3 +584,74 @@ jobs:
584584 assert .Equal (t , 2 , countGraphQL (ct ), "resolve + parity: %v" , ct .urls )
585585 assert .Contains (t , readTempLockfilePins (t ), "actions/checkout@v4.2.1" )
586586}
587+
588+ // useDefaultTransport routes anonymous REST calls, which use
589+ // http.DefaultTransport, through rt for the rest of the test.
590+ func useDefaultTransport (t * testing.T , rt http.RoundTripper ) {
591+ t .Helper ()
592+ orig := http .DefaultTransport
593+ http .DefaultTransport = rt
594+ t .Cleanup (func () { http .DefaultTransport = orig })
595+ }
596+
597+ // TestParity_DependabotProxyInconclusiveAborts: under the Dependabot proxy
598+ // a rate limit or server error on a recorded pin aborts with exit 2 so
599+ // Dependabot retries, instead of passing on a warning. Outside the proxy
600+ // the same failure stays a warning.
601+ func TestParity_DependabotProxyInconclusiveAborts (t * testing.T ) {
602+ for name , tc := range map [string ]struct {
603+ resp httpmock.Responder
604+ status string
605+ }{
606+ "rate-limited 403" : {httpmock .StatusResponseWithHeaders (http .StatusForbidden , map [string ]string {"X-RateLimit-Remaining" : "0" }), "HTTP 403" },
607+ "503" : {httpmock .StatusResponse (http .StatusServiceUnavailable ), "HTTP 503" },
608+ } {
609+ t .Run (name , func (t * testing.T ) {
610+ for _ , args := range [][]string {nil , {"--verify" }} {
611+ t .Setenv ("GH_ACTIONS_LOCK_DEPENDABOT_PROXY" , "1" )
612+ reg := & httpmock.Registry {}
613+ reg .Register (httpmock .REST ("GET" , `^/repos/actions/checkout$` ), tc .resp )
614+ useDefaultTransport (t , reg )
615+ path := writeTempWorkflow (t , `
616+ name: ci
617+ on: push
618+ jobs:
619+ test:
620+ runs-on: ubuntu-latest
621+ steps:
622+ - uses: actions/checkout@v4.2.1
623+ ` , "actions/checkout@v4.2.1=sha1-" + parityTestSHA )
624+ lockBefore := readTempLockfilePins (t )
625+ wfBefore , err := os .ReadFile (path )
626+ require .NoError (t , err )
627+
628+ _ , stderr , err := runCommandWithHTTP (t , reg , append (args , path )... )
629+ require .Error (t , err , stderr )
630+ assert .NotErrorIs (t , err , errSilent , "a tool failure exits 2" )
631+ assert .Contains (t , err .Error (), tc .status )
632+ assert .Contains (t , err .Error (), "actions/checkout" )
633+ assert .Equal (t , lockBefore , readTempLockfilePins (t ))
634+ wfAfter , err := os .ReadFile (path )
635+ require .NoError (t , err )
636+ assert .Equal (t , string (wfBefore ), string (wfAfter ))
637+ }
638+ })
639+ }
640+ }
641+
642+ func TestParity_InconclusiveWarnsWithoutProxy (t * testing.T ) {
643+ reg := & httpmock.Registry {}
644+ path := writeTempWorkflow (t , `
645+ name: ci
646+ on: push
647+ jobs:
648+ test:
649+ runs-on: ubuntu-latest
650+ steps:
651+ - uses: actions/checkout@v4.2.1
652+ ` , "actions/checkout@v4.2.1=sha1-" + parityTestSHA )
653+
654+ _ , stderr , err := runCommandWithHTTP (t , parityDown {reg }, "--verify" , path )
655+ require .NoError (t , err , stderr )
656+ assert .Contains (t , stderr , "could not verify locked actions/checkout" )
657+ }
0 commit comments