@@ -2,6 +2,7 @@ package shared
22
33import (
44 "encoding/json"
5+ "errors"
56 "fmt"
67 "io/ioutil"
78 "net/http"
@@ -18,9 +19,10 @@ type Release struct {
1819 Body string `json:"body"`
1920 IsDraft bool `json:"draft"`
2021 IsPrerelease bool `json:"prerelease"`
22+ CreatedAt time.Time `json:"created_at"`
2123 PublishedAt time.Time `json:"published_at"`
2224
23- URL string `json:"url"`
25+ APIURL string `json:"url"`
2426 UploadURL string `json:"upload_url"`
2527 HTMLURL string `json:"html_url"`
2628 Assets []ReleaseAsset
@@ -37,25 +39,30 @@ type ReleaseAsset struct {
3739 URL string
3840}
3941
42+ // FetchRelease finds a repository release by its tagName.
4043func FetchRelease (httpClient * http.Client , baseRepo ghrepo.Interface , tagName string ) (* Release , error ) {
41- // FIXME: this doesn't find draft releases
4244 path := fmt .Sprintf ("repos/%s/%s/releases/tags/%s" , baseRepo .RepoOwner (), baseRepo .RepoName (), tagName )
4345 url := ghinstance .RESTPrefix (baseRepo .RepoHost ()) + path
4446 req , err := http .NewRequest ("GET" , url , nil )
4547 if err != nil {
4648 return nil , err
4749 }
4850
49- req .Header .Set ("Content-Type" , "application/json; charset=utf-8" )
50-
5151 resp , err := httpClient .Do (req )
5252 if err != nil {
5353 return nil , err
5454 }
5555 defer resp .Body .Close ()
5656
57- success := resp .StatusCode >= 200 && resp .StatusCode < 300
58- if ! success {
57+ if resp .StatusCode == 404 {
58+ if canPush , err := api .CanPushToRepo (httpClient , baseRepo ); err == nil && canPush {
59+ return FindDraftRelease (httpClient , baseRepo , tagName )
60+ } else if err != nil {
61+ return nil , err
62+ }
63+ }
64+
65+ if resp .StatusCode > 299 {
5966 return nil , api .HandleHTTPError (resp )
6067 }
6168
@@ -72,3 +79,52 @@ func FetchRelease(httpClient *http.Client, baseRepo ghrepo.Interface, tagName st
7279
7380 return & release , nil
7481}
82+
83+ // FindDraftRelease interates over all releases in a repository until it finds one that matches tagName.
84+ func FindDraftRelease (httpClient * http.Client , baseRepo ghrepo.Interface , tagName string ) (* Release , error ) {
85+ path := fmt .Sprintf ("repos/%s/%s/releases" , baseRepo .RepoOwner (), baseRepo .RepoName ())
86+ url := ghinstance .RESTPrefix (baseRepo .RepoHost ()) + path
87+
88+ perPage := 100
89+ page := 1
90+ for {
91+ req , err := http .NewRequest ("GET" , fmt .Sprintf ("%s?per_page=%d&page=%d" , url , perPage , page ), nil )
92+ if err != nil {
93+ return nil , err
94+ }
95+
96+ resp , err := httpClient .Do (req )
97+ if err != nil {
98+ return nil , err
99+ }
100+ defer resp .Body .Close ()
101+
102+ if resp .StatusCode > 299 {
103+ return nil , api .HandleHTTPError (resp )
104+ }
105+
106+ b , err := ioutil .ReadAll (resp .Body )
107+ if err != nil {
108+ return nil , err
109+ }
110+
111+ var releases []Release
112+ err = json .Unmarshal (b , & releases )
113+ if err != nil {
114+ return nil , err
115+ }
116+
117+ for _ , r := range releases {
118+ if r .TagName == tagName {
119+ return & r , nil
120+ }
121+ }
122+
123+ if len (releases ) < perPage {
124+ break
125+ }
126+ page ++
127+ }
128+
129+ return nil , errors .New ("release not found" )
130+ }
0 commit comments