mirror of https://github.com/dapr/cli.git
173 lines
4.7 KiB
Go
173 lines
4.7 KiB
Go
/*
|
|
Copyright 2021 The Dapr Authors
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package version
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/go-version"
|
|
yaml "gopkg.in/yaml.v2"
|
|
|
|
"github.com/dapr/cli/pkg/print"
|
|
"github.com/dapr/cli/utils"
|
|
)
|
|
|
|
const (
|
|
// DaprGitHubOrg is the org name of dapr on GitHub.
|
|
DaprGitHubOrg = "dapr"
|
|
// DaprGitHubRepo is the repo name of dapr runtime on GitHub.
|
|
DaprGitHubRepo = "dapr"
|
|
// DashboardGitHubRepo is the repo name of dapr dashboard on GitHub.
|
|
DashboardGitHubRepo = "dashboard"
|
|
)
|
|
|
|
type githubRepoReleaseItem struct {
|
|
URL string `json:"url"`
|
|
TagName string `json:"tag_name"`
|
|
Name string `json:"name"`
|
|
Draft bool `json:"draft"`
|
|
}
|
|
|
|
type helmChartItems struct {
|
|
Entries struct {
|
|
Dapr []struct {
|
|
Version string `yaml:"appVersion"`
|
|
}
|
|
DaprDashboard []struct {
|
|
Version string `yaml:"appVersion"`
|
|
} `yaml:"dapr-dashboard"`
|
|
}
|
|
}
|
|
|
|
func GetDashboardVersion() (string, error) {
|
|
return GetLatestReleaseGithub(fmt.Sprintf("https://api.github.com/repos/%s/%s/releases", DaprGitHubOrg, DashboardGitHubRepo))
|
|
}
|
|
|
|
func GetDaprVersion() (string, error) {
|
|
version, err := GetLatestReleaseGithub(fmt.Sprintf("https://api.github.com/repos/%s/%s/releases", DaprGitHubOrg, DaprGitHubRepo))
|
|
if err != nil {
|
|
print.WarningStatusEvent(os.Stdout, "Failed to get runtime version: '%s'. Trying secondary source", err)
|
|
|
|
version, err = GetLatestReleaseHelmChart("https://dapr.github.io/helm-charts/index.yaml")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return version, nil
|
|
}
|
|
|
|
func GetVersionFromURL(releaseURL string, parseVersion func(body []byte) (string, error)) (string, error) {
|
|
req, err := http.NewRequest(http.MethodGet, releaseURL, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
githubToken := utils.GetEnv("GITHUB_TOKEN", "")
|
|
if githubToken != "" {
|
|
req.Header.Add("Authorization", "token "+githubToken)
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("%s - %s", releaseURL, resp.Status)
|
|
}
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return parseVersion(body)
|
|
}
|
|
|
|
// GetLatestReleaseGithub return the latest release version of dapr from GitHub API.
|
|
func GetLatestReleaseGithub(githubURL string) (string, error) {
|
|
return GetVersionFromURL(githubURL, func(body []byte) (string, error) {
|
|
var githubRepoReleases []githubRepoReleaseItem
|
|
err := json.Unmarshal(body, &githubRepoReleases)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if len(githubRepoReleases) == 0 {
|
|
return "", errors.New("no releases")
|
|
}
|
|
|
|
defaultVersion, _ := version.NewVersion("0.0.0")
|
|
latestVersion := defaultVersion
|
|
|
|
for _, release := range githubRepoReleases {
|
|
cur, err := version.NewVersion(strings.TrimPrefix(release.TagName, "v"))
|
|
if err != nil || cur == nil {
|
|
print.WarningStatusEvent(os.Stdout, "Malformed version %s, skipping", release.TagName)
|
|
continue
|
|
}
|
|
// Prerelease versions and versions with metadata are skipped.
|
|
if cur.Prerelease() != "" || cur.Metadata() != "" {
|
|
continue
|
|
}
|
|
|
|
if cur.GreaterThan(latestVersion) {
|
|
latestVersion = cur
|
|
}
|
|
}
|
|
|
|
if latestVersion.Equal(defaultVersion) {
|
|
return "", errors.New("no releases")
|
|
}
|
|
|
|
return latestVersion.String(), nil
|
|
})
|
|
}
|
|
|
|
// GetLatestReleaseHelmChart return the latest release version of dapr from helm chart static index.yaml.
|
|
func GetLatestReleaseHelmChart(helmChartURL string) (string, error) {
|
|
return GetVersionFromURL(helmChartURL, func(body []byte) (string, error) {
|
|
var helmChartReleases helmChartItems
|
|
err := yaml.Unmarshal(body, &helmChartReleases)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(helmChartReleases.Entries.Dapr) == 0 {
|
|
return "", errors.New("no releases")
|
|
}
|
|
|
|
for _, release := range helmChartReleases.Entries.Dapr {
|
|
if !strings.Contains(release.Version, "-rc") {
|
|
return release.Version, nil
|
|
}
|
|
}
|
|
|
|
// Did not find a non-rc version, so we fallback to an RC.
|
|
// This is helpful to allow us to validate installation of new charts (Dashboard).
|
|
for _, release := range helmChartReleases.Entries.Dapr {
|
|
return release.Version, nil
|
|
}
|
|
|
|
return "", errors.New("no releases")
|
|
})
|
|
}
|