@@ -597,6 +597,96 @@ var _ = Describe("GitHub Client", func() {
597597 })
598598
599599 })
600+ Context ("When GitHub returns a chain of annotated tags" , func () {
601+ BeforeEach (func () {
602+ // First call: get the ref which points to the first tag
603+ server .AppendHandlers (
604+ ghttp .CombineHandlers (
605+ ghttp .VerifyRequest ("GET" , "/repos/concourse/concourse/git/ref/tags/v1.0.0-rc90" ),
606+ ghttp .RespondWith (200 , `{ "ref": "refs/tags/v1.0.0-rc90", "object" : { "type": "tag", "sha": "first-tag-sha"} }` ),
607+ ),
608+ )
609+
610+ // Second call: get the first tag object, which points to another tag
611+ server .AppendHandlers (
612+ ghttp .CombineHandlers (
613+ ghttp .VerifyRequest ("GET" , "/repos/concourse/concourse/git/tags/first-tag-sha" ),
614+ ghttp .RespondWith (200 , `{ "object" : { "type": "tag", "sha": "second-tag-sha"} }` ),
615+ ),
616+ )
617+
618+ // Third call: get the second tag object, which finally points to a commit
619+ server .AppendHandlers (
620+ ghttp .CombineHandlers (
621+ ghttp .VerifyRequest ("GET" , "/repos/concourse/concourse/git/tags/second-tag-sha" ),
622+ ghttp .RespondWith (200 , `{ "object" : { "type": "commit", "sha": "final-commit-sha"} }` ),
623+ ),
624+ )
625+ })
626+
627+ It ("follows the chain and returns the final commit SHA" , func () {
628+ commitSHA , err := client .ResolveTagToCommitSHA ("v1.0.0-rc90" )
629+
630+ Expect (err ).ShouldNot (HaveOccurred ())
631+ Expect (commitSHA ).To (Equal ("final-commit-sha" ))
632+ })
633+ })
634+
635+ Context ("When GitHub returns a very deep chain of annotated tags" , func () {
636+ BeforeEach (func () {
637+ // First call: get the ref
638+ server .AppendHandlers (
639+ ghttp .CombineHandlers (
640+ ghttp .VerifyRequest ("GET" , "/repos/concourse/concourse/git/ref/tags/deeply-nested" ),
641+ ghttp .RespondWith (200 , `{ "ref": "refs/tags/deeply-nested", "object" : { "type": "tag", "sha": "tag-sha-0"} }` ),
642+ ),
643+ )
644+
645+ // Add 11 tag-to-tag redirections (exceeding our max depth of 10)
646+ for i := 0 ; i < 11 ; i ++ {
647+ currentSHA := fmt .Sprintf ("tag-sha-%d" , i )
648+ nextSHA := fmt .Sprintf ("tag-sha-%d" , i + 1 )
649+ server .AppendHandlers (
650+ ghttp .CombineHandlers (
651+ ghttp .VerifyRequest ("GET" , fmt .Sprintf ("/repos/concourse/concourse/git/tags/%s" , currentSHA )),
652+ ghttp .RespondWith (200 , fmt .Sprintf (`{ "object" : { "type": "tag", "sha": "%s"} }` , nextSHA )),
653+ ),
654+ )
655+ }
656+ })
657+
658+ It ("returns an error when max depth is exceeded" , func () {
659+ _ , err := client .ResolveTagToCommitSHA ("deeply-nested" )
660+
661+ Expect (err ).Should (HaveOccurred ())
662+ Expect (err .Error ()).To (ContainSubstring ("exceeded maximum tag chain depth" ))
663+ })
664+ })
665+
666+ Context ("When a tag in the chain points to an unexpected object type" , func () {
667+ BeforeEach (func () {
668+ server .AppendHandlers (
669+ ghttp .CombineHandlers (
670+ ghttp .VerifyRequest ("GET" , "/repos/concourse/concourse/git/ref/tags/bad-tag" ),
671+ ghttp .RespondWith (200 , `{ "ref": "refs/tags/bad-tag", "object" : { "type": "tag", "sha": "tag-sha"} }` ),
672+ ),
673+ )
674+
675+ server .AppendHandlers (
676+ ghttp .CombineHandlers (
677+ ghttp .VerifyRequest ("GET" , "/repos/concourse/concourse/git/tags/tag-sha" ),
678+ ghttp .RespondWith (200 , `{ "object" : { "type": "tree", "sha": "tree-sha"} }` ),
679+ ),
680+ )
681+ })
682+
683+ It ("returns an error for unexpected object types" , func () {
684+ _ , err := client .ResolveTagToCommitSHA ("bad-tag" )
685+
686+ Expect (err ).Should (HaveOccurred ())
687+ Expect (err .Error ()).To (ContainSubstring ("expected 'commit' or 'tag'" ))
688+ })
689+ })
600690 })
601691
602692 Describe ("DownloadReleaseAsset" , func () {
0 commit comments