From 9c79a33697cea02f313e7a48b78c218cad012143 Mon Sep 17 00:00:00 2001 From: Hannes Hayashi Date: Wed, 14 Jan 2026 08:42:40 +0100 Subject: [PATCH] feat: extract schema-level descriptions from OpenAPI tags This adds support for extracting resource and data source descriptions from the OpenAPI tags section. When an operation has tags, the description of the first matching tag from the document's tags array is used as the schema-level description. This addresses the feature request in issue #123. Changes: - Add Description field to explorer.Resource and explorer.DataSource - Add helper functions getTagDescription and getOperationTagDescription - Update resource_mapper.go to set resourceSchema.Description - Update datasource_mapper.go to set dataSourceSchema.Description - Regenerate golden test files --- .../testdata/github/provider_code_spec.json | 12 +++++++--- .../petstore3/provider_code_spec.json | 24 ++++++++++++++----- .../testdata/scaleway/provider_code_spec.json | 16 +++++++++---- internal/explorer/config_explorer.go | 20 ++++++++++++++++ internal/explorer/explorer.go | 2 ++ internal/mapper/datasource_mapper.go | 7 ++++++ internal/mapper/resource_mapper.go | 7 ++++++ 7 files changed, 75 insertions(+), 13 deletions(-) diff --git a/internal/cmd/testdata/github/provider_code_spec.json b/internal/cmd/testdata/github/provider_code_spec.json index 7032b02a..9fbd4cec 100644 --- a/internal/cmd/testdata/github/provider_code_spec.json +++ b/internal/cmd/testdata/github/provider_code_spec.json @@ -1185,7 +1185,9 @@ "computed_optional_required": "computed" } } - ] + ], + "description": "View, modify your gists.", + "markdown_description": "View, modify your gists." } }, { @@ -6981,7 +6983,9 @@ "computed_optional_required": "computed" } } - ] + ], + "description": "Interact with GitHub Repos.", + "markdown_description": "Interact with GitHub Repos." } } ], @@ -13175,7 +13179,9 @@ "description": "A repository on GitHub." } } - ] + ], + "description": "Interact with GitHub Repos.", + "markdown_description": "Interact with GitHub Repos." } } ], diff --git a/internal/cmd/testdata/petstore3/provider_code_spec.json b/internal/cmd/testdata/petstore3/provider_code_spec.json index 2c01765c..9e6cc2c7 100644 --- a/internal/cmd/testdata/petstore3/provider_code_spec.json +++ b/internal/cmd/testdata/petstore3/provider_code_spec.json @@ -43,7 +43,9 @@ "description": "Order status, possible values - 'placed', 'approved', or 'delivered'" } } - ] + ], + "description": "Access to Petstore orders", + "markdown_description": "Access to Petstore orders" } }, { @@ -124,7 +126,9 @@ } } } - ] + ], + "description": "Everything about your Pets", + "markdown_description": "Everything about your Pets" } }, { @@ -204,7 +208,9 @@ } } } - ] + ], + "description": "Everything about your Pets", + "markdown_description": "Everything about your Pets" } } ], @@ -267,7 +273,9 @@ ] } } - ] + ], + "description": "Access to Petstore orders", + "markdown_description": "Access to Petstore orders" } }, { @@ -360,7 +368,9 @@ } } } - ] + ], + "description": "Everything about your Pets", + "markdown_description": "Everything about your Pets" } }, { @@ -410,7 +420,9 @@ "description": "User Status" } } - ] + ], + "description": "Operations about user", + "markdown_description": "Operations about user" } } ], diff --git a/internal/cmd/testdata/scaleway/provider_code_spec.json b/internal/cmd/testdata/scaleway/provider_code_spec.json index 5a4539fb..837be96c 100644 --- a/internal/cmd/testdata/scaleway/provider_code_spec.json +++ b/internal/cmd/testdata/scaleway/provider_code_spec.json @@ -987,7 +987,9 @@ ] } } - ] + ], + "description": "Server types are denomination of the different instances we provide.\nScaleway offers **Virtual Cloud** and **dedicated GPU** instances.\n\n**Virtual Cloud Instances**\n\nVirtual cloud instances are offering the best performance/price ratio for most workloads.\nDifferent instance ranges are proposed:\n\n* The **Development** instances range provides stable and consistent performance for\n development and testing needs. Spin up a development or test environment within seconds.\n Refer to the [Development Instance offer details](https://www.scaleway.com/en/virtual-instances/play2/)\n for more information.\n\n* The **General Purpose** instances range is the solution for production workloads. Powerful\n AMD EPYC CPUs back those instances and offer up to 48 Cores, 256GB of RAM and storage\n options up to 600GB of replicated local NVMe SSD storage and/or up to 10TB of Block Storage.\n Refer to the [General Purpose offer details](https://www.scaleway.com/en/virtual-instances/pro2/) for more information.\n\n* The **Enterprise** instances range is the solution for most demanding workloads and\n mission-critical applications. Powerful AMD EPYC CPUs back those instances and\n offer up to 96 Cores, 384GB of RAM and up to 10TB of Block Storage. Refer to the\n [Enterprise offer details](https://www.scaleway.com/en/virtual-instances/enterprise/) for more information.\n\n**Dedicated GPU Instances**\n\nScaleway GPU Instances are virtual compute instances equipped with dedicated high-end\nNvidia graphical processing unit (GPUs). They are ideal for data processing, artificial\nintelligence, rendering and video encoding. The GPU is dedicated to each instance and\ndirectly exposed through PCI-e. For more information, refer to the\n[GPU Instances Developper Documentation](https://www.scaleway.com/en/docs/compute/gpu/quickstart/).\n", + "markdown_description": "Server types are denomination of the different instances we provide.\nScaleway offers **Virtual Cloud** and **dedicated GPU** instances.\n\n**Virtual Cloud Instances**\n\nVirtual cloud instances are offering the best performance/price ratio for most workloads.\nDifferent instance ranges are proposed:\n\n* The **Development** instances range provides stable and consistent performance for\n development and testing needs. Spin up a development or test environment within seconds.\n Refer to the [Development Instance offer details](https://www.scaleway.com/en/virtual-instances/play2/)\n for more information.\n\n* The **General Purpose** instances range is the solution for production workloads. Powerful\n AMD EPYC CPUs back those instances and offer up to 48 Cores, 256GB of RAM and storage\n options up to 600GB of replicated local NVMe SSD storage and/or up to 10TB of Block Storage.\n Refer to the [General Purpose offer details](https://www.scaleway.com/en/virtual-instances/pro2/) for more information.\n\n* The **Enterprise** instances range is the solution for most demanding workloads and\n mission-critical applications. Powerful AMD EPYC CPUs back those instances and\n offer up to 96 Cores, 384GB of RAM and up to 10TB of Block Storage. Refer to the\n [Enterprise offer details](https://www.scaleway.com/en/virtual-instances/enterprise/) for more information.\n\n**Dedicated GPU Instances**\n\nScaleway GPU Instances are virtual compute instances equipped with dedicated high-end\nNvidia graphical processing unit (GPUs). They are ideal for data processing, artificial\nintelligence, rendering and video encoding. The GPU is dedicated to each instance and\ndirectly exposed through PCI-e. For more information, refer to the\n[GPU Instances Developper Documentation](https://www.scaleway.com/en/docs/compute/gpu/quickstart/).\n" } }, { @@ -2081,7 +2083,9 @@ "description": "List of servers." } } - ] + ], + "description": "Server types are denomination of the different instances we provide.\nScaleway offers **Virtual Cloud** and **dedicated GPU** instances.\n\n**Virtual Cloud Instances**\n\nVirtual cloud instances are offering the best performance/price ratio for most workloads.\nDifferent instance ranges are proposed:\n\n* The **Development** instances range provides stable and consistent performance for\n development and testing needs. Spin up a development or test environment within seconds.\n Refer to the [Development Instance offer details](https://www.scaleway.com/en/virtual-instances/play2/)\n for more information.\n\n* The **General Purpose** instances range is the solution for production workloads. Powerful\n AMD EPYC CPUs back those instances and offer up to 48 Cores, 256GB of RAM and storage\n options up to 600GB of replicated local NVMe SSD storage and/or up to 10TB of Block Storage.\n Refer to the [General Purpose offer details](https://www.scaleway.com/en/virtual-instances/pro2/) for more information.\n\n* The **Enterprise** instances range is the solution for most demanding workloads and\n mission-critical applications. Powerful AMD EPYC CPUs back those instances and\n offer up to 96 Cores, 384GB of RAM and up to 10TB of Block Storage. Refer to the\n [Enterprise offer details](https://www.scaleway.com/en/virtual-instances/enterprise/) for more information.\n\n**Dedicated GPU Instances**\n\nScaleway GPU Instances are virtual compute instances equipped with dedicated high-end\nNvidia graphical processing unit (GPUs). They are ideal for data processing, artificial\nintelligence, rendering and video encoding. The GPU is dedicated to each instance and\ndirectly exposed through PCI-e. For more information, refer to the\n[GPU Instances Developper Documentation](https://www.scaleway.com/en/docs/compute/gpu/quickstart/).\n", + "markdown_description": "Server types are denomination of the different instances we provide.\nScaleway offers **Virtual Cloud** and **dedicated GPU** instances.\n\n**Virtual Cloud Instances**\n\nVirtual cloud instances are offering the best performance/price ratio for most workloads.\nDifferent instance ranges are proposed:\n\n* The **Development** instances range provides stable and consistent performance for\n development and testing needs. Spin up a development or test environment within seconds.\n Refer to the [Development Instance offer details](https://www.scaleway.com/en/virtual-instances/play2/)\n for more information.\n\n* The **General Purpose** instances range is the solution for production workloads. Powerful\n AMD EPYC CPUs back those instances and offer up to 48 Cores, 256GB of RAM and storage\n options up to 600GB of replicated local NVMe SSD storage and/or up to 10TB of Block Storage.\n Refer to the [General Purpose offer details](https://www.scaleway.com/en/virtual-instances/pro2/) for more information.\n\n* The **Enterprise** instances range is the solution for most demanding workloads and\n mission-critical applications. Powerful AMD EPYC CPUs back those instances and\n offer up to 96 Cores, 384GB of RAM and up to 10TB of Block Storage. Refer to the\n [Enterprise offer details](https://www.scaleway.com/en/virtual-instances/enterprise/) for more information.\n\n**Dedicated GPU Instances**\n\nScaleway GPU Instances are virtual compute instances equipped with dedicated high-end\nNvidia graphical processing unit (GPUs). They are ideal for data processing, artificial\nintelligence, rendering and video encoding. The GPU is dedicated to each instance and\ndirectly exposed through PCI-e. For more information, refer to the\n[GPU Instances Developper Documentation](https://www.scaleway.com/en/docs/compute/gpu/quickstart/).\n" } } ], @@ -2623,7 +2627,9 @@ "description": "UUID of the image you want to get." } } - ] + ], + "description": "Images are backups of your instances.\nYou can reuse that image to restore your data or create a series of instances with a predefined configuration.\n\nAn image is a complete backup of your server including all volumes.\n", + "markdown_description": "Images are backups of your instances.\nYou can reuse that image to restore your data or create a series of instances with a predefined configuration.\n\nAn image is a complete backup of your server including all volumes.\n" } }, { @@ -2755,7 +2761,9 @@ ] } } - ] + ], + "description": "A flexible IP address is an IP address which you hold independently of any server.\nYou can attach it to any of your servers and do live migration of the IP address between your servers.\n\nBe aware that attaching a flexible IP address to a server will remove the previous public IP address of the server and cut any ongoing public connection to the server.\n", + "markdown_description": "A flexible IP address is an IP address which you hold independently of any server.\nYou can attach it to any of your servers and do live migration of the IP address between your servers.\n\nBe aware that attaching a flexible IP address to a server will remove the previous public IP address of the server and cut any ongoing public connection to the server.\n" } } ], diff --git a/internal/explorer/config_explorer.go b/internal/explorer/config_explorer.go index cc5fa13d..d9de525a 100644 --- a/internal/explorer/config_explorer.go +++ b/internal/explorer/config_explorer.go @@ -94,6 +94,7 @@ func (e configExplorer) FindResources() (map[string]Resource, error) { DeleteOp: deleteOp, CommonParameters: commonParameters, SchemaOptions: extractSchemaOptions(resourceConfig.SchemaOptions), + Description: getOperationTagDescription(e.spec, createOp), } } @@ -121,6 +122,7 @@ func (e configExplorer) FindDataSources() (map[string]DataSource, error) { ReadOp: readOp, CommonParameters: commonParameters, SchemaOptions: extractSchemaOptions(dataSourceConfig.SchemaOptions), + Description: getOperationTagDescription(e.spec, readOp), } } return dataSources, errResult @@ -216,3 +218,21 @@ func extractOverrides(cfgOverrides map[string]config.Override) map[string]Overri return overrides } + +// getTagDescription looks up the description for a tag name from the document's tags +func getTagDescription(tags []*highbase.Tag, tagName string) string { + for _, tag := range tags { + if tag.Name == tagName { + return tag.Description + } + } + return "" +} + +// getOperationTagDescription gets the description from the first tag of an operation +func getOperationTagDescription(spec high.Document, op *high.Operation) string { + if op == nil || len(op.Tags) == 0 { + return "" + } + return getTagDescription(spec.Tags, op.Tags[0]) +} diff --git a/internal/explorer/explorer.go b/internal/explorer/explorer.go index 908b62c9..2e4fc8e9 100644 --- a/internal/explorer/explorer.go +++ b/internal/explorer/explorer.go @@ -23,6 +23,7 @@ type Resource struct { DeleteOp *high.Operation CommonParameters []*high.Parameter SchemaOptions SchemaOptions + Description string // Resource-level description from OpenAPI tags } // DataSource contains a Read operation and schema options for configuration. @@ -30,6 +31,7 @@ type DataSource struct { ReadOp *high.Operation CommonParameters []*high.Parameter SchemaOptions SchemaOptions + Description string // DataSource-level description from OpenAPI tags } // Provider contains a name and a schema. diff --git a/internal/mapper/datasource_mapper.go b/internal/mapper/datasource_mapper.go index ac0229e3..caa35b69 100644 --- a/internal/mapper/datasource_mapper.go +++ b/internal/mapper/datasource_mapper.go @@ -156,5 +156,12 @@ func generateDataSourceSchema(logger *slog.Logger, name string, dataSource explo dataSourceAttributes, _ = dataSourceAttributes.ApplyOverrides(dataSource.SchemaOptions.AttributeOptions.Overrides) dataSourceSchema.Attributes = dataSourceAttributes.ToSpec() + + // Set the data source-level description from OpenAPI tags if available + if dataSource.Description != "" { + dataSourceSchema.Description = &dataSource.Description + dataSourceSchema.MarkdownDescription = &dataSource.Description + } + return dataSourceSchema, nil } diff --git a/internal/mapper/resource_mapper.go b/internal/mapper/resource_mapper.go index 1b393db2..6a1957f0 100644 --- a/internal/mapper/resource_mapper.go +++ b/internal/mapper/resource_mapper.go @@ -186,5 +186,12 @@ func generateResourceSchema(logger *slog.Logger, explorerResource explorer.Resou resourceAttributes, _ = resourceAttributes.ApplyOverrides(explorerResource.SchemaOptions.AttributeOptions.Overrides) resourceSchema.Attributes = resourceAttributes.ToSpec() + + // Set the resource-level description from OpenAPI tags if available + if explorerResource.Description != "" { + resourceSchema.Description = &explorerResource.Description + resourceSchema.MarkdownDescription = &explorerResource.Description + } + return resourceSchema, nil }