2019-02-04 13:51:29 +03:00
package commands
import (
"fmt"
"os"
2020-03-05 09:55:33 +03:00
"github.com/Masterminds/semver"
2021-06-16 14:44:15 +03:00
"github.com/hasura/graphql-engine/cli/v2"
2022-11-07 14:13:12 +03:00
"github.com/hasura/graphql-engine/cli/v2/internal/errors"
2021-06-16 14:44:15 +03:00
"github.com/hasura/graphql-engine/cli/v2/update"
2022-11-07 14:13:12 +03:00
2019-02-04 13:51:29 +03:00
"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" ,
2022-12-30 06:50:48 +03:00
Long : "You can use this command to update the CLI to the latest version or a specific version. Each time you run a CLI command, if a new version is available, you will be prompted to update the CLI." ,
2019-02-04 13:51:29 +03:00
SilenceUsage : true ,
PreRunE : func ( cmd * cobra . Command , args [ ] string ) error {
2022-11-07 14:13:12 +03:00
op := genOpName ( cmd , "PreRunE" )
if err := ec . Prepare ( ) ; err != nil {
return errors . E ( op , err )
}
return nil
2019-02-04 13:51:29 +03:00
} ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2022-11-07 14:13:12 +03:00
op := genOpName ( cmd , "RunE" )
if err := opts . run ( false ) ; err != nil {
return errors . E ( op , err )
}
return nil
2019-02-04 13:51:29 +03:00
} ,
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 ) {
2022-11-07 14:13:12 +03:00
var op errors . Op = "commands.updateOptions.run"
2019-02-04 13:51:29 +03:00
currentVersion := o . EC . Version . CLISemver
if currentVersion == nil {
2022-11-07 14:13:12 +03:00
return errors . E ( op , fmt . Errorf ( "cannot update from a non-semver version: %s" , o . EC . Version . GetCLIVersion ( ) ) )
2019-02-04 13:51:29 +03:00
}
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 {
2022-11-07 14:13:12 +03:00
return errors . E ( op , fmt . Errorf ( "unable to parse version: %w" , err ) )
2020-03-05 09:55:33 +03:00
}
} 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 {
2022-11-07 14:13:12 +03:00
return errors . E ( op , fmt . Errorf ( "command: check update: %w" , err ) )
2020-03-05 09:55:33 +03:00
}
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 :
2023-01-11 13:30:56 +03:00
o . EC . Logger . Infof ( "A new version (v%s) is available for CLI, you can update it by running 'hasura update-cli'" , latestVersion . String ( ) )
return nil
2020-03-05 09:55:33 +03:00
case hasPreReleaseUpdate :
2021-11-11 13:55:16 +03:00
o . EC . Logger . WithFields ( logrus . Fields {
"version" : preReleaseVersion . Original ( ) ,
"changelog" : getChangeLogLink ( preReleaseVersion ) ,
} ) . Infof ( ` a new pre-release version is available ` )
o . EC . Logger . Infof ( ` to update cli to this version , execute :
2020-03-05 09:55:33 +03:00
hasura update - cli -- version % s
2021-11-11 13:55:16 +03:00
` , preReleaseVersion . Original ( ) )
2020-03-05 09:55:33 +03:00
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 ) {
2022-11-07 14:13:12 +03:00
return errors . E ( op , "permission denied, try again as admin or with sudo" )
2019-02-04 13:51:29 +03:00
}
2022-11-07 14:13:12 +03:00
return errors . E ( op , fmt . Errorf ( "apply update: %w" , err ) )
2019-02-04 13:51:29 +03:00
}
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
}
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 ( ) )
}