mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
161 lines
3.6 KiB
Go
161 lines
3.6 KiB
Go
package versions
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"github.com/Masterminds/semver/v3"
|
|
)
|
|
|
|
var (
|
|
reGrafanaTag = regexp.MustCompile(`^v(\d+\.\d+\.\d+$)`)
|
|
reGrafanaTagBeta = regexp.MustCompile(`^v(\d+\.\d+\.\d+-beta)`)
|
|
reGrafanaTagCustom = regexp.MustCompile(`^v(\d+\.\d+\.\d+-\w+)`)
|
|
)
|
|
|
|
const (
|
|
Latest = "latest"
|
|
Next = "next"
|
|
Test = "test"
|
|
)
|
|
|
|
type Version struct {
|
|
Version string
|
|
Channel string
|
|
}
|
|
|
|
type VersionFromAPI struct {
|
|
Version string `json:"version"`
|
|
}
|
|
|
|
type LatestGcomAPI = string
|
|
|
|
const (
|
|
LatestStableVersionURL LatestGcomAPI = "https://grafana.com/api/grafana/versions/stable"
|
|
LatestBetaVersionURL LatestGcomAPI = "https://grafana.com/api/grafana/versions/beta"
|
|
)
|
|
|
|
func GetLatestVersion(url LatestGcomAPI) (string, error) {
|
|
// nolint:gosec
|
|
resp, err := http.Get(url)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer func() {
|
|
if err := resp.Body.Close(); err != nil {
|
|
log.Printf("Failed to close body: %s", err.Error())
|
|
}
|
|
}()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("server returned non 200 status code: %d", resp.StatusCode)
|
|
}
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var apiResponse VersionFromAPI
|
|
err = json.Unmarshal(body, &apiResponse)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return apiResponse.Version, nil
|
|
}
|
|
|
|
// IsGreaterThanOrEqual semantically checks whether newVersion is greater than or equal to stableVersion.
|
|
func IsGreaterThanOrEqual(newVersion, stableVersion string) (bool, error) {
|
|
v1SemVer, err := semver.NewVersion(newVersion)
|
|
if err != nil {
|
|
return isGreaterThanOrEqualFourDigit(newVersion, stableVersion)
|
|
}
|
|
|
|
v2SemVer, err := semver.NewVersion(stableVersion)
|
|
if err != nil {
|
|
return isGreaterThanOrEqualFourDigit(newVersion, stableVersion)
|
|
}
|
|
|
|
comp := v1SemVer.Compare(v2SemVer)
|
|
switch comp {
|
|
case -1:
|
|
return false, nil
|
|
case 1, 0:
|
|
return true, nil
|
|
default:
|
|
return true, fmt.Errorf("unknown comparison value between scemantic versions, err: %q", err)
|
|
}
|
|
}
|
|
|
|
var fourDigitRe = regexp.MustCompile(`(\d+\.\d+\.\d+)\.(\d+)`)
|
|
|
|
func parseFourDigit(version string) (*semver.Version, int, error) {
|
|
matches := fourDigitRe.FindStringSubmatch(version)
|
|
if len(matches) < 2 {
|
|
semVer, err := semver.NewVersion(version)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return semVer, 0, nil
|
|
}
|
|
semVer, err := semver.NewVersion(matches[1])
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
i, err := strconv.Atoi(matches[2])
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return semVer, i, nil
|
|
}
|
|
|
|
func isGreaterThanOrEqualFourDigit(newVersion, stableVersion string) (bool, error) {
|
|
newVersionSemVer, newVersionSemVerNo, err := parseFourDigit(newVersion)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
stableVersionSemVer, stableVersionSemVerNo, err := parseFourDigit(stableVersion)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if stableVersionSemVer.Original() != newVersionSemVer.Original() {
|
|
return IsGreaterThanOrEqual(newVersionSemVer.Original(), stableVersionSemVer.Original())
|
|
}
|
|
|
|
return newVersionSemVerNo >= stableVersionSemVerNo, nil
|
|
}
|
|
|
|
func GetVersion(tag string) (*Version, error) {
|
|
var version Version
|
|
switch {
|
|
case reGrafanaTag.MatchString(tag):
|
|
version = Version{
|
|
Version: reGrafanaTag.FindStringSubmatch(tag)[1],
|
|
Channel: Latest,
|
|
}
|
|
case reGrafanaTagBeta.MatchString(tag):
|
|
version = Version{
|
|
Version: reGrafanaTagBeta.FindStringSubmatch(tag)[1],
|
|
Channel: Next,
|
|
}
|
|
case reGrafanaTagCustom.MatchString(tag):
|
|
version = Version{
|
|
Version: reGrafanaTagCustom.FindStringSubmatch(tag)[1],
|
|
Channel: Test,
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("%s not a supported Grafana version, exitting", tag)
|
|
}
|
|
|
|
return &version, nil
|
|
}
|