From d2dc493ac8e47aa3474ee761b68fb0dad4ee3b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20SZKIBA?= Date: Wed, 25 Sep 2024 19:56:31 +0200 Subject: [PATCH] feat: added version constraints support --- cmd/api.go | 12 ++++- cmd/cmd.go | 2 + cmd/legacy.go | 2 +- cmd/load.go | 98 ++++++++++++++++++++++++++------------- cmd/origin.go | 4 ++ docs/custom-catalog.json | 15 ++---- docs/custom.json | 15 ++---- docs/custom.yaml | 8 +--- docs/registry.schema.json | 13 ++++++ registry.go | 14 ------ registry_gen.go | 11 ++++- releases/v0.1.28.md | 7 +++ 12 files changed, 125 insertions(+), 76 deletions(-) create mode 100644 releases/v0.1.28.md diff --git a/cmd/api.go b/cmd/api.go index b0d7b86..05c758f 100644 --- a/cmd/api.go +++ b/cmd/api.go @@ -1,6 +1,7 @@ package cmd import ( + "bytes" "encoding/json" "errors" "fmt" @@ -41,12 +42,19 @@ func writeData(filename string, data []byte) error { } func writeJSON(filename string, source interface{}) error { - data, err := json.MarshalIndent(source, "", " ") + var buff bytes.Buffer + + encoder := json.NewEncoder(&buff) + + encoder.SetIndent("", " ") + encoder.SetEscapeHTML(false) + + err := encoder.Encode(source) if err != nil { return err } - return writeData(filename, data) + return writeData(filename, buff.Bytes()) } func writeAPIGroupGlobal(registry k6registry.Registry, target string) error { diff --git a/cmd/cmd.go b/cmd/cmd.go index 642cb5b..b3c0670 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -165,6 +165,8 @@ func writeOutput(registry k6registry.Registry, output io.Writer, opts *options) encoder.SetIndent("", " ") } + encoder.SetEscapeHTML(false) + var source interface{} = registry if opts.catalog { diff --git a/cmd/legacy.go b/cmd/legacy.go index 43cd110..939301b 100644 --- a/cmd/legacy.go +++ b/cmd/legacy.go @@ -87,7 +87,7 @@ func legacyConvert(ctx context.Context) error { tmp := *ext tmp.Repo = repo - tmp.Versions = filterVersions(tags) + tmp.Versions = tagsToVersions(tags) if ok, _ := lintExtension(tmp); ok { reg = append(reg, ext) diff --git a/cmd/load.go b/cmd/load.go index e9d9b04..16afec4 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -74,56 +74,72 @@ func loadSource(in io.Reader, loose bool) (k6registry.Registry, error) { return registry, nil } -func load(ctx context.Context, in io.Reader, loose bool, lint bool, origin string) (k6registry.Registry, error) { - registry, err := loadSource(in, loose) - if err != nil { - return nil, err +func loadOne(ctx context.Context, ext *k6registry.Extension, lint bool) error { + if len(ext.Tier) == 0 { + ext.Tier = k6registry.TierCommunity } - orig, err := loadOrigin(ctx, origin) + if len(ext.Products) == 0 { + ext.Products = append(ext.Products, k6registry.ProductOSS) + } + + if len(ext.Categories) == 0 { + ext.Categories = append(ext.Categories, k6registry.CategoryMisc) + } + + repo, tags, err := loadRepository(ctx, ext) if err != nil { - return nil, err + return err } - for idx, ext := range registry { - slog.Debug("Process extension", "module", ext.Module) + ext.Repo = repo - if fromOrigin(®istry[idx], orig, origin) { - continue - } + if len(ext.Versions) == 0 { + ext.Versions = tagsToVersions(tags) + } - if len(ext.Tier) == 0 { - registry[idx].Tier = k6registry.TierCommunity + if lint && ext.Module != k6Module && ext.Compliance == nil && ext.Repo != nil { + compliance, err := checkCompliance(ctx, ext.Module, repo.CloneURL, repo.Timestamp) + if err != nil { + return err } - if len(ext.Products) == 0 { - registry[idx].Products = append(registry[idx].Products, k6registry.ProductOSS) - } + ext.Compliance = &k6registry.Compliance{Grade: k6registry.Grade(compliance.Grade), Level: compliance.Level} + } - if len(ext.Categories) == 0 { - registry[idx].Categories = append(registry[idx].Categories, k6registry.CategoryMisc) - } + return nil +} - ext := ext +func load(ctx context.Context, in io.Reader, loose bool, lint bool, origin string) (k6registry.Registry, error) { + registry, err := loadSource(in, loose) + if err != nil { + return nil, err + } - repo, tags, err := loadRepository(ctx, &ext) - if err != nil { - return nil, err - } + orig, err := loadOrigin(ctx, origin) + if err != nil { + return nil, err + } - registry[idx].Repo = repo + for idx := range registry { + ext := ®istry[idx] - if len(registry[idx].Versions) == 0 { - registry[idx].Versions = filterVersions(tags) + slog.Debug("Process extension", "module", ext.Module) + + if !fromOrigin(ext, orig, origin) { + err := loadOne(ctx, ext, lint) + if err != nil { + return nil, err + } } - if lint && ext.Module != k6Module && ext.Compliance == nil && ext.Repo != nil { - compliance, err := checkCompliance(ctx, ext.Module, repo.CloneURL, repo.Timestamp) + if len(ext.Constraints) > 0 { + constraints, err := semver.NewConstraint(ext.Constraints) if err != nil { return nil, err } - registry[idx].Compliance = &k6registry.Compliance{Grade: k6registry.Grade(compliance.Grade), Level: compliance.Level} + ext.Versions = filterVersions(ext.Versions, constraints) } } @@ -180,11 +196,12 @@ func loadRepository(ctx context.Context, ext *k6registry.Extension) (*k6registry return nil, nil, fmt.Errorf("%w: %s", errUnsupportedModule, module) } -func filterVersions(tags []string) []string { +func tagsToVersions(tags []string) []string { versions := make([]string, 0, len(tags)) for _, tag := range tags { - if _, err := semver.NewVersion(tag); err != nil { + _, err := semver.NewVersion(tag) + if err != nil { continue } @@ -194,6 +211,23 @@ func filterVersions(tags []string) []string { return versions } +func filterVersions(tags []string, constraints *semver.Constraints) []string { + versions := make([]string, 0, len(tags)) + + for _, tag := range tags { + version, err := semver.NewVersion(tag) + if err != nil { + continue + } + + if constraints.Check(version) { + versions = append(versions, tag) + } + } + + return versions +} + func loadGitHub(ctx context.Context, module string) (*k6registry.Repository, []string, error) { slog.Debug("Loading GitHub repository", "module", module) diff --git a/cmd/origin.go b/cmd/origin.go index 9a51b5f..5632e2a 100644 --- a/cmd/origin.go +++ b/cmd/origin.go @@ -71,6 +71,10 @@ func fromOrigin(ext *k6registry.Extension, origin map[string]k6registry.Extensio ext.Versions = oext.Versions } + if len(ext.Constraints) == 0 { + ext.Constraints = oext.Constraints + } + if len(ext.Description) == 0 { ext.Description = oext.Description } diff --git a/docs/custom-catalog.json b/docs/custom-catalog.json index 0b07a94..6607b78 100644 --- a/docs/custom-catalog.json +++ b/docs/custom-catalog.json @@ -3,6 +3,7 @@ "categories": [ "misc" ], + "constraints": ">=v0.50.0", "description": "A modern load testing tool, using Go and JavaScript", "imports": [ "k6" @@ -35,7 +36,8 @@ "versions": [ "v0.53.0", "v0.52.0", - "v0.51.0" + "v0.51.0", + "v0.50.0" ] }, "k6/x/codename": { @@ -69,10 +71,7 @@ "categories": [ "data" ], - "compliance": { - "grade": "A", - "level": 100 - }, + "constraints": ">=v0.4.0", "description": "Generate random fake data", "imports": [ "k6/x/faker" @@ -133,10 +132,6 @@ "categories": [ "data" ], - "compliance": { - "grade": "A", - "level": 100 - }, "description": "Load-test SQL Servers", "imports": [ "k6/x/sql" @@ -153,7 +148,7 @@ "name": "xk6-sql", "owner": "grafana", "public": true, - "stars": 108, + "stars": 109, "timestamp": 1725979901, "topics": [ "k6", diff --git a/docs/custom.json b/docs/custom.json index 534be6f..77da5e7 100644 --- a/docs/custom.json +++ b/docs/custom.json @@ -58,10 +58,7 @@ "categories": [ "data" ], - "compliance": { - "grade": "A", - "level": 100 - }, + "constraints": ">=v0.4.0", "description": "Generate random fake data", "imports": [ "k6/x/faker" @@ -94,10 +91,6 @@ "categories": [ "data" ], - "compliance": { - "grade": "A", - "level": 100 - }, "description": "Load-test SQL Servers", "imports": [ "k6/x/sql" @@ -114,7 +107,7 @@ "name": "xk6-sql", "owner": "grafana", "public": true, - "stars": 108, + "stars": 109, "timestamp": 1725979901, "topics": [ "k6", @@ -139,6 +132,7 @@ "categories": [ "misc" ], + "constraints": ">=v0.50.0", "description": "A modern load testing tool, using Go and JavaScript", "imports": [ "k6" @@ -171,7 +165,8 @@ "versions": [ "v0.53.0", "v0.52.0", - "v0.51.0" + "v0.51.0", + "v0.50.0" ] } ] diff --git a/docs/custom.yaml b/docs/custom.yaml index ff6a676..b699ba3 100644 --- a/docs/custom.yaml +++ b/docs/custom.yaml @@ -25,13 +25,9 @@ clone_url: git@bitbucket.org:szkiba/xk6-sqids.git - module: github.com/grafana/xk6-faker - versions: - - v0.4.0 + constraints: ">=v0.4.0" - module: github.com/grafana/xk6-sql - module: go.k6.io/k6 - versions: - - v0.53.0 - - v0.52.0 - - v0.51.0 + constraints: ">=v0.50.0" diff --git a/docs/registry.schema.json b/docs/registry.schema.json index 6b23274..74458c5 100644 --- a/docs/registry.schema.json +++ b/docs/registry.schema.json @@ -63,6 +63,7 @@ }, "description": { "type": "string", + "default": "", "description": "Brief description of the extension.\n", "examples": [ "This is a very cool extension, it displays the message 'Hello World!'" @@ -82,6 +83,18 @@ ] ] }, + "constraints": { + "type": "string", + "pattern": "[vxX*|,&\\^0-9.+-><=, ~]+", + "default": "", + "description": "Version constraints.\n\nVersion constraints are primarily used to filter automatically detected versions.\nIt can also be used to filter the versions property imported from the origin registry.\n", + "examples": [ + [ + ">=v0.4.0", + ">v0.50.0" + ] + ] + }, "repo": { "$ref": "#/$defs/repository", "description": "Repository metadata.\n\nMetadata provided by the extension's git repository manager. Repository metadata are not registered, they are queried at runtime using the repository manager API.\n" diff --git a/registry.go b/registry.go index 11d5c04..cfdefa4 100644 --- a/registry.go +++ b/registry.go @@ -65,17 +65,3 @@ func RegistryToCatalog(reg Registry) Catalog { return catalog } - -// ModuleReference returns true if only the "Module" property has value. -func (ext *Extension) ModuleReference() bool { - return len(ext.Module) > 0 && - len(ext.Description) == 0 && - len(ext.Imports) == 0 && - len(ext.Outputs) == 0 && - len(ext.Versions) == 0 && - len(ext.Categories) == 0 && - len(ext.Products) == 0 && - len(ext.Tier) == 0 && - ext.Repo == nil && - ext.Compliance == nil -} diff --git a/registry_gen.go b/registry_gen.go index e561e8c..bef8b6f 100644 --- a/registry_gen.go +++ b/registry_gen.go @@ -70,9 +70,18 @@ type Extension struct { // Compliance *Compliance `json:"compliance,omitempty" yaml:"compliance,omitempty" mapstructure:"compliance,omitempty"` + // Version constraints. + // + // Version constraints are primarily used to filter automatically detected + // versions. + // It can also be used to filter the versions property imported from the origin + // registry. + // + Constraints string `json:"constraints,omitempty" yaml:"constraints,omitempty" mapstructure:"constraints,omitempty"` + // Brief description of the extension. // - Description string `json:"description" yaml:"description" mapstructure:"description"` + Description string `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` // List of JavaScript import paths registered by the extension. // diff --git a/releases/v0.1.28.md b/releases/v0.1.28.md new file mode 100644 index 0000000..3ab22fd --- /dev/null +++ b/releases/v0.1.28.md @@ -0,0 +1,7 @@ +k6registry `v0.1.28` is here 🎉! + +This is an internal maintenance release. + +**Add version constraints support** + +Version constraints are primarily used to filter automatically detected versions. It can also be used to filter the versions property imported from the origin registry.