diff --git a/pkg/api/check_version.go b/pkg/api/check_version.go index 4e4ed3fe71e..ca79170b44b 100644 --- a/pkg/api/check_version.go +++ b/pkg/api/check_version.go @@ -14,6 +14,7 @@ import ( //we use the github REST V3 API as no login is required const apiReleases string = "https://api.github.com/repos/stashapp/stash/releases" +const apiTags string = "https://api.github.com/repos/stashapp/stash/tags" const apiAcceptHeader string = "application/vnd.github.v3+json" const developmentTag string = "latest_develop" @@ -84,6 +85,50 @@ type githubAsset struct { Browser_download_url string } +type githubTagResponse struct { + Name string + Zipball_url string + Tarball_url string + Commit struct { + Sha string + Url string + } + Node_id string +} + +func makeGithubRequest(url string, output interface{}) error { + client := &http.Client{ + Timeout: 3 * time.Second, + } + + req, _ := http.NewRequest("GET", url, nil) + + req.Header.Add("Accept", apiAcceptHeader) // gh api recommendation , send header with api version + response, err := client.Do(req) + + if err != nil { + return fmt.Errorf("Github API request failed: %s", err) + } + + if response.StatusCode != http.StatusOK { + return fmt.Errorf("Github API request failed: %s", response.Status) + } + + defer response.Body.Close() + + data, err := ioutil.ReadAll(response.Body) + if err != nil { + return fmt.Errorf("Github API read response failed: %s", err) + } + + err = json.Unmarshal(data, output) + if err != nil { + return fmt.Errorf("Unmarshalling Github API response failed: %s", err) + } + + return nil +} + // GetLatestVersion gets latest version (git commit hash) from github API // If running a build from the "master" branch, then the latest full release // is used, otherwise it uses the release that is tagged with "latest_develop" @@ -105,10 +150,6 @@ func GetLatestVersion(shortHash bool) (latestVersion string, latestRelease strin usePreRelease = true } - client := &http.Client{ - Timeout: 3 * time.Second, - } - url := apiReleases if !usePreRelease { // just get the latest full release @@ -117,38 +158,17 @@ func GetLatestVersion(shortHash bool) (latestVersion string, latestRelease strin // get the release tagged with the development tag url += "/tags/" + developmentTag } - req, _ := http.NewRequest("GET", url, nil) - - req.Header.Add("Accept", apiAcceptHeader) // gh api recommendation , send header with api version - response, err := client.Do(req) release := githubReleasesResponse{} + err = makeGithubRequest(url, &release) if err != nil { - return "", "", fmt.Errorf("Github API request failed: %s", err) - } - - if response.StatusCode != http.StatusOK { - return "", "", fmt.Errorf("Github API request failed: %s", response.Status) - } - - defer response.Body.Close() - - data, err := ioutil.ReadAll(response.Body) - if err != nil { - return "", "", fmt.Errorf("Github API read response failed: %s", err) - } - err = json.Unmarshal(data, &release) - if err != nil { - return "", "", fmt.Errorf("Unmarshalling Github API response failed: %s", err) + return "", "", err } if release.Prerelease == usePreRelease { - if shortHash { - latestVersion = release.Target_commitish[0:7] //shorthash is first 7 digits of git commit hash - } else { - latestVersion = release.Target_commitish - } + latestVersion = getReleaseHash(release, shortHash, usePreRelease) + if wantedRelease != "" { for _, asset := range release.Assets { if asset.Name == wantedRelease { @@ -165,6 +185,20 @@ func GetLatestVersion(shortHash bool) (latestVersion string, latestRelease strin return latestVersion, latestRelease, nil } +func getReleaseHash(release githubReleasesResponse, shortHash bool, usePreRelease bool) string { + // the /latest API call doesn't return the hash in target_commitish + // also add sanity check in case Target_commitish is not 40 characters + if !usePreRelease || len(release.Target_commitish) != 40 { + return getShaFromTags(shortHash, release.Tag_name) + } + + if shortHash { + return release.Target_commitish[0:7] //shorthash is first 7 digits of git commit hash + } + + return release.Target_commitish +} + func printLatestVersion() { _, githash, _ = GetVersion() latest, _, err := GetLatestVersion(true) @@ -178,3 +212,31 @@ func printLatestVersion() { } } } + +// get sha from the github api tags endpoint +// returns the sha1 hash/shorthash or "" if something's wrong +func getShaFromTags(shortHash bool, name string) string { + url := apiTags + tags := []githubTagResponse{} + err := makeGithubRequest(url, &tags) + + if err != nil { + logger.Errorf("Github Tags Api %v", err) + return "" + } + + for _, tag := range tags { + if tag.Name == name { + if len(tag.Commit.Sha) != 40 { + return "" + } + if shortHash { + return tag.Commit.Sha[0:7] //shorthash is first 7 digits of git commit hash + } + + return tag.Commit.Sha + } + } + + return "" +}