Add version tracking and validation to prevent downgrade issues
Store the last pluginctl version used in plugin.json props and validate before running commands. Prevents issues when using older pluginctl versions on plugins modified by newer versions. - Add Version field to PluginCtlConfig struct - Implement version validation before command execution - Add WritePluginManifest and SavePluginCtlConfig helper functions - Add comprehensive tests for version comparison logic - Skip validation for 'version' command and when no plugin.json exists 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9d3c6b357f
commit
353cc9efc7
5 changed files with 286 additions and 51 deletions
67
manifest.go
67
manifest.go
|
@ -15,6 +15,9 @@ const (
|
|||
// File permissions for generated directories and files.
|
||||
manifestDirPerm = 0o750
|
||||
manifestFilePerm = 0o600
|
||||
|
||||
// Name of the plugin manifest file.
|
||||
PluginManifestName = "plugin.json"
|
||||
)
|
||||
|
||||
const pluginIDGoFileTemplate = `// This file is automatically generated. Do not modify it manually.
|
||||
|
@ -44,6 +47,51 @@ const manifest = JSON.parse(` + "`%s`" + `);
|
|||
export default manifest;
|
||||
`
|
||||
|
||||
// PluginCtlConfig represents the configuration for pluginctl stored in the manifest props.
|
||||
type PluginCtlConfig struct {
|
||||
Version string `json:"version,omitempty"`
|
||||
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 != ""
|
||||
}
|
||||
|
||||
// applyManifest generates manifest files for server and webapp components.
|
||||
func applyManifest(manifest *model.Manifest, pluginPath string) error {
|
||||
manifestBytes, err := json.Marshal(manifest)
|
||||
|
@ -168,3 +216,22 @@ Examples:
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WritePluginManifest saves the manifest to plugin.json in the specified path.
|
||||
func WritePluginManifest(manifest *model.Manifest, path string) error {
|
||||
manifestPath := filepath.Join(path, PluginManifestName)
|
||||
|
||||
// Marshal manifest to JSON with proper indentation
|
||||
data, err := json.MarshalIndent(manifest, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal manifest: %w", err)
|
||||
}
|
||||
|
||||
// Write to file
|
||||
const fileMode = 0600
|
||||
if err := os.WriteFile(manifestPath, data, fileMode); err != nil {
|
||||
return fmt.Errorf("failed to write plugin.json: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue