2019-02-04 13:51:29 +03:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
"github.com/Masterminds/semver"
|
|
|
|
|
2019-02-04 13:51:29 +03:00
|
|
|
"github.com/hasura/graphql-engine/cli"
|
|
|
|
"github.com/hasura/graphql-engine/cli/update"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
)
|
|
|
|
|
|
|
|
const updateCLICmdUse = "update-cli"
|
|
|
|
|
|
|
|
const updateCLICmdExample = ` # Update CLI to latest version:
|
|
|
|
hasura update-cli
|
|
|
|
|
|
|
|
# To disable auto-update check on the CLI, set
|
|
|
|
# "show_update_notification": false
|
|
|
|
# in ~/.hasura/config.json
|
2020-03-05 09:55:33 +03:00
|
|
|
|
|
|
|
# Update CLI to a specific version (say v1.2.0-beta.1):
|
|
|
|
hasura update-cli --version v1.2.0-beta.1
|
2019-02-04 13:51:29 +03:00
|
|
|
`
|
|
|
|
|
|
|
|
// NewUpdateCLICmd returns the update-cli command.
|
|
|
|
func NewUpdateCLICmd(ec *cli.ExecutionContext) *cobra.Command {
|
|
|
|
opts := &updateOptions{
|
|
|
|
EC: ec,
|
|
|
|
}
|
|
|
|
updateCmd := &cobra.Command{
|
|
|
|
Use: updateCLICmdUse,
|
2020-03-05 09:55:33 +03:00
|
|
|
Short: "Update the CLI to latest or a specific version",
|
2019-02-04 13:51:29 +03:00
|
|
|
SilenceUsage: true,
|
|
|
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
return ec.Prepare()
|
|
|
|
},
|
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
return opts.run(false)
|
|
|
|
},
|
|
|
|
Example: updateCLICmdExample,
|
|
|
|
}
|
2020-03-05 09:55:33 +03:00
|
|
|
|
|
|
|
f := updateCmd.Flags()
|
|
|
|
f.StringVar(&opts.version, "version", "", "a specific version to install")
|
|
|
|
|
2019-02-04 13:51:29 +03:00
|
|
|
return updateCmd
|
|
|
|
}
|
|
|
|
|
|
|
|
type updateOptions struct {
|
|
|
|
EC *cli.ExecutionContext
|
2020-03-05 09:55:33 +03:00
|
|
|
|
|
|
|
version string
|
2019-02-04 13:51:29 +03:00
|
|
|
}
|
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
func (o *updateOptions) run(showPrompt bool) (err error) {
|
2019-02-04 13:51:29 +03:00
|
|
|
currentVersion := o.EC.Version.CLISemver
|
|
|
|
if currentVersion == nil {
|
|
|
|
return errors.Errorf("cannot update from a non-semver version: %s", o.EC.Version.GetCLIVersion())
|
|
|
|
}
|
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
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, hasPreReleaseUpdate, preReleaseVersion, err := update.HasUpdate(currentVersion, o.EC.LastUpdateCheckFile)
|
|
|
|
o.EC.Spinner.Stop()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "command: check update")
|
|
|
|
}
|
2019-02-04 13:51:29 +03:00
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-16 06:53:18 +03:00
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
if versionToBeInstalled == nil {
|
2019-02-04 13:51:29 +03:00
|
|
|
o.EC.Logger.WithField("version", currentVersion).Info("hasura cli is up to date")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
ec.Logger.Debugln("versionToBeInstalled: ", versionToBeInstalled.String())
|
2019-02-04 13:51:29 +03:00
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
o.EC.Spin(fmt.Sprintf("Updating cli to v%s... ", versionToBeInstalled.String()))
|
|
|
|
err = update.ApplyUpdate(versionToBeInstalled)
|
2019-02-04 13:51:29 +03:00
|
|
|
o.EC.Spinner.Stop()
|
|
|
|
if err != nil {
|
|
|
|
if os.IsPermission(err) {
|
|
|
|
return errors.New("permission denied, try again as admin or with sudo")
|
|
|
|
}
|
|
|
|
return errors.Wrap(err, "apply update")
|
|
|
|
}
|
|
|
|
|
2020-03-05 09:55:33 +03:00
|
|
|
o.EC.Logger.WithField("version", "v"+versionToBeInstalled.String()).Info("Updated to latest version")
|
2019-02-04 13:51:29 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ask2confirm(v string, log *logrus.Logger) bool {
|
|
|
|
var s string
|
|
|
|
|
|
|
|
log.Infof("A new version (v%s) is available for CLI, update? (y/N)", v)
|
|
|
|
_, err := fmt.Scan(&s)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("unable to take input, skipping update")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
s = strings.TrimSpace(s)
|
|
|
|
s = strings.ToLower(s)
|
|
|
|
|
|
|
|
if s == "y" || s == "yes" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2020-03-05 09:55:33 +03:00
|
|
|
|
|
|
|
func getChangeLogLink(version *semver.Version) string {
|
|
|
|
return fmt.Sprintf("https://github.com/hasura/graphql-engine/releases/tag/%s", version.Original())
|
|
|
|
}
|