Output deprecated annotations in the JSON schema (#2422)

## Changes
Start outputting `deprecated` and `deprecationMessage` annotations in
the JSON schema

## Why
So that deprecated fields are shown as deprecated in VSCode (and other
editors)

## Tests
- manually tested

||||
|---|---|---|
|<img width="682" alt="Screenshot 2025-03-03 at 16 04 21"
src="https://github.com/user-attachments/assets/9712aa2f-0f41-48a9-8bd0-ec92b8b75c3f"
/>|<img width="682" alt="Screenshot 2025-03-03 at 16 04 29"
src="https://github.com/user-attachments/assets/a14f3523-ad85-4fed-96d7-2a8cf3a458e5"
/>|<img width="682" alt="Screenshot 2025-03-03 at 16 06 03"
src="https://github.com/user-attachments/assets/b9ab1050-048e-4c14-b183-96d615a4fbc1"
/>|
This commit is contained in:
Russell Clarey 2025-03-05 12:17:03 +01:00 committed by GitHub
parent a26461c5a3
commit 3a3076d9ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 47 additions and 15 deletions

View File

@ -145,7 +145,10 @@ jobs:
go run main.go bundle schema > schema.json go run main.go bundle schema > schema.json
# Add markdownDescription keyword to ajv # Add markdownDescription keyword to ajv
echo "module.exports=function(a){a.addKeyword('markdownDescription')}" >> keywords.js echo "module.exports = function(a) {
a.addKeyword('markdownDescription');
a.addKeyword('deprecationMessage');
}" >> keywords.js
for file in ./bundle/internal/schema/testdata/pass/*.yml; do for file in ./bundle/internal/schema/testdata/pass/*.yml; do
ajv test -s schema.json -d $file --valid -c=./keywords.js ajv test -s schema.json -d $file --valid -c=./keywords.js

View File

@ -52,7 +52,7 @@ type Root struct {
Targets map[string]*Target `json:"targets,omitempty"` Targets map[string]*Target `json:"targets,omitempty"`
// DEPRECATED. Left for backward compatibility with Targets // DEPRECATED. Left for backward compatibility with Targets
Environments map[string]*Target `json:"environments,omitempty" bundle:"deprecated"` Environments map[string]*Target `json:"environments,omitempty"`
// Sync section specifies options for files synchronization // Sync section specifies options for files synchronization
Sync Sync `json:"sync,omitempty"` Sync Sync `json:"sync,omitempty"`

View File

@ -7,6 +7,7 @@ type Descriptor struct {
Default any `json:"default,omitempty"` Default any `json:"default,omitempty"`
Enum []any `json:"enum,omitempty"` Enum []any `json:"enum,omitempty"`
MarkdownExamples string `json:"markdown_examples,omitempty"` MarkdownExamples string `json:"markdown_examples,omitempty"`
DeprecationMessage string `json:"deprecation_message,omitempty"`
} }
const Placeholder = "PLACEHOLDER" const Placeholder = "PLACEHOLDER"

View File

@ -127,6 +127,12 @@ func assignAnnotation(s *jsonschema.Schema, a annotation.Descriptor) {
if a.Default != nil { if a.Default != nil {
s.Default = a.Default s.Default = a.Default
} }
if a.DeprecationMessage != "" {
s.Deprecated = true
s.DeprecationMessage = a.DeprecationMessage
}
s.MarkdownDescription = convertLinksToAbsoluteUrl(a.MarkdownDescription) s.MarkdownDescription = convertLinksToAbsoluteUrl(a.MarkdownDescription)
s.Title = a.Title s.Title = a.Title
s.Enum = a.Enum s.Enum = a.Enum

View File

@ -61,6 +61,8 @@ github.com/databricks/cli/bundle/config.Experimental:
"pydabs": "pydabs":
"description": |- "description": |-
The PyDABs configuration. The PyDABs configuration.
"deprecation_message": |-
Deprecated: please use python instead
"python": "python":
"description": |- "description": |-
Configures loading of Python code defined with 'databricks-bundles' package. Configures loading of Python code defined with 'databricks-bundles' package.
@ -220,6 +222,11 @@ github.com/databricks/cli/bundle/config.Root:
The bundle attributes when deploying to this target. The bundle attributes when deploying to this target.
"markdown_description": |- "markdown_description": |-
The bundle attributes when deploying to this target, The bundle attributes when deploying to this target,
"environments":
"description": |-
PLACEHOLDER
"deprecation_message": |-
Deprecated: please use targets instead
"experimental": "experimental":
"description": |- "description": |-
Defines attributes for experimental features. Defines attributes for experimental features.
@ -308,6 +315,8 @@ github.com/databricks/cli/bundle/config.Target:
"compute_id": "compute_id":
"description": |- "description": |-
Deprecated. The ID of the compute to use for this target. Deprecated. The ID of the compute to use for this target.
"deprecation_message": |-
Deprecated: please use cluster_id instead
"default": "default":
"description": |- "description": |-
Whether this target is the default target. Whether this target is the default target.

View File

@ -1217,7 +1217,9 @@
"properties": { "properties": {
"pydabs": { "pydabs": {
"description": "The PyDABs configuration.", "description": "The PyDABs configuration.",
"$ref": "#/$defs/github.com/databricks/cli/bundle/config.PyDABs" "$ref": "#/$defs/github.com/databricks/cli/bundle/config.PyDABs",
"deprecationMessage": "Deprecated: please use python instead",
"deprecated": true
}, },
"python": { "python": {
"description": "Configures loading of Python code defined with 'databricks-bundles' package.", "description": "Configures loading of Python code defined with 'databricks-bundles' package.",
@ -1506,7 +1508,9 @@
}, },
"compute_id": { "compute_id": {
"description": "Deprecated. The ID of the compute to use for this target.", "description": "Deprecated. The ID of the compute to use for this target.",
"$ref": "#/$defs/string" "$ref": "#/$defs/string",
"deprecationMessage": "Deprecated: please use cluster_id instead",
"deprecated": true
}, },
"default": { "default": {
"description": "Whether this target is the default target.", "description": "Whether this target is the default target.",
@ -7409,6 +7413,11 @@
"$ref": "#/$defs/github.com/databricks/cli/bundle/config.Bundle", "$ref": "#/$defs/github.com/databricks/cli/bundle/config.Bundle",
"markdownDescription": "The bundle attributes when deploying to this target," "markdownDescription": "The bundle attributes when deploying to this target,"
}, },
"environments": {
"$ref": "#/$defs/map/github.com/databricks/cli/bundle/config.Target",
"deprecationMessage": "Deprecated: please use targets instead",
"deprecated": true
},
"experimental": { "experimental": {
"description": "Defines attributes for experimental features.", "description": "Defines attributes for experimental features.",
"$ref": "#/$defs/github.com/databricks/cli/bundle/config.Experimental" "$ref": "#/$defs/github.com/databricks/cli/bundle/config.Experimental"

View File

@ -40,4 +40,8 @@ type Extension struct {
// https://code.visualstudio.com/docs/languages/json#_use-rich-formatting-in-hovers // https://code.visualstudio.com/docs/languages/json#_use-rich-formatting-in-hovers
// Also it can be used in documentation generation. // Also it can be used in documentation generation.
MarkdownDescription string `json:"markdownDescription,omitempty"` MarkdownDescription string `json:"markdownDescription,omitempty"`
// This field is not in the JSON schema spec, but it is supported in VSCode
// It is used to provide a warning for deprectated fields
DeprecationMessage string `json:"deprecationMessage,omitempty"`
} }

View File

@ -18,10 +18,6 @@ var skipTags = []string{
// Annotation for internal bundle fields that should not be exposed to customers. // Annotation for internal bundle fields that should not be exposed to customers.
// Fields can be tagged as "internal" to remove them from the generated schema. // Fields can be tagged as "internal" to remove them from the generated schema.
"internal", "internal",
// Annotation for bundle fields that have been deprecated.
// Fields tagged as "deprecated" are omitted from the generated schema.
"deprecated",
} }
type constructor struct { type constructor struct {
@ -259,8 +255,8 @@ func (c *constructor) fromTypeStruct(typ reflect.Type) (Schema, error) {
structFields := getStructFields(typ) structFields := getStructFields(typ)
for _, structField := range structFields { for _, structField := range structFields {
bundleTags := strings.Split(structField.Tag.Get("bundle"), ",") bundleTags := strings.Split(structField.Tag.Get("bundle"), ",")
// Fields marked as "readonly", "internal" or "deprecated" are skipped // Fields marked as "readonly" or "internal" are skipped while generating
// while generating the schema // the schema
skip := false skip := false
for _, tag := range skipTags { for _, tag := range skipTags {
if slices.Contains(bundleTags, tag) { if slices.Contains(bundleTags, tag) {

View File

@ -17,11 +17,10 @@ func TestFromTypeBasic(t *testing.T) {
TriplePointer ***int `json:"triple_pointer,omitempty"` TriplePointer ***int `json:"triple_pointer,omitempty"`
// These fields should be ignored in the resulting schema. // These fields should be ignored in the resulting schema.
NotAnnotated string NotAnnotated string
DashedTag string `json:"-"` DashedTag string `json:"-"`
InternalTagged string `json:"internal_tagged" bundle:"internal"` InternalTagged string `json:"internal_tagged" bundle:"internal"`
DeprecatedTagged string `json:"deprecated_tagged" bundle:"deprecated"` ReadOnlyTagged string `json:"readonly_tagged" bundle:"readonly"`
ReadOnlyTagged string `json:"readonly_tagged" bundle:"readonly"`
} }
strRef := "#/$defs/string" strRef := "#/$defs/string"

View File

@ -80,6 +80,11 @@ type Schema struct {
// Examples of the value for properties in the schema. // Examples of the value for properties in the schema.
// https://json-schema.org/understanding-json-schema/reference/annotations // https://json-schema.org/understanding-json-schema/reference/annotations
Examples any `json:"examples,omitempty"` Examples any `json:"examples,omitempty"`
// A boolean that indicates the field should not be used and may be removed
// in the future.
// https://json-schema.org/understanding-json-schema/reference/annotations
Deprecated bool `json:"deprecated,omitempty"`
} }
// Default value defined in a JSON Schema, represented as a string. // Default value defined in a JSON Schema, represented as a string.