diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d9d58033..1b5c4f691a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.28.0](https://github.com/cloudquery/plugin-sdk/compare/v4.27.2...v4.28.0) (2024-01-30) + + +### Features + +* Package JSON Schema with plugins ([#1494](https://github.com/cloudquery/plugin-sdk/issues/1494)) ([790e240](https://github.com/cloudquery/plugin-sdk/commit/790e240c3ff90e756881114037f1857b392934f0)) + ## [4.27.2](https://github.com/cloudquery/plugin-sdk/compare/v4.27.1...v4.27.2) (2024-01-29) diff --git a/examples/simple_plugin/go.mod b/examples/simple_plugin/go.mod index eb02c63d08..eae14fae16 100644 --- a/examples/simple_plugin/go.mod +++ b/examples/simple_plugin/go.mod @@ -4,7 +4,7 @@ go 1.21.1 require ( github.com/apache/arrow/go/v15 v15.0.0-20240114144300-7e703aae55c1 - github.com/cloudquery/plugin-sdk/v4 v4.27.1 + github.com/cloudquery/plugin-sdk/v4 v4.27.2 github.com/rs/zerolog v1.30.0 ) diff --git a/plugin/plugin.go b/plugin/plugin.go index d0393ec856..702ca83ad6 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -126,6 +126,10 @@ func (p *Plugin) Version() string { return p.version } +func (p *Plugin) JSONSchema() string { + return p.schema +} + func (p *Plugin) Meta() Meta { return Meta{ Team: p.team, diff --git a/serve/package.go b/serve/package.go index fedfa45d4e..41dbdc1624 100644 --- a/serve/package.go +++ b/serve/package.go @@ -234,6 +234,14 @@ func (s *PluginServe) writePackageJSON(dir, version, message string, targets []T return os.WriteFile(outputPath, buffer.Bytes(), 0644) } +func (s *PluginServe) writeSpecJSONSchema(dir string) error { + if s.plugin.JSONSchema() == "" { + return nil + } + + return os.WriteFile(filepath.Join(dir, "spec_json_schema.json"), []byte(s.plugin.JSONSchema()), 0644) +} + func (*PluginServe) copyDocs(distPath, docsPath string) error { err := os.MkdirAll(filepath.Join(distPath, "docs"), 0755) if err != nil { @@ -427,6 +435,9 @@ func (s *PluginServe) newCmdPluginPackage() *cobra.Command { if err := s.copyDocs(distPath, docsPath); err != nil { return fmt.Errorf("failed to copy docs: %w", err) } + if err := s.writeSpecJSONSchema(distPath); err != nil { + return fmt.Errorf("failed to write spec json schema: %w", err) + } return nil }, } diff --git a/serve/package_test.go b/serve/package_test.go index 25f3b21c1e..bbd23013e7 100644 --- a/serve/package_test.go +++ b/serve/package_test.go @@ -21,6 +21,12 @@ import ( //go:embed testdata/memdbtables.json var memDBPackageJSON string +//go:embed testdata/source_spec_schema.json +var sourceSpecSchema string + +//go:embed testdata/destination_spec_schema.json +var destinationSpecSchema string + func TestPluginPackage_Source(t *testing.T) { _, filename, _, ok := runtime.Caller(0) if !ok { @@ -39,6 +45,7 @@ func TestPluginPackage_Source(t *testing.T) { }), plugin.WithKind("source"), plugin.WithTeam("test-team"), + plugin.WithJSONSchema(sourceSpecSchema), ) msg := `Test message with multiple lines and **markdown**` @@ -78,6 +85,7 @@ with multiple lines and **markdown**` "package.json", "plugin-test-plugin-v1.2.3-linux-amd64.zip", "plugin-test-plugin-v1.2.3-windows-amd64.zip", + "spec_json_schema.json", "tables.json", } if diff := cmp.Diff(expect, fileNames(files)); diff != "" { @@ -112,6 +120,7 @@ with multiple lines and **markdown**` } checkDocs(t, filepath.Join(distDir, "docs"), expectDocs) checkTables(t, distDir) + checkFileContent(t, filepath.Join(distDir, "spec_json_schema.json"), sourceSpecSchema) }) } } @@ -134,6 +143,7 @@ func TestPluginPackage_Destination(t *testing.T) { }), plugin.WithKind("destination"), plugin.WithTeam("test-team"), + plugin.WithJSONSchema(destinationSpecSchema), ) msg := `Test message with multiple lines and **markdown**` @@ -173,6 +183,7 @@ with multiple lines and **markdown**` "package.json", "plugin-test-plugin-v1.2.3-darwin-amd64.zip", "plugin-test-plugin-v1.2.3-windows-amd64.zip", + "spec_json_schema.json", } if diff := cmp.Diff(expect, fileNames(files)); diff != "" { t.Fatalf("unexpected files in dist directory (-want +got):\n%s", diff) @@ -205,6 +216,7 @@ with multiple lines and **markdown**` "overview.md", } checkDocs(t, filepath.Join(distDir, "docs"), expectDocs) + checkFileContent(t, filepath.Join(distDir, "spec_json_schema.json"), destinationSpecSchema) }) } } @@ -327,6 +339,21 @@ func checkPackageJSONContents(t *testing.T, filename string, expect PackageJSON) } } +func checkFileContent(t *testing.T, filename string, expect string) { + f, err := os.Open(filename) + if err != nil { + t.Fatalf("failed to open %s: %v", filename, err) + } + defer f.Close() + b, err := io.ReadAll(f) + if err != nil { + t.Fatalf("failed to read %s: %v", filename, err) + } + if diff := cmp.Diff(expect, string(b)); diff != "" { + t.Fatalf("%s contents mismatch (-want +got):\n%s", filename, diff) + } +} + func fileNames(files []os.DirEntry) []string { names := make([]string, 0, len(files)) for _, file := range files { diff --git a/serve/testdata/destination_spec_schema.json b/serve/testdata/destination_spec_schema.json new file mode 100644 index 0000000000..2396d773ad --- /dev/null +++ b/serve/testdata/destination_spec_schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$ref": "#/$defs/Spec", + "$defs": { + "Spec": { + "properties": { + "connection_string": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + } + } + } \ No newline at end of file diff --git a/serve/testdata/source_spec_schema.json b/serve/testdata/source_spec_schema.json new file mode 100644 index 0000000000..e2266bf612 --- /dev/null +++ b/serve/testdata/source_spec_schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$ref": "#/$defs/Spec", + "$defs": { + "Spec": { + "properties": { + "concurrency": { + "type": "integer" + } + }, + "additionalProperties": false, + "type": "object" + } + } + } \ No newline at end of file