Add enable/disable/reset commands
This commit is contained in:
parent
fd6e4a4513
commit
1ea8f2b38a
11 changed files with 221 additions and 163 deletions
10
CLAUDE.md
10
CLAUDE.md
|
@ -22,18 +22,22 @@ pluginctl/
|
||||||
|
|
||||||
#### 1. **Separation of Concerns**
|
#### 1. **Separation of Concerns**
|
||||||
- **CLI Framework**: `cmd/pluginctl/main.go` handles argument parsing, command routing, and error handling
|
- **CLI Framework**: `cmd/pluginctl/main.go` handles argument parsing, command routing, and error handling
|
||||||
- **Command Implementation**: Each command gets its own file (e.g., `info.go`, `build.go`, `deploy.go`)
|
- **Command Implementation**: Each command gets its own file (e.g., `info.go`, `build.go`, `deploy.go`) **IN THE ROOT FOLDER, NOT IN cmd/pluginctl/**
|
||||||
- **Utility Functions**: Common plugin operations in `plugin.go`
|
- **Utility Functions**: Common plugin operations in `plugin.go`
|
||||||
|
|
||||||
|
**CRITICAL ARCHITECTURE RULE**: ALL COMMAND LOGIC MUST BE IN SEPARATE FILES IN THE ROOT FOLDER. The cmd/pluginctl/main.go file should ONLY contain CLI framework code (argument parsing, command routing, wrapper functions). Never put command implementation logic directly in main.go.
|
||||||
|
|
||||||
#### 2. **Plugin Manifest Handling**
|
#### 2. **Plugin Manifest Handling**
|
||||||
- **Always use official Mattermost types**: Import `github.com/mattermost/mattermost/server/public/model` and use `model.Manifest`
|
- **Always use official Mattermost types**: Import `github.com/mattermost/mattermost/server/public/model` and use `model.Manifest`
|
||||||
- **Validation**: Always validate plugin.json existence and format before operations
|
- **Validation**: Always validate plugin.json existence and format before operations
|
||||||
- **Path handling**: Support both current directory and custom path operations
|
- **Path handling**: Support both current directory and custom path operations
|
||||||
|
|
||||||
#### 3. **Command Structure**
|
#### 3. **Command Structure**
|
||||||
- **Main command router**: Add new commands to the `runCommand()` function in `main.go`
|
- **Main command router**: Add new commands to the `runCommand()` function in `cmd/pluginctl/main.go`
|
||||||
- **Command functions**: Name pattern: `run[Command]Command(args []string) error`
|
- **Command functions**: Name pattern: `run[Command]Command(args []string, pluginPath string) error`
|
||||||
- **Error handling**: Return descriptive errors, let main.go handle exit codes
|
- **Error handling**: Return descriptive errors, let main.go handle exit codes
|
||||||
|
- **Command implementation**: Each command's logic goes in a separate file in the root folder (e.g., `enable.go`, `disable.go`, `reset.go`)
|
||||||
|
- **Command wrapper functions**: The main.go file contains simple wrapper functions that call the actual command implementations
|
||||||
|
|
||||||
#### 4. **Code Organization**
|
#### 4. **Code Organization**
|
||||||
- **No inline implementations**: Keep command logic in separate files
|
- **No inline implementations**: Keep command logic in separate files
|
||||||
|
|
102
client.go
Normal file
102
client.go
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
package pluginctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
const commandTimeout = 120 * time.Second
|
||||||
|
|
||||||
|
func getClient(ctx context.Context) (*model.Client4, error) {
|
||||||
|
socketPath := os.Getenv("MM_LOCALSOCKETPATH")
|
||||||
|
if socketPath == "" {
|
||||||
|
socketPath = model.LocalModeSocketPath
|
||||||
|
}
|
||||||
|
|
||||||
|
client, connected := getUnixClient(socketPath)
|
||||||
|
if connected {
|
||||||
|
log.Printf("Connecting using local mode over %s", socketPath)
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("MM_LOCALSOCKETPATH") != "" {
|
||||||
|
log.Printf("No socket found at %s for local mode deployment. "+
|
||||||
|
"Attempting to authenticate with credentials.", socketPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
siteURL := os.Getenv("MM_SERVICESETTINGS_SITEURL")
|
||||||
|
adminToken := os.Getenv("MM_ADMIN_TOKEN")
|
||||||
|
adminUsername := os.Getenv("MM_ADMIN_USERNAME")
|
||||||
|
adminPassword := os.Getenv("MM_ADMIN_PASSWORD")
|
||||||
|
|
||||||
|
if siteURL == "" {
|
||||||
|
return nil, errors.New("MM_SERVICESETTINGS_SITEURL is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
client = model.NewAPIv4Client(siteURL)
|
||||||
|
|
||||||
|
if adminToken != "" {
|
||||||
|
log.Printf("Authenticating using token against %s.", siteURL)
|
||||||
|
client.SetToken(adminToken)
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if adminUsername != "" && adminPassword != "" {
|
||||||
|
client := model.NewAPIv4Client(siteURL)
|
||||||
|
log.Printf("Authenticating as %s against %s.", adminUsername, siteURL)
|
||||||
|
_, _, err := client.Login(ctx, adminUsername, adminPassword)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to login as %s: %w", adminUsername, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("one of MM_ADMIN_TOKEN or MM_ADMIN_USERNAME/MM_ADMIN_PASSWORD must be defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUnixClient(socketPath string) (*model.Client4, bool) {
|
||||||
|
_, err := net.Dial("unix", socketPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return model.NewAPIv4SocketClient(socketPath), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// runPluginCommand executes a plugin command using the plugin from the current folder.
|
||||||
|
func runPluginCommand(
|
||||||
|
_ []string,
|
||||||
|
pluginPath string,
|
||||||
|
action func(context.Context, *model.Client4, string) error,
|
||||||
|
) error {
|
||||||
|
// Load plugin manifest to get the plugin ID
|
||||||
|
manifest, err := LoadPluginManifestFromPath(pluginPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to load plugin manifest: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginID := manifest.Id
|
||||||
|
if pluginID == "" {
|
||||||
|
return errors.New("plugin ID not found in manifest")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), commandTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
client, err := getClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return action(ctx, client, pluginID)
|
||||||
|
}
|
|
@ -1,14 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"runtime/debug"
|
|
||||||
|
|
||||||
"github.com/mattermost/mattermost/server/public/model"
|
"github.com/mattermost/pluginctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -34,7 +31,7 @@ func main() {
|
||||||
commandArgs := args[1:]
|
commandArgs := args[1:]
|
||||||
|
|
||||||
// Determine plugin path from flag, environment variable, or current directory
|
// Determine plugin path from flag, environment variable, or current directory
|
||||||
effectivePluginPath := getEffectivePluginPath(pluginPath)
|
effectivePluginPath := pluginctl.GetEffectivePluginPath(pluginPath)
|
||||||
|
|
||||||
if err := runCommand(command, commandArgs, effectivePluginPath); err != nil {
|
if err := runCommand(command, commandArgs, effectivePluginPath); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
@ -46,6 +43,12 @@ func runCommand(command string, args []string, pluginPath string) error {
|
||||||
switch command {
|
switch command {
|
||||||
case "info":
|
case "info":
|
||||||
return runInfoCommand(args, pluginPath)
|
return runInfoCommand(args, pluginPath)
|
||||||
|
case "enable":
|
||||||
|
return runEnableCommand(args, pluginPath)
|
||||||
|
case "disable":
|
||||||
|
return runDisableCommand(args, pluginPath)
|
||||||
|
case "reset":
|
||||||
|
return runResetCommand(args, pluginPath)
|
||||||
case "help":
|
case "help":
|
||||||
showUsage()
|
showUsage()
|
||||||
|
|
||||||
|
@ -58,160 +61,25 @@ func runCommand(command string, args []string, pluginPath string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runInfoCommand(args []string, pluginPath string) error {
|
func runInfoCommand(args []string, pluginPath string) error {
|
||||||
// Convert to absolute path
|
return pluginctl.RunInfoCommand(args, pluginPath)
|
||||||
absPath, err := filepath.Abs(pluginPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to resolve path: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return infoCommandWithPath(absPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runVersionCommand(args []string) error {
|
func runVersionCommand(_ []string) error {
|
||||||
version := getVersion()
|
version := pluginctl.GetVersion()
|
||||||
fmt.Printf("pluginctl version %s\n", version)
|
fmt.Printf("pluginctl version %s\n", version)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func runEnableCommand(args []string, pluginPath string) error {
|
||||||
// getVersion returns the version information from build info.
|
return pluginctl.RunEnableCommand(args, pluginPath)
|
||||||
func getVersion() string {
|
|
||||||
info, ok := debug.ReadBuildInfo()
|
|
||||||
if !ok {
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
// First try to get version from main module
|
|
||||||
if info.Main.Version != "" && info.Main.Version != "(devel)" {
|
|
||||||
return info.Main.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for version in build settings (set by goreleaser)
|
|
||||||
for _, setting := range info.Settings {
|
|
||||||
if setting.Key == "vcs.revision" {
|
|
||||||
// Return short commit hash if no version tag
|
|
||||||
if len(setting.Value) >= 7 {
|
|
||||||
return setting.Value[:7]
|
|
||||||
}
|
|
||||||
return setting.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "dev"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getEffectivePluginPath determines the plugin path from flag, environment variable, or current directory.
|
func runDisableCommand(args []string, pluginPath string) error {
|
||||||
func getEffectivePluginPath(flagPath string) string {
|
return pluginctl.RunDisableCommand(args, pluginPath)
|
||||||
// Priority: 1. Command line flag, 2. Environment variable, 3. Current directory
|
|
||||||
if flagPath != "" {
|
|
||||||
return flagPath
|
|
||||||
}
|
|
||||||
|
|
||||||
if envPath := os.Getenv(EnvPluginPath); envPath != "" {
|
|
||||||
return envPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default to current directory
|
|
||||||
cwd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return "."
|
|
||||||
}
|
|
||||||
|
|
||||||
return cwd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func infoCommandWithPath(path string) error {
|
func runResetCommand(args []string, pluginPath string) error {
|
||||||
manifest, err := loadPluginManifestFromPath(path)
|
return pluginctl.RunResetCommand(args, pluginPath)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to load plugin manifest from %s: %w", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return printPluginInfo(manifest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadPluginManifestFromPath(dir string) (*model.Manifest, error) {
|
|
||||||
manifestPath := filepath.Join(dir, "plugin.json")
|
|
||||||
|
|
||||||
if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
|
|
||||||
return nil, fmt.Errorf("plugin.json not found in directory %s", dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := os.ReadFile(manifestPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to read plugin.json: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var manifest model.Manifest
|
|
||||||
if err := json.Unmarshal(data, &manifest); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse plugin.json: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &manifest, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func printPluginInfo(manifest *model.Manifest) error {
|
|
||||||
fmt.Printf("Plugin Information:\n")
|
|
||||||
fmt.Printf("==================\n\n")
|
|
||||||
|
|
||||||
fmt.Printf("ID: %s\n", manifest.Id)
|
|
||||||
fmt.Printf("Name: %s\n", manifest.Name)
|
|
||||||
fmt.Printf("Version: %s\n", manifest.Version)
|
|
||||||
|
|
||||||
if manifest.MinServerVersion != "" {
|
|
||||||
fmt.Printf("Min MM Version: %s\n", manifest.MinServerVersion)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Min MM Version: Not specified\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if manifest.Description != "" {
|
|
||||||
fmt.Printf("Description: %s\n", manifest.Description)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\nCode Components:\n")
|
|
||||||
fmt.Printf("================\n")
|
|
||||||
|
|
||||||
if hasServerCode(manifest) {
|
|
||||||
fmt.Printf("Server Code: Yes\n")
|
|
||||||
if manifest.Server != nil && len(manifest.Server.Executables) > 0 {
|
|
||||||
fmt.Printf(" Executables: ")
|
|
||||||
first := true
|
|
||||||
for platform := range manifest.Server.Executables {
|
|
||||||
if !first {
|
|
||||||
fmt.Printf(", ")
|
|
||||||
}
|
|
||||||
fmt.Printf("%s", platform)
|
|
||||||
first = false
|
|
||||||
}
|
|
||||||
fmt.Printf("\n")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Server Code: No\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if hasWebappCode(manifest) {
|
|
||||||
fmt.Printf("Webapp Code: Yes\n")
|
|
||||||
if manifest.Webapp != nil && manifest.Webapp.BundlePath != "" {
|
|
||||||
fmt.Printf(" Bundle Path: %s\n", manifest.Webapp.BundlePath)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Webapp Code: No\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
if manifest.SettingsSchema != nil {
|
|
||||||
fmt.Printf("Settings Schema: Yes\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Settings Schema: No\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasServerCode(manifest *model.Manifest) bool {
|
|
||||||
return manifest.Server != nil && len(manifest.Server.Executables) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasWebappCode(manifest *model.Manifest) bool {
|
|
||||||
return manifest.Webapp != nil && manifest.Webapp.BundlePath != ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showUsage() {
|
func showUsage() {
|
||||||
|
@ -225,18 +93,29 @@ Global Options:
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
info Display plugin information
|
info Display plugin information
|
||||||
|
enable Enable plugin from current directory in Mattermost server
|
||||||
|
disable Disable plugin from current directory in Mattermost server
|
||||||
|
reset Reset plugin from current directory (disable then enable)
|
||||||
help Show this help message
|
help Show this help message
|
||||||
version Show version information
|
version Show version information
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
pluginctl info # Show info for plugin in current directory
|
pluginctl info # Show info for plugin in current directory
|
||||||
pluginctl --plugin-path /path/to/plugin info # Show info for plugin at specific path
|
pluginctl --plugin-path /path/to/plugin info # Show info for plugin at specific path
|
||||||
|
pluginctl enable # Enable plugin from current directory
|
||||||
|
pluginctl disable # Disable plugin from current directory
|
||||||
|
pluginctl reset # Reset plugin from current directory (disable then enable)
|
||||||
export PLUGINCTL_PLUGIN_PATH=/path/to/plugin
|
export PLUGINCTL_PLUGIN_PATH=/path/to/plugin
|
||||||
pluginctl info # Show info using environment variable
|
pluginctl info # Show info using environment variable
|
||||||
pluginctl version # Show version information
|
pluginctl version # Show version information
|
||||||
|
|
||||||
Environment Variables:
|
Environment Variables:
|
||||||
PLUGINCTL_PLUGIN_PATH Default plugin directory path
|
PLUGINCTL_PLUGIN_PATH Default plugin directory path
|
||||||
|
MM_LOCALSOCKETPATH Path to Mattermost local socket
|
||||||
|
MM_SERVICESETTINGS_SITEURL Mattermost server URL
|
||||||
|
MM_ADMIN_TOKEN Admin token for authentication
|
||||||
|
MM_ADMIN_USERNAME Admin username for authentication
|
||||||
|
MM_ADMIN_PASSWORD Admin password for authentication
|
||||||
|
|
||||||
For more information about Mattermost plugin development, visit:
|
For more information about Mattermost plugin development, visit:
|
||||||
https://developers.mattermost.com/integrate/plugins/
|
https://developers.mattermost.com/integrate/plugins/
|
||||||
|
|
23
disable.go
Normal file
23
disable.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package pluginctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunDisableCommand(args []string, pluginPath string) error {
|
||||||
|
return runPluginCommand(args, pluginPath, disablePlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func disablePlugin(ctx context.Context, client *model.Client4, pluginID string) error {
|
||||||
|
log.Print("Disabling plugin.")
|
||||||
|
_, err := client.DisablePlugin(ctx, pluginID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to disable plugin: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
23
enable.go
Normal file
23
enable.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package pluginctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunEnableCommand(args []string, pluginPath string) error {
|
||||||
|
return runPluginCommand(args, pluginPath, enablePlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func enablePlugin(ctx context.Context, client *model.Client4, pluginID string) error {
|
||||||
|
log.Print("Enabling plugin.")
|
||||||
|
_, err := client.EnablePlugin(ctx, pluginID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to enable plugin: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
2
info.go
2
info.go
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package pluginctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package pluginctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package pluginctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package pluginctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
25
reset.go
Normal file
25
reset.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package pluginctl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/mattermost/mattermost/server/public/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunResetCommand(args []string, pluginPath string) error {
|
||||||
|
return runPluginCommand(args, pluginPath, resetPlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resetPlugin(ctx context.Context, client *model.Client4, pluginID string) error {
|
||||||
|
err := disablePlugin(ctx, client, pluginID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = enablePlugin(ctx, client, pluginID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
14
version.go
14
version.go
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package pluginctl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -7,14 +7,14 @@ import (
|
||||||
|
|
||||||
// RunVersionCommand implements the 'version' command functionality.
|
// RunVersionCommand implements the 'version' command functionality.
|
||||||
func RunVersionCommand(args []string) error {
|
func RunVersionCommand(args []string) error {
|
||||||
version := getVersion()
|
version := GetVersion()
|
||||||
fmt.Printf("pluginctl version %s\n", version)
|
fmt.Printf("pluginctl version %s\n", version)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getVersion returns the version information from build info.
|
// GetVersion returns the version information from build info.
|
||||||
func getVersion() string {
|
func GetVersion() string {
|
||||||
info, ok := debug.ReadBuildInfo()
|
info, ok := debug.ReadBuildInfo()
|
||||||
if !ok {
|
if !ok {
|
||||||
return "unknown"
|
return "unknown"
|
||||||
|
@ -29,9 +29,11 @@ func getVersion() string {
|
||||||
for _, setting := range info.Settings {
|
for _, setting := range info.Settings {
|
||||||
if setting.Key == "vcs.revision" {
|
if setting.Key == "vcs.revision" {
|
||||||
// Return short commit hash if no version tag
|
// Return short commit hash if no version tag
|
||||||
if len(setting.Value) >= 7 {
|
const shortHashLength = 7
|
||||||
return setting.Value[:7]
|
if len(setting.Value) >= shortHashLength {
|
||||||
|
return setting.Value[:shortHashLength]
|
||||||
}
|
}
|
||||||
|
|
||||||
return setting.Value
|
return setting.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue