pluginctl/plugin.go
Felipe Martin 873bf78c22
Add custom parser for props["pluginctl"] with ignore assets support
- Add PluginCtlConfig struct with IgnoreAssets field for glob patterns
- Add ParsePluginCtlConfig function to parse manifest props["pluginctl"]
- Update updateassets command to respect ignore patterns with glob matching
- Add comprehensive logging when files are skipped due to ignore patterns
- Support patterns like *.test.js, build/, node_modules for flexible exclusion
- Add extensive tests for config parsing and path matching functionality
- Maintain backward compatibility with existing manifests
- Fix Makefile check-changes target and add logger init to tests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-14 17:38:38 +02:00

116 lines
3.1 KiB
Go

package pluginctl
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/mattermost/mattermost/server/public/model"
)
const PluginManifestName = "plugin.json"
// PluginCtlConfig represents the configuration for pluginctl stored in the manifest props.
type PluginCtlConfig struct {
IgnoreAssets []string `json:"ignore_assets,omitempty"`
}
// LoadPluginManifest loads and parses the plugin.json file from the current directory.
func LoadPluginManifest() (*model.Manifest, error) {
return LoadPluginManifestFromPath(".")
}
// LoadPluginManifestFromPath loads and parses the plugin.json file from the specified directory.
func LoadPluginManifestFromPath(dir string) (*model.Manifest, error) {
manifestPath := filepath.Join(dir, PluginManifestName)
// Check if plugin.json exists
if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
return nil, fmt.Errorf("plugin.json not found in directory %s", dir)
}
// Read the file
data, err := os.ReadFile(manifestPath)
if err != nil {
return nil, fmt.Errorf("failed to read plugin.json: %w", err)
}
// Parse JSON into Manifest struct
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
}
// HasServerCode checks if the plugin contains server-side code.
func HasServerCode(manifest *model.Manifest) bool {
return manifest.Server != nil && len(manifest.Server.Executables) > 0
}
// HasWebappCode checks if the plugin contains webapp code.
func HasWebappCode(manifest *model.Manifest) bool {
return manifest.Webapp != nil && manifest.Webapp.BundlePath != ""
}
// IsValidPluginDirectory checks if the current directory contains a valid plugin.
func IsValidPluginDirectory() error {
_, err := LoadPluginManifest()
return err
}
// GetEffectivePluginPath determines the plugin path from flag, environment variable, or current directory.
func GetEffectivePluginPath(flagPath string) string {
const EnvPluginPath = "PLUGINCTL_PLUGIN_PATH"
// 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
}
// ParsePluginCtlConfig extracts and parses the pluginctl configuration from the manifest props.
func ParsePluginCtlConfig(manifest *model.Manifest) (*PluginCtlConfig, error) {
// Default configuration
config := &PluginCtlConfig{
IgnoreAssets: []string{},
}
// Check if props exist
if manifest.Props == nil {
return config, nil
}
// Check if pluginctl config exists in props
pluginctlData, exists := manifest.Props["pluginctl"]
if !exists {
return config, nil
}
// Convert to JSON and parse
jsonData, err := json.Marshal(pluginctlData)
if err != nil {
return nil, fmt.Errorf("failed to marshal pluginctl config: %w", err)
}
if err := json.Unmarshal(jsonData, config); err != nil {
return nil, fmt.Errorf("failed to parse pluginctl config: %w", err)
}
return config, nil
}