mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 08:02:15 +03:00
parent
76fbe90b60
commit
491a50b1e9
@ -119,7 +119,11 @@ deploy_cli_ext() {
|
||||
git clone https://github.com/hasura/cli-plugins-index.git ~/plugins-index
|
||||
cd ~/plugins-index
|
||||
git checkout -b cli-ext-${LATEST_TAG}
|
||||
mkdir -p ./plugins/cli-ext/${LATEST_TAG}
|
||||
# Replace existing cli-ext.yaml to work with previous versions of plugin system
|
||||
cp ${DIST_PATH}/manifest.yaml ./plugins/cli-ext.yaml
|
||||
# Copy the manifest to versioned folder structure
|
||||
cp ${DIST_PATH}/manifest.yaml ./plugins/cli-ext/${LATEST_TAG}/manifest.yaml
|
||||
git add .
|
||||
git commit -m "update cli-ext manifest to ${LATEST_TAG}"
|
||||
git push -q https://${GITHUB_TOKEN}@github.com/hasura/cli-plugins-index.git cli-ext-${LATEST_TAG}
|
||||
|
41
cli/cli.go
41
cli/cli.go
@ -19,8 +19,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/hasura/graphql-engine/cli/metadata/actions/types"
|
||||
@ -32,6 +31,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Other constants used in the package
|
||||
@ -43,6 +43,9 @@ const (
|
||||
|
||||
// Name of the file to store last update check time
|
||||
LastUpdateCheckFileName = "last_update_check_at"
|
||||
|
||||
// Name of the cli extension plugin
|
||||
CLIExtPluginName = "cli-ext"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -606,6 +609,40 @@ func (ec *ExecutionContext) setVersion() {
|
||||
}
|
||||
}
|
||||
|
||||
// InstallPlugin installs a plugin depending on forceCLIVersion.
|
||||
// If forceCLIVersion is set, it uses ec.Version.CLISemver version for the plugin to be installed.
|
||||
// Else, it installs the latest version of the plugin
|
||||
func (ec ExecutionContext) InstallPlugin(name string, forceCLIVersion bool) error {
|
||||
prevPrefix := ec.Spinner.Prefix
|
||||
ec.Spin(fmt.Sprintf("Installing plugin %s...", name))
|
||||
defer ec.Spin(prevPrefix)
|
||||
|
||||
var version *semver.Version
|
||||
if forceCLIVersion {
|
||||
err := ec.PluginsConfig.Repo.EnsureUpdated()
|
||||
if err != nil {
|
||||
ec.Logger.Debugf("cannot update plugin index %v", err)
|
||||
}
|
||||
version = ec.Version.CLISemver
|
||||
}
|
||||
err := ec.PluginsConfig.Install(name, plugins.InstallOpts{
|
||||
Version: version,
|
||||
})
|
||||
if err != nil {
|
||||
if err != plugins.ErrIsAlreadyInstalled {
|
||||
msg := fmt.Sprintf(`unable to install %s plugin. execute the following commands to continue:
|
||||
|
||||
hasura plugins install %s
|
||||
`, name, name)
|
||||
ec.Logger.Info(msg)
|
||||
return errors.Wrapf(err, "cannot install plugin %s", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
ec.Logger.WithField("name", name).Infoln("plugin installed")
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAdminSecretHeaderName(v *version.Version) string {
|
||||
if v.ServerFeatureFlags.HasAccessKey {
|
||||
return XHasuraAccessKey
|
||||
|
@ -77,5 +77,8 @@ type PluginInstallOptions struct {
|
||||
}
|
||||
|
||||
func (o *PluginInstallOptions) Run() error {
|
||||
return o.EC.PluginsConfig.Install(o.Name, o.ManifestFile, o.Version.Version)
|
||||
return o.EC.PluginsConfig.Install(o.Name, plugins.InstallOpts{
|
||||
ManifestFile: o.ManifestFile,
|
||||
Version: o.Version.Version,
|
||||
})
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import (
|
||||
"github.com/hasura/graphql-engine/cli/migrate/database/hasuradb"
|
||||
"github.com/hasura/graphql-engine/cli/migrate/source"
|
||||
"github.com/hasura/graphql-engine/cli/migrate/source/file"
|
||||
"github.com/hasura/graphql-engine/cli/plugins"
|
||||
"github.com/hasura/graphql-engine/cli/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -66,10 +65,10 @@ func newScriptsUpdateConfigV2Cmd(ec *cli.ExecutionContext) *cobra.Command {
|
||||
return errors.Wrap(err, "cannot update plugin index")
|
||||
}
|
||||
// install the plugin
|
||||
ec.Spin("Installing cli-ext plugin...")
|
||||
err = ec.PluginsConfig.Install("cli-ext", "", nil)
|
||||
if err != nil && err != plugins.ErrIsAlreadyInstalled {
|
||||
return errors.Wrap(err, "cannot install plugin")
|
||||
ec.Spin(fmt.Sprintf("Installing %s plugin...", cli.CLIExtPluginName))
|
||||
err = ec.InstallPlugin(cli.CLIExtPluginName, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Move copy migrations directory to migrations_backup
|
||||
ec.Spin("Backing up migrations...")
|
||||
|
@ -94,12 +94,12 @@ func TestCommands(t *testing.T) {
|
||||
t.Run("cli-ext-plugin-install", func(t *testing.T) {
|
||||
installOpts := &commands.PluginInstallOptions{
|
||||
EC: ec,
|
||||
Name: "cli-ext",
|
||||
Name: cli.CLIExtPluginName,
|
||||
ManifestFile: "/build/_cli_ext_output/manifest-dev.yaml",
|
||||
}
|
||||
err := installOpts.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to install cli-ext plugin, got %v", err)
|
||||
t.Fatalf("unable to install %s plugin, got %v", cli.CLIExtPluginName, err)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
const (
|
||||
actionsFileName string = "actions.yaml"
|
||||
graphqlFileName = "actions.graphql"
|
||||
pluginName = "cli-ext"
|
||||
)
|
||||
|
||||
type ActionConfig struct {
|
||||
@ -33,6 +32,7 @@ type ActionConfig struct {
|
||||
serverFeatureFlags *version.ServerFeatureFlags
|
||||
pluginsCfg *plugins.Config
|
||||
cliExtensionConfig *cliextension.Config
|
||||
pluginInstallFunc func(string, bool) error
|
||||
|
||||
logger *logrus.Logger
|
||||
}
|
||||
@ -45,15 +45,16 @@ func New(ec *cli.ExecutionContext, baseDir string) *ActionConfig {
|
||||
logger: ec.Logger,
|
||||
pluginsCfg: ec.PluginsConfig,
|
||||
cliExtensionConfig: cliextension.NewCLIExtensionConfig(ec.PluginsConfig.Paths.BinPath(), ec.Logger),
|
||||
pluginInstallFunc: ec.InstallPlugin,
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (a *ActionConfig) Create(name string, introSchema interface{}, deriveFrom string) error {
|
||||
// Ensure CLI Extesnion
|
||||
err := a.ensureCLIExtension()
|
||||
err := a.pluginInstallFunc(cli.CLIExtPluginName, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error in install cli-extension plugin")
|
||||
return err
|
||||
}
|
||||
// Read the content of graphql file
|
||||
graphqlFileContent, err := a.GetActionsGraphQLFileContent()
|
||||
@ -283,9 +284,9 @@ input SampleInput {
|
||||
}
|
||||
|
||||
func (a *ActionConfig) Codegen(name string, derivePld types.DerivePayload) error {
|
||||
err := a.ensureCLIExtension()
|
||||
err := a.pluginInstallFunc(cli.CLIExtPluginName, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error in install cli-extension plugin")
|
||||
return err
|
||||
}
|
||||
|
||||
graphqlFileContent, err := a.GetActionsGraphQLFileContent()
|
||||
@ -350,9 +351,9 @@ func (a *ActionConfig) Build(metadata *yaml.MapSlice) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err := a.ensureCLIExtension()
|
||||
err := a.pluginInstallFunc(cli.CLIExtPluginName, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error in install cli-extension plugin")
|
||||
return err
|
||||
}
|
||||
// Read actions.graphql
|
||||
graphqlFileContent, err := a.GetActionsGraphQLFileContent()
|
||||
@ -471,9 +472,9 @@ func (a *ActionConfig) Export(metadata yaml.MapSlice) (map[string][]byte, error)
|
||||
a.logger.Debugf("Skipping creating %s and %s", actionsFileName, graphqlFileName)
|
||||
return make(map[string][]byte), nil
|
||||
}
|
||||
err := a.ensureCLIExtension()
|
||||
err := a.pluginInstallFunc(cli.CLIExtPluginName, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error in install cli-extension plugin")
|
||||
return nil, err
|
||||
}
|
||||
var actions yaml.MapSlice
|
||||
for _, item := range metadata {
|
||||
@ -520,19 +521,6 @@ func (a *ActionConfig) Name() string {
|
||||
return "actions"
|
||||
}
|
||||
|
||||
func (a *ActionConfig) ensureCLIExtension() error {
|
||||
err := a.pluginsCfg.Install(pluginName, "", nil)
|
||||
if err != nil && err != plugins.ErrIsAlreadyInstalled {
|
||||
msg := fmt.Sprintf(`unable to install cli-ext plugin. execute the following commands to continue:
|
||||
|
||||
hasura plugins install %s
|
||||
`, pluginName)
|
||||
a.logger.Info(msg)
|
||||
return errors.Wrap(err, "cannot install cli-ext plugin")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *ActionConfig) GetActionsFileContent() (content types.Common, err error) {
|
||||
commonByt, err := ioutil.ReadFile(filepath.Join(a.MetadataDir, actionsFileName))
|
||||
if err != nil {
|
||||
|
@ -9,8 +9,11 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hasura/graphql-engine/cli"
|
||||
|
||||
gyaml "github.com/ghodss/yaml"
|
||||
"github.com/hasura/graphql-engine/cli/metadata/actions/types"
|
||||
"github.com/hasura/graphql-engine/cli/plugins"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
@ -25,7 +28,7 @@ type Config struct {
|
||||
// NewCLIExtensionConfig creates CLIExtensionConfig to interact with cli-extension plugin
|
||||
func NewCLIExtensionConfig(binDir string, logger *logrus.Logger) *Config {
|
||||
return &Config{
|
||||
binPath: filepath.Join(binDir, "hasura-cli_ext"),
|
||||
binPath: filepath.Join(binDir, plugins.PluginNameToBin(cli.CLIExtPluginName, plugins.IsWindows())),
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
@ -45,11 +45,18 @@ type Config struct {
|
||||
Logger *logrus.Logger
|
||||
}
|
||||
|
||||
// InstallOpts - options available during plugin install
|
||||
type InstallOpts struct {
|
||||
ManifestFile string
|
||||
|
||||
Version *semver.Version
|
||||
}
|
||||
|
||||
func New(base string) *Config {
|
||||
p := paths.NewPaths(base)
|
||||
return &Config{
|
||||
Paths: p,
|
||||
Repo: util.NewGitUtil(indexURI, p.IndexPath(), ""),
|
||||
Repo: util.NewGitUtil(indexURI, p.IndexPath(), "multiple-version"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,10 +93,10 @@ func (c *Config) ListPlugins() (Plugins, error) {
|
||||
return c.LoadPluginListFromFS(c.Paths.IndexPluginsPath())
|
||||
}
|
||||
|
||||
func (c *Config) Install(pluginName string, mainfestFile string, version *semver.Version) error {
|
||||
func (c *Config) Install(pluginName string, opts InstallOpts) error {
|
||||
var plugin Plugin
|
||||
var err error
|
||||
if mainfestFile == "" {
|
||||
if opts.ManifestFile == "" {
|
||||
// Load the plugin index by name
|
||||
ps, err := c.LoadPluginByName(pluginName)
|
||||
if err != nil {
|
||||
@ -105,12 +112,12 @@ func (c *Config) Install(pluginName string, mainfestFile string, version *semver
|
||||
return errors.Wrap(err, "failed to look up plugin receipt")
|
||||
}
|
||||
|
||||
if version != nil {
|
||||
if pluginReceipt.Version == version.Original() {
|
||||
if opts.Version != nil {
|
||||
if pluginReceipt.Version == opts.Version.Original() {
|
||||
return ErrIsAlreadyInstalled
|
||||
}
|
||||
// check if version is available
|
||||
ver := ps.Index.Search(version)
|
||||
ver := ps.Index.Search(opts.Version)
|
||||
if ver != nil {
|
||||
plugin = ps.Versions[ver]
|
||||
} else {
|
||||
@ -125,12 +132,12 @@ func (c *Config) Install(pluginName string, mainfestFile string, version *semver
|
||||
plugin = ps.Versions[latestVersion]
|
||||
}
|
||||
} else {
|
||||
plugin, err = c.ReadPluginFromFile(mainfestFile)
|
||||
plugin, err = c.ReadPluginFromFile(opts.ManifestFile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load plugin manifest from file")
|
||||
}
|
||||
if plugin.Name != pluginName {
|
||||
return fmt.Errorf("plugin name %s doesn't match with plugin in the manifest file %s", pluginName, mainfestFile)
|
||||
return fmt.Errorf("plugin name %s doesn't match with plugin in the manifest file %s", pluginName, opts.ManifestFile)
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +149,6 @@ func (c *Config) Install(pluginName string, mainfestFile string, version *semver
|
||||
if !ok {
|
||||
return errors.Errorf("plugin %q does not offer installation for this platform", plugin.Name)
|
||||
}
|
||||
|
||||
if err := c.installPlugin(plugin, platform); err != nil {
|
||||
return errors.Wrap(err, "install failed")
|
||||
}
|
||||
@ -159,7 +165,7 @@ func (c *Config) Uninstall(name string) error {
|
||||
return errors.Wrapf(err, "failed to look up install receipt for plugin %q", name)
|
||||
}
|
||||
|
||||
symlinkPath := filepath.Join(c.Paths.BinPath(), pluginNameToBin(name, IsWindows()))
|
||||
symlinkPath := filepath.Join(c.Paths.BinPath(), PluginNameToBin(name, IsWindows()))
|
||||
if err := removeLink(symlinkPath); err != nil {
|
||||
return errors.Wrap(err, "could not uninstall symlink of plugin")
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ func IsWindows() bool {
|
||||
}
|
||||
|
||||
func createOrUpdateLink(binDir, binary, plugin string) error {
|
||||
dst := filepath.Join(binDir, pluginNameToBin(plugin, IsWindows()))
|
||||
dst := filepath.Join(binDir, PluginNameToBin(plugin, IsWindows()))
|
||||
|
||||
if err := removeLink(dst); err != nil {
|
||||
return errors.Wrap(err, "failed to remove old symlink")
|
||||
@ -168,9 +168,9 @@ func removeLink(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// pluginNameToBin creates the name of the symlink file for the plugin name.
|
||||
// PluginNameToBin creates the name of the symlink file for the plugin name.
|
||||
// It converts dashes to underscores.
|
||||
func pluginNameToBin(name string, isWindows bool) string {
|
||||
func PluginNameToBin(name string, isWindows bool) string {
|
||||
name = strings.ReplaceAll(name, "-", "_")
|
||||
name = "hasura-" + name
|
||||
if isWindows {
|
||||
|
Loading…
Reference in New Issue
Block a user