Skip to content

Commit cfe2d0a

Browse files
committed
ref: extract to separate analyzer, use semver
1 parent bbbfb76 commit cfe2d0a

9 files changed

Lines changed: 144 additions & 110 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/grafana/plugin-validator
33
go 1.25.5
44

55
require (
6+
github.com/Masterminds/semver/v3 v3.4.0
67
github.com/bmatcuk/doublestar/v4 v4.9.2
78
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
89
github.com/fatih/color v1.18.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ github.com/CycloneDX/cyclonedx-go v0.9.3 h1:Pyk/lwavPz7AaZNvugKFkdWOm93MzaIyWmBw
4242
github.com/CycloneDX/cyclonedx-go v0.9.3/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg=
4343
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 h1:IEjq88XO4PuBDcvmjQJcQGg+w+UaafSy8G5Kcb5tBhI=
4444
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5/go.mod h1:exZ0C/1emQJAw5tHOaUDyY1ycttqBAPcxuzf7QbY6ec=
45+
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
46+
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
4547
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
4648
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
4749
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=

pkg/analysis/passes/analysis.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/grafana/plugin-validator/pkg/analysis/passes/discoverability"
1818
"github.com/grafana/plugin-validator/pkg/analysis/passes/gomanifest"
1919
"github.com/grafana/plugin-validator/pkg/analysis/passes/gosec"
20+
"github.com/grafana/plugin-validator/pkg/analysis/passes/grafanadependency"
2021
"github.com/grafana/plugin-validator/pkg/analysis/passes/includesnested"
2122
"github.com/grafana/plugin-validator/pkg/analysis/passes/jargon"
2223
"github.com/grafana/plugin-validator/pkg/analysis/passes/jssourcemap"
@@ -103,4 +104,5 @@ var Analyzers = []*analysis.Analyzer{
103104
virusscan.Analyzer,
104105
circulardependencies.Analyzer,
105106
codediff.Analyzer,
107+
grafanadependency.Analyzer,
106108
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package grafanadependency
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
"github.com/Masterminds/semver/v3"
8+
"github.com/grafana/plugin-validator/pkg/analysis"
9+
"github.com/grafana/plugin-validator/pkg/analysis/passes/metadata"
10+
)
11+
12+
var (
13+
invalidGrafanaDependency = &analysis.Rule{Name: "invalid-grafana-dependency", Severity: analysis.Error}
14+
validGrafanaDependency = &analysis.Rule{Name: "valid-grafana-dependency", Severity: analysis.OK}
15+
)
16+
17+
var Analyzer = &analysis.Analyzer{
18+
Name: "grafanadependency",
19+
Requires: []*analysis.Analyzer{metadata.Analyzer},
20+
Run: run,
21+
Rules: []*analysis.Rule{invalidGrafanaDependency, validGrafanaDependency},
22+
ReadmeInfo: analysis.ReadmeInfo{
23+
Name: "Metadata Grafana Dependency",
24+
Description: "Checks that dependencies.grafanaDependency in `plugin.json` is valid.",
25+
},
26+
}
27+
28+
func run(pass *analysis.Pass) (interface{}, error) {
29+
metadataBytes, ok := pass.ResultOf[metadata.Analyzer].([]byte)
30+
if !ok {
31+
return nil, nil
32+
}
33+
34+
var data metadata.Metadata
35+
if err := json.Unmarshal(metadataBytes, &data); err != nil {
36+
// if we fail to unmarshall it means the schema is incorrect
37+
// we will let the metadatavalid validator handle it
38+
return nil, nil
39+
}
40+
41+
_, err := semver.NewConstraint(data.Dependencies.GrafanaDependency)
42+
if err != nil {
43+
pass.ReportResult(
44+
pass.AnalyzerName,
45+
invalidGrafanaDependency,
46+
fmt.Sprintf("plugin.json: dependencies.grafanaDependency field has invalid or empty version constraint: %q", data.Dependencies.GrafanaDependency),
47+
"The plugin.json file has an invalid or empty grafanaDependency field. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/#grafanadependency",
48+
)
49+
return nil, nil
50+
}
51+
52+
if validGrafanaDependency.ReportAll {
53+
pass.ReportResult(pass.AnalyzerName, validGrafanaDependency, "plugin.json: dependencies.grafanaDependency field is valid", "")
54+
}
55+
56+
return nil, nil
57+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package grafanadependency
2+
3+
import (
4+
"path/filepath"
5+
"testing"
6+
7+
"github.com/grafana/plugin-validator/pkg/analysis"
8+
"github.com/grafana/plugin-validator/pkg/analysis/passes/metadata"
9+
"github.com/grafana/plugin-validator/pkg/testpassinterceptor"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestGrafanaDependency(t *testing.T) {
14+
for _, tc := range []struct {
15+
name string
16+
pluginJSON string
17+
titleMsg string
18+
}{
19+
{
20+
name: "valid grafanaDependency constraint",
21+
pluginJSON: `{
22+
"id": "test-org-app",
23+
"dependencies": { "grafanaDependency": ">=11.6.0" }
24+
}`,
25+
titleMsg: "",
26+
},
27+
{
28+
name: "complex but valid grafanaDependency constraint",
29+
pluginJSON: `{
30+
"id": "test-org-app",
31+
"dependencies": { "grafanaDependency": ">=11.6.11 <12 || >=12.0.10 <12.1 || >=12.1.7 <12.2 || >=12.2.5" }
32+
}`,
33+
titleMsg: "",
34+
},
35+
{
36+
name: "invalid grafanaDependency constraint",
37+
pluginJSON: `{
38+
"id": "test-org-app",
39+
"dependencies": { "grafanaDependency": ">=invalid" }
40+
}`,
41+
titleMsg: "plugin.json: dependencies.grafanaDependency field has invalid or empty version constraint: \">=invalid\"",
42+
},
43+
} {
44+
t.Run(tc.name, func(t *testing.T) {
45+
var interceptor testpassinterceptor.TestPassInterceptor
46+
pass := &analysis.Pass{
47+
RootDir: filepath.Join("./"),
48+
ResultOf: map[*analysis.Analyzer]interface{}{
49+
metadata.Analyzer: []byte(tc.pluginJSON),
50+
},
51+
Report: interceptor.ReportInterceptor(),
52+
}
53+
54+
_, err := Analyzer.Run(pass)
55+
require.NoError(t, err)
56+
if len(tc.titleMsg) > 0 {
57+
require.Len(t, interceptor.Diagnostics, 1)
58+
require.Equal(
59+
t,
60+
tc.titleMsg,
61+
interceptor.Diagnostics[0].Title,
62+
)
63+
} else {
64+
require.Len(t, interceptor.Diagnostics, 0)
65+
}
66+
})
67+
}
68+
}

pkg/analysis/passes/metadatavalid/metadatavalid.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,17 @@ package metadatavalid
22

33
import (
44
"bytes"
5-
"encoding/json"
65
"fmt"
76
"io"
87
"os"
98
"path/filepath"
10-
"strings"
119

12-
"github.com/hashicorp/go-version"
1310
"github.com/xeipuuv/gojsonschema"
1411

1512
"github.com/grafana/plugin-validator/pkg/analysis"
1613
"github.com/grafana/plugin-validator/pkg/analysis/passes/archive"
1714
"github.com/grafana/plugin-validator/pkg/analysis/passes/metadata"
1815
"github.com/grafana/plugin-validator/pkg/analysis/passes/metadataschema"
19-
"github.com/grafana/plugin-validator/pkg/logme"
2016
)
2117

2218
var (
@@ -89,26 +85,6 @@ func run(pass *analysis.Pass) (interface{}, error) {
8985
break
9086
}
9187

92-
pluginJsonBytes, err := os.ReadFile(metadataPath)
93-
if err != nil {
94-
// log the error and continue with schema validation
95-
logme.ErrorF("failed to read plugin.json in metadatavalid check: %q", err)
96-
}
97-
if pluginJsonBytes != nil {
98-
var data metadata.Metadata
99-
if err := json.Unmarshal(pluginJsonBytes, &data); err == nil {
100-
_, err = version.NewConstraint(data.Dependencies.GrafanaDependency)
101-
if err != nil {
102-
pass.ReportResult(
103-
pass.AnalyzerName,
104-
invalidMetadata,
105-
fmt.Sprintf("plugin.json: Dependencies.grafanaDependency field has invalid or empty version constraint: %q", data.Dependencies.GrafanaDependency),
106-
"The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/#grafanadependency",
107-
)
108-
}
109-
}
110-
}
111-
11288
schemaLoader := gojsonschema.NewReferenceLoader("file:///" + schemaPath)
11389
documentLoader := gojsonschema.NewReferenceLoader("file:///" + metadataPath)
11490

@@ -119,12 +95,6 @@ func run(pass *analysis.Pass) (interface{}, error) {
11995

12096
errLen := len(result.Errors())
12197
for _, desc := range result.Errors() {
122-
// we validate grafanaDependency at line 91-100,
123-
// so we ignore the error from schema validation
124-
if strings.Contains(desc.Field(), "grafanaDependency") || strings.Contains(desc.Description(), "grafanaDependency") {
125-
errLen -= 1
126-
continue
127-
}
12898
pass.ReportResult(
12999
pass.AnalyzerName,
130100
invalidMetadata,

pkg/analysis/passes/metadatavalid/metadatavalid_test.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,32 +53,6 @@ func TestMetadataInvalid(t *testing.T) {
5353
)
5454
}
5555

56-
func TestGrafanaDependencyInvalid(t *testing.T) {
57-
var interceptor testpassinterceptor.TestPassInterceptor
58-
pass := &analysis.Pass{
59-
RootDir: filepath.Join("./"),
60-
ResultOf: map[*analysis.Analyzer]interface{}{
61-
archive.Analyzer: filepath.Join("testdata", "invalid", "grafana-dep"),
62-
metadataschema.Analyzer: getSchema(),
63-
},
64-
Report: interceptor.ReportInterceptor(),
65-
}
66-
67-
_, err := Analyzer.Run(pass)
68-
require.NoError(t, err)
69-
require.Len(t, interceptor.Diagnostics, 2)
70-
require.Equal(
71-
t,
72-
"plugin.json: Dependencies.grafanaDependency field has invalid or empty version constraint: \">=invalid\"",
73-
interceptor.Diagnostics[0].Title,
74-
)
75-
require.Equal(
76-
t,
77-
"plugin.json: (root): Additional property invalid is not allowed",
78-
interceptor.Diagnostics[1].Title,
79-
)
80-
}
81-
8256
func getSchema() []byte {
8357
if len(schemaContent) > 0 {
8458
return schemaContent

pkg/analysis/passes/metadatavalid/testdata/invalid/grafana-dep/plugin.json

Lines changed: 0 additions & 48 deletions
This file was deleted.

pkg/cmd/plugincheck2/main_test.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,8 @@ func TestIntegration(t *testing.T) {
258258
"metadatavalid": {
259259
{
260260
Severity: "error",
261-
Title: "plugin.json: Dependencies.grafanaDependency field has invalid or empty version constraint: \"\"",
262-
Detail: "The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/#grafanadependency",
261+
Title: "plugin.json: dependencies: grafanaDependency is required",
262+
Detail: "The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/",
263263
Name: "invalid-metadata",
264264
},
265265
},
@@ -303,6 +303,14 @@ func TestIntegration(t *testing.T) {
303303
Name: "code-diff-skipped",
304304
},
305305
},
306+
"grafanadependency": {
307+
{
308+
Severity: "error",
309+
Title: "plugin.json: dependencies.grafanaDependency field has invalid or empty version constraint: \"\"",
310+
Detail: "The plugin.json file has an invalid or empty grafanaDependency field. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/#grafanadependency",
311+
Name: "invalid-grafana-dependency",
312+
},
313+
},
306314
},
307315
},
308316
},
@@ -317,8 +325,8 @@ func TestIntegration(t *testing.T) {
317325
"metadatavalid": {
318326
{
319327
Severity: "error",
320-
Title: "plugin.json: Dependencies.grafanaDependency field has invalid or empty version constraint: \"\"",
321-
Detail: "The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/#grafanadependency",
328+
Title: "plugin.json: dependencies: grafanaDependency is required",
329+
Detail: "The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/",
322330
Name: "invalid-metadata",
323331
},
324332
},
@@ -336,8 +344,8 @@ func TestIntegration(t *testing.T) {
336344
"metadatavalid": {
337345
{
338346
Severity: "warning",
339-
Title: "plugin.json: Dependencies.grafanaDependency field has invalid or empty version constraint: \"\"",
340-
Detail: "The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/#grafanadependency",
347+
Title: "plugin.json: dependencies: grafanaDependency is required",
348+
Detail: "The plugin.json file is not following the schema. Please refer to the documentation for more information. https://grafana.com/docs/grafana/latest/developers/plugins/metadata/",
341349
Name: "invalid-metadata",
342350
},
343351
},

0 commit comments

Comments
 (0)