From 1c5822dc945974882d35e8a4bcff922e090b9e60 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Fri, 8 Aug 2025 08:21:21 -0400 Subject: [PATCH 01/18] update go mod to use new tfjson PR --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 838fe89..1753ae7 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/hc-install v0.9.2 github.com/hashicorp/terraform-exec v0.23.0 - github.com/hashicorp/terraform-json v0.25.0 + github.com/hashicorp/terraform-json v0.25.1-0.20250808120122-465ba375ab0a github.com/mattn/go-colorable v0.1.14 github.com/rogpeppe/go-internal v1.14.1 github.com/yuin/goldmark v1.7.7 diff --git a/go.sum b/go.sum index c7b636c..ac149ea 100644 --- a/go.sum +++ b/go.sum @@ -74,8 +74,8 @@ github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+O github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I= github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= -github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ= -github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc= +github.com/hashicorp/terraform-json v0.25.1-0.20250808120122-465ba375ab0a h1:gzMCStpg0ySSzpPa6KnWha9DUiadfoN9yVsrqOWiwLs= +github.com/hashicorp/terraform-json v0.25.1-0.20250808120122-465ba375ab0a/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= From e864bc6be921836c37b4b015682385c0a22983a0 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Fri, 8 Aug 2025 10:54:08 -0400 Subject: [PATCH 02/18] add generate command --- internal/provider/action_template.go | 79 +++++++++++++++++++++++++ internal/provider/generate.go | 88 +++++++++++++++++++++++++++- internal/provider/util.go | 13 ++++ internal/schemamd/render.go | 19 ++++++ 4 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 internal/provider/action_template.go diff --git a/internal/provider/action_template.go b/internal/provider/action_template.go new file mode 100644 index 0000000..00a0965 --- /dev/null +++ b/internal/provider/action_template.go @@ -0,0 +1,79 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "bytes" + + tfjson "github.com/hashicorp/terraform-json" + "github.com/hashicorp/terraform-plugin-docs/internal/schemamd" +) + +const actionSchemaComment = "" + +type actionTemplate string + +func (t actionTemplate) Render(providerDir, name, providerName, renderedProviderName, typeName, exampleFile string, schema *tfjson.ActionSchema) (string, error) { + schemaBuffer := bytes.NewBuffer(nil) + err := schemamd.RenderAction(schema, schemaBuffer) + if err != nil { + return "", err + } + + s := string(t) + if s == "" { + return "", nil + } + + return renderStringTemplate(providerDir, "actionTemplate", s, struct { + Type string + Name string + Description string + + HasExample bool + ExampleFile string + + ProviderName string + ProviderShortName string + + SchemaMarkdown string + + RenderedProviderName string + }{ + Type: typeName, + Name: name, + Description: schema.Block.Description, + + HasExample: exampleFile != "" && fileExists(exampleFile), + ExampleFile: exampleFile, + + ProviderName: providerName, + ProviderShortName: providerShortName(renderedProviderName), + + SchemaMarkdown: actionSchemaComment + "\n" + schemaBuffer.String(), + + RenderedProviderName: renderedProviderName, + }) +} + +const defaultActionTemplate actionTemplate = `--- +` + frontmatterComment + ` +page_title: "{{.Name}} {{.Type}} - {{.RenderedProviderName}}" +subcategory: "" +description: |- +{{ .Description | plainmarkdown | trimspace | prefixlines " " }} +--- + +# {{.Name}} ({{.Type}}) + +{{ .Description | trimspace }} + +{{ if .HasExample -}} +## Example Usage + +{{tffile .ExampleFile }} +{{- end }} + +{{ .SchemaMarkdown | trimspace }} +` diff --git a/internal/provider/generate.go b/internal/provider/generate.go index 8537094..ee9a099 100644 --- a/internal/provider/generate.go +++ b/internal/provider/generate.go @@ -67,6 +67,14 @@ var ( "ephemeral-resources/%s.html.markdown", "ephemeral-resources/%s.html.md", } + websiteActionFile = "actions/%s.md.tmpl" + websiteActionFallbackFile = "actions.md.tmpl" + websiteActionFileStaticCandidates = []string{ + "actions/%s.md", + "actions/%s.markdown", + "actions/%s.html.markdown", + "actions/%s.html.md", + } websiteProviderFile = "index.md.tmpl" websiteProviderFileStaticCandidates = []string{ "index.markdown", @@ -81,6 +89,7 @@ var ( "resources", "functions", "ephemeral-resources", + "actions", } managedWebsiteFiles = []string{ @@ -418,6 +427,42 @@ func (g *generator) generateMissingEphemeralResourceTemplate(resourceName string return nil } +func (g *generator) generateMissingActionTemplate(actionName string) error { + templatePath := fmt.Sprintf(websiteActionFile, resourceShortName(actionName, g.providerName)) + templatePath = filepath.Join(g.TempTemplatesDir(), templatePath) + if fileExists(templatePath) { + g.infof("action %q template exists, skipping", actionName) + return nil + } + + fallbackTemplatePath := filepath.Join(g.TempTemplatesDir(), websiteActionFallbackFile) + if fileExists(fallbackTemplatePath) { + g.infof("action %q fallback template exists, creating template", actionName) + err := cp(fallbackTemplatePath, templatePath) + if err != nil { + return fmt.Errorf("unable to copy fallback template for %q: %w", actionName, err) + } + return nil + } + + for _, candidate := range websiteActionFileStaticCandidates { + candidatePath := fmt.Sprintf(candidate, resourceShortName(actionName, g.providerName)) + candidatePath = filepath.Join(g.TempTemplatesDir(), candidatePath) + if fileExists(candidatePath) { + g.infof("action %q static file exists, skipping", actionName) + return nil + } + } + + g.infof("generating new template for %q", actionName) + err := writeFile(templatePath, string(defaultActionTemplate)) + if err != nil { + return fmt.Errorf("unable to write template for %q: %w", actionName, err) + } + + return nil +} + func (g *generator) generateMissingProviderTemplate() error { templatePath := filepath.Join(g.TempTemplatesDir(), websiteProviderFile) if fileExists(templatePath) { @@ -527,6 +572,27 @@ func (g *generator) generateMissingTemplates(providerSchema *tfjson.ProviderSche } } + g.infof("generating missing action content") + + actionKeys := make([]string, 0, len(providerSchema.ActionSchemas)) + for key := range providerSchema.ActionSchemas { + actionKeys = append(actionKeys, key) + } + sort.Strings(actionKeys) + + for _, name := range actionKeys { + schema := providerSchema.ActionSchemas[name] + + if g.ignoreDeprecated && schema.Block.Deprecated { + continue + } + + err := g.generateMissingActionTemplate(name) + if err != nil { + return fmt.Errorf("unable to generate template for action %q: %w", name, err) + } + } + g.infof("generating missing provider content") err := g.generateMissingProviderTemplate() if err != nil { @@ -588,11 +654,12 @@ func (g *generator) renderStaticWebsite(providerSchema *tfjson.ProviderSchema) e relDir, relFile := filepath.Split(rel) relDir = filepath.ToSlash(relDir) - // skip special top-level generic resource, data source, function, and ephemeral resource templates + // skip special top-level generic resource, data source, function, ephemeral resource, and action templates if relDir == "" && (relFile == "resources.md.tmpl" || relFile == "data-sources.md.tmpl" || relFile == "functions.md.tmpl" || - relFile == "ephemeral-resources.md.tmpl") { + relFile == "ephemeral-resources.md.tmpl" || + relFile == "actions.md.tmpl") { return nil } @@ -696,6 +763,23 @@ func (g *generator) renderStaticWebsite(providerSchema *tfjson.ProviderSchema) e return nil } g.warnf("ephemeral resource entitled %q, or %q does not exist", shortName, resName) + case "actions/": + actionSchema, resName := actionSchema(providerSchema.ActionSchemas, shortName, relFile) + exampleFilePath := filepath.Join(g.ProviderExamplesDir(), "actions", resName, "action.tf") + + if actionSchema != nil { + tmpl := actionTemplate(tmplData) + render, err := tmpl.Render(g.providerDir, resName, g.providerName, g.renderedProviderName, "Action", exampleFilePath, actionSchema) + if err != nil { + return fmt.Errorf("unable to render action template %q: %w", rel, err) + } + _, err = out.WriteString(render) + if err != nil { + return fmt.Errorf("unable to write rendered string: %w", err) + } + return nil + } + g.warnf("action entitled %q, or %q does not exist", shortName, resName) case "": // provider if relFile == "index.md.tmpl" { tmpl := providerTemplate(tmplData) diff --git a/internal/provider/util.go b/internal/provider/util.go index 8a879cf..5cdc99c 100644 --- a/internal/provider/util.go +++ b/internal/provider/util.go @@ -89,6 +89,19 @@ func resourceSchema(schemas map[string]*tfjson.Schema, providerShortName, templa return nil, resName } +func actionSchema(schemas map[string]*tfjson.ActionSchema, providerShortName, templateFileName string) (*tfjson.ActionSchema, string) { + resName := providerShortName + "_" + removeAllExt(templateFileName) + if schema, ok := schemas[resName]; ok { + return schema, resName + } + + if schema, ok := schemas[providerShortName]; ok { + return schema, providerShortName + } + + return nil, resName +} + func resourceIdentitySchema(schemas map[string]*tfjson.IdentitySchema, providerShortName, templateFileName string) *tfjson.IdentitySchema { resName := providerShortName + "_" + removeAllExt(templateFileName) if schema, ok := schemas[resName]; ok { diff --git a/internal/schemamd/render.go b/internal/schemamd/render.go index cc5cdc4..71daa90 100644 --- a/internal/schemamd/render.go +++ b/internal/schemamd/render.go @@ -36,6 +36,25 @@ func Render(schema *tfjson.Schema, w io.Writer) error { return nil } +// RenderAction is a variant of Render for action schemas. Action schemas share the same config block as +// resource schemas, with the addition of other schema data based on the type of action it is. +// +// Currently, the only action type is unlinked, which has no additional information to document, but future +// actions may have useful information to generate documentation for (example: linked resources). +func RenderAction(schema *tfjson.ActionSchema, w io.Writer) error { + _, err := io.WriteString(w, "## Schema\n\n") + if err != nil { + return err + } + + err = writeRootBlock(w, schema.Block) + if err != nil { + return fmt.Errorf("unable to render action schema: %w", err) + } + + return nil +} + func RenderIdentitySchema(identitySchema *tfjson.IdentitySchema, w io.Writer) error { _, err := io.WriteString(w, "### Identity Schema\n\n") if err != nil { From 9e18c3f48e14a60260ca4d3aa2b43962a8a8c40d Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 09:25:37 -0400 Subject: [PATCH 03/18] add action log messages to allow tests to pass --- .../generate/framework_provider_success_generic_templates.txtar | 1 + .../generate/framework_provider_success_named_templates.txtar | 1 + .../generate/framework_provider_success_no_templates.txtar | 1 + .../scripts/provider-build/generate/null_provider_success.txtar | 1 + .../framework_provider_success_all_framework_types.txtar | 1 + .../generate/framework_provider_success_generic_templates.txtar | 1 + .../generate/framework_provider_success_legacy_docs.txtar | 1 + .../generate/framework_provider_success_named_templates.txtar | 1 + .../generate/framework_provider_success_no_templates.txtar | 1 + .../generate/framework_provider_success_static_files.txtar | 1 + .../scripts/schema-json/generate/nested_id_attribute.txtar | 1 + .../scripts/schema-json/generate/null_provider_success.txtar | 1 + 12 files changed, 12 insertions(+) diff --git a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_generic_templates.txtar b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_generic_templates.txtar index b0029a0..8dd3e6c 100644 --- a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_generic_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_generic_templates.txtar @@ -27,6 +27,7 @@ generating missing data source content data-source "scaffolding_example" fallback template exists, creating template generating missing function content generating missing ephemeral resource content +generating missing action content generating missing provider content provider "terraform-provider-scaffolding" template exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar index 6cad31f..492690c 100644 --- a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_named_templates.txtar @@ -27,6 +27,7 @@ generating missing data source content data-source "scaffolding_example" template exists, skipping generating missing function content generating missing ephemeral resource content +generating missing action content generating missing provider content provider "terraform-provider-scaffolding" template exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar index 6a13f4c..f599fc4e 100644 --- a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/framework_provider_success_no_templates.txtar @@ -25,6 +25,7 @@ generating missing data source content generating new template for data-source "scaffolding_example" generating missing function content generating missing ephemeral resource content +generating missing action content generating missing provider content generating new template for "terraform-provider-scaffolding" rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/null_provider_success.txtar b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/null_provider_success.txtar index 263e85c..1ae070d 100644 --- a/cmd/tfplugindocs/testdata/scripts/provider-build/generate/null_provider_success.txtar +++ b/cmd/tfplugindocs/testdata/scripts/provider-build/generate/null_provider_success.txtar @@ -24,6 +24,7 @@ generating missing data source content data-source "null_data_source" fallback template exists, creating template generating missing function content generating missing ephemeral resource content +generating missing action content generating missing provider content provider "terraform-provider-null" template exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_all_framework_types.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_all_framework_types.txtar index 8aba364..3a4c9bb 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_all_framework_types.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_all_framework_types.txtar @@ -20,6 +20,7 @@ generating missing data source content generating missing function content generating new template for function "scaffolding" generating missing ephemeral resource content +generating missing action content generating missing provider content generating new template for "terraform-provider-scaffolding" rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar index 85a766b..472cbf8 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar @@ -27,6 +27,7 @@ generating missing function content function "example" fallback template exists, creating template generating missing ephemeral resource content ephemeral resource "scaffolding_example" fallback template exists, creating template +generating missing action content generating missing provider content provider "terraform-provider-scaffolding" template exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar index 0c049c1..8862b3f 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar @@ -45,6 +45,7 @@ generating missing function content function "example" static file exists, skipping generating missing ephemeral resource content ephemeral resource "scaffolding_example" static file exists, skipping +generating missing action content generating missing provider content provider "terraform-provider-scaffolding" static file exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar index c5cfe00..5e5d13a 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar @@ -26,6 +26,7 @@ generating missing function content function "example" template exists, skipping generating missing ephemeral resource content ephemeral resource "scaffolding_example" template exists, skipping +generating missing action content generating missing provider content provider "terraform-provider-scaffolding" template exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar index bb1e596..a52feef 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar @@ -26,6 +26,7 @@ generating new template for function "example" generating new template for function "no-variadic" generating missing ephemeral resource content generating new template for "scaffolding_example" +generating missing action content generating missing provider content generating new template for "terraform-provider-scaffolding" rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar index a082d55..3c46ed5 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar @@ -45,6 +45,7 @@ generating missing function content function "example" static file exists, skipping generating missing ephemeral resource content ephemeral resource "scaffolding_example" static file exists, skipping +generating missing action content generating missing provider content provider "terraform-provider-scaffolding" static file exists, skipping rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/nested_id_attribute.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/nested_id_attribute.txtar index 886c20a..f685ac4 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/nested_id_attribute.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/nested_id_attribute.txtar @@ -18,6 +18,7 @@ generating new template for "scaffolding_example" generating missing data source content generating missing function content generating missing ephemeral resource content +generating missing action content generating missing provider content generating new template for "terraform-provider-scaffolding" rendering static website diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/null_provider_success.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/null_provider_success.txtar index e05ef44..619257a 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/null_provider_success.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/null_provider_success.txtar @@ -19,6 +19,7 @@ generating missing data source content data-source "null_data_source" fallback template exists, creating template generating missing function content generating missing ephemeral resource content +generating missing action content generating missing provider content provider "terraform-provider-null" template exists, skipping rendering static website From 0fc5d4db0f1317ae806634a3b56d72f5d8414a08 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 15:11:31 -0400 Subject: [PATCH 04/18] add generate tests --- ...k_provider_success_generic_templates.txtar | 122 ++++++++++++++++++ ...amework_provider_success_legacy_docs.txtar | 60 +++++++++ ...ork_provider_success_named_templates.txtar | 122 ++++++++++++++++++ ...mework_provider_success_no_templates.txtar | 66 ++++++++++ ...mework_provider_success_static_files.txtar | 60 +++++++++ 5 files changed, 430 insertions(+) diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar index 472cbf8..e4474ef 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_generic_templates.txtar @@ -11,6 +11,7 @@ cmpenv docs/data-sources/example.md expected-datasource.md cmpenv docs/resources/example.md expected-resource.md cmpenv docs/functions/example.md expected-function.md cmpenv docs/ephemeral-resources/example.md expected-ephemeral-resource.md +cmpenv docs/actions/unlinked_example.md expected-unlinked-action.md -- expected-output.txt -- @@ -28,16 +29,69 @@ function "example" fallback template exists, creating template generating missing ephemeral resource content ephemeral resource "scaffolding_example" fallback template exists, creating template generating missing action content +action "scaffolding_unlinked_example" fallback template exists, creating template generating missing provider content provider "terraform-provider-scaffolding" template exists, skipping rendering static website cleaning rendered website dir rendering templated website to static markdown +rendering "actions/unlinked_example.md.tmpl" rendering "data-sources/example.md.tmpl" rendering "ephemeral-resources/example.md.tmpl" rendering "functions/example.md.tmpl" rendering "index.md.tmpl" rendering "resources/example.md.tmpl" +-- expected-unlinked-action.md -- +# Data Fields + +Name: scaffolding_unlinked_example +Type: Action +Description: Example unlinked action +HasExample: true +ExampleFile: $WORK/examples/actions/scaffolding_unlinked_example/action.tf +ProviderName: terraform-provider-scaffolding +ProviderShortName: scaffolding +RenderedProviderName: terraform-provider-scaffolding +SchemaMarkdown: +## Schema + +### Required + +- `required_attr` (String) Example required attribute + +### Optional + +- `optional_attr` (String) Example optional attribute + + + +# Functions + +lower: action +plainmarkdown: Action +prefixlines: Prefix: Action +split: [scaffolding unlinked example] +title: Action +trimspace: Action +upper: ACTION + +# Conditionals and File Functions + +printf tffile: +## Example Usage + +{{tffile "$WORK/examples/actions/scaffolding_unlinked_example/action.tf"}} + +tffile: +## Example Usage + +```terraform +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} +``` -- expected-datasource.md -- # Data Fields @@ -311,6 +365,44 @@ resource "scaffolding_example" "example" { configurable_attribute = "some-value" } ``` +-- templates/actions.md.tmpl -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +Description: {{.Description}} +HasExample: {{.HasExample}} +ExampleFile: {{.ExampleFile}} +ProviderName: {{.ProviderName}} +ProviderShortName: {{.ProviderShortName}} +RenderedProviderName: {{.RenderedProviderName}} +SchemaMarkdown: {{.SchemaMarkdown}} + +# Functions + +lower: {{ .Type | lower }} +plainmarkdown: {{ .Type | plainmarkdown }} +prefixlines: {{ .Type | prefixlines "Prefix: " }} +split: {{ split .Name "_" }} +title: {{ .Type | title }} +trimspace: {{ .Type | trimspace }} +upper: {{ .Type | upper }} + +# Conditionals and File Functions + +printf tffile: +{{ if .HasExample -}} +## Example Usage + +{{ printf "{{tffile %q}}" .ExampleFile }} +{{- end }} + +tffile: +{{ if .HasExample -}} +## Example Usage + +{{tffile .ExampleFile }} +{{- end }} -- templates/data-sources.md.tmpl -- # Data Fields @@ -573,6 +665,12 @@ The document generation tool looks for files in the following locations by defau * **provider/provider.tf** example file for the provider index page * **data-sources/`full data source name`/data-source.tf** example file for the named data source page * **resources/`full resource name`/resource.tf** example file for the named data source page +-- examples/actions/scaffolding_unlinked_example/action.tf -- +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} -- examples/data-sources/scaffolding_example/data-source.tf -- data "scaffolding_example" "example" { configurable_attribute = "some-value" @@ -624,6 +722,30 @@ resource "scaffolding_example" "example" { "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar index 8862b3f..d54dd00 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_legacy_docs.txtar @@ -27,6 +27,11 @@ cmp templates/ephemeral-resources/example.markdown docs/ephemeral-resources/exam cmp templates/ephemeral-resources/example.html.markdown docs/ephemeral-resources/example.html.markdown cmp templates/ephemeral-resources/example.html.md docs/ephemeral-resources/example.html.md +cmp templates/actions/unlinked_example.md docs/actions/unlinked_example.md +cmp templates/actions/unlinked_example.markdown docs/actions/unlinked_example.markdown +cmp templates/actions/unlinked_example.html.markdown docs/actions/unlinked_example.html.markdown +cmp templates/actions/unlinked_example.html.md docs/actions/unlinked_example.html.md + cmp templates/index.md docs/index.md cmp templates/index.markdown docs/index.markdown cmp templates/index.html.markdown docs/index.html.markdown @@ -46,11 +51,16 @@ function "example" static file exists, skipping generating missing ephemeral resource content ephemeral resource "scaffolding_example" static file exists, skipping generating missing action content +action "scaffolding_unlinked_example" static file exists, skipping generating missing provider content provider "terraform-provider-scaffolding" static file exists, skipping rendering static website cleaning rendered website dir rendering templated website to static markdown +copying non-template file: "actions/unlinked_example.html.markdown" +copying non-template file: "actions/unlinked_example.html.md" +copying non-template file: "actions/unlinked_example.markdown" +copying non-template file: "actions/unlinked_example.md" copying non-template file: "d/example.html.markdown" copying non-template file: "d/example.html.md" copying non-template file: "d/example.markdown" @@ -71,6 +81,26 @@ copying non-template file: "r/example.html.markdown" copying non-template file: "r/example.html.md" copying non-template file: "r/example.markdown" copying non-template file: "r/example.md" +-- templates/actions/unlinked_example.md -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +-- templates/actions/unlinked_example.markdown -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +-- templates/actions/unlinked_example.html.markdown -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +-- templates/actions/unlinked_example.html.md -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} -- templates/r/example.md -- # Data Fields @@ -181,6 +211,12 @@ The document generation tool looks for files in the following locations by defau * **provider/provider.tf** example file for the provider index page * **data-sources/`full data source name`/data-source.tf** example file for the named data source page * **resources/`full resource name`/resource.tf** example file for the named data source page +-- examples/actions/scaffolding_unlinked_example/action.tf -- +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} -- examples/data-sources/scaffolding_example/data-source.tf -- data "scaffolding_example" "example" { configurable_attribute = "some-value" @@ -228,6 +264,30 @@ terraform import scaffolding_example.example "id-123" "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar index 5e5d13a..434223c 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_named_templates.txtar @@ -11,6 +11,7 @@ cmpenv docs/data-sources/example.md expected-datasource.md cmpenv docs/resources/example.md expected-resource.md cmpenv docs/functions/example.md expected-function.md cmpenv docs/ephemeral-resources/example.md expected-ephemeral-resource.md +cmpenv docs/actions/unlinked_example.md expected-unlinked-action.md -- expected-output.txt -- rendering website for provider "terraform-provider-scaffolding" (as "Scaffolding") @@ -27,16 +28,69 @@ function "example" template exists, skipping generating missing ephemeral resource content ephemeral resource "scaffolding_example" template exists, skipping generating missing action content +action "scaffolding_unlinked_example" template exists, skipping generating missing provider content provider "terraform-provider-scaffolding" template exists, skipping rendering static website cleaning rendered website dir rendering templated website to static markdown +rendering "actions/unlinked_example.md.tmpl" rendering "data-sources/example.md.tmpl" rendering "ephemeral-resources/example.md.tmpl" rendering "functions/example.md.tmpl" rendering "index.md.tmpl" rendering "resources/example.md.tmpl" +-- expected-unlinked-action.md -- +# Data Fields + +Name: scaffolding_unlinked_example +Type: Action +Description: Example unlinked action +HasExample: true +ExampleFile: $WORK/examples/actions/scaffolding_unlinked_example/action.tf +ProviderName: terraform-provider-scaffolding +ProviderShortName: Scaffolding +RenderedProviderName: Scaffolding +SchemaMarkdown: +## Schema + +### Required + +- `required_attr` (String) Example required attribute + +### Optional + +- `optional_attr` (String) Example optional attribute + + + +# Functions + +lower: action +plainmarkdown: Action +prefixlines: Prefix: Action +split: [scaffolding unlinked example] +title: Action +trimspace: Action +upper: ACTION + +# Conditionals and File Functions + +printf tffile: +## Example Usage + +{{tffile "$WORK/examples/actions/scaffolding_unlinked_example/action.tf"}} + +tffile: +## Example Usage + +```terraform +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} +``` -- expected-datasource.md -- # Data Fields @@ -324,6 +378,44 @@ resource "scaffolding_example" "example" { configurable_attribute = "some-value" } ``` +-- templates/actions/unlinked_example.md.tmpl -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +Description: {{.Description}} +HasExample: {{.HasExample}} +ExampleFile: {{.ExampleFile}} +ProviderName: {{.ProviderName}} +ProviderShortName: {{.ProviderShortName}} +RenderedProviderName: {{.RenderedProviderName}} +SchemaMarkdown: {{.SchemaMarkdown}} + +# Functions + +lower: {{ .Type | lower }} +plainmarkdown: {{ .Type | plainmarkdown }} +prefixlines: {{ .Type | prefixlines "Prefix: " }} +split: {{ split .Name "_" }} +title: {{ .Type | title }} +trimspace: {{ .Type | trimspace }} +upper: {{ .Type | upper }} + +# Conditionals and File Functions + +printf tffile: +{{ if .HasExample -}} +## Example Usage + +{{ printf "{{tffile %q}}" .ExampleFile }} +{{- end }} + +tffile: +{{ if .HasExample -}} +## Example Usage + +{{tffile .ExampleFile }} +{{- end }} -- templates/data-sources/example.md.tmpl -- # Data Fields @@ -589,6 +681,12 @@ The document generation tool looks for files in the following locations by defau * **provider/provider.tf** example file for the provider index page * **data-sources/`full data source name`/data-source.tf** example file for the named data source page * **resources/`full resource name`/resource.tf** example file for the named data source page +-- examples/actions/scaffolding_unlinked_example/action.tf -- +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} -- examples/data-sources/scaffolding_example/data-source.tf -- data "scaffolding_example" "example" { configurable_attribute = "some-value" @@ -653,6 +751,30 @@ terraform import scaffolding_example.example "id-123" "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar index a52feef..9231266 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_no_templates.txtar @@ -11,6 +11,7 @@ cmp docs/resources/example.md expected-resource.md cmp docs/functions/example.md expected-function.md cmp docs/functions/no-variadic.md expected-no-variadic-function.md cmp docs/ephemeral-resources/example.md expected-ephemeral-resource.md +cmp docs/actions/unlinked_example.md expected-unlinked-action.md -- expected-output.txt -- rendering website for provider "terraform-provider-scaffolding" (as "Scaffolding") @@ -27,17 +28,52 @@ generating new template for function "no-variadic" generating missing ephemeral resource content generating new template for "scaffolding_example" generating missing action content +generating new template for "scaffolding_unlinked_example" generating missing provider content generating new template for "terraform-provider-scaffolding" rendering static website cleaning rendered website dir rendering templated website to static markdown +rendering "actions/unlinked_example.md.tmpl" rendering "data-sources/example.md.tmpl" rendering "ephemeral-resources/example.md.tmpl" rendering "functions/example.md.tmpl" rendering "functions/no-variadic.md.tmpl" rendering "index.md.tmpl" rendering "resources/example.md.tmpl" +-- expected-unlinked-action.md -- +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "scaffolding_unlinked_example Action - Scaffolding" +subcategory: "" +description: |- + Example unlinked action +--- + +# scaffolding_unlinked_example (Action) + +Example unlinked action + +## Example Usage + +```terraform +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} +``` + + +## Schema + +### Required + +- `required_attr` (String) Example required attribute + +### Optional + +- `optional_attr` (String) Example optional attribute -- expected-datasource.md -- --- # generated by https://github.com/hashicorp/terraform-plugin-docs @@ -281,6 +317,12 @@ The document generation tool looks for files in the following locations by defau * **provider/provider.tf** example file for the provider index page * **data-sources/`full data source name`/data-source.tf** example file for the named data source page * **resources/`full resource name`/resource.tf** example file for the named data source page +-- examples/actions/scaffolding_unlinked_example/action.tf -- +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} -- examples/data-sources/scaffolding_example/data-source.tf -- data "scaffolding_example" "example" { configurable_attribute = "some-value" @@ -348,6 +390,30 @@ resource "scaffolding_example" "example" { "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar index 3c46ed5..39ac300 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/generate/framework_provider_success_static_files.txtar @@ -27,6 +27,11 @@ cmp templates/ephemeral-resources/example.markdown docs/ephemeral-resources/exam cmp templates/ephemeral-resources/example.html.markdown docs/ephemeral-resources/example.html.markdown cmp templates/ephemeral-resources/example.html.md docs/ephemeral-resources/example.html.md +cmp templates/actions/unlinked_example.md docs/actions/unlinked_example.md +cmp templates/actions/unlinked_example.markdown docs/actions/unlinked_example.markdown +cmp templates/actions/unlinked_example.html.markdown docs/actions/unlinked_example.html.markdown +cmp templates/actions/unlinked_example.html.md docs/actions/unlinked_example.html.md + cmp templates/index.md docs/index.md cmp templates/index.markdown docs/index.markdown cmp templates/index.html.markdown docs/index.html.markdown @@ -46,11 +51,16 @@ function "example" static file exists, skipping generating missing ephemeral resource content ephemeral resource "scaffolding_example" static file exists, skipping generating missing action content +action "scaffolding_unlinked_example" static file exists, skipping generating missing provider content provider "terraform-provider-scaffolding" static file exists, skipping rendering static website cleaning rendered website dir rendering templated website to static markdown +copying non-template file: "actions/unlinked_example.html.markdown" +copying non-template file: "actions/unlinked_example.html.md" +copying non-template file: "actions/unlinked_example.markdown" +copying non-template file: "actions/unlinked_example.md" copying non-template file: "data-sources/example.html.markdown" copying non-template file: "data-sources/example.html.md" copying non-template file: "data-sources/example.markdown" @@ -71,6 +81,26 @@ copying non-template file: "resources/example.html.markdown" copying non-template file: "resources/example.html.md" copying non-template file: "resources/example.markdown" copying non-template file: "resources/example.md" +-- templates/actions/unlinked_example.md -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +-- templates/actions/unlinked_example.markdown -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +-- templates/actions/unlinked_example.html.markdown -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} +-- templates/actions/unlinked_example.html.md -- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} -- templates/resources/example.md -- # Data Fields @@ -181,6 +211,12 @@ The document generation tool looks for files in the following locations by defau * **provider/provider.tf** example file for the provider index page * **data-sources/`full data source name`/data-source.tf** example file for the named data source page * **resources/`full resource name`/resource.tf** example file for the named data source page +-- examples/actions/scaffolding_unlinked_example/action.tf -- +action "scaffolding_unlinked_example" "example" { + config { + required_attr = "some-value" + } +} -- examples/data-sources/scaffolding_example/data-source.tf -- data "scaffolding_example" "example" { configurable_attribute = "some-value" @@ -228,6 +264,30 @@ terraform import scaffolding_example.example "id-123" "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, From e045a09613ad98f3cde839409a09ea0ca81e212a Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 16:22:28 -0400 Subject: [PATCH 05/18] validate command and tests --- ...amework_provider_error_file_mismatch.txtar | 37 +++++ ...amework_provider_success_legacy_docs.txtar | 38 +++++ ...ework_provider_success_registry_docs.txtar | 37 +++++ internal/check/directory.go | 6 + internal/check/directory_test.go | 16 +- internal/check/file_mismatch.go | 91 +++++++++++ internal/check/file_mismatch_test.go | 90 +++++++++++ internal/provider/testdata/schema.json | 22 +++ internal/provider/util_test.go | 6 + internal/provider/validate.go | 12 +- internal/provider/validate_test.go | 144 +++++++++++++++++- 11 files changed, 490 insertions(+), 9 deletions(-) diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_error_file_mismatch.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_error_file_mismatch.txtar index e19a80b..64e4859 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_error_file_mismatch.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_error_file_mismatch.txtar @@ -13,7 +13,20 @@ stderr 'matching function for documentation file \(example2.md\) not found, file stderr 'missing documentation file for function: example' stderr 'matching ephemeral resource for documentation file \(example2.md\) not found, file is extraneous or incorrectly named' stderr 'missing documentation file for ephemeral resource: scaffolding_example' +stderr 'matching action for documentation file \(example2.md\) not found, file is extraneous or incorrectly named' +stderr 'missing documentation file for action: scaffolding_unlinked_example' +-- docs/actions/example2.md -- +--- +subcategory: "Example" +page_title: "Example: example_thing" +description: |- + Example description. +--- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} -- docs/data-sources/example2.md -- --- subcategory: "Example" @@ -78,6 +91,30 @@ Type: {{.Type}} "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_legacy_docs.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_legacy_docs.txtar index fa9df60..ba4e2fd 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_legacy_docs.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_legacy_docs.txtar @@ -11,6 +11,8 @@ exporting schema from JSON file getting provider schema running mixed directories check detected legacy website directory, running checks +running invalid directories check on website/docs/actions +running file checks on website/docs/actions/unlinked_example.html.md running invalid directories check on website/docs/d running file checks on website/docs/d/example.html.md running invalid directories check on website/docs/ephemeral-resources @@ -36,6 +38,18 @@ description: |- Example contents. +-- website/docs/actions/unlinked_example.html.md -- +--- +subcategory: "Example" +layout: "example" +page_title: "Example: example_thing" +description: |- + Example description. +--- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} -- website/docs/r/example.html.md -- --- subcategory: "Example" @@ -115,6 +129,30 @@ Type: {{.Type}} "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_registry_docs.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_registry_docs.txtar index 5fc2165..20ad2cf 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_registry_docs.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/validate/framework_provider_success_registry_docs.txtar @@ -11,6 +11,8 @@ exporting schema from JSON file getting provider schema running mixed directories check detected static docs directory, running checks +running invalid directories check on docs/actions +running file checks on docs/actions/unlinked_example.md running invalid directories check on docs/data-sources running file checks on docs/data-sources/example.md running invalid directories check on docs/ephemeral-resources @@ -35,6 +37,17 @@ description: |- Example contents. +-- docs/actions/unlinked_example.md -- +--- +subcategory: "Example" +page_title: "Example: example_thing" +description: |- + Example description. +--- +# Data Fields + +Name: {{.Name}} +Type: {{.Type}} -- docs/resources/example.md -- --- subcategory: "Example" @@ -109,6 +122,30 @@ Type: {{.Type}} "description_kind": "markdown" } }, + "action_schemas": { + "scaffolding_unlinked_example": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Example required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Example optional attribute", + "description_kind": "plain", + "optional": true + } + }, + "description": "Example unlinked action", + "description_kind": "plain" + }, + "unlinked": {} + } + }, "resource_schemas": { "scaffolding_example": { "version": 0, diff --git a/internal/check/directory.go b/internal/check/directory.go index 15be21c..2f92576 100644 --- a/internal/check/directory.go +++ b/internal/check/directory.go @@ -19,6 +19,7 @@ const ( LegacyGuidesDirectory = `guides` LegacyResourcesDirectory = `r` LegacyFunctionsDirectory = `functions` + LegacyActionsDirectory = `actions` RegistryIndexDirectory = `docs` RegistryDataSourcesDirectory = `data-sources` @@ -26,6 +27,7 @@ const ( RegistryGuidesDirectory = `guides` RegistryResourcesDirectory = `resources` RegistryFunctionsDirectory = `functions` + RegistryActionsDirectory = `actions` // Terraform Registry Storage Limits // https://www.terraform.io/docs/registry/providers/docs.html#storage-limits @@ -41,6 +43,7 @@ var ValidLegacyDirectories = []string{ LegacyIndexDirectory + "/" + LegacyGuidesDirectory, LegacyIndexDirectory + "/" + LegacyResourcesDirectory, LegacyIndexDirectory + "/" + LegacyFunctionsDirectory, + LegacyIndexDirectory + "/" + LegacyActionsDirectory, } var ValidRegistryDirectories = []string{ @@ -50,6 +53,7 @@ var ValidRegistryDirectories = []string{ RegistryIndexDirectory + "/" + RegistryGuidesDirectory, RegistryIndexDirectory + "/" + RegistryResourcesDirectory, RegistryIndexDirectory + "/" + RegistryFunctionsDirectory, + RegistryIndexDirectory + "/" + RegistryActionsDirectory, } var ValidCdktfLanguages = []string{ @@ -66,6 +70,7 @@ var ValidLegacySubdirectories = []string{ LegacyEphemeralResourcesDirectory, LegacyGuidesDirectory, LegacyResourcesDirectory, + LegacyActionsDirectory, } var ValidRegistrySubdirectories = []string{ @@ -74,6 +79,7 @@ var ValidRegistrySubdirectories = []string{ RegistryEphemeralResourcesDirectory, RegistryGuidesDirectory, RegistryResourcesDirectory, + RegistryActionsDirectory, } func InvalidDirectoriesCheck(dirPath string) error { diff --git a/internal/check/directory_test.go b/internal/check/directory_test.go index 274705c..991ca7a 100644 --- a/internal/check/directory_test.go +++ b/internal/check/directory_test.go @@ -11,7 +11,7 @@ import ( "github.com/bmatcuk/doublestar/v4" ) -var DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{data-sources,ephemeral-resources,guides,resources,functions}/**/*,website/docs/**/*}` +var DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{actions,data-sources,ephemeral-resources,guides,resources,functions}/**/*,website/docs/**/*}` func TestMixedDirectoriesCheck(t *testing.T) { t.Parallel() @@ -31,6 +31,13 @@ func TestMixedDirectoriesCheck(t *testing.T) { "website/docs/index.md": {}, }, }, + "invalid mixed directories - registry action": { + ProviderFS: fstest.MapFS{ + "docs/actions/invalid.md": {}, + "website/docs/index.md": {}, + }, + ExpectError: true, + }, "invalid mixed directories - registry data source": { ProviderFS: fstest.MapFS{ "docs/data-sources/invalid.md": {}, @@ -66,6 +73,13 @@ func TestMixedDirectoriesCheck(t *testing.T) { }, ExpectError: true, }, + "invalid mixed directories - legacy action": { + ProviderFS: fstest.MapFS{ + "website/docs/actions/invalid.html.markdown": {}, + "docs/resources/thing.md": {}, + }, + ExpectError: true, + }, "invalid mixed directories - legacy data source": { ProviderFS: fstest.MapFS{ "website/docs/d/invalid.html.markdown": {}, diff --git a/internal/check/file_mismatch.go b/internal/check/file_mismatch.go index 97d78d7..9c77d23 100644 --- a/internal/check/file_mismatch.go +++ b/internal/check/file_mismatch.go @@ -30,6 +30,8 @@ type FileMismatchOptions struct { EphemeralResourceEntries []os.DirEntry + ActionEntries []os.DirEntry + Schema *tfjson.ProviderSchema } @@ -81,6 +83,11 @@ func (check *FileMismatchCheck) Run() error { result = errors.Join(result, err) } + if check.Options.ActionEntries != nil { + err := check.ActionFileMismatchCheck(check.Options.ActionEntries, "action", check.Options.Schema.ActionSchemas) + result = errors.Join(result, err) + } + return result } @@ -198,6 +205,65 @@ func (check *FileMismatchCheck) FunctionFileMismatchCheck(files []os.DirEntry, f } +// ActionFileMismatchCheck checks for mismatched files, either missing or extraneous, against the action schema +func (check *FileMismatchCheck) ActionFileMismatchCheck(files []os.DirEntry, actionType string, schemas map[string]*tfjson.ActionSchema) error { + if len(files) == 0 { + log.Printf("[DEBUG] Skipping %s file mismatch checks due to missing file list", actionType) + return nil + } + + if len(schemas) == 0 { + log.Printf("[DEBUG] Skipping %s file mismatch checks due to missing schemas", actionType) + return nil + } + + var extraFiles []string + var missingFiles []string + + for _, file := range files { + log.Printf("[DEBUG] Found file %s", file.Name()) + if fileHasAction(schemas, check.Options.ProviderShortName, file.Name()) { + continue + } + + if check.IgnoreFileMismatch(file.Name()) { + continue + } + + log.Printf("[DEBUG] Found extraneous file %s", file.Name()) + extraFiles = append(extraFiles, file.Name()) + } + + for _, actionName := range actionNames(schemas) { + log.Printf("[DEBUG] Found %s %s", actionType, actionName) + if resourceHasFile(files, check.Options.ProviderShortName, actionName) { + continue + } + + if check.IgnoreFileMissing(actionName) { + continue + } + + log.Printf("[DEBUG] Missing file for %s %s", actionType, actionName) + missingFiles = append(missingFiles, actionName) + } + + var result error + + for _, extraFile := range extraFiles { + err := fmt.Errorf("matching %s for documentation file (%s) not found, file is extraneous or incorrectly named", actionType, extraFile) + result = errors.Join(result, err) + } + + for _, missingFile := range missingFiles { + err := fmt.Errorf("missing documentation file for %s: %s", actionType, missingFile) + result = errors.Join(result, err) + } + + return result + +} + func (check *FileMismatchCheck) IgnoreFileMismatch(file string) bool { for _, ignoreResourceName := range check.Options.IgnoreFileMismatch { if ignoreResourceName == fileResourceNameWithProvider(check.Options.ProviderShortName, file) { @@ -244,6 +310,19 @@ func fileHasFunction(functions map[string]*tfjson.FunctionSignature, file string return false } +func fileHasAction(schemaActions map[string]*tfjson.ActionSchema, providerName, file string) bool { + if _, ok := schemaActions[fileResourceNameWithProvider(providerName, file)]; ok { + return true + } + + // While uncommon, it is valid for an action to be named the same as the provider itself. + if _, ok := schemaActions[TrimFileExtension(file)]; ok { + return true + } + + return false +} + func fileResourceNameWithProvider(providerName, fileName string) string { resourceSuffix := TrimFileExtension(fileName) @@ -281,6 +360,18 @@ func functionHasFile(files []os.DirEntry, functionName string) bool { return found } +func actionNames(actions map[string]*tfjson.ActionSchema) []string { + names := make([]string, 0, len(actions)) + + for name := range actions { + names = append(names, name) + } + + sort.Strings(names) + + return names +} + func resourceNames(resources map[string]*tfjson.Schema) []string { names := make([]string, 0, len(resources)) diff --git a/internal/check/file_mismatch_test.go b/internal/check/file_mismatch_test.go index 4beecc5..9e469bd 100644 --- a/internal/check/file_mismatch_test.go +++ b/internal/check/file_mismatch_test.go @@ -93,6 +93,7 @@ func TestFileMismatchCheck(t *testing.T) { testCases := map[string]struct { ResourceFiles fstest.MapFS FunctionFiles fstest.MapFS + ActionFiles fstest.MapFS Options *FileMismatchOptions ExpectError bool }{ @@ -139,6 +140,21 @@ func TestFileMismatchCheck(t *testing.T) { }, }, }, + "all found - action": { + ActionFiles: fstest.MapFS{ + "action1.md": {}, + "action2.md": {}, + }, + Options: &FileMismatchOptions{ + ProviderShortName: "test", + Schema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "action1": {}, + "action2": {}, + }, + }, + }, + }, "extra file - resource": { ResourceFiles: fstest.MapFS{ "resource1.md": {}, @@ -173,6 +189,23 @@ func TestFileMismatchCheck(t *testing.T) { }, ExpectError: true, }, + "extra file - action": { + ActionFiles: fstest.MapFS{ + "action1.md": {}, + "action2.md": {}, + "action3.md": {}, + }, + Options: &FileMismatchOptions{ + ProviderShortName: "test", + Schema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "action1": {}, + "action2": {}, + }, + }, + }, + ExpectError: true, + }, "ignore extra file - resource": { ResourceFiles: fstest.MapFS{ "resource1.md": {}, @@ -225,6 +258,24 @@ func TestFileMismatchCheck(t *testing.T) { }, }, }, + "ignore extra file - action": { + ActionFiles: fstest.MapFS{ + "action1.md": {}, + "action2.md": {}, + "action3.md": {}, + }, + Options: &FileMismatchOptions{ + IgnoreFileMismatch: []string{"action3"}, + ProviderShortName: "test", + Schema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "action1": {}, + "action2": {}, + "action3": {}, + }, + }, + }, + }, "missing file - resource": { ResourceFiles: fstest.MapFS{ "resource1.md": {}, @@ -270,6 +321,21 @@ func TestFileMismatchCheck(t *testing.T) { }, ExpectError: true, }, + "missing file - action": { + ActionFiles: fstest.MapFS{ + "action1.md": {}, + }, + Options: &FileMismatchOptions{ + ProviderShortName: "test", + Schema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "action1": {}, + "action2": {}, + }, + }, + }, + ExpectError: true, + }, "ignore missing file - resource": { ResourceFiles: fstest.MapFS{ "resource1.md": {}, @@ -300,6 +366,21 @@ func TestFileMismatchCheck(t *testing.T) { }, }, }, + "ignore missing file - action": { + ActionFiles: fstest.MapFS{ + "action1.md": {}, + }, + Options: &FileMismatchOptions{ + IgnoreFileMissing: []string{"action2"}, + ProviderShortName: "test", + Schema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "action1": {}, + "action2": {}, + }, + }, + }, + }, "no files": { Options: &FileMismatchOptions{ ProviderShortName: "test", @@ -312,6 +393,10 @@ func TestFileMismatchCheck(t *testing.T) { "function1": {}, "function2": {}, }, + ActionSchemas: map[string]*tfjson.ActionSchema{ + "action1": {}, + "action2": {}, + }, }, }, }, @@ -322,6 +407,9 @@ func TestFileMismatchCheck(t *testing.T) { FunctionFiles: fstest.MapFS{ "function1.md": {}, }, + ActionFiles: fstest.MapFS{ + "action1.md": {}, + }, Options: &FileMismatchOptions{ ProviderShortName: "test", }, @@ -334,8 +422,10 @@ func TestFileMismatchCheck(t *testing.T) { resourceFiles, _ := testCase.ResourceFiles.ReadDir(".") functionFiles, _ := testCase.FunctionFiles.ReadDir(".") + actionFiles, _ := testCase.ActionFiles.ReadDir(".") testCase.Options.ResourceEntries = resourceFiles testCase.Options.FunctionEntries = functionFiles + testCase.Options.ActionEntries = actionFiles got := NewFileMismatchCheck(testCase.Options).Run() if got == nil && testCase.ExpectError { diff --git a/internal/provider/testdata/schema.json b/internal/provider/testdata/schema.json index 4887649..df76d06 100644 --- a/internal/provider/testdata/schema.json +++ b/internal/provider/testdata/schema.json @@ -8,6 +8,28 @@ "description_kind": "plain" } }, + "action_schemas": { + "null_fake_action": { + "version": 0, + "block": { + "attributes": { + "required_attr": { + "type": "string", + "description": "Required attribute", + "description_kind": "plain", + "required": true + }, + "optional_attr": { + "type": "string", + "description": "Optional attribute", + "description_kind": "plain", + "optional": true + } + } + }, + "unlinked": {} + } + }, "resource_schemas": { "null_resource": { "version": 0, diff --git a/internal/provider/util_test.go b/internal/provider/util_test.go index 8a1bc80..c0a6e20 100644 --- a/internal/provider/util_test.go +++ b/internal/provider/util_test.go @@ -110,6 +110,9 @@ func Test_extractSchemaFromFile(t *testing.T) { if providerSchema.EphemeralResourceSchemas["null_ephemeral_resource"] == nil { t.Fatalf("null_ephemeral_resource not found") } + if providerSchema.ActionSchemas["null_fake_action"] == nil { + t.Fatalf("null_fake_action not found") + } if providerSchema.ResourceSchemas["null_resource"].Block.Attributes["id"] == nil { t.Fatalf("null_resoruce id attribute not found") } @@ -119,4 +122,7 @@ func Test_extractSchemaFromFile(t *testing.T) { if providerSchema.EphemeralResourceSchemas["null_ephemeral_resource"].Block.Attributes["id"] == nil { t.Fatalf("null_ephemeral_resoruce id attribute not found") } + if providerSchema.ActionSchemas["null_fake_action"].Block.Attributes["required_attr"] == nil { + t.Fatalf("null_fake_action required_attr attribute not found") + } } diff --git a/internal/provider/validate.go b/internal/provider/validate.go index b6139d5..5b2151d 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -26,8 +26,8 @@ const ( FileExtensionMarkdown = `.markdown` FileExtensionMd = `.md` - DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{data-sources,ephemeral-resources,guides,resources,functions}/**/*,website/docs/**/*}` - DocumentationDirGlobPattern = `{docs/{,cdktf/}{data-sources,ephemeral-resources,guides,resources,functions}{,/*},website/docs/**/*}` + DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{actions,data-sources,ephemeral-resources,guides,resources,functions}/**/*,website/docs/**/*}` + DocumentationDirGlobPattern = `{docs/{,cdktf/}{actions,data-sources,ephemeral-resources,guides,resources,functions}{,/*},website/docs/**/*}` ) var ValidLegacyFileExtensions = []string{ @@ -314,6 +314,10 @@ func (v *validator) validateStaticDocs() error { ephemeralResourceFiles, _ := fs.ReadDir(v.providerFS, dir+"/ephemeral-resources") mismatchOpt.EphemeralResourceEntries = ephemeralResourceFiles } + if dirExists(v.providerFS, dir+"/actions") { + actionFiles, _ := fs.ReadDir(v.providerFS, dir+"/actions") + mismatchOpt.ActionEntries = actionFiles + } v.logger.infof("running file mismatch check") if err := check.NewFileMismatchCheck(mismatchOpt).Run(); err != nil { @@ -401,6 +405,10 @@ func (v *validator) validateLegacyWebsite() error { ephemeralResourceFiles, _ := fs.ReadDir(v.providerFS, dir+"/ephemeral-resources") mismatchOpt.EphemeralResourceEntries = ephemeralResourceFiles } + if dirExists(v.providerFS, dir+"/actions") { + actionFiles, _ := fs.ReadDir(v.providerFS, dir+"/actions") + mismatchOpt.ActionEntries = actionFiles + } v.logger.infof("running file mismatch check") if err := check.NewFileMismatchCheck(mismatchOpt).Run(); err != nil { diff --git a/internal/provider/validate_test.go b/internal/provider/validate_test.go index 63ea3b3..6b718cf 100644 --- a/internal/provider/validate_test.go +++ b/internal/provider/validate_test.go @@ -79,6 +79,9 @@ func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { }{ "valid registry directories": { ProviderFS: fstest.MapFS{ + "docs/actions/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, "docs/data-sources/thing.md": { Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), }, @@ -107,6 +110,9 @@ func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { }, "valid registry directories with cdktf docs": { ProviderFS: fstest.MapFS{ + "docs/cdktf/typescript/actions/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, "docs/cdktf/typescript/data-sources/thing.md": { Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), }, @@ -150,6 +156,9 @@ func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { }, "invalid registry directories": { ProviderFS: fstest.MapFS{ + "docs/actions/invalid/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, "docs/data-sources/invalid/thing.md": { Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), }, @@ -175,7 +184,8 @@ func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { Data: encodeYAML(t, &ValidRegistryIndexFrontMatter), }, }, - ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("docs", "data-sources", "invalid") + + ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("docs", "actions", "invalid") + + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "data-sources", "invalid") + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "ephemeral-resources", "invalid") + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "functions", "invalid") + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "guides", "invalid") + @@ -276,6 +286,38 @@ func TestValidateStaticDocs_FileChecks(t *testing.T) { filepath.Join("docs", "ephemeral-resources", "with_layout.md") + ": error checking file frontmatter: YAML frontmatter should not contain layout\n" + filepath.Join("docs", "ephemeral-resources", "with_sidebar_current.md") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current", }, + "invalid action files": { + ProviderFS: fstest.MapFS{ + "docs/actions/invalid_extension.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/actions/invalid_frontmatter.md": &InvalidYAMLFrontMatter, + "docs/actions/with_layout.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "docs/actions/with_sidebar_current.md": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "actions", "invalid_extension.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.md]\n" + + filepath.Join("docs", "actions", "invalid_frontmatter.md") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("docs", "actions", "with_layout.md") + ": error checking file frontmatter: YAML frontmatter should not contain layout\n" + + filepath.Join("docs", "actions", "with_sidebar_current.md") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current", + }, "invalid resource files": { ProviderFS: fstest.MapFS{ "docs/resources/invalid_extension.txt": { @@ -439,6 +481,9 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { }{ "valid - no mismatch": { ProviderSchema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "test_action": {}, + }, DataSourceSchemas: map[string]*tfjson.Schema{ "test_pet": {}, }, @@ -453,6 +498,9 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { }, }, ProviderFS: fstest.MapFS{ + "docs/actions/action.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, "docs/data-sources/pet.md": { Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), }, @@ -469,6 +517,10 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { }, "invalid - missing files": { ProviderSchema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "test_action": {}, + "test_action2": {}, + }, DataSourceSchemas: map[string]*tfjson.Schema{ "test_pet": {}, "test_pet2": {}, @@ -487,6 +539,9 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { }, }, ProviderFS: fstest.MapFS{ + "docs/actions/action.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, "docs/data-sources/pet.md": { Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), }, @@ -503,10 +558,14 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { ExpectedError: "missing documentation file for resource: test_id2\n" + "missing documentation file for datasource: test_pet2\n" + "missing documentation file for function: parse_id2\n" + - "missing documentation file for ephemeral resource: test_ephemeral_id2", + "missing documentation file for ephemeral resource: test_ephemeral_id2\n" + + "missing documentation file for action: test_action2", }, "invalid - extra files": { ProviderSchema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "test_action": {}, + }, DataSourceSchemas: map[string]*tfjson.Schema{ "test_pet": {}, }, @@ -521,6 +580,12 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { }, }, ProviderFS: fstest.MapFS{ + "docs/actions/action.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/actions/action2.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, "docs/data-sources/pet.md": { Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), }, @@ -549,7 +614,8 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { ExpectedError: "matching resource for documentation file (id2.md) not found, file is extraneous or incorrectly named\n" + "matching datasource for documentation file (pet2.md) not found, file is extraneous or incorrectly named\n" + "matching function for documentation file (parse_id2.md) not found, file is extraneous or incorrectly named\n" + - "matching ephemeral resource for documentation file (ephemeral_id2.md) not found, file is extraneous or incorrectly named", + "matching ephemeral resource for documentation file (ephemeral_id2.md) not found, file is extraneous or incorrectly named\n" + + "matching action for documentation file (action2.md) not found, file is extraneous or incorrectly named", }, } @@ -585,6 +651,9 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { }{ "valid legacy directories": { ProviderFS: fstest.MapFS{ + "website/docs/actions/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, "website/docs/d/thing.html.markdown": { Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), }, @@ -607,6 +676,9 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { }, "valid legacy directories with cdktf docs": { ProviderFS: fstest.MapFS{ + "website/docs/cdktf/typescript/actions/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, "website/docs/cdktf/typescript/d/thing.html.markdown": { Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), }, @@ -638,6 +710,9 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { }, "invalid legacy directories": { ProviderFS: fstest.MapFS{ + "website/docs/actions/invalid/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, "website/docs/d/invalid/thing.html.markdown": { Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), }, @@ -657,7 +732,8 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { Data: encodeYAML(t, &ValidLegacyIndexFrontMatter), }, }, - ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "d", "invalid") + + ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "actions", "invalid") + + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "d", "invalid") + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "ephemeral-resources", "invalid") + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "functions", "invalid") + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "guides", "invalid") + @@ -758,6 +834,38 @@ func TestValidateLegacyWebsite_FileChecks(t *testing.T) { filepath.Join("website", "docs", "ephemeral-resources", "with_sidebar_current.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current\n" + filepath.Join("website", "docs", "ephemeral-resources", "without_layout.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required layout", }, + "invalid action files": { + ProviderFS: fstest.MapFS{ + "website/docs/actions/invalid_extension.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "website/docs/actions/invalid_frontmatter.html.markdown": &InvalidYAMLFrontMatter, + "website/docs/actions/without_layout.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "website/docs/actions/with_sidebar_current.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "actions", "invalid_extension.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.html.markdown .html.md .markdown .md]\n" + + filepath.Join("website", "docs", "actions", "invalid_frontmatter.html.markdown") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("website", "docs", "actions", "with_sidebar_current.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current\n" + + filepath.Join("website", "docs", "actions", "without_layout.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required layout", + }, "invalid resource files": { ProviderFS: fstest.MapFS{ "website/docs/r/invalid_extension.txt": { @@ -929,6 +1037,9 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { }{ "valid - no mismatch": { ProviderSchema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "test_action": {}, + }, DataSourceSchemas: map[string]*tfjson.Schema{ "test_pet": {}, }, @@ -943,6 +1054,9 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { }, }, ProviderFS: fstest.MapFS{ + "website/docs/actions/action.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, "website/docs/d/pet.html.markdown": { Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), }, @@ -959,6 +1073,10 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { }, "invalid - missing files": { ProviderSchema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "test_action": {}, + "test_action2": {}, + }, DataSourceSchemas: map[string]*tfjson.Schema{ "test_pet": {}, "test_pet2": {}, @@ -977,6 +1095,9 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { }, }, ProviderFS: fstest.MapFS{ + "website/docs/actions/action.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, "website/docs/d/pet.html.markdown": { Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), }, @@ -993,10 +1114,14 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { ExpectedError: "missing documentation file for resource: test_id2\n" + "missing documentation file for datasource: test_pet2\n" + "missing documentation file for function: parse_id2\n" + - "missing documentation file for ephemeral resource: test_ephemeral_id2", + "missing documentation file for ephemeral resource: test_ephemeral_id2\n" + + "missing documentation file for action: test_action2", }, "invalid - extra files": { ProviderSchema: &tfjson.ProviderSchema{ + ActionSchemas: map[string]*tfjson.ActionSchema{ + "test_action": {}, + }, DataSourceSchemas: map[string]*tfjson.Schema{ "test_pet": {}, }, @@ -1011,6 +1136,12 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { }, }, ProviderFS: fstest.MapFS{ + "website/docs/actions/action.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/actions/action2.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, "website/docs/d/pet.html.markdown": { Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), }, @@ -1039,7 +1170,8 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { ExpectedError: "matching resource for documentation file (id2.html.markdown) not found, file is extraneous or incorrectly named\n" + "matching datasource for documentation file (pet2.html.markdown) not found, file is extraneous or incorrectly named\n" + "matching function for documentation file (parse_id2.html.markdown) not found, file is extraneous or incorrectly named\n" + - "matching ephemeral resource for documentation file (ephemeral_id2.html.markdown) not found, file is extraneous or incorrectly named", + "matching ephemeral resource for documentation file (ephemeral_id2.html.markdown) not found, file is extraneous or incorrectly named\n" + + "matching action for documentation file (action2.html.markdown) not found, file is extraneous or incorrectly named", }, } From 77bf71637e426939ba805e980b5bfcb9b4f3bbfe Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 17:04:09 -0400 Subject: [PATCH 06/18] add migrate support + tests --- .../time_provider_success_docs_website.txtar | 66 ++++++++++++++++++- ...der_success_docs_website_with_prefix.txtar | 66 ++++++++++++++++++- ...time_provider_success_legacy_website.txtar | 66 ++++++++++++++++++- ...r_success_legacy_website_with_prefix.txtar | 66 ++++++++++++++++++- internal/provider/migrate.go | 7 ++ 5 files changed, 267 insertions(+), 4 deletions(-) diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website.txtar index 6928f37..414cbfa 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website.txtar @@ -16,6 +16,7 @@ cmpenv templates/resources/rotating.md.tmpl exp-templates/resources/rotating.md. cmpenv templates/resources/sleep.md.tmpl exp-templates/resources/sleep.md.tmpl cmpenv templates/resources/static.md.tmpl exp-templates/resources/static.md.tmpl cmpenv templates/ephemeral-resources/ephemeral_static.md.tmpl exp-templates/ephemeral-resources/ephemeral_static.md.tmpl +cmpenv templates/actions/unlinked_example.md.tmpl exp-templates/actions/unlinked_example.md.tmpl # Check generated example files cmpenv examples/example_1.tf examples/example_1.tf @@ -44,8 +45,18 @@ cmpenv examples/ephemeral-resources/ephemeral_static/example_1.tf exp-examples/e cmpenv examples/ephemeral-resources/ephemeral_static/example_2.tf exp-examples/ephemeral-resources/ephemeral_static/example_2.tf cmpenv examples/ephemeral-resources/ephemeral_static/import_1.sh exp-examples/ephemeral-resources/ephemeral_static/import_1.sh +cmpenv examples/actions/unlinked_example/example_1.tf exp-examples/actions/unlinked_example/example_1.tf +cmpenv examples/actions/unlinked_example/example_2.tf exp-examples/actions/unlinked_example/example_2.tf + -- expected-output.txt -- migrating website from "$WORK/docs" to "$WORK/templates" +migrating actions directory: actions +migrating file "unlinked_example.html.markdown" +extracting YAML frontmatter to "$WORK/templates/actions/unlinked_example.md.tmpl" +extracting code examples from "unlinked_example.html.markdown" +creating example file "$WORK/examples/actions/unlinked_example/example_1.tf" +creating example file "$WORK/examples/actions/unlinked_example/example_2.tf" +finished creating template "$WORK/templates/actions/unlinked_example.md.tmpl" migrating ephemeral resources directory: ephemeral-resources migrating file "ephemeral_static.html.markdown" extracting YAML frontmatter to "$WORK/templates/ephemeral-resources/ephemeral_static.md.tmpl" @@ -528,6 +539,31 @@ $ terraform import time_static.example 2020-02-12T06:36:13Z ``` The `triggers` argument cannot be imported. +-- docs/actions/unlinked_example.html.markdown -- +--- +layout: "time" +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +Just a fake example. + +```hcl +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +``` + +```hcl +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} +``` -- docs/ephemeral-resources/ephemeral_static.html.markdown -- --- layout: "time" @@ -753,6 +789,18 @@ resource "aws_instance" "server" { } -- exp-examples/resources/static/import_1.sh -- $ terraform import time_static.example 2020-02-12T06:36:13Z +-- exp-examples/actions/unlinked_example/example_1.tf -- +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +-- exp-examples/actions/unlinked_example/example_2.tf -- +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} -- exp-examples/ephemeral-resources/ephemeral_static/example_1.tf -- resource "time_static" "example" {} @@ -1135,4 +1183,20 @@ This resource can be imported using the UTC RFC3339 value, e.g. {{codefile "shell" "examples/ephemeral-resources/ephemeral_static/import_1.sh"}} -The `triggers` argument cannot be imported. \ No newline at end of file +The `triggers` argument cannot be imported. +-- exp-templates/actions/unlinked_example.md.tmpl -- +--- +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +{{/* This template serves as a starting point for documentation generation, and can be customized with hardcoded values and/or doc gen templates. + +For example, the {{ .SchemaMarkdown }} template can be used to replace manual schema documentation if descriptions of schema attributes are added in the provider source code. */ -}} + +Just a fake example. + +{{tffile "examples/actions/unlinked_example/example_1.tf"}} + +{{tffile "examples/actions/unlinked_example/example_2.tf"}} \ No newline at end of file diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website_with_prefix.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website_with_prefix.txtar index 11704c4..6a217c2 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website_with_prefix.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_docs_website_with_prefix.txtar @@ -16,6 +16,7 @@ cmpenv templates/resources/rotating.md.tmpl exp-templates/resources/rotating.md. cmpenv templates/resources/sleep.md.tmpl exp-templates/resources/sleep.md.tmpl cmpenv templates/resources/static.md.tmpl exp-templates/resources/static.md.tmpl cmpenv templates/ephemeral-resources/ephemeral_static.md.tmpl exp-templates/ephemeral-resources/ephemeral_static.md.tmpl +cmpenv templates/actions/unlinked_example.md.tmpl exp-templates/actions/unlinked_example.md.tmpl # Check generated example files cmpenv examples/example_1.tf examples/example_1.tf @@ -44,8 +45,18 @@ cmpenv examples/ephemeral-resources/ephemeral_static/example_1.tf exp-examples/e cmpenv examples/ephemeral-resources/ephemeral_static/example_2.tf exp-examples/ephemeral-resources/ephemeral_static/example_2.tf cmpenv examples/ephemeral-resources/ephemeral_static/import_1.sh exp-examples/ephemeral-resources/ephemeral_static/import_1.sh +cmpenv examples/actions/unlinked_example/example_1.tf exp-examples/actions/unlinked_example/example_1.tf +cmpenv examples/actions/unlinked_example/example_2.tf exp-examples/actions/unlinked_example/example_2.tf + -- expected-output.txt -- migrating website from "$WORK/docs" to "$WORK/templates" +migrating actions directory: actions +migrating file "time_unlinked_example.html.markdown" +extracting YAML frontmatter to "$WORK/templates/actions/unlinked_example.md.tmpl" +extracting code examples from "time_unlinked_example.html.markdown" +creating example file "$WORK/examples/actions/unlinked_example/example_1.tf" +creating example file "$WORK/examples/actions/unlinked_example/example_2.tf" +finished creating template "$WORK/templates/actions/unlinked_example.md.tmpl" migrating ephemeral resources directory: ephemeral-resources migrating file "time_ephemeral_static.html.markdown" extracting YAML frontmatter to "$WORK/templates/ephemeral-resources/ephemeral_static.md.tmpl" @@ -528,6 +539,31 @@ $ terraform import time_static.example 2020-02-12T06:36:13Z ``` The `triggers` argument cannot be imported. +-- docs/actions/time_unlinked_example.html.markdown -- +--- +layout: "time" +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +Just a fake example. + +```hcl +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +``` + +```hcl +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} +``` -- docs/ephemeral-resources/time_ephemeral_static.html.markdown -- --- layout: "time" @@ -753,6 +789,18 @@ resource "aws_instance" "server" { } -- exp-examples/resources/static/import_1.sh -- $ terraform import time_static.example 2020-02-12T06:36:13Z +-- exp-examples/actions/unlinked_example/example_1.tf -- +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +-- exp-examples/actions/unlinked_example/example_2.tf -- +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} -- exp-examples/ephemeral-resources/ephemeral_static/example_1.tf -- resource "time_static" "example" {} @@ -1135,4 +1183,20 @@ This resource can be imported using the UTC RFC3339 value, e.g. {{codefile "shell" "examples/ephemeral-resources/ephemeral_static/import_1.sh"}} -The `triggers` argument cannot be imported. \ No newline at end of file +The `triggers` argument cannot be imported. +-- exp-templates/actions/unlinked_example.md.tmpl -- +--- +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +{{/* This template serves as a starting point for documentation generation, and can be customized with hardcoded values and/or doc gen templates. + +For example, the {{ .SchemaMarkdown }} template can be used to replace manual schema documentation if descriptions of schema attributes are added in the provider source code. */ -}} + +Just a fake example. + +{{tffile "examples/actions/unlinked_example/example_1.tf"}} + +{{tffile "examples/actions/unlinked_example/example_2.tf"}} \ No newline at end of file diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website.txtar index 1b06780..af00bf0 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website.txtar @@ -16,6 +16,7 @@ cmpenv templates/resources/rotating.md.tmpl exp-templates/resources/rotating.md. cmpenv templates/resources/sleep.md.tmpl exp-templates/resources/sleep.md.tmpl cmpenv templates/resources/static.md.tmpl exp-templates/resources/static.md.tmpl cmpenv templates/ephemeral-resources/ephemeral_static.md.tmpl exp-templates/ephemeral-resources/ephemeral_static.md.tmpl +cmpenv templates/actions/unlinked_example.md.tmpl exp-templates/actions/unlinked_example.md.tmpl # Check generated example files cmpenv examples/example_1.tf examples/example_1.tf @@ -44,11 +45,21 @@ cmpenv examples/ephemeral-resources/ephemeral_static/example_1.tf exp-examples/e cmpenv examples/ephemeral-resources/ephemeral_static/example_2.tf exp-examples/ephemeral-resources/ephemeral_static/example_2.tf cmpenv examples/ephemeral-resources/ephemeral_static/import_1.sh exp-examples/ephemeral-resources/ephemeral_static/import_1.sh +cmpenv examples/actions/unlinked_example/example_1.tf exp-examples/actions/unlinked_example/example_1.tf +cmpenv examples/actions/unlinked_example/example_2.tf exp-examples/actions/unlinked_example/example_2.tf + # Verify legacy website directory is removed ! exists website/ -- expected-output.txt -- migrating website from "$WORK/website/docs" to "$WORK/templates" +migrating actions directory: actions +migrating file "unlinked_example.html.markdown" +extracting YAML frontmatter to "$WORK/templates/actions/unlinked_example.md.tmpl" +extracting code examples from "unlinked_example.html.markdown" +creating example file "$WORK/examples/actions/unlinked_example/example_1.tf" +creating example file "$WORK/examples/actions/unlinked_example/example_2.tf" +finished creating template "$WORK/templates/actions/unlinked_example.md.tmpl" migrating ephemeral resources directory: ephemeral-resources migrating file "ephemeral_static.html.markdown" extracting YAML frontmatter to "$WORK/templates/ephemeral-resources/ephemeral_static.md.tmpl" @@ -531,6 +542,31 @@ $ terraform import time_static.example 2020-02-12T06:36:13Z ``` The `triggers` argument cannot be imported. +-- website/docs/actions/unlinked_example.html.markdown -- +--- +layout: "time" +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +Just a fake example. + +```hcl +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +``` + +```hcl +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} +``` -- website/docs/ephemeral-resources/ephemeral_static.html.markdown -- --- layout: "time" @@ -756,6 +792,18 @@ resource "aws_instance" "server" { } -- exp-examples/resources/static/import_1.sh -- $ terraform import time_static.example 2020-02-12T06:36:13Z +-- exp-examples/actions/unlinked_example/example_1.tf -- +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +-- exp-examples/actions/unlinked_example/example_2.tf -- +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} -- exp-examples/ephemeral-resources/ephemeral_static/example_1.tf -- resource "time_static" "example" {} @@ -1138,4 +1186,20 @@ This resource can be imported using the UTC RFC3339 value, e.g. {{codefile "shell" "examples/ephemeral-resources/ephemeral_static/import_1.sh"}} -The `triggers` argument cannot be imported. \ No newline at end of file +The `triggers` argument cannot be imported. +-- exp-templates/actions/unlinked_example.md.tmpl -- +--- +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +{{/* This template serves as a starting point for documentation generation, and can be customized with hardcoded values and/or doc gen templates. + +For example, the {{ .SchemaMarkdown }} template can be used to replace manual schema documentation if descriptions of schema attributes are added in the provider source code. */ -}} + +Just a fake example. + +{{tffile "examples/actions/unlinked_example/example_1.tf"}} + +{{tffile "examples/actions/unlinked_example/example_2.tf"}} \ No newline at end of file diff --git a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website_with_prefix.txtar b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website_with_prefix.txtar index e1ce230..fe30ab3 100644 --- a/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website_with_prefix.txtar +++ b/cmd/tfplugindocs/testdata/scripts/schema-json/migrate/time_provider_success_legacy_website_with_prefix.txtar @@ -16,6 +16,7 @@ cmpenv templates/resources/rotating.md.tmpl exp-templates/resources/rotating.md. cmpenv templates/resources/sleep.md.tmpl exp-templates/resources/sleep.md.tmpl cmpenv templates/resources/static.md.tmpl exp-templates/resources/static.md.tmpl cmpenv templates/ephemeral-resources/ephemeral_static.md.tmpl exp-templates/ephemeral-resources/ephemeral_static.md.tmpl +cmpenv templates/actions/unlinked_example.md.tmpl exp-templates/actions/unlinked_example.md.tmpl # Check generated example files cmpenv examples/example_1.tf examples/example_1.tf @@ -44,11 +45,21 @@ cmpenv examples/ephemeral-resources/ephemeral_static/example_1.tf exp-examples/e cmpenv examples/ephemeral-resources/ephemeral_static/example_2.tf exp-examples/ephemeral-resources/ephemeral_static/example_2.tf cmpenv examples/ephemeral-resources/ephemeral_static/import_1.sh exp-examples/ephemeral-resources/ephemeral_static/import_1.sh +cmpenv examples/actions/unlinked_example/example_1.tf exp-examples/actions/unlinked_example/example_1.tf +cmpenv examples/actions/unlinked_example/example_2.tf exp-examples/actions/unlinked_example/example_2.tf + # Verify legacy website directory is removed ! exists website/ -- expected-output.txt -- migrating website from "$WORK/website/docs" to "$WORK/templates" +migrating actions directory: actions +migrating file "time_unlinked_example.html.markdown" +extracting YAML frontmatter to "$WORK/templates/actions/unlinked_example.md.tmpl" +extracting code examples from "time_unlinked_example.html.markdown" +creating example file "$WORK/examples/actions/unlinked_example/example_1.tf" +creating example file "$WORK/examples/actions/unlinked_example/example_2.tf" +finished creating template "$WORK/templates/actions/unlinked_example.md.tmpl" migrating ephemeral resources directory: ephemeral-resources migrating file "time_ephemeral_static.html.markdown" extracting YAML frontmatter to "$WORK/templates/ephemeral-resources/ephemeral_static.md.tmpl" @@ -531,6 +542,31 @@ $ terraform import time_static.example 2020-02-12T06:36:13Z ``` The `triggers` argument cannot be imported. +-- website/docs/actions/time_unlinked_example.html.markdown -- +--- +layout: "time" +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +Just a fake example. + +```hcl +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +``` + +```hcl +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} +``` -- website/docs/ephemeral-resources/time_ephemeral_static.html.markdown -- --- layout: "time" @@ -756,6 +792,18 @@ resource "aws_instance" "server" { } -- exp-examples/resources/static/import_1.sh -- $ terraform import time_static.example 2020-02-12T06:36:13Z +-- exp-examples/actions/unlinked_example/example_1.tf -- +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} +-- exp-examples/actions/unlinked_example/example_2.tf -- +action "scaffolding_unlinked_example" "example2" { + config { + required_attr = "value-2" + } +} -- exp-examples/ephemeral-resources/ephemeral_static/example_1.tf -- resource "time_static" "example" {} @@ -1138,4 +1186,20 @@ This resource can be imported using the UTC RFC3339 value, e.g. {{codefile "shell" "examples/ephemeral-resources/ephemeral_static/import_1.sh"}} -The `triggers` argument cannot be imported. \ No newline at end of file +The `triggers` argument cannot be imported. +-- exp-templates/actions/unlinked_example.md.tmpl -- +--- +page_title: "Time: time_unlinked_example" +description: |- + Just a fake example. +--- + +{{/* This template serves as a starting point for documentation generation, and can be customized with hardcoded values and/or doc gen templates. + +For example, the {{ .SchemaMarkdown }} template can be used to replace manual schema documentation if descriptions of schema attributes are added in the provider source code. */ -}} + +Just a fake example. + +{{tffile "examples/actions/unlinked_example/example_1.tf"}} + +{{tffile "examples/actions/unlinked_example/example_2.tf"}} \ No newline at end of file diff --git a/internal/provider/migrate.go b/internal/provider/migrate.go index 9abd773..0aeadf3 100644 --- a/internal/provider/migrate.go +++ b/internal/provider/migrate.go @@ -139,6 +139,13 @@ func (m *migrator) Migrate() error { return fmt.Errorf("unable to copy guides directory %q: %w", path, err) } return filepath.SkipDir + case "actions": + m.infof("migrating actions directory: %s", d.Name()) + err := filepath.WalkDir(path, m.MigrateTemplate("actions")) + if err != nil { + return err + } + return filepath.SkipDir } } else { switch { From 70e0ee023c0104b358b7754a6ae1f4aedb1202b4 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 17:26:23 -0400 Subject: [PATCH 07/18] add unit tests --- internal/provider/action_template_test.go | 62 +++++++++++++++++++ .../testdata/test-action-dir/action.tf | 5 ++ internal/schemamd/render_test.go | 53 ++++++++++++++++ .../testdata/actions/test_unlinked_action.md | 16 +++++ .../actions/test_unlinked_action.schema.json | 32 ++++++++++ 5 files changed, 168 insertions(+) create mode 100644 internal/provider/action_template_test.go create mode 100644 internal/provider/testdata/test-action-dir/action.tf create mode 100644 internal/schemamd/testdata/actions/test_unlinked_action.md create mode 100644 internal/schemamd/testdata/actions/test_unlinked_action.schema.json diff --git a/internal/provider/action_template_test.go b/internal/provider/action_template_test.go new file mode 100644 index 0000000..066856e --- /dev/null +++ b/internal/provider/action_template_test.go @@ -0,0 +1,62 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + tfjson "github.com/hashicorp/terraform-json" + "github.com/zclconf/go-cty/cty" +) + +func TestActionTemplate_Render(t *testing.T) { + t.Parallel() + + template := ` +Printf tffile: {{ printf "{{tffile %q}}" .ExampleFile }} +tffile: {{ tffile .ExampleFile }} +` + expectedString := ` +Printf tffile: {{tffile "action.tf"}} +tffile: terraform +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} + +` + + tpl := actionTemplate(template) + + schema := tfjson.ActionSchema{ + Unlinked: &tfjson.UnlinkedSchemaType{}, + Block: &tfjson.SchemaBlock{ + Attributes: map[string]*tfjson.SchemaAttribute{ + "required_attr": { + AttributeType: cty.String, + Description: "Required attribute", + Required: true, + }, + "optional_attr": { + AttributeType: cty.String, + Description: "Optional attribute", + Optional: true, + }, + }, + }, + } + + result, err := tpl.Render("testdata/test-action-dir", "testTemplate", "test-action", "test-action", "action", "action.tf", &schema) + if err != nil { + t.Error(err) + } + + cleanedResult := strings.ReplaceAll(result, "```", "") + if !cmp.Equal(expectedString, cleanedResult) { + t.Errorf("expected: %+v, got: %+v", expectedString, cleanedResult) + } +} diff --git a/internal/provider/testdata/test-action-dir/action.tf b/internal/provider/testdata/test-action-dir/action.tf new file mode 100644 index 0000000..b4d434d --- /dev/null +++ b/internal/provider/testdata/test-action-dir/action.tf @@ -0,0 +1,5 @@ +action "scaffolding_unlinked_example" "example1" { + config { + required_attr = "value-1" + } +} diff --git a/internal/schemamd/render_test.go b/internal/schemamd/render_test.go index f836d6d..05165a1 100644 --- a/internal/schemamd/render_test.go +++ b/internal/schemamd/render_test.go @@ -151,3 +151,56 @@ func TestRenderIdentitySchema(t *testing.T) { }) } } + +func TestRenderAction(t *testing.T) { + t.Parallel() + + for _, c := range []struct { + name string + inputFile string + expectedFile string + }{ + { + "test_unlinked_action", + "testdata/actions/test_unlinked_action.schema.json", + "testdata/actions/test_unlinked_action.md", + }, + } { + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + input, err := os.ReadFile(c.inputFile) + if err != nil { + t.Fatal(err) + } + + expected, err := os.ReadFile(c.expectedFile) + if err != nil { + t.Fatal(err) + } + + var schema tfjson.ActionSchema + + err = json.Unmarshal(input, &schema) + if err != nil { + t.Fatal(err) + } + + b := &strings.Builder{} + err = schemamd.RenderAction(&schema, b) + if err != nil { + t.Fatal(err) + } + + // Remove \r characters so tests don't fail on windows + expectedStr := strings.ReplaceAll(string(expected), "\r", "") + + // Remove trailing newlines before comparing (some text editors remove them). + expectedStr = strings.TrimRight(expectedStr, "\n") + actual := strings.TrimRight(b.String(), "\n") + if diff := cmp.Diff(expectedStr, actual); diff != "" { + t.Fatalf("Unexpected diff (-wanted, +got): %s", diff) + } + }) + } +} diff --git a/internal/schemamd/testdata/actions/test_unlinked_action.md b/internal/schemamd/testdata/actions/test_unlinked_action.md new file mode 100644 index 0000000..5b1cd17 --- /dev/null +++ b/internal/schemamd/testdata/actions/test_unlinked_action.md @@ -0,0 +1,16 @@ +## Schema + +### Required + +- `required_attr` (String) Required attribute + +### Optional + +- `list_block` (Block List, Max: 1) (see [below for nested schema](#nestedblock--list_block)) + + +### Nested Schema for `list_block` + +Optional: + +- `optional_attr` (String) Optional attribute diff --git a/internal/schemamd/testdata/actions/test_unlinked_action.schema.json b/internal/schemamd/testdata/actions/test_unlinked_action.schema.json new file mode 100644 index 0000000..5b5fde9 --- /dev/null +++ b/internal/schemamd/testdata/actions/test_unlinked_action.schema.json @@ -0,0 +1,32 @@ +{ + "block": { + "unlinked": {}, + "attributes": { + "required_attr": { + "description_kind": "plain", + "description": "Required attribute", + "required": true, + "type": "string" + } + }, + "block_types": { + "list_block": { + "block": { + "attributes": { + "optional_attr": { + "description_kind": "plain", + "description": "Optional attribute", + "optional": true, + "type": "string" + } + }, + "description_kind": "plain" + }, + "max_items": 1, + "nesting_mode": "list" + } + }, + "description_kind": "plain" + }, + "version": 0 +} \ No newline at end of file From fce71fa1d710204e4a4c073209604468bf03bb1c Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 17:39:33 -0400 Subject: [PATCH 08/18] update readme --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c72c187..d6ed83c 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ When you run `tfplugindocs`, by default from the root directory of a provider co * Generate data source template files, if missing * Generate function template files, if missing (Requires Terraform v1.8.0+) * Generate ephemeral resource template files, if missing (Requires Terraform v1.10.0+) +* Generate action template files, if missing (Requires Terraform v1.14.0+) * Copy all non-template files to the output website directory > [!NOTE] @@ -207,10 +208,12 @@ For templates: |--------------------------------------------------------------------|-----------------------------------------------| | `templates/` | Root of templated docs | | `templates/index.md[.tmpl]` | Docs index page (or template) | +| `templates/actions.md[.tmpl]` | Generic action page (or template) | +| `templates/actions/.md[.tmpl]` | Action page (or template) | | `templates/data-sources.md[.tmpl]` | Generic data source page (or template) | | `templates/data-sources/.md[.tmpl]` | Data source page (or template) | | `templates/ephemeral-resources.md[.tmpl]` | Generic ephemeral resource page (or template) | -| `templates/ephemeral-resources/.md[.tmpl]` | Ephemeral resource page (or template) | +| `templates/ephemeral-resources/.md[.tmpl]`| Ephemeral resource page (or template) | | `templates/functions.md[.tmpl]` | Generic function page (or template) | | `templates/functions/.md[.tmpl]` | Function page (or template) | | `templates/resources.md[.tmpl]` | Generic resource page (or template) | @@ -227,6 +230,7 @@ For examples: |---------------------------------------------------------------------------|--------------------------------------------| | `examples/` | Root of examples | | `examples/provider/provider.tf` | Provider example config | +| `examples/actions//action.tf` | Action example config | | `examples/data-sources//data-source.tf` | Data source example config | | `examples/ephemeral-resources//ephemeral-resource.tf` | Ephemeral resource example config | | `examples/functions//function.tf` | Function example config | @@ -249,6 +253,7 @@ Legacy website directory structure: | `website/` | Root of website docs | | `website/docs/guides` | Root of guides subdirectory | | `website/docs/index.html.markdown` | Docs index page | +| `website/docs/actions/.html.markdown` | Action page | | `website/docs/d/.html.markdown` | Data source page | | `website/docs/ephemeral-resources/.html.markdown` | Ephemeral resource page | | `website/docs/functons/.html.markdown` | Functions page | @@ -261,6 +266,7 @@ Docs website directory structure: | `docs/` | Root of website docs | | `docs/guides` | Root of guides subdirectory | | `docs/index.html.markdown` | Docs index page | +| `docs/actions/.html.markdown` | Action page | | `docs/data-sources/.html.markdown` | Data source page | | `docs/ephemeral-resources/.html.markdown` | Ephemeral resource page | | `docs/functions/.html.markdown` | Function page | @@ -331,6 +337,20 @@ using the following data fields and functions: | `.HasVariadic` | bool | Does this function have a variadic argument? | | `.FunctionVariadicArgumentMarkdown` | string | a Markdown formatted Function variadic argument definition | +##### Action Fields + +| Field | Type | Description | +|-------------------------|--------|-------------------------------------------------------------------------------------------| +| `.Name` | string | Name of the action (ex. `examplecloud_do_thing`) | +| `.Type` | string | `Action` | +| `.Description` | string | Action description | +| `.HasExample` | bool | Is there an example file? | +| `.ExampleFile` | string | Path to the file with the terraform configuration example | +| `.ProviderName` | string | Canonical provider name (ex. `terraform-provider-random`) | +| `.ProviderShortName` | string | Short version of the rendered provider name (ex. `random`) | +| `.RenderedProviderName` | string | Value provided via argument `--rendered-provider-name`, otherwise same as `.ProviderName` | +| `.SchemaMarkdown` | string | a Markdown formatted Action Schema definition | + #### Template Functions | Function | Description | From 286c0777c63bd9390b2065b3fdf85923360b5721 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 11 Aug 2025 17:44:11 -0400 Subject: [PATCH 09/18] add TBD changelogs --- .changes/unreleased/FEATURES-20250811-174112.yaml | 5 +++++ .changes/unreleased/FEATURES-20250811-174141.yaml | 5 +++++ .changes/unreleased/FEATURES-20250811-174155.yaml | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 .changes/unreleased/FEATURES-20250811-174112.yaml create mode 100644 .changes/unreleased/FEATURES-20250811-174141.yaml create mode 100644 .changes/unreleased/FEATURES-20250811-174155.yaml diff --git a/.changes/unreleased/FEATURES-20250811-174112.yaml b/.changes/unreleased/FEATURES-20250811-174112.yaml new file mode 100644 index 0000000..065172e --- /dev/null +++ b/.changes/unreleased/FEATURES-20250811-174112.yaml @@ -0,0 +1,5 @@ +kind: FEATURES +body: 'generate: Add support for unlinked actions' +time: 2025-08-11T17:41:12.858383-04:00 +custom: + Issue: "TBD" diff --git a/.changes/unreleased/FEATURES-20250811-174141.yaml b/.changes/unreleased/FEATURES-20250811-174141.yaml new file mode 100644 index 0000000..c0c3788 --- /dev/null +++ b/.changes/unreleased/FEATURES-20250811-174141.yaml @@ -0,0 +1,5 @@ +kind: FEATURES +body: 'migrate: Add support for unlinked actions' +time: 2025-08-11T17:41:41.553344-04:00 +custom: + Issue: "TBD" diff --git a/.changes/unreleased/FEATURES-20250811-174155.yaml b/.changes/unreleased/FEATURES-20250811-174155.yaml new file mode 100644 index 0000000..5c5f24e --- /dev/null +++ b/.changes/unreleased/FEATURES-20250811-174155.yaml @@ -0,0 +1,5 @@ +kind: FEATURES +body: 'validate: Add support for unlinked actions' +time: 2025-08-11T17:41:55.966547-04:00 +custom: + Issue: "TBD" From be3235b17ddd73644723d4595a7311deac21d121 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Tue, 12 Aug 2025 09:20:01 -0400 Subject: [PATCH 10/18] update changelogs --- .changes/unreleased/FEATURES-20250811-174112.yaml | 2 +- .changes/unreleased/FEATURES-20250811-174141.yaml | 2 +- .changes/unreleased/FEATURES-20250811-174155.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changes/unreleased/FEATURES-20250811-174112.yaml b/.changes/unreleased/FEATURES-20250811-174112.yaml index 065172e..bed6a32 100644 --- a/.changes/unreleased/FEATURES-20250811-174112.yaml +++ b/.changes/unreleased/FEATURES-20250811-174112.yaml @@ -2,4 +2,4 @@ kind: FEATURES body: 'generate: Add support for unlinked actions' time: 2025-08-11T17:41:12.858383-04:00 custom: - Issue: "TBD" + Issue: "505" diff --git a/.changes/unreleased/FEATURES-20250811-174141.yaml b/.changes/unreleased/FEATURES-20250811-174141.yaml index c0c3788..3013f10 100644 --- a/.changes/unreleased/FEATURES-20250811-174141.yaml +++ b/.changes/unreleased/FEATURES-20250811-174141.yaml @@ -2,4 +2,4 @@ kind: FEATURES body: 'migrate: Add support for unlinked actions' time: 2025-08-11T17:41:41.553344-04:00 custom: - Issue: "TBD" + Issue: "505" diff --git a/.changes/unreleased/FEATURES-20250811-174155.yaml b/.changes/unreleased/FEATURES-20250811-174155.yaml index 5c5f24e..9138660 100644 --- a/.changes/unreleased/FEATURES-20250811-174155.yaml +++ b/.changes/unreleased/FEATURES-20250811-174155.yaml @@ -2,4 +2,4 @@ kind: FEATURES body: 'validate: Add support for unlinked actions' time: 2025-08-11T17:41:55.966547-04:00 custom: - Issue: "TBD" + Issue: "505" From c62546eca31b39941cbc65a3b4cf28da1e48bc22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 08:33:53 +0200 Subject: [PATCH 11/18] build(deps): bump github.com/hashicorp/terraform-json (#506) Bumps [github.com/hashicorp/terraform-json](https://github.com/hashicorp/terraform-json) from 0.25.0 to 0.26.0. - [Release notes](https://github.com/hashicorp/terraform-json/releases) - [Commits](https://github.com/hashicorp/terraform-json/compare/v0.25.0...v0.26.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-json dependency-version: 0.26.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1753ae7..76e4258 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/hc-install v0.9.2 github.com/hashicorp/terraform-exec v0.23.0 - github.com/hashicorp/terraform-json v0.25.1-0.20250808120122-465ba375ab0a + github.com/hashicorp/terraform-json v0.26.0 github.com/mattn/go-colorable v0.1.14 github.com/rogpeppe/go-internal v1.14.1 github.com/yuin/goldmark v1.7.7 diff --git a/go.sum b/go.sum index ac149ea..5bdc22c 100644 --- a/go.sum +++ b/go.sum @@ -74,8 +74,8 @@ github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+O github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I= github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= -github.com/hashicorp/terraform-json v0.25.1-0.20250808120122-465ba375ab0a h1:gzMCStpg0ySSzpPa6KnWha9DUiadfoN9yVsrqOWiwLs= -github.com/hashicorp/terraform-json v0.25.1-0.20250808120122-465ba375ab0a/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= +github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4= +github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= From 14b3e9a25d992abeeb4491d98769b53db4237871 Mon Sep 17 00:00:00 2001 From: Service Account - Terraform Provider DevEx <100357958+hc-github-team-tf-provider-devex@users.noreply.github.com> Date: Thu, 14 Aug 2025 12:22:46 -0400 Subject: [PATCH 12/18] [CI] Update lock workflow file --- .github/workflows/lock.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 8b519cf..560ddc0 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -14,6 +14,7 @@ jobs: # https://github.com/hashicorp/terraform-devex-repos/blob/main/modules/repo/workflows/lock.tftpl - uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1 with: + process-only: 'issues, prs' github-token: ${{ github.token }} issue-inactive-days: '30' issue-lock-reason: resolved From 159b1f28d7e69069b6b683a70c0206ddf2bf2075 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:23:26 +0200 Subject: [PATCH 13/18] build(deps): bump the github-actions group with 2 updates (#507) Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action). Updates `actions/checkout` from 4.2.2 to 5.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8) Updates `goreleaser/goreleaser-action` from 6.3.0 to 6.4.0 - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/9c156ee8a17a598857849441385a2041ef570552...e435ccd777264be153ace6237001ef4d979d3a7a) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: goreleaser/goreleaser-action dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-changie.yml | 2 +- .github/workflows/compliance.yml | 2 +- .github/workflows/release.yml | 8 ++++---- .github/workflows/test.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-changie.yml b/.github/workflows/ci-changie.yml index 3031aad..57a798d 100644 --- a/.github/workflows/ci-changie.yml +++ b/.github/workflows/ci-changie.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: # Ensure terraform-devex-repos is updated on version changes. - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 # Ensure terraform-devex-repos is updated on version changes. - uses: miniscruff/changie-action@6dcc2533cac0495148ed4046c438487e4dceaa23 # v2.0.0 with: diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 6a82766..c53644e 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -11,7 +11,7 @@ jobs: copywrite: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: hashicorp/setup-copywrite@32638da2d4e81d56a0764aa1547882fc4d209636 # v1.1.3 - run: copywrite headers --plan - run: copywrite license --plan diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 48cd9c3..4f83fa8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 # Avoid persisting GITHUB_TOKEN credentials as they take priority over our service account PAT for `git push` operations @@ -54,7 +54,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 # Default input is the SHA that initially triggered the workflow. As we created a new commit in the previous job, @@ -79,7 +79,7 @@ jobs: contents: write # Needed for goreleaser to create GitHub release issues: write # Needed for goreleaser to close associated milestone steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: ref: ${{ inputs.versionNumber }} fetch-depth: 0 @@ -93,7 +93,7 @@ jobs: cd .changes sed -e "1{/# /d;}" -e "2{/^$/d;}" ${{ needs.changelog-version.outputs.version }}.md > /tmp/release-notes.txt - - uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 + - uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a122735..bd32416 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: git config --global core.eol lf - name: Check out code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: From 760c1b16f9be94ed62b7b92962dfacb9c626761b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:44:05 -0400 Subject: [PATCH 14/18] build(deps): bump github.com/zclconf/go-cty from 1.16.3 to 1.16.4 (#514) Bumps [github.com/zclconf/go-cty](https://github.com/zclconf/go-cty) from 1.16.3 to 1.16.4. - [Release notes](https://github.com/zclconf/go-cty/releases) - [Changelog](https://github.com/zclconf/go-cty/blob/main/CHANGELOG.md) - [Commits](https://github.com/zclconf/go-cty/compare/v1.16.3...v1.16.4) --- updated-dependencies: - dependency-name: github.com/zclconf/go-cty dependency-version: 1.16.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 76e4258..9f6fbfa 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/rogpeppe/go-internal v1.14.1 github.com/yuin/goldmark v1.7.7 github.com/yuin/goldmark-meta v1.1.0 - github.com/zclconf/go-cty v1.16.3 + github.com/zclconf/go-cty v1.16.4 go.abhg.dev/goldmark/frontmatter v0.2.0 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df golang.org/x/text v0.28.0 diff --git a/go.sum b/go.sum index 5bdc22c..269f99b 100644 --- a/go.sum +++ b/go.sum @@ -132,8 +132,8 @@ github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU= github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0= -github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= -github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty v1.16.4 h1:QGXaag7/7dCzb+odlGrgr+YmYZFaOCMW6DEpS+UD1eE= +github.com/zclconf/go-cty v1.16.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= From ea85a8a9b45e107b5c1f16f25cc8f139f60ea449 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 17:39:41 -0400 Subject: [PATCH 15/18] build(deps): bump github.com/hashicorp/terraform-exec (#515) Bumps [github.com/hashicorp/terraform-exec](https://github.com/hashicorp/terraform-exec) from 0.23.0 to 0.23.1. - [Release notes](https://github.com/hashicorp/terraform-exec/releases) - [Changelog](https://github.com/hashicorp/terraform-exec/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-exec/compare/v0.23.0...v0.23.1) --- updated-dependencies: - dependency-name: github.com/hashicorp/terraform-exec dependency-version: 0.23.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9f6fbfa..f0f0f54 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/hashicorp/cli v1.1.7 github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/hc-install v0.9.2 - github.com/hashicorp/terraform-exec v0.23.0 + github.com/hashicorp/terraform-exec v0.23.1 github.com/hashicorp/terraform-json v0.26.0 github.com/mattn/go-colorable v0.1.14 github.com/rogpeppe/go-internal v1.14.1 diff --git a/go.sum b/go.sum index 269f99b..b5b0f9f 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+OmtO24= github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= -github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEsiXmzATMW/I= -github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= +github.com/hashicorp/terraform-exec v0.23.1 h1:diK5NSSDXDKqHEOIQefBMu9ny+FhzwlwV0xgUTB7VTo= +github.com/hashicorp/terraform-exec v0.23.1/go.mod h1:e4ZEg9BJDRaSalGm2z8vvrPONt0XWG0/tXpmzYTf+dM= github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4= github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= From 4aaa2cb7ada4ac07d8cce878d13850f927198f76 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 3 Sep 2025 10:28:26 -0400 Subject: [PATCH 16/18] update go mod --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f0f0f54..8d8d61a 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/hc-install v0.9.2 github.com/hashicorp/terraform-exec v0.23.1 - github.com/hashicorp/terraform-json v0.26.0 + github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed github.com/mattn/go-colorable v0.1.14 github.com/rogpeppe/go-internal v1.14.1 github.com/yuin/goldmark v1.7.7 diff --git a/go.sum b/go.sum index b5b0f9f..bde26e1 100644 --- a/go.sum +++ b/go.sum @@ -76,6 +76,8 @@ github.com/hashicorp/terraform-exec v0.23.1 h1:diK5NSSDXDKqHEOIQefBMu9ny+FhzwlwV github.com/hashicorp/terraform-exec v0.23.1/go.mod h1:e4ZEg9BJDRaSalGm2z8vvrPONt0XWG0/tXpmzYTf+dM= github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4= github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= +github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed h1:o4lC3qBOqlj+/b3WgnokYcwARvG8P6keLasy/0UfhPo= +github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= From bfd766e573ea454b396995f67f5557a8e3d16ffd Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 3 Sep 2025 10:29:42 -0400 Subject: [PATCH 17/18] update go sum --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index bde26e1..88c1e3a 100644 --- a/go.sum +++ b/go.sum @@ -74,8 +74,6 @@ github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+O github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= github.com/hashicorp/terraform-exec v0.23.1 h1:diK5NSSDXDKqHEOIQefBMu9ny+FhzwlwV0xgUTB7VTo= github.com/hashicorp/terraform-exec v0.23.1/go.mod h1:e4ZEg9BJDRaSalGm2z8vvrPONt0XWG0/tXpmzYTf+dM= -github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4= -github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4= github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed h1:o4lC3qBOqlj+/b3WgnokYcwARvG8P6keLasy/0UfhPo= github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= From fc72238b2ff8476b7a79db6328fd9100713d0474 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Mon, 8 Sep 2025 16:12:31 -0400 Subject: [PATCH 18/18] update to use main of tfjson --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8d8d61a..bf819ac 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/hc-install v0.9.2 github.com/hashicorp/terraform-exec v0.23.1 - github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed + github.com/hashicorp/terraform-json v0.26.1-0.20250908200803-41f8aafc40af github.com/mattn/go-colorable v0.1.14 github.com/rogpeppe/go-internal v1.14.1 github.com/yuin/goldmark v1.7.7 diff --git a/go.sum b/go.sum index 88c1e3a..16396b7 100644 --- a/go.sum +++ b/go.sum @@ -74,8 +74,8 @@ github.com/hashicorp/hc-install v0.9.2 h1:v80EtNX4fCVHqzL9Lg/2xkp62bbvQMnvPQ0G+O github.com/hashicorp/hc-install v0.9.2/go.mod h1:XUqBQNnuT4RsxoxiM9ZaUk0NX8hi2h+Lb6/c0OZnC/I= github.com/hashicorp/terraform-exec v0.23.1 h1:diK5NSSDXDKqHEOIQefBMu9ny+FhzwlwV0xgUTB7VTo= github.com/hashicorp/terraform-exec v0.23.1/go.mod h1:e4ZEg9BJDRaSalGm2z8vvrPONt0XWG0/tXpmzYTf+dM= -github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed h1:o4lC3qBOqlj+/b3WgnokYcwARvG8P6keLasy/0UfhPo= -github.com/hashicorp/terraform-json v0.26.1-0.20250903142550-e43f20a0f5ed/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE= +github.com/hashicorp/terraform-json v0.26.1-0.20250908200803-41f8aafc40af h1:TXYkA1zjKTAJrpuY4NqdBsdpa1Msii6LGhax3Ywf1MQ= +github.com/hashicorp/terraform-json v0.26.1-0.20250908200803-41f8aafc40af/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=