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