mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
cli: add version flag in update-cli command (#3996)
Co-authored-by: Shahidh K Muhammed <muhammedshahid.k@gmail.com>
This commit is contained in:
parent
cb75660b3e
commit
d7d53f222c
@ -5,6 +5,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
|
||||
"github.com/hasura/graphql-engine/cli"
|
||||
"github.com/hasura/graphql-engine/cli/update"
|
||||
"github.com/pkg/errors"
|
||||
@ -20,6 +22,9 @@ const updateCLICmdExample = ` # Update CLI to latest version:
|
||||
# To disable auto-update check on the CLI, set
|
||||
# "show_update_notification": false
|
||||
# in ~/.hasura/config.json
|
||||
|
||||
# Update CLI to a specific version (say v1.2.0-beta.1):
|
||||
hasura update-cli --version v1.2.0-beta.1
|
||||
`
|
||||
|
||||
// NewUpdateCLICmd returns the update-cli command.
|
||||
@ -29,7 +34,7 @@ func NewUpdateCLICmd(ec *cli.ExecutionContext) *cobra.Command {
|
||||
}
|
||||
updateCmd := &cobra.Command{
|
||||
Use: updateCLICmdUse,
|
||||
Short: "Update the CLI to latest version",
|
||||
Short: "Update the CLI to latest or a specific version",
|
||||
SilenceUsage: true,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return ec.Prepare()
|
||||
@ -39,43 +44,77 @@ func NewUpdateCLICmd(ec *cli.ExecutionContext) *cobra.Command {
|
||||
},
|
||||
Example: updateCLICmdExample,
|
||||
}
|
||||
|
||||
f := updateCmd.Flags()
|
||||
f.StringVar(&opts.version, "version", "", "a specific version to install")
|
||||
|
||||
return updateCmd
|
||||
}
|
||||
|
||||
type updateOptions struct {
|
||||
EC *cli.ExecutionContext
|
||||
|
||||
version string
|
||||
}
|
||||
|
||||
func (o *updateOptions) run(showPrompt bool) error {
|
||||
func (o *updateOptions) run(showPrompt bool) (err error) {
|
||||
currentVersion := o.EC.Version.CLISemver
|
||||
if currentVersion == nil {
|
||||
return errors.Errorf("cannot update from a non-semver version: %s", o.EC.Version.GetCLIVersion())
|
||||
}
|
||||
|
||||
var versionToBeInstalled *semver.Version
|
||||
if o.version != "" {
|
||||
// parse the version
|
||||
versionToBeInstalled, err = semver.NewVersion(o.version)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to parse version")
|
||||
}
|
||||
} else {
|
||||
o.EC.Spin("Checking for update... ")
|
||||
hasUpdate, latestVersion, err := update.HasUpdate(currentVersion, o.EC.LastUpdateCheckFile)
|
||||
hasUpdate, latestVersion, hasPreReleaseUpdate, preReleaseVersion, err := update.HasUpdate(currentVersion, o.EC.LastUpdateCheckFile)
|
||||
o.EC.Spinner.Stop()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "command: check update")
|
||||
}
|
||||
|
||||
ec.Logger.Debugln("hasUpdate: ", hasUpdate, "latestVersion: ", latestVersion, "currentVersion:", currentVersion)
|
||||
|
||||
if !hasUpdate {
|
||||
o.EC.Logger.WithField("version", currentVersion).Info("hasura cli is up to date")
|
||||
return nil
|
||||
}
|
||||
ec.Logger.Debugln("hasUpdate: ", hasUpdate, "latestVersion: ", latestVersion, "hasPreReleaseUpdate: ", hasPreReleaseUpdate, "preReleaseVersion: ", preReleaseVersion, "currentVersion:", currentVersion)
|
||||
|
||||
if showPrompt {
|
||||
switch {
|
||||
case hasUpdate:
|
||||
ok := ask2confirm(latestVersion.String(), o.EC.Logger)
|
||||
if !ok {
|
||||
o.EC.Logger.Info("skipping update, run 'hasura update-cli' to update manually")
|
||||
return nil
|
||||
}
|
||||
versionToBeInstalled = latestVersion
|
||||
case hasPreReleaseUpdate:
|
||||
o.EC.Logger.Infof(`a new pre-release version is available:
|
||||
- %s (changelog: %s)
|
||||
to update cli to this version, execute:
|
||||
|
||||
hasura update-cli --version %s
|
||||
|
||||
`, preReleaseVersion.Original(), getChangeLogLink(preReleaseVersion), preReleaseVersion.Original())
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if hasUpdate {
|
||||
versionToBeInstalled = latestVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o.EC.Spin(fmt.Sprintf("Updating cli to v%s... ", latestVersion.String()))
|
||||
err = update.ApplyUpdate(latestVersion)
|
||||
if versionToBeInstalled == nil {
|
||||
o.EC.Logger.WithField("version", currentVersion).Info("hasura cli is up to date")
|
||||
return nil
|
||||
}
|
||||
|
||||
ec.Logger.Debugln("versionToBeInstalled: ", versionToBeInstalled.String())
|
||||
|
||||
o.EC.Spin(fmt.Sprintf("Updating cli to v%s... ", versionToBeInstalled.String()))
|
||||
err = update.ApplyUpdate(versionToBeInstalled)
|
||||
o.EC.Spinner.Stop()
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
@ -84,7 +123,7 @@ func (o *updateOptions) run(showPrompt bool) error {
|
||||
return errors.Wrap(err, "apply update")
|
||||
}
|
||||
|
||||
o.EC.Logger.WithField("version", "v"+latestVersion.String()).Info("Updated to latest version")
|
||||
o.EC.Logger.WithField("version", "v"+versionToBeInstalled.String()).Info("Updated to latest version")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -106,3 +145,7 @@ func ask2confirm(v string, log *logrus.Logger) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getChangeLogLink(version *semver.Version) string {
|
||||
return fmt.Sprintf("https://github.com/hasura/graphql-engine/releases/tag/%s", version.Original())
|
||||
}
|
||||
|
@ -22,28 +22,24 @@ import (
|
||||
const updateCheckURL = "https://releases.hasura.io/graphql-engine?agent=cli"
|
||||
|
||||
type updateCheckResponse struct {
|
||||
Latest string `json:"latest"`
|
||||
Latest *semver.Version `json:"latest"`
|
||||
PreRelease *semver.Version `json:"prerelease"`
|
||||
}
|
||||
|
||||
func getLatestVersion() (*semver.Version, error) {
|
||||
func getLatestVersion() (*semver.Version, *semver.Version, error) {
|
||||
res, err := http.Get(updateCheckURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "update check request")
|
||||
return nil, nil, errors.Wrap(err, "update check request")
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
var response updateCheckResponse
|
||||
err = json.NewDecoder(res.Body).Decode(&response)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "decoding update check response")
|
||||
return nil, nil, errors.Wrap(err, "decoding update check response")
|
||||
}
|
||||
|
||||
v, err := semver.NewVersion(response.Latest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "semver parsing")
|
||||
}
|
||||
|
||||
return v, nil
|
||||
return response.Latest, response.PreRelease, nil
|
||||
}
|
||||
|
||||
func buildAssetURL(v string) string {
|
||||
@ -88,23 +84,18 @@ func downloadAsset(url, fileName, filePath string) (*os.File, error) {
|
||||
return asset, nil
|
||||
}
|
||||
|
||||
// HasUpdate tells us if there is a new update available.
|
||||
func HasUpdate(currentVersion *semver.Version, timeFile string) (bool, *semver.Version, error) {
|
||||
// HasUpdate tells us if there is a new stable or prerelease update available.
|
||||
func HasUpdate(currentVersion *semver.Version, timeFile string) (bool, *semver.Version, bool, *semver.Version, error) {
|
||||
if timeFile != "" {
|
||||
defer writeTimeToFile(timeFile, time.Now().UTC())
|
||||
}
|
||||
|
||||
latestVersion, err := getLatestVersion()
|
||||
latestVersion, preReleaseVersion, err := getLatestVersion()
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "get latest version")
|
||||
return false, nil, false, nil, errors.Wrap(err, "get latest version")
|
||||
}
|
||||
|
||||
c, err := semver.NewConstraint(fmt.Sprintf("> %s", currentVersion.String()))
|
||||
if err != nil {
|
||||
return false, nil, errors.Wrap(err, "semver constraint build")
|
||||
}
|
||||
|
||||
return c.Check(latestVersion), latestVersion, nil
|
||||
return latestVersion.GreaterThan(currentVersion), latestVersion, preReleaseVersion.GreaterThan(currentVersion), preReleaseVersion, nil
|
||||
}
|
||||
|
||||
// ApplyUpdate downloads and applies the update indicated by version v.
|
||||
|
Loading…
Reference in New Issue
Block a user