code.vegaprotocol.io/vega@v0.79.0/libs/version/github.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package version 17 18 import ( 19 "context" 20 "encoding/json" 21 "fmt" 22 "io" 23 "net/http" 24 25 "github.com/blang/semver/v4" 26 ) 27 28 type githubReleaseResponse struct { 29 Name string `json:"name"` 30 IsDraft bool `json:"draft"` 31 IsPreRelease bool `json:"prerelease"` 32 } 33 34 func GetGithubReleaseURL(releasesURL string, v *semver.Version) string { 35 return fmt.Sprintf("%v/tag/v%v", releasesURL, v) 36 } 37 38 func BuildGithubReleasesRequestFrom(ctx context.Context, releasesURL string) ReleasesGetter { 39 return func() ([]*Version, error) { 40 req, err := http.NewRequestWithContext(ctx, http.MethodGet, releasesURL, nil) 41 if err != nil { 42 return nil, fmt.Errorf("couldn't build request: %w", err) 43 } 44 req.Header.Add("Accept", "application/vnd.github.v3+json") 45 46 client := &http.Client{} 47 resp, err := client.Do(req) 48 if err != nil { 49 return nil, fmt.Errorf("couldn't deliver request: %w", err) 50 } 51 defer resp.Body.Close() 52 53 body, err := io.ReadAll(resp.Body) 54 if err != nil { 55 return nil, fmt.Errorf("couldn't read response body: %w", err) 56 } 57 58 responses := []githubReleaseResponse{} 59 if err = json.Unmarshal(body, &responses); err != nil { 60 // try to parse as a general error message which would be useful information 61 // to know e.g. if we were blocked due to GitHub rate-limiting 62 m := struct { 63 Message string `json:"message"` 64 }{} 65 if mErr := json.Unmarshal(body, &m); mErr == nil { 66 return nil, fmt.Errorf("couldn't read response message: %s: %w", m.Message, err) 67 } 68 69 return nil, fmt.Errorf("couldn't unmarshal response body: %w", err) 70 } 71 72 releases := []*Version{} 73 for _, response := range responses { 74 release, err := NewVersionFromString(response.Name) 75 if err != nil { 76 // unsupported version 77 continue 78 } 79 80 // At this point, the Version has been initialised based on the 81 // segment of the version string. We have to readjust it based on 82 // GitHub metadata. 83 84 // We set the draft flag from GitHub response unconditionally as this 85 // can only be inferred from GitHub metadata. 86 release.IsDraft = response.IsDraft 87 88 // If this is not marked as pre-release already, this means it's 89 // either a stable version, either a temporary pre-release. 90 // Temporary pre-release are releases that are supposed to be genuine 91 // ones, but have been temporarily marked as pre-release in GitHub 92 // to warn incompatibility with mainnet. 93 // As a result, if not set, we verify if the state in GitHub. 94 if !release.IsPreReleased { 95 release.IsPreReleased = response.IsPreRelease 96 } 97 98 // We recompute the release flag based on the update above. 99 release.IsReleased = !release.IsDevelopment && !release.IsPreReleased && !release.IsDraft 100 101 releases = append(releases, release) 102 } 103 104 return releases, nil 105 } 106 }