diff --git a/Magefile.go b/Magefile.go index 20515fe0..544efa85 100644 --- a/Magefile.go +++ b/Magefile.go @@ -10,6 +10,7 @@ import ( "log" "os" "runtime" + "strings" "github.com/magefile/mage/mg" "github.com/magefile/mage/sh" @@ -260,6 +261,12 @@ func (Run) V2Local(ctx context.Context, path string, sourceCodePath string) erro func (Run) SourceDiffLocal(ctx context.Context, archive string, source string) error { buildCommand("sourcemapdiff", runtime.GOOS+"_"+runtime.GOARCH) + + // if source doesn't start with http or file:// add file:// + if !strings.HasPrefix(source, "http://") && !strings.HasPrefix(source, "file://") { + source = "file://" + source + } + command := []string{ "./bin/" + runtime.GOOS + "_" + runtime.GOARCH + "/sourcemapdiff", "-archiveUri", archive} diff --git a/pkg/cmd/plugincheck2/main.go b/pkg/cmd/plugincheck2/main.go index e4f2d1fe..d3ea9fd8 100644 --- a/pkg/cmd/plugincheck2/main.go +++ b/pkg/cmd/plugincheck2/main.go @@ -6,8 +6,10 @@ import ( "flag" "fmt" "os" + "path/filepath" "strings" + "github.com/bmatcuk/doublestar/v4" "github.com/fatih/color" "github.com/grafana/plugin-validator/pkg/analysis" "github.com/grafana/plugin-validator/pkg/analysis/passes" @@ -86,13 +88,12 @@ func main() { if cfg.Global.JSONOutput { pluginID, pluginVersion, err := GetIDAndVersion(archiveDir) if err != nil { - pluginID = "unknown" - pluginVersion = "unknown" + pluginID, pluginVersion = GetIDAndVersionFallBack(archiveDir) archiveDiag := analysis.Diagnostic{ Name: "zip-invalid", Severity: analysis.Error, - Title: "ZIP is improperly structured", - Context: "could not read plugin.json from archive to determine id and version", + Title: "Plugin archive is improperly structured", + Context: "Could not find a plugin.json in the expected located. It is possible your plugin archive structure is incorrect.", } diags["archive"] = append(diags["archive"], archiveDiag) } @@ -178,6 +179,26 @@ func readConfigFile(path string) (runner.Config, error) { return config, nil } +func getSourceCodeDirSubDir(sourceCodePath string) string { + // check if there's a package.json in the source code directory + // if so return the source code directory as is + if _, err := os.Stat(filepath.Join(sourceCodePath, "package.json")); err == nil { + return sourceCodePath + } + + // use double start to find the first ocurrance of package.json + possiblePath, err := doublestar.FilepathGlob(sourceCodePath + "/**/package.json") + if err != nil { + return sourceCodePath + } + if len(possiblePath) == 0 { + return sourceCodePath + } + logme.DebugFln("Detected sourcecode inside a subdir: %v. Returning %s", possiblePath, filepath.Dir(possiblePath[0])) + // possiblePath points to a file, return the dir + return filepath.Dir(possiblePath[0]) +} + func getSourceCodeDir(sourceCodeUri string) (string, func(), error) { // If source code URI is not provided, return immediately with an empty string // otherwise we will get an error when trying to extract the source code archive @@ -207,6 +228,9 @@ func getSourceCodeDir(sourceCodeUri string) (string, func(), error) { if err != nil { return "", sourceCodeCleanUp, fmt.Errorf("couldn't extract source code archive: %s. %w", sourceCodeUri, err) } + // some submissions from zip have their source code in a subdirectory + // of the extracted archive + extractedDir = getSourceCodeDirSubDir(extractedDir) return extractedDir, sourceCodeCleanUp, nil } diff --git a/pkg/cmd/plugincheck2/quickmeta.go b/pkg/cmd/plugincheck2/quickmeta.go index 8ec92e61..2687b8f3 100644 --- a/pkg/cmd/plugincheck2/quickmeta.go +++ b/pkg/cmd/plugincheck2/quickmeta.go @@ -5,8 +5,45 @@ import ( "fmt" "os" "path/filepath" + + "github.com/bmatcuk/doublestar/v4" ) +func getIdAndVersionFromFile(pluginJsonPath string) (string, string, error) { + b, err := os.ReadFile(pluginJsonPath) + if err != nil { + fmt.Fprintln(os.Stderr, fmt.Errorf("cannot read plugin.json: %w", err)) + return "", "", err + } + var data struct { + ID string `json:"id"` + Info struct { + Version string `json:"version"` + } `json:"info"` + } + if err := json.Unmarshal(b, &data); err != nil { + fmt.Fprintln(os.Stderr, fmt.Errorf("couldn't get plugin meta: %w", err)) + return "", "", err + } + return data.ID, data.Info.Version, nil + +} + +func GetIDAndVersionFallBack(archiveDir string) (string, string) { + // try to find a plugin.json anywhere in the archive + pluginJsonPath, err := doublestar.FilepathGlob(archiveDir + "/**/plugin.json") + if err != nil { + return "unknown", "unknown" + } + + pluginId, pluginVersion, err := getIdAndVersionFromFile(pluginJsonPath[0]) + if err != nil { + return "unknown", "unknown" + } + return pluginId, pluginVersion + +} + // GetIDAndVersion Gets plugin id and version from extracted zip func GetIDAndVersion(archiveDir string) (string, string, error) { // check extracted archive directory first @@ -40,20 +77,11 @@ func GetIDAndVersion(archiveDir string) (string, string, error) { fmt.Fprintln(os.Stderr, fmt.Errorf("plugin.json is not a file: %s", filename)) return "", "", err } - b, err := os.ReadFile(filename) + + pluginId, pluginVersion, err := getIdAndVersionFromFile(filename) if err != nil { - fmt.Fprintln(os.Stderr, fmt.Errorf("cannot read plugin.json: %w", err)) return "", "", err } - var data struct { - ID string `json:"id"` - Info struct { - Version string `json:"version"` - } `json:"info"` - } - if err := json.Unmarshal(b, &data); err != nil { - fmt.Fprintln(os.Stderr, fmt.Errorf("couldn't get plugin meta: %w", err)) - return "nil", "", err - } - return data.ID, data.Info.Version, nil + + return pluginId, pluginVersion, nil }