From 339e988b01f43590c05731c84df284b50885b18f Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Thu, 17 Oct 2024 12:55:23 -0400 Subject: [PATCH 01/14] Refactor `validateStaticDocs()` and `validateLegacyWebsite()` to use a `fs.FS` interface for walking. --- internal/provider/validate.go | 79 ++++++++++++++---------------- internal/provider/validate_test.go | 10 ++-- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/internal/provider/validate.go b/internal/provider/validate.go index a72be37..4f1d796 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "io/fs" "log" "os" "path/filepath" @@ -81,6 +82,7 @@ var RegistryGuideFrontMatterOptions = &check.FrontMatterOptions{ type validator struct { providerName string providerDir string + providerFS fs.FS providersSchemaPath string tfVersion string @@ -120,9 +122,12 @@ func Validate(ui cli.Ui, providerDir, providerName, providersSchemaPath, tfversi return fmt.Errorf("expected %q to be a directory", providerDir) } + providerFs := os.DirFS(providerDir) + v := &validator{ providerName: providerName, providerDir: providerDir, + providerFS: providerFs, providersSchemaPath: providersSchemaPath, tfVersion: tfversion, @@ -157,9 +162,7 @@ func (v *validator) validate(ctx context.Context) error { } } - providerFs := os.DirFS(v.providerDir) - - files, globErr := doublestar.Glob(providerFs, DocumentationGlobPattern) + files, globErr := doublestar.Glob(v.providerFS, DocumentationGlobPattern) if globErr != nil { return fmt.Errorf("error finding documentation files: %w", err) } @@ -170,15 +173,15 @@ func (v *validator) validate(ctx context.Context) error { err = check.MixedDirectoriesCheck(files) result = errors.Join(result, err) - if dirExists(filepath.Join(v.providerDir, "docs")) { + if dirExists(v.providerFS, "docs") { v.logger.infof("detected static docs directory, running checks") - err = v.validateStaticDocs(filepath.Join(v.providerDir, "docs")) + err = v.validateStaticDocs("docs") result = errors.Join(result, err) } - if dirExists(filepath.Join(v.providerDir, filepath.Join("website", "docs"))) { + if dirExists(v.providerFS, "website/docs") { v.logger.infof("detected legacy website directory, running checks") - err = v.validateLegacyWebsite(filepath.Join(v.providerDir, "website/docs")) + err = v.validateLegacyWebsite("website/docs") result = errors.Join(result, err) } @@ -190,23 +193,19 @@ func (v *validator) validateStaticDocs(dir string) error { var result error options := &check.ProviderFileOptions{ + FileOptions: &check.FileOptions{BasePath: v.providerDir}, FrontMatter: RegistryFrontMatterOptions, ValidExtensions: ValidRegistryFileExtensions, } var files []string - err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + err := fs.WalkDir(v.providerFS, dir, func(path string, d fs.DirEntry, err error) error { if err != nil { return fmt.Errorf("error walking directory %q: %w", dir, err) } - - rel, err := filepath.Rel(v.providerDir, path) - if err != nil { - return err - } if d.IsDir() { - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationDirGlobPattern), rel) + match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationDirGlobPattern), path) if err != nil { return err } @@ -214,11 +213,11 @@ func (v *validator) validateStaticDocs(dir string) error { return nil // skip valid non-documentation directories } - v.logger.infof("running invalid directories check on %s", rel) - result = errors.Join(result, check.InvalidDirectoriesCheck(rel)) + v.logger.infof("running invalid directories check on %s", path) + result = errors.Join(result, check.InvalidDirectoriesCheck(path)) return nil } - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationGlobPattern), rel) + match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationGlobPattern), path) if err != nil { return err } @@ -229,12 +228,12 @@ func (v *validator) validateStaticDocs(dir string) error { // Configure FrontMatterOptions based on file type if d.Name() == "index.md" { options.FrontMatter = RegistryIndexFrontMatterOptions - } else if _, relErr := filepath.Rel(rel, "guides"); relErr != nil { + } else if _, relErr := filepath.Rel(path, "guides"); relErr != nil { options.FrontMatter = RegistryGuideFrontMatterOptions } else { options.FrontMatter = RegistryFrontMatterOptions } - v.logger.infof("running file checks on %s", rel) + v.logger.infof("running file checks on %s", path) result = errors.Join(result, check.NewProviderFileCheck(options).Run(path)) files = append(files, path) @@ -249,15 +248,15 @@ func (v *validator) validateStaticDocs(dir string) error { Schema: v.providerSchema, } - if dirExists(filepath.Join(dir, "data-sources")) { + if dirExists(v.providerFS, filepath.Join(dir, "data-sources")) { dataSourceFiles, _ := os.ReadDir(filepath.Join(dir, "data-sources")) mismatchOpt.DatasourceEntries = dataSourceFiles } - if dirExists(filepath.Join(dir, "resources")) { + if dirExists(v.providerFS, filepath.Join(dir, "resources")) { resourceFiles, _ := os.ReadDir(filepath.Join(dir, "resources")) mismatchOpt.ResourceEntries = resourceFiles } - if dirExists(filepath.Join(dir, "functions")) { + if dirExists(v.providerFS, filepath.Join(dir, "functions")) { functionFiles, _ := os.ReadDir(filepath.Join(dir, "functions")) mismatchOpt.FunctionEntries = functionFiles } @@ -275,22 +274,18 @@ func (v *validator) validateLegacyWebsite(dir string) error { var result error options := &check.ProviderFileOptions{ + FileOptions: &check.FileOptions{BasePath: v.providerDir}, FrontMatter: LegacyFrontMatterOptions, ValidExtensions: ValidLegacyFileExtensions, } var files []string - err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + err := fs.WalkDir(v.providerFS, dir, func(path string, d fs.DirEntry, err error) error { if err != nil { return fmt.Errorf("error walking directory %q: %w", dir, err) } - - rel, err := filepath.Rel(v.providerDir, path) - if err != nil { - return err - } if d.IsDir() { - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationDirGlobPattern), rel) + match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationDirGlobPattern), path) if err != nil { return err } @@ -298,12 +293,12 @@ func (v *validator) validateLegacyWebsite(dir string) error { return nil // skip valid non-documentation directories } - v.logger.infof("running invalid directories check on %s", rel) - result = errors.Join(result, check.InvalidDirectoriesCheck(rel)) + v.logger.infof("running invalid directories check on %s", path) + result = errors.Join(result, check.InvalidDirectoriesCheck(path)) return nil } - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationGlobPattern), rel) + match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationGlobPattern), path) if err != nil { return err } @@ -314,12 +309,12 @@ func (v *validator) validateLegacyWebsite(dir string) error { // Configure FrontMatterOptions based on file type if d.Name() == "index.md" { options.FrontMatter = LegacyIndexFrontMatterOptions - } else if _, relErr := filepath.Rel(rel, "guides"); relErr != nil { + } else if _, relErr := filepath.Rel(path, "guides"); relErr != nil { options.FrontMatter = LegacyGuideFrontMatterOptions } else { options.FrontMatter = LegacyFrontMatterOptions } - v.logger.infof("running file checks on %s", rel) + v.logger.infof("running file checks on %s", path) result = errors.Join(result, check.NewProviderFileCheck(options).Run(path)) files = append(files, path) @@ -334,16 +329,16 @@ func (v *validator) validateLegacyWebsite(dir string) error { Schema: v.providerSchema, } - if dirExists(filepath.Join(dir, "d")) { - dataSourceFiles, _ := os.ReadDir(filepath.Join(dir, "d")) + if dirExists(v.providerFS, filepath.Join(dir, "d")) { + dataSourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "d")) mismatchOpt.DatasourceEntries = dataSourceFiles } - if dirExists(filepath.Join(dir, "r")) { - resourceFiles, _ := os.ReadDir(filepath.Join(dir, "r")) + if dirExists(v.providerFS, filepath.Join(dir, "r")) { + resourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "r")) mismatchOpt.ResourceEntries = resourceFiles } - if dirExists(filepath.Join(dir, "functions")) { - functionFiles, _ := os.ReadDir(filepath.Join(dir, "functions")) + if dirExists(v.providerFS, filepath.Join(dir, "functions")) { + functionFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "functions")) mismatchOpt.FunctionEntries = functionFiles } @@ -355,8 +350,8 @@ func (v *validator) validateLegacyWebsite(dir string) error { return result } -func dirExists(name string) bool { - if file, err := os.Stat(name); err != nil { +func dirExists(fileSys fs.FS, name string) bool { + if file, err := fs.Stat(fileSys, name); err != nil { return false } else if !file.IsDir() { return false diff --git a/internal/provider/validate_test.go b/internal/provider/validate_test.go index 4f087b9..c94d210 100644 --- a/internal/provider/validate_test.go +++ b/internal/provider/validate_test.go @@ -4,6 +4,7 @@ package provider import ( + "os" "path/filepath" "testing" @@ -38,14 +39,15 @@ func TestValidateStaticDocs(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() + providerFs := os.DirFS(testCase.BasePath) v := &validator{ + providerFS: providerFs, providerDir: testCase.BasePath, providerName: "terraform-provider-test", logger: NewLogger(cli.NewMockUi()), } - - got := v.validateStaticDocs(filepath.Join(v.providerDir, "docs")) + got := v.validateStaticDocs("docs") if got == nil && testCase.ExpectError { t.Errorf("expected error, got no error") @@ -88,14 +90,16 @@ func TestValidateLegacyWebsite(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() + providerFs := os.DirFS(testCase.BasePath) v := &validator{ + providerFS: providerFs, providerDir: testCase.BasePath, providerName: "terraform-provider-test", logger: NewLogger(cli.NewMockUi()), } - got := v.validateLegacyWebsite(filepath.Join(v.providerDir, "website")) + got := v.validateLegacyWebsite("website/docs") if got == nil && testCase.ExpectError { t.Errorf("expected error, got no error") From a4a520c99eaa48836e9fe8f3ccdb6c08f94a7715 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Mon, 21 Oct 2024 19:10:42 -0400 Subject: [PATCH 02/14] Refactor `validate_test.go` to use `fstest.MapFS` --- internal/check/file.go | 8 +- internal/check/file_extension.go | 2 +- internal/check/file_test.go | 32 +- internal/check/provider_file.go | 14 +- .../docs/r/invalid/thing.html.markdown | 27 - .../data_source_invalid_extension.txt | 27 - ...a_source_invalid_frontmatter.html.markdown | 27 - ..._source_with_sidebar_current.html.markdown | 28 - .../data_source_without_layout.html.markdown | 26 - .../guide_invalid_extension.txt | 11 - .../guide_invalid_frontmatter.html.markdown | 11 - .../guide_with_sidebar_current.html.markdown | 12 - .../guide_without_layout.html.markdown | 10 - .../index_invalid_extension.txt | 10 - .../index_invalid_frontmatter.html.markdown | 10 - .../index_with_sidebar_current.html.markdown | 11 - .../index_with_subcategory.html.markdown | 10 - .../index_without_layout.html.markdown | 9 - .../resource_invalid_extension.txt | 27 - ...resource_invalid_frontmatter.html.markdown | 27 - ...esource_with_sidebar_current.html.markdown | 28 - .../resource_without_layout.html.markdown | 26 - .../docs/resources/invalid/thing.md | 26 - .../data_source_invalid_extension.markdown | 26 - .../data_source_invalid_frontmatter.md | 26 - .../data_source_with_layout.md | 27 - .../data_source_with_sidebar_current.md | 27 - .../guide_invalid_extension.markdown | 10 - .../guide_invalid_frontmatter.md | 10 - .../guide_with_layout.md | 11 - .../guide_with_sidebar_current.md | 11 - .../index_invalid_extension.markdown | 9 - .../index_invalid_frontmatter.md | 9 - .../index_with_layout.md | 10 - .../index_with_sidebar_current.md | 10 - .../index_with_subcategory.md | 10 - .../resource_invalid_extension.markdown | 26 - .../resource_invalid_frontmatter.md | 26 - .../resource_with_layout.md | 27 - .../resource_with_sidebar_current.md | 27 - .../cdktf/typescript/d/thing.html.markdown | 37 - .../cdktf/typescript/r/thing.html.markdown | 37 - .../website/docs/d/thing.html.markdown | 27 - .../website/docs/r/thing.html.markdown | 27 - .../website/docs/d/thing.html.markdown | 27 - .../website/docs/r/thing.html.markdown | 27 - .../2.0-guide.html.markdown | 11 - .../data_source.html.markdown | 27 - .../valid-legacy-files/guide.html.markdown | 11 - .../valid-legacy-files/index.html.markdown | 10 - .../valid-legacy-files/resource.html.markdown | 27 - .../docs/CONTRIBUTING.md | 3 - .../docs/cdktf/typescript/CONTRIBUTING.md | 3 - .../cdktf/typescript/data-sources/thing.md | 36 - .../docs/cdktf/typescript/index.md | 9 - .../cdktf/typescript/nonregistrydocs/valid.md | 3 - .../docs/cdktf/typescript/resources/thing.md | 36 - .../docs/data-sources/thing.md | 26 - .../docs/index.md | 9 - .../docs/nonregistrydocs/valid.md | 3 - .../docs/resources/thing.md | 26 - .../docs/CONTRIBUTING.md | 3 - .../docs/data-sources/thing.md | 26 - .../valid-registry-directories/docs/index.md | 9 - .../docs/nonregistrydocs/valid.md | 3 - .../docs/resources/thing.md | 26 - .../valid-registry-files/2.0-guide.md | 10 - .../valid-registry-files/data_source.md | 26 - .../testdata/valid-registry-files/guide.md | 10 - .../testdata/valid-registry-files/index.md | 9 - .../testdata/valid-registry-files/resource.md | 26 - internal/provider/validate.go | 27 +- internal/provider/validate_test.go | 653 +++++++++++++++++- 73 files changed, 664 insertions(+), 1307 deletions(-) delete mode 100644 internal/provider/testdata/invalid-legacy-directories/website/docs/r/invalid/thing.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/data_source_invalid_extension.txt delete mode 100644 internal/provider/testdata/invalid-legacy-files/data_source_invalid_frontmatter.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/data_source_with_sidebar_current.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/data_source_without_layout.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/guide_invalid_extension.txt delete mode 100644 internal/provider/testdata/invalid-legacy-files/guide_invalid_frontmatter.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/guide_with_sidebar_current.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/guide_without_layout.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/index_invalid_extension.txt delete mode 100644 internal/provider/testdata/invalid-legacy-files/index_invalid_frontmatter.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/index_with_sidebar_current.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/index_with_subcategory.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/index_without_layout.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/resource_invalid_extension.txt delete mode 100644 internal/provider/testdata/invalid-legacy-files/resource_invalid_frontmatter.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/resource_with_sidebar_current.html.markdown delete mode 100644 internal/provider/testdata/invalid-legacy-files/resource_without_layout.html.markdown delete mode 100644 internal/provider/testdata/invalid-registry-directories/docs/resources/invalid/thing.md delete mode 100644 internal/provider/testdata/invalid-registry-files/data_source_invalid_extension.markdown delete mode 100644 internal/provider/testdata/invalid-registry-files/data_source_invalid_frontmatter.md delete mode 100644 internal/provider/testdata/invalid-registry-files/data_source_with_layout.md delete mode 100644 internal/provider/testdata/invalid-registry-files/data_source_with_sidebar_current.md delete mode 100644 internal/provider/testdata/invalid-registry-files/guide_invalid_extension.markdown delete mode 100644 internal/provider/testdata/invalid-registry-files/guide_invalid_frontmatter.md delete mode 100644 internal/provider/testdata/invalid-registry-files/guide_with_layout.md delete mode 100644 internal/provider/testdata/invalid-registry-files/guide_with_sidebar_current.md delete mode 100644 internal/provider/testdata/invalid-registry-files/index_invalid_extension.markdown delete mode 100644 internal/provider/testdata/invalid-registry-files/index_invalid_frontmatter.md delete mode 100644 internal/provider/testdata/invalid-registry-files/index_with_layout.md delete mode 100644 internal/provider/testdata/invalid-registry-files/index_with_sidebar_current.md delete mode 100644 internal/provider/testdata/invalid-registry-files/index_with_subcategory.md delete mode 100644 internal/provider/testdata/invalid-registry-files/resource_invalid_extension.markdown delete mode 100644 internal/provider/testdata/invalid-registry-files/resource_invalid_frontmatter.md delete mode 100644 internal/provider/testdata/invalid-registry-files/resource_with_layout.md delete mode 100644 internal/provider/testdata/invalid-registry-files/resource_with_sidebar_current.md delete mode 100644 internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/d/thing.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/r/thing.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/d/thing.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/r/thing.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-directories/website/docs/d/thing.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-directories/website/docs/r/thing.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-files/2.0-guide.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-files/data_source.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-files/guide.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-files/index.html.markdown delete mode 100644 internal/provider/testdata/valid-legacy-files/resource.html.markdown delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/CONTRIBUTING.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/CONTRIBUTING.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/data-sources/thing.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/index.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/nonregistrydocs/valid.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/resources/thing.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/data-sources/thing.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/index.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/nonregistrydocs/valid.md delete mode 100644 internal/provider/testdata/valid-registry-directories-with-cdktf/docs/resources/thing.md delete mode 100644 internal/provider/testdata/valid-registry-directories/docs/CONTRIBUTING.md delete mode 100644 internal/provider/testdata/valid-registry-directories/docs/data-sources/thing.md delete mode 100644 internal/provider/testdata/valid-registry-directories/docs/index.md delete mode 100644 internal/provider/testdata/valid-registry-directories/docs/nonregistrydocs/valid.md delete mode 100644 internal/provider/testdata/valid-registry-directories/docs/resources/thing.md delete mode 100644 internal/provider/testdata/valid-registry-files/2.0-guide.md delete mode 100644 internal/provider/testdata/valid-registry-files/data_source.md delete mode 100644 internal/provider/testdata/valid-registry-files/guide.md delete mode 100644 internal/provider/testdata/valid-registry-files/index.md delete mode 100644 internal/provider/testdata/valid-registry-files/resource.md diff --git a/internal/check/file.go b/internal/check/file.go index cb079b3..5cf94b1 100644 --- a/internal/check/file.go +++ b/internal/check/file.go @@ -5,8 +5,8 @@ package check import ( "fmt" + "io/fs" "log" - "os" "path/filepath" ) @@ -23,14 +23,14 @@ func (opts *FileOptions) FullPath(path string) string { } // FileSizeCheck verifies that documentation file is below the Terraform Registry storage limit. -func FileSizeCheck(fullpath string) error { - fi, err := os.Stat(fullpath) +func FileSizeCheck(providerFs fs.FS, path string) error { + fi, err := fs.Stat(providerFs, path) if err != nil { return err } - log.Printf("[DEBUG] File %s size: %d (limit: %d)", fullpath, fi.Size(), RegistryMaximumSizeOfFile) + log.Printf("[DEBUG] File %s size: %d (limit: %d)", path, fi.Size(), RegistryMaximumSizeOfFile) if fi.Size() >= int64(RegistryMaximumSizeOfFile) { return fmt.Errorf("exceeded maximum (%d) size of documentation file for Terraform Registry: %d", RegistryMaximumSizeOfFile, fi.Size()) } diff --git a/internal/check/file_extension.go b/internal/check/file_extension.go index dd5f37b..7ca7b20 100644 --- a/internal/check/file_extension.go +++ b/internal/check/file_extension.go @@ -30,7 +30,7 @@ var ValidRegistryFileExtensions = []string{ // FileExtensionCheck checks if the file extension of the given path is valid. func FileExtensionCheck(path string, validExtensions []string) error { if !FilePathEndsWithExtensionFrom(path, validExtensions) { - return fmt.Errorf("file does not end with a valid extension, valid extensions: %v", ValidLegacyFileExtensions) + return fmt.Errorf("file does not end with a valid extension, valid extensions: %v", validExtensions) } return nil diff --git a/internal/check/file_test.go b/internal/check/file_test.go index c8ec7b8..d29a7e7 100644 --- a/internal/check/file_test.go +++ b/internal/check/file_test.go @@ -4,26 +4,40 @@ package check import ( - "os" + "io/fs" "path/filepath" "testing" + "testing/fstest" ) func TestFileSizeCheck(t *testing.T) { t.Parallel() testCases := map[string]struct { + FileSystem fs.FS Size int64 ExpectError bool }{ "under limit": { - Size: RegistryMaximumSizeOfFile - 1, + FileSystem: fstest.MapFS{ + "file.md": { + Data: make([]byte, RegistryMaximumSizeOfFile-1), + }, + }, }, "on limit": { - Size: RegistryMaximumSizeOfFile, + FileSystem: fstest.MapFS{ + "file.md": { + Data: make([]byte, RegistryMaximumSizeOfFile), + }, + }, ExpectError: true, }, "over limit": { - Size: RegistryMaximumSizeOfFile + 1, + FileSystem: fstest.MapFS{ + "file.md": { + Data: make([]byte, RegistryMaximumSizeOfFile+1), + }, + }, ExpectError: true, }, } @@ -34,15 +48,7 @@ func TestFileSizeCheck(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - file, _ := os.CreateTemp(t.TempDir(), "TestFileSizeCheck") - - defer file.Close() - - if err := file.Truncate(testCase.Size); err != nil { - t.Fatalf("error writing temporary file: %s", err) - } - - got := FileSizeCheck(file.Name()) + got := FileSizeCheck(testCase.FileSystem, "file.md") if got == nil && testCase.ExpectError { t.Errorf("expected error, got no error") diff --git a/internal/check/provider_file.go b/internal/check/provider_file.go index 5358b66..8bc94ac 100644 --- a/internal/check/provider_file.go +++ b/internal/check/provider_file.go @@ -5,8 +5,8 @@ package check import ( "fmt" + "io/fs" "log" - "os" ) type ProviderFileOptions struct { @@ -17,12 +17,14 @@ type ProviderFileOptions struct { } type ProviderFileCheck struct { - Options *ProviderFileOptions + Options *ProviderFileOptions + ProviderFs fs.FS } -func NewProviderFileCheck(opts *ProviderFileOptions) *ProviderFileCheck { +func NewProviderFileCheck(providerFs fs.FS, opts *ProviderFileOptions) *ProviderFileCheck { check := &ProviderFileCheck{ - Options: opts, + Options: opts, + ProviderFs: providerFs, } if check.Options == nil { @@ -49,11 +51,11 @@ func (check *ProviderFileCheck) Run(path string) error { return fmt.Errorf("%s: error checking file extension: %w", path, err) } - if err := FileSizeCheck(fullpath); err != nil { + if err := FileSizeCheck(check.ProviderFs, path); err != nil { return fmt.Errorf("%s: error checking file size: %w", path, err) } - content, err := os.ReadFile(fullpath) + content, err := fs.ReadFile(check.ProviderFs, path) if err != nil { return fmt.Errorf("%s: error reading file: %w", path, err) diff --git a/internal/provider/testdata/invalid-legacy-directories/website/docs/r/invalid/thing.html.markdown b/internal/provider/testdata/invalid-legacy-directories/website/docs/r/invalid/thing.html.markdown deleted file mode 100644 index 59bb04c..0000000 --- a/internal/provider/testdata/invalid-legacy-directories/website/docs/r/invalid/thing.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/data_source_invalid_extension.txt b/internal/provider/testdata/invalid-legacy-files/data_source_invalid_extension.txt deleted file mode 100644 index caee79a..0000000 --- a/internal/provider/testdata/invalid-legacy-files/data_source_invalid_extension.txt +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/data_source_invalid_frontmatter.html.markdown b/internal/provider/testdata/invalid-legacy-files/data_source_invalid_frontmatter.html.markdown deleted file mode 100644 index 1cb8750..0000000 --- a/internal/provider/testdata/invalid-legacy-files/data_source_invalid_frontmatter.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- -Missing indentation. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/data_source_with_sidebar_current.html.markdown b/internal/provider/testdata/invalid-legacy-files/data_source_with_sidebar_current.html.markdown deleted file mode 100644 index 510d48a..0000000 --- a/internal/provider/testdata/invalid-legacy-files/data_source_with_sidebar_current.html.markdown +++ /dev/null @@ -1,28 +0,0 @@ ---- -subcategory: "Example" -sidebar_current: "example_thing" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/data_source_without_layout.html.markdown b/internal/provider/testdata/invalid-legacy-files/data_source_without_layout.html.markdown deleted file mode 100644 index 688fa59..0000000 --- a/internal/provider/testdata/invalid-legacy-files/data_source_without_layout.html.markdown +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/guide_invalid_extension.txt b/internal/provider/testdata/invalid-legacy-files/guide_invalid_extension.txt deleted file mode 100644 index b02bcc8..0000000 --- a/internal/provider/testdata/invalid-legacy-files/guide_invalid_extension.txt +++ /dev/null @@ -1,11 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example Guide" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/guide_invalid_frontmatter.html.markdown b/internal/provider/testdata/invalid-legacy-files/guide_invalid_frontmatter.html.markdown deleted file mode 100644 index 33997fc..0000000 --- a/internal/provider/testdata/invalid-legacy-files/guide_invalid_frontmatter.html.markdown +++ /dev/null @@ -1,11 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example Guide" -description: |- -Missing indentation. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/guide_with_sidebar_current.html.markdown b/internal/provider/testdata/invalid-legacy-files/guide_with_sidebar_current.html.markdown deleted file mode 100644 index 5a101a3..0000000 --- a/internal/provider/testdata/invalid-legacy-files/guide_with_sidebar_current.html.markdown +++ /dev/null @@ -1,12 +0,0 @@ ---- -subcategory: "Example" -sidebar_current: "example" -layout: "example" -page_title: "Example Guide" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/guide_without_layout.html.markdown b/internal/provider/testdata/invalid-legacy-files/guide_without_layout.html.markdown deleted file mode 100644 index 61331ef..0000000 --- a/internal/provider/testdata/invalid-legacy-files/guide_without_layout.html.markdown +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example Guide" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/index_invalid_extension.txt b/internal/provider/testdata/invalid-legacy-files/index_invalid_extension.txt deleted file mode 100644 index c4ab147..0000000 --- a/internal/provider/testdata/invalid-legacy-files/index_invalid_extension.txt +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: "example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/index_invalid_frontmatter.html.markdown b/internal/provider/testdata/invalid-legacy-files/index_invalid_frontmatter.html.markdown deleted file mode 100644 index c4903d5..0000000 --- a/internal/provider/testdata/invalid-legacy-files/index_invalid_frontmatter.html.markdown +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: "example" -page_title: "Example Provider" -description: |- -Missing indentation. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/index_with_sidebar_current.html.markdown b/internal/provider/testdata/invalid-legacy-files/index_with_sidebar_current.html.markdown deleted file mode 100644 index fe33d3f..0000000 --- a/internal/provider/testdata/invalid-legacy-files/index_with_sidebar_current.html.markdown +++ /dev/null @@ -1,11 +0,0 @@ ---- -sidebar_current: "example" -layout: "example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/index_with_subcategory.html.markdown b/internal/provider/testdata/invalid-legacy-files/index_with_subcategory.html.markdown deleted file mode 100644 index 9766b6d..0000000 --- a/internal/provider/testdata/invalid-legacy-files/index_with_subcategory.html.markdown +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/index_without_layout.html.markdown b/internal/provider/testdata/invalid-legacy-files/index_without_layout.html.markdown deleted file mode 100644 index 9daab15..0000000 --- a/internal/provider/testdata/invalid-legacy-files/index_without_layout.html.markdown +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-legacy-files/resource_invalid_extension.txt b/internal/provider/testdata/invalid-legacy-files/resource_invalid_extension.txt deleted file mode 100644 index 59bb04c..0000000 --- a/internal/provider/testdata/invalid-legacy-files/resource_invalid_extension.txt +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/resource_invalid_frontmatter.html.markdown b/internal/provider/testdata/invalid-legacy-files/resource_invalid_frontmatter.html.markdown deleted file mode 100644 index 0cd796a..0000000 --- a/internal/provider/testdata/invalid-legacy-files/resource_invalid_frontmatter.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- -Missing indentation. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/resource_with_sidebar_current.html.markdown b/internal/provider/testdata/invalid-legacy-files/resource_with_sidebar_current.html.markdown deleted file mode 100644 index 32ec468..0000000 --- a/internal/provider/testdata/invalid-legacy-files/resource_with_sidebar_current.html.markdown +++ /dev/null @@ -1,28 +0,0 @@ ---- -subcategory: "Example" -sidebar_current: "example_thing" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-legacy-files/resource_without_layout.html.markdown b/internal/provider/testdata/invalid-legacy-files/resource_without_layout.html.markdown deleted file mode 100644 index aa156f3..0000000 --- a/internal/provider/testdata/invalid-legacy-files/resource_without_layout.html.markdown +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-directories/docs/resources/invalid/thing.md b/internal/provider/testdata/invalid-registry-directories/docs/resources/invalid/thing.md deleted file mode 100644 index aa156f3..0000000 --- a/internal/provider/testdata/invalid-registry-directories/docs/resources/invalid/thing.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/data_source_invalid_extension.markdown b/internal/provider/testdata/invalid-registry-files/data_source_invalid_extension.markdown deleted file mode 100644 index 688fa59..0000000 --- a/internal/provider/testdata/invalid-registry-files/data_source_invalid_extension.markdown +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/data_source_invalid_frontmatter.md b/internal/provider/testdata/invalid-registry-files/data_source_invalid_frontmatter.md deleted file mode 100644 index 224dcf7..0000000 --- a/internal/provider/testdata/invalid-registry-files/data_source_invalid_frontmatter.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- -Missing indentation. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/data_source_with_layout.md b/internal/provider/testdata/invalid-registry-files/data_source_with_layout.md deleted file mode 100644 index caee79a..0000000 --- a/internal/provider/testdata/invalid-registry-files/data_source_with_layout.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/data_source_with_sidebar_current.md b/internal/provider/testdata/invalid-registry-files/data_source_with_sidebar_current.md deleted file mode 100644 index afc1af9..0000000 --- a/internal/provider/testdata/invalid-registry-files/data_source_with_sidebar_current.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -sidebar_current: "example_thing" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/guide_invalid_extension.markdown b/internal/provider/testdata/invalid-registry-files/guide_invalid_extension.markdown deleted file mode 100644 index 9acc401..0000000 --- a/internal/provider/testdata/invalid-registry-files/guide_invalid_extension.markdown +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/guide_invalid_frontmatter.md b/internal/provider/testdata/invalid-registry-files/guide_invalid_frontmatter.md deleted file mode 100644 index 1dbe958..0000000 --- a/internal/provider/testdata/invalid-registry-files/guide_invalid_frontmatter.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- -Missing indentation. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/guide_with_layout.md b/internal/provider/testdata/invalid-registry-files/guide_with_layout.md deleted file mode 100644 index ff7efb9..0000000 --- a/internal/provider/testdata/invalid-registry-files/guide_with_layout.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/guide_with_sidebar_current.md b/internal/provider/testdata/invalid-registry-files/guide_with_sidebar_current.md deleted file mode 100644 index 1954289..0000000 --- a/internal/provider/testdata/invalid-registry-files/guide_with_sidebar_current.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -subcategory: "Example" -sidebar_current: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/index_invalid_extension.markdown b/internal/provider/testdata/invalid-registry-files/index_invalid_extension.markdown deleted file mode 100644 index 9daab15..0000000 --- a/internal/provider/testdata/invalid-registry-files/index_invalid_extension.markdown +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/index_invalid_frontmatter.md b/internal/provider/testdata/invalid-registry-files/index_invalid_frontmatter.md deleted file mode 100644 index f19cf71..0000000 --- a/internal/provider/testdata/invalid-registry-files/index_invalid_frontmatter.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- -Missing indentation. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/index_with_layout.md b/internal/provider/testdata/invalid-registry-files/index_with_layout.md deleted file mode 100644 index c4ab147..0000000 --- a/internal/provider/testdata/invalid-registry-files/index_with_layout.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: "example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/index_with_sidebar_current.md b/internal/provider/testdata/invalid-registry-files/index_with_sidebar_current.md deleted file mode 100644 index cd0a42c..0000000 --- a/internal/provider/testdata/invalid-registry-files/index_with_sidebar_current.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -sidebar_current: "example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/index_with_subcategory.md b/internal/provider/testdata/invalid-registry-files/index_with_subcategory.md deleted file mode 100644 index eb4751c..0000000 --- a/internal/provider/testdata/invalid-registry-files/index_with_subcategory.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/invalid-registry-files/resource_invalid_extension.markdown b/internal/provider/testdata/invalid-registry-files/resource_invalid_extension.markdown deleted file mode 100644 index aa156f3..0000000 --- a/internal/provider/testdata/invalid-registry-files/resource_invalid_extension.markdown +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/resource_invalid_frontmatter.md b/internal/provider/testdata/invalid-registry-files/resource_invalid_frontmatter.md deleted file mode 100644 index 39a2823..0000000 --- a/internal/provider/testdata/invalid-registry-files/resource_invalid_frontmatter.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- -Missing indentation. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/resource_with_layout.md b/internal/provider/testdata/invalid-registry-files/resource_with_layout.md deleted file mode 100644 index 59bb04c..0000000 --- a/internal/provider/testdata/invalid-registry-files/resource_with_layout.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/invalid-registry-files/resource_with_sidebar_current.md b/internal/provider/testdata/invalid-registry-files/resource_with_sidebar_current.md deleted file mode 100644 index 91e6dcb..0000000 --- a/internal/provider/testdata/invalid-registry-files/resource_with_sidebar_current.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -sidebar_current: "example_thing" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/d/thing.html.markdown b/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/d/thing.html.markdown deleted file mode 100644 index 32e9de6..0000000 --- a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/d/thing.html.markdown +++ /dev/null @@ -1,37 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```ts -import { Construct } from "construct"; -import { TerraformStack } from "cdktf"; -import { DataExample } from "./.gen/providers/example/data_example_thing"; - -class MyStack extends TerraformStack { - constructs(scope: Construct, name: string) { - super(scope, name); - - new DataExampleThing(this, "example", { - name: "example", - }); - } -} -``` - -## Argument Reference - -- `name` - (Required) Name of thing. - -## Attribute Reference - -- `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/r/thing.html.markdown b/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/r/thing.html.markdown deleted file mode 100644 index 962ae86..0000000 --- a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/cdktf/typescript/r/thing.html.markdown +++ /dev/null @@ -1,37 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```ts -import { Construct } from "construct"; -import { TerraformStack } from "cdktf"; -import { Thing } from "./.gen/providers/example/thing"; - -class MyStack extends TerraformStack { - constructs(scope: Construct, name: string) { - super(scope, name); - - new Thing(this, "example", { - name: "example", - }); - } -} -``` - -## Argument Reference - -- `name` - (Required) Name of thing. - -## Attribute Reference - -- `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/d/thing.html.markdown b/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/d/thing.html.markdown deleted file mode 100644 index caee79a..0000000 --- a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/d/thing.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/r/thing.html.markdown b/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/r/thing.html.markdown deleted file mode 100644 index 59bb04c..0000000 --- a/internal/provider/testdata/valid-legacy-directories-with-cdktf/website/docs/r/thing.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-directories/website/docs/d/thing.html.markdown b/internal/provider/testdata/valid-legacy-directories/website/docs/d/thing.html.markdown deleted file mode 100644 index caee79a..0000000 --- a/internal/provider/testdata/valid-legacy-directories/website/docs/d/thing.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-directories/website/docs/r/thing.html.markdown b/internal/provider/testdata/valid-legacy-directories/website/docs/r/thing.html.markdown deleted file mode 100644 index 59bb04c..0000000 --- a/internal/provider/testdata/valid-legacy-directories/website/docs/r/thing.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-files/2.0-guide.html.markdown b/internal/provider/testdata/valid-legacy-files/2.0-guide.html.markdown deleted file mode 100644 index b02bcc8..0000000 --- a/internal/provider/testdata/valid-legacy-files/2.0-guide.html.markdown +++ /dev/null @@ -1,11 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example Guide" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/valid-legacy-files/data_source.html.markdown b/internal/provider/testdata/valid-legacy-files/data_source.html.markdown deleted file mode 100644 index caee79a..0000000 --- a/internal/provider/testdata/valid-legacy-files/data_source.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-legacy-files/guide.html.markdown b/internal/provider/testdata/valid-legacy-files/guide.html.markdown deleted file mode 100644 index b02bcc8..0000000 --- a/internal/provider/testdata/valid-legacy-files/guide.html.markdown +++ /dev/null @@ -1,11 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example Guide" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/valid-legacy-files/index.html.markdown b/internal/provider/testdata/valid-legacy-files/index.html.markdown deleted file mode 100644 index c4ab147..0000000 --- a/internal/provider/testdata/valid-legacy-files/index.html.markdown +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: "example" -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/valid-legacy-files/resource.html.markdown b/internal/provider/testdata/valid-legacy-files/resource.html.markdown deleted file mode 100644 index 59bb04c..0000000 --- a/internal/provider/testdata/valid-legacy-files/resource.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/CONTRIBUTING.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/CONTRIBUTING.md deleted file mode 100644 index 423305c..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributing Guide - -This file has contents and no YAML frontmatter, because it is not a Terraform Provider documentation file and that is okay. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/CONTRIBUTING.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/CONTRIBUTING.md deleted file mode 100644 index 423305c..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributing Guide - -This file has contents and no YAML frontmatter, because it is not a Terraform Provider documentation file and that is okay. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/data-sources/thing.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/data-sources/thing.md deleted file mode 100644 index 5c415db..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/data-sources/thing.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```ts -import { Construct } from "construct"; -import { TerraformStack } from "cdktf"; -import { DataExample } from "./.gen/providers/example/data_example_thing"; - -class MyStack extends TerraformStack { - constructs(scope: Construct, name: string) { - super(scope, name); - - new DataExampleThing(this, "example", { - name: "example", - }); - } -} -``` - -## Argument Reference - -- `name` - (Required) Name of thing. - -## Attribute Reference - -- `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/index.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/index.md deleted file mode 100644 index 9daab15..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/nonregistrydocs/valid.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/nonregistrydocs/valid.md deleted file mode 100644 index a7f1fce..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/nonregistrydocs/valid.md +++ /dev/null @@ -1,3 +0,0 @@ -# Valid - -Files in `/docs`, but outside Registry documentation directories, should be ignored. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/resources/thing.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/resources/thing.md deleted file mode 100644 index 1f46f48..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/cdktf/typescript/resources/thing.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```ts -import { Construct } from "construct"; -import { TerraformStack } from "cdktf"; -import { Thing } from "./.gen/providers/example/thing"; - -class MyStack extends TerraformStack { - constructs(scope: Construct, name: string) { - super(scope, name); - - new Thing(this, "example", { - name: "example", - }); - } -} -``` - -## Argument Reference - -- `name` - (Required) Name of thing. - -## Attribute Reference - -- `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/data-sources/thing.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/data-sources/thing.md deleted file mode 100644 index 688fa59..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/data-sources/thing.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/index.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/index.md deleted file mode 100644 index 9daab15..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/nonregistrydocs/valid.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/nonregistrydocs/valid.md deleted file mode 100644 index a7f1fce..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/nonregistrydocs/valid.md +++ /dev/null @@ -1,3 +0,0 @@ -# Valid - -Files in `/docs`, but outside Registry documentation directories, should be ignored. diff --git a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/resources/thing.md b/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/resources/thing.md deleted file mode 100644 index aa156f3..0000000 --- a/internal/provider/testdata/valid-registry-directories-with-cdktf/docs/resources/thing.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-directories/docs/CONTRIBUTING.md b/internal/provider/testdata/valid-registry-directories/docs/CONTRIBUTING.md deleted file mode 100644 index 423305c..0000000 --- a/internal/provider/testdata/valid-registry-directories/docs/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributing Guide - -This file has contents and no YAML frontmatter, because it is not a Terraform Provider documentation file and that is okay. diff --git a/internal/provider/testdata/valid-registry-directories/docs/data-sources/thing.md b/internal/provider/testdata/valid-registry-directories/docs/data-sources/thing.md deleted file mode 100644 index 688fa59..0000000 --- a/internal/provider/testdata/valid-registry-directories/docs/data-sources/thing.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-directories/docs/index.md b/internal/provider/testdata/valid-registry-directories/docs/index.md deleted file mode 100644 index 9daab15..0000000 --- a/internal/provider/testdata/valid-registry-directories/docs/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/valid-registry-directories/docs/nonregistrydocs/valid.md b/internal/provider/testdata/valid-registry-directories/docs/nonregistrydocs/valid.md deleted file mode 100644 index a7f1fce..0000000 --- a/internal/provider/testdata/valid-registry-directories/docs/nonregistrydocs/valid.md +++ /dev/null @@ -1,3 +0,0 @@ -# Valid - -Files in `/docs`, but outside Registry documentation directories, should be ignored. diff --git a/internal/provider/testdata/valid-registry-directories/docs/resources/thing.md b/internal/provider/testdata/valid-registry-directories/docs/resources/thing.md deleted file mode 100644 index aa156f3..0000000 --- a/internal/provider/testdata/valid-registry-directories/docs/resources/thing.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-files/2.0-guide.md b/internal/provider/testdata/valid-registry-files/2.0-guide.md deleted file mode 100644 index 9acc401..0000000 --- a/internal/provider/testdata/valid-registry-files/2.0-guide.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/valid-registry-files/data_source.md b/internal/provider/testdata/valid-registry-files/data_source.md deleted file mode 100644 index 688fa59..0000000 --- a/internal/provider/testdata/valid-registry-files/data_source.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Data Source: example_thing - -Byline. - -## Example Usage - -```terraform -data "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/testdata/valid-registry-files/guide.md b/internal/provider/testdata/valid-registry-files/guide.md deleted file mode 100644 index 9acc401..0000000 --- a/internal/provider/testdata/valid-registry-files/guide.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Example Guide - -Example contents. diff --git a/internal/provider/testdata/valid-registry-files/index.md b/internal/provider/testdata/valid-registry-files/index.md deleted file mode 100644 index 9daab15..0000000 --- a/internal/provider/testdata/valid-registry-files/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -page_title: "Example Provider" -description: |- - Example description. ---- - -# Example Provider - -Example contents. diff --git a/internal/provider/testdata/valid-registry-files/resource.md b/internal/provider/testdata/valid-registry-files/resource.md deleted file mode 100644 index aa156f3..0000000 --- a/internal/provider/testdata/valid-registry-files/resource.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -subcategory: "Example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/validate.go b/internal/provider/validate.go index 4f1d796..241a628 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -25,7 +25,7 @@ const ( FileExtensionMarkdown = `.markdown` FileExtensionMd = `.md` - DocumentationGlobPattern = `{docs/index.md,docs/{,cdktf/}{data-sources,guides,resources,functions}/**/*,website/docs/**/*}` + DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{data-sources,guides,resources,functions}/**/*,website/docs/**/*}` DocumentationDirGlobPattern = `{docs/{,cdktf/}{data-sources,guides,resources,functions}{,/*},website/docs/**/*}` ) @@ -55,13 +55,6 @@ var LegacyIndexFrontMatterOptions = &check.FrontMatterOptions{ RequirePageTitle: true, } -var LegacyGuideFrontMatterOptions = &check.FrontMatterOptions{ - NoSidebarCurrent: true, - RequireDescription: true, - RequireLayout: true, - RequirePageTitle: true, -} - var RegistryFrontMatterOptions = &check.FrontMatterOptions{ NoLayout: true, NoSidebarCurrent: true, @@ -226,15 +219,15 @@ func (v *validator) validateStaticDocs(dir string) error { } // Configure FrontMatterOptions based on file type - if d.Name() == "index.md" { + if removeAllExt(d.Name()) == "index" { options.FrontMatter = RegistryIndexFrontMatterOptions - } else if _, relErr := filepath.Rel(path, "guides"); relErr != nil { + } else if _, relErr := filepath.Rel(filepath.Join(dir, "guides"), path); relErr == nil { options.FrontMatter = RegistryGuideFrontMatterOptions } else { options.FrontMatter = RegistryFrontMatterOptions } v.logger.infof("running file checks on %s", path) - result = errors.Join(result, check.NewProviderFileCheck(options).Run(path)) + result = errors.Join(result, check.NewProviderFileCheck(v.providerFS, options).Run(path)) files = append(files, path) return nil @@ -249,15 +242,15 @@ func (v *validator) validateStaticDocs(dir string) error { } if dirExists(v.providerFS, filepath.Join(dir, "data-sources")) { - dataSourceFiles, _ := os.ReadDir(filepath.Join(dir, "data-sources")) + dataSourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "data-sources")) mismatchOpt.DatasourceEntries = dataSourceFiles } if dirExists(v.providerFS, filepath.Join(dir, "resources")) { - resourceFiles, _ := os.ReadDir(filepath.Join(dir, "resources")) + resourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "resources")) mismatchOpt.ResourceEntries = resourceFiles } if dirExists(v.providerFS, filepath.Join(dir, "functions")) { - functionFiles, _ := os.ReadDir(filepath.Join(dir, "functions")) + functionFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "functions")) mismatchOpt.FunctionEntries = functionFiles } @@ -307,15 +300,13 @@ func (v *validator) validateLegacyWebsite(dir string) error { } // Configure FrontMatterOptions based on file type - if d.Name() == "index.md" { + if removeAllExt(d.Name()) == "index" { options.FrontMatter = LegacyIndexFrontMatterOptions - } else if _, relErr := filepath.Rel(path, "guides"); relErr != nil { - options.FrontMatter = LegacyGuideFrontMatterOptions } else { options.FrontMatter = LegacyFrontMatterOptions } v.logger.infof("running file checks on %s", path) - result = errors.Join(result, check.NewProviderFileCheck(options).Run(path)) + result = errors.Join(result, check.NewProviderFileCheck(v.providerFS, options).Run(path)) files = append(files, path) return nil diff --git a/internal/provider/validate_test.go b/internal/provider/validate_test.go index c94d210..3458f8a 100644 --- a/internal/provider/validate_test.go +++ b/internal/provider/validate_test.go @@ -4,32 +4,170 @@ package provider import ( - "os" + "bytes" + "io/fs" "path/filepath" "testing" + "testing/fstest" "github.com/bmatcuk/doublestar/v4" + "github.com/google/go-cmp/cmp" "github.com/hashicorp/cli" + "gopkg.in/yaml.v3" ) -func TestValidateStaticDocs(t *testing.T) { +// FrontMatterData represents the YAML frontmatter of Terraform Provider documentation. +type FrontMatterData struct { + Description *string `yaml:"description,omitempty"` + Layout *string `yaml:"layout,omitempty"` + PageTitle *string `yaml:"page_title,omitempty"` + SidebarCurrent *string `yaml:"sidebar_current,omitempty"` + Subcategory *string `yaml:"subcategory,omitempty"` +} + +var exampleDescription = "Example description." +var exampleLayout = "Example Layout" +var examplePageTitle = "Example Page Title" +var exampleSidebarCurrent = "Example Sidebar Current" +var exampleSubcategory = "Example Subcategory" + +var ValidRegistryResourceFrontMatter = FrontMatterData{ + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, +} + +var ValidLegacyResourceFrontMatter = FrontMatterData{ + Subcategory: &exampleSubcategory, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, +} + +var ValidRegistryIndexFrontMatter = FrontMatterData{ + PageTitle: &examplePageTitle, + Description: &exampleDescription, +} + +var ValidLegacyIndexFrontMatter = FrontMatterData{ + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, +} + +var ValidRegistryGuideFrontMatter = FrontMatterData{ + PageTitle: &examplePageTitle, +} + +var ValidLegacyGuideFrontMatter = FrontMatterData{ + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, +} + +var InvalidYAMLFrontMatter = fstest.MapFile{ + Data: []byte("---\nsubcategory: \"Example\"\npage_title: \"Example: example_thing\"\ndescription: |-\nMissing indentation.\n---\n"), +} + +func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { t.Parallel() testCases := map[string]struct { - BasePath string - ExpectError bool + ProviderFS fs.FS ExpectedError string }{ "valid registry directories": { - BasePath: filepath.Join("testdata", "valid-registry-directories"), + ProviderFS: fstest.MapFS{ + "docs/data-sources/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/functions/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/guides/thing.md": { + Data: encodeYAML(t, &ValidRegistryGuideFrontMatter), + }, + "docs/nonregistrydocs/valid.md": { + Data: []byte("non-registry documentation"), + }, + "docs/resources/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/CONTRIBUTING.md": { + Data: []byte("contribution guidelines"), + }, + "docs/index.md": { + Data: encodeYAML(t, &ValidRegistryIndexFrontMatter), + }, + }, }, - "valid registry directories with cdktf docs": { - BasePath: filepath.Join("testdata", "valid-registry-directories-with-cdktf"), + ProviderFS: fstest.MapFS{ + "docs/cdktf/typescript/data-sources/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/cdktf/typescirpt/guides/thing.md": { + Data: encodeYAML(t, &ValidRegistryGuideFrontMatter), + }, + "docs/cdktf/typescript/nonregistrydocs/valid.md": { + Data: []byte("non-registry documentation"), + }, + "docs/cdktf/typescript/resources/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/cdktf/typescript/CONTRIBUTING.md": { + Data: []byte("contribution guidelines"), + }, + "docs/cdktf/typescript/index.md": { + Data: encodeYAML(t, &ValidRegistryIndexFrontMatter), + }, + "docs/data-sources/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/guides/thing.md": { + Data: encodeYAML(t, &ValidRegistryGuideFrontMatter), + }, + "docs/nonregistrydocs/valid.md": { + Data: []byte("non-registry documentation"), + }, + "docs/resources/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/CONTRIBUTING.md": { + Data: []byte("contribution guidelines"), + }, + "docs/index.md": { + Data: encodeYAML(t, &ValidRegistryIndexFrontMatter), + }, + }, }, "invalid registry directories": { - BasePath: filepath.Join("testdata", "invalid-registry-directories"), - ExpectError: true, - ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("docs", "resources", "invalid"), + ProviderFS: fstest.MapFS{ + "docs/data-sources/invalid/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/guides/invalid/thing.md": { + Data: encodeYAML(t, &ValidRegistryGuideFrontMatter), + }, + "docs/nonregistrydocs/valid.md": { + Data: []byte("non-registry documentation"), + }, + "docs/functions/invalid/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/resources/invalid/thing.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/CONTRIBUTING.md": { + Data: []byte("contribution guidelines"), + }, + "docs/index.md": { + Data: encodeYAML(t, &ValidRegistryIndexFrontMatter), + }, + }, + ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("docs", "data-sources", "invalid") + + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "functions", "invalid") + + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "guides", "invalid") + + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("docs", "resources", "invalid"), }, } @@ -39,48 +177,292 @@ func TestValidateStaticDocs(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - providerFs := os.DirFS(testCase.BasePath) v := &validator{ - providerFS: providerFs, - providerDir: testCase.BasePath, + providerFS: testCase.ProviderFS, providerName: "terraform-provider-test", logger: NewLogger(cli.NewMockUi()), } got := v.validateStaticDocs("docs") - if got == nil && testCase.ExpectError { - t.Errorf("expected error, got no error") + if got != nil && got.Error() != testCase.ExpectedError { + t.Errorf("expected error: %s, got error: %s", testCase.ExpectedError, got) } + }) + } +} - if got != nil && !testCase.ExpectError { - t.Errorf("expected no error, got error: %s", got) +func TestValidateStaticDocs_FileChecks(t *testing.T) { + t.Parallel() + testCases := map[string]struct { + ProviderFS fs.FS + ExpectedError string + }{ + "invalid data source files": { + ProviderFS: fstest.MapFS{ + "docs/data-sources/invalid_extension.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/data-sources/invalid_frontmatter.md": &InvalidYAMLFrontMatter, + "docs/data-sources/with_layout.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "docs/data-sources/with_sidebar_current.md": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "data-sources", "invalid_extension.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.md]\n" + + filepath.Join("docs", "data-sources", "invalid_frontmatter.md") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("docs", "data-sources", "with_layout.md") + ": error checking file frontmatter: YAML frontmatter should not contain layout\n" + + filepath.Join("docs", "data-sources", "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": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/resources/invalid_frontmatter.md": &InvalidYAMLFrontMatter, + "docs/resources/with_layout.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "docs/resources/with_sidebar_current.md": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "resources", "invalid_extension.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.md]\n" + + filepath.Join("docs", "resources", "invalid_frontmatter.md") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("docs", "resources", "with_layout.md") + ": error checking file frontmatter: YAML frontmatter should not contain layout\n" + + filepath.Join("docs", "resources", "with_sidebar_current.md") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current", + }, + "invalid guide files": { + ProviderFS: fstest.MapFS{ + "docs/guides/invalid_extension.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/guides/invalid_frontmatter.md": &InvalidYAMLFrontMatter, + "docs/guides/with_layout.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "docs/guides/with_sidebar_current.md": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "docs/guides/without_page_title.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Subcategory: &exampleSubcategory, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "guides", "invalid_extension.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.md]\n" + + filepath.Join("docs", "guides", "invalid_frontmatter.md") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("docs", "guides", "with_layout.md") + ": error checking file frontmatter: YAML frontmatter should not contain layout\n" + + filepath.Join("docs", "guides", "with_sidebar_current.md") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current\n" + + filepath.Join("docs", "guides", "without_page_title.md") + ": error checking file frontmatter: YAML frontmatter missing required page_title", + }, + "invalid index file - invalid extension": { + ProviderFS: fstest.MapFS{ + "docs/index.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + }, + ExpectedError: filepath.Join("docs", "index.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.md]", + }, + "invalid index file - invalid frontmatter": { + ProviderFS: fstest.MapFS{ + "docs/index.md": &InvalidYAMLFrontMatter, + }, + ExpectedError: filepath.Join("docs", "index.md") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'", + }, + "invalid index file - with layout": { + ProviderFS: fstest.MapFS{ + "docs/index.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "index.md") + ": error checking file frontmatter: YAML frontmatter should not contain layout", + }, + "invalid index file - with sidebar current": { + ProviderFS: fstest.MapFS{ + "docs/index.md": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "index.md") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current", + }, + "invalid index file - with subcategory": { + ProviderFS: fstest.MapFS{ + "docs/index.md": { + Data: encodeYAML(t, + &FrontMatterData{ + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("docs", "index.md") + ": error checking file frontmatter: YAML frontmatter should not contain subcategory", + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + v := &validator{ + providerFS: testCase.ProviderFS, + providerName: "terraform-provider-test", + + logger: NewLogger(cli.NewMockUi()), } + got := v.validateStaticDocs("docs") - if got != nil && got.Error() != testCase.ExpectedError { - t.Errorf("expected error: %s, got error: %s", testCase.ExpectedError, got) + if got == nil && testCase.ExpectedError != "" { + t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) + } + + if diff := cmp.Diff(got.Error(), testCase.ExpectedError); diff != "" { + t.Errorf("Unexpected response (+wanted, -got): %s", diff) } }) } } -func TestValidateLegacyWebsite(t *testing.T) { +func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { t.Parallel() testCases := map[string]struct { - BasePath string + ProviderFS fs.FS ExpectError bool ExpectedError string }{ "valid legacy directories": { - BasePath: filepath.Join("testdata", "valid-legacy-directories"), + ProviderFS: fstest.MapFS{ + "website/docs/d/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/functions/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/guides/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyGuideFrontMatter), + }, + "website/docs/r/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/index.html.markdown": { + Data: encodeYAML(t, &ValidLegacyIndexFrontMatter), + }, + }, }, "valid legacy directories with cdktf docs": { - BasePath: filepath.Join("testdata", "valid-legacy-directories-with-cdktf"), + ProviderFS: fstest.MapFS{ + "website/docs/cdktf/typescript/d/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/cdktf/typescript/guides/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyGuideFrontMatter), + }, + "website/docs/cdktf/typescript/r/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/cdktf/typescript/index.html.markdown": { + Data: encodeYAML(t, &ValidLegacyIndexFrontMatter), + }, + "website/docs/d/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/guides/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyGuideFrontMatter), + }, + "website/docs/r/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/index.html.markdown": { + Data: encodeYAML(t, &ValidLegacyIndexFrontMatter), + }, + }, }, "invalid legacy directories": { - BasePath: filepath.Join("testdata", "invalid-legacy-directories"), - ExpectError: true, - ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "r", "invalid"), + ProviderFS: fstest.MapFS{ + "website/docs/d/invalid/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/functions/invalid/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/guides/invalid/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyGuideFrontMatter), + }, + "website/docs/r/invalid/thing.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/index.html.markdown": { + Data: encodeYAML(t, &ValidLegacyIndexFrontMatter), + }, + }, + ExpectError: true, + ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "d", "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") + + "\ninvalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "r", "invalid"), }, } @@ -90,15 +472,12 @@ func TestValidateLegacyWebsite(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - providerFs := os.DirFS(testCase.BasePath) v := &validator{ - providerFS: providerFs, - providerDir: testCase.BasePath, + providerFS: testCase.ProviderFS, providerName: "terraform-provider-test", logger: NewLogger(cli.NewMockUi()), } - got := v.validateLegacyWebsite("website/docs") if got == nil && testCase.ExpectError { @@ -116,6 +495,208 @@ func TestValidateLegacyWebsite(t *testing.T) { } } +func TestValidateLegacyWebsite_FileChecks(t *testing.T) { + t.Parallel() + testCases := map[string]struct { + ProviderFS fs.FS + ExpectedError string + }{ + "invalid data source files": { + ProviderFS: fstest.MapFS{ + "website/docs/d/invalid_extension.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "website/docs/d/invalid_frontmatter.html.markdown": &InvalidYAMLFrontMatter, + "website/docs/d/without_layout.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "website/docs/d/with_sidebar_current.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "d", "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", "d", "invalid_frontmatter.html.markdown") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("website", "docs", "d", "with_sidebar_current.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current\n" + + filepath.Join("website", "docs", "d", "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": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "website/docs/r/invalid_frontmatter.html.markdown": &InvalidYAMLFrontMatter, + "website/docs/r/without_layout.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + Subcategory: &exampleSubcategory, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "website/docs/r/with_sidebar_current.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Subcategory: &exampleSubcategory, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "r", "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", "r", "invalid_frontmatter.html.markdown") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("website", "docs", "r", "with_sidebar_current.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current\n" + + filepath.Join("website", "docs", "r", "without_layout.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required layout", + }, + "invalid guide files": { + ProviderFS: fstest.MapFS{ + "website/docs/guides/invalid_extension.txt": { + Data: encodeYAML(t, &ValidLegacyGuideFrontMatter), + }, + "website/docs/guides/invalid_frontmatter.html.markdown": &InvalidYAMLFrontMatter, + "website/docs/guides/with_sidebar_current.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "website/docs/guides/without_description.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + }, + ), + }, + "website/docs/guides/without_layout.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + "website/docs/guides/without_page_title.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + Layout: &exampleLayout, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "guides", "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", "guides", "invalid_frontmatter.html.markdown") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'\n" + + filepath.Join("website", "docs", "guides", "with_sidebar_current.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current\n" + + filepath.Join("website", "docs", "guides", "without_description.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required description\n" + + filepath.Join("website", "docs", "guides", "without_layout.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required layout\n" + + filepath.Join("website", "docs", "guides", "without_page_title.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required page_title", + }, + "invalid index file - invalid extension": { + ProviderFS: fstest.MapFS{ + "website/docs/index.txt": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + }, + ExpectedError: filepath.Join("website", "docs", "index.txt") + ": error checking file extension: file does not end with a valid extension, valid extensions: [.html.markdown .html.md .markdown .md]", + }, + "invalid index file - invalid frontmatter": { + ProviderFS: fstest.MapFS{ + "website/docs/index.html.markdown": &InvalidYAMLFrontMatter, + }, + ExpectedError: filepath.Join("website", "docs", "index.html.markdown") + ": error checking file frontmatter: error parsing YAML frontmatter: yaml: line 4: could not find expected ':'", + }, + "invalid index file - with sidebar current": { + ProviderFS: fstest.MapFS{ + "website/docs/index.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + SidebarCurrent: &exampleSidebarCurrent, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "index.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain sidebar_current", + }, + "invalid index file - with subcategory": { + ProviderFS: fstest.MapFS{ + "website/docs/index.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + Subcategory: &exampleSubcategory, + Layout: &exampleLayout, + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "index.html.markdown") + ": error checking file frontmatter: YAML frontmatter should not contain subcategory", + }, + "invalid index file - without layout": { + ProviderFS: fstest.MapFS{ + "website/docs/index.html.markdown": { + Data: encodeYAML(t, + &FrontMatterData{ + PageTitle: &examplePageTitle, + Description: &exampleDescription, + }, + ), + }, + }, + ExpectedError: filepath.Join("website", "docs", "index.html.markdown") + ": error checking file frontmatter: YAML frontmatter missing required layout", + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + v := &validator{ + providerFS: testCase.ProviderFS, + providerName: "terraform-provider-test", + + logger: NewLogger(cli.NewMockUi()), + } + got := v.validateLegacyWebsite("website/docs") + + if got == nil && testCase.ExpectedError != "" { + t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) + } + + if diff := cmp.Diff(got.Error(), testCase.ExpectedError); diff != "" { + t.Errorf("Unexpected response (+wanted, -got): %s", diff) + } + }) + } +} + func TestDocumentationDirGlobPattern(t *testing.T) { t.Parallel() testCases := map[string]struct { @@ -170,3 +751,15 @@ func TestDocumentationDirGlobPattern(t *testing.T) { }) } } + +func encodeYAML(t *testing.T, data *FrontMatterData) []byte { + t.Helper() + var buf bytes.Buffer + buf.Write([]byte("---\n")) + err := yaml.NewEncoder(&buf).Encode(data) + if err != nil { + t.Fatalf("error encoding YAML: %s", err) + } + buf.Write([]byte("---\n")) + return buf.Bytes() +} From 04f4b59a013c62d6e4686765d18dd660fcb68238 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 14:05:46 -0400 Subject: [PATCH 03/14] Refactor `directory_test.go` to use `fstest.MapFS` --- internal/check/directory_test.go | 86 ++++++++++++++++--- .../docs/resources/thing.md | 27 ------ .../website/docs/r/thing.html.markdown | 0 .../docs/CONTRIBUTING.md | 3 - .../docs/nonregistrydocs/valid.md | 3 - .../website/docs/r/thing.html.markdown | 27 ------ internal/provider/validate_test.go | 26 +++--- 7 files changed, 88 insertions(+), 84 deletions(-) delete mode 100644 internal/check/testdata/invalid-mixed-directories/docs/resources/thing.md delete mode 100644 internal/check/testdata/invalid-mixed-directories/website/docs/r/thing.html.markdown delete mode 100644 internal/check/testdata/valid-mixed-directories/docs/CONTRIBUTING.md delete mode 100644 internal/check/testdata/valid-mixed-directories/docs/nonregistrydocs/valid.md delete mode 100644 internal/check/testdata/valid-mixed-directories/website/docs/r/thing.html.markdown diff --git a/internal/check/directory_test.go b/internal/check/directory_test.go index 2966071..95c6f8a 100644 --- a/internal/check/directory_test.go +++ b/internal/check/directory_test.go @@ -4,26 +4,94 @@ package check import ( - "os" - "path/filepath" + "io/fs" "testing" + "testing/fstest" "github.com/bmatcuk/doublestar/v4" ) -var DocumentationGlobPattern = `{docs/index.md,docs/{,cdktf/}{data-sources,guides,resources,functions}/**/*,website/docs/**/*}` +var DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{data-sources,guides,resources,functions}/**/*,website/docs/**/*}` func TestMixedDirectoriesCheck(t *testing.T) { t.Parallel() testCases := map[string]struct { - BasePath string + ProviderFS fs.FS ExpectError bool }{ "valid mixed directories": { - BasePath: filepath.Join("testdata", "valid-mixed-directories"), + ProviderFS: fstest.MapFS{ + "docs/nonregistrydocs/thing.md": {}, + "website/docs/index.md": {}, + }, }, - "invalid mixed directories": { - BasePath: filepath.Join("testdata", "invalid-mixed-directories"), + "valid mixed directories - cdktf": { + ProviderFS: fstest.MapFS{ + "docs/cdktf/typescript/index.md": {}, + "website/docs/index.md": {}, + }, + }, + "invalid mixed directories - registry data source": { + ProviderFS: fstest.MapFS{ + "docs/data-sources/invalid.md": {}, + "website/docs/index.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - registry resource": { + ProviderFS: fstest.MapFS{ + "docs/resources/invalid.md": {}, + "website/docs/index.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - registry guide": { + ProviderFS: fstest.MapFS{ + "docs/guides/invalid.md": {}, + "website/docs/index.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - registry function": { + ProviderFS: fstest.MapFS{ + "docs/functions/invalid.md": {}, + "website/docs/index.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - legacy data source": { + ProviderFS: fstest.MapFS{ + "website/docs/d/invalid.html.markdown": {}, + "docs/resources/thing.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - legacy resource": { + ProviderFS: fstest.MapFS{ + "website/docs/r/invalid.html.markdown": {}, + "docs/resources/thing.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - legacy guide": { + ProviderFS: fstest.MapFS{ + "website/docs/guides/invalid.html.markdown": {}, + "docs/resources/thing.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - legacy function": { + ProviderFS: fstest.MapFS{ + "website/docs/functions/invalid.html.markdown": {}, + "docs/resources/thing.md": {}, + }, + ExpectError: true, + }, + "invalid mixed directories - legacy index": { + ProviderFS: fstest.MapFS{ + "website/docs/index.html.markdown": {}, + "docs/resources/thing.md": {}, + }, ExpectError: true, }, } @@ -34,9 +102,7 @@ func TestMixedDirectoriesCheck(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - providerFs := os.DirFS(testCase.BasePath) - - files, err := doublestar.Glob(providerFs, DocumentationGlobPattern) + files, err := doublestar.Glob(testCase.ProviderFS, DocumentationGlobPattern) if err != nil { t.Fatalf("error finding documentation files: %s", err) } diff --git a/internal/check/testdata/invalid-mixed-directories/docs/resources/thing.md b/internal/check/testdata/invalid-mixed-directories/docs/resources/thing.md deleted file mode 100644 index 59bb04c..0000000 --- a/internal/check/testdata/invalid-mixed-directories/docs/resources/thing.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/check/testdata/invalid-mixed-directories/website/docs/r/thing.html.markdown b/internal/check/testdata/invalid-mixed-directories/website/docs/r/thing.html.markdown deleted file mode 100644 index e69de29..0000000 diff --git a/internal/check/testdata/valid-mixed-directories/docs/CONTRIBUTING.md b/internal/check/testdata/valid-mixed-directories/docs/CONTRIBUTING.md deleted file mode 100644 index 423305c..0000000 --- a/internal/check/testdata/valid-mixed-directories/docs/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributing Guide - -This file has contents and no YAML frontmatter, because it is not a Terraform Provider documentation file and that is okay. diff --git a/internal/check/testdata/valid-mixed-directories/docs/nonregistrydocs/valid.md b/internal/check/testdata/valid-mixed-directories/docs/nonregistrydocs/valid.md deleted file mode 100644 index a7f1fce..0000000 --- a/internal/check/testdata/valid-mixed-directories/docs/nonregistrydocs/valid.md +++ /dev/null @@ -1,3 +0,0 @@ -# Valid - -Files in `/docs`, but outside Registry documentation directories, should be ignored. diff --git a/internal/check/testdata/valid-mixed-directories/website/docs/r/thing.html.markdown b/internal/check/testdata/valid-mixed-directories/website/docs/r/thing.html.markdown deleted file mode 100644 index 59bb04c..0000000 --- a/internal/check/testdata/valid-mixed-directories/website/docs/r/thing.html.markdown +++ /dev/null @@ -1,27 +0,0 @@ ---- -subcategory: "Example" -layout: "example" -page_title: "Example: example_thing" -description: |- - Example description. ---- - -# Resource: example_thing - -Byline. - -## Example Usage - -```terraform -resource "example_thing" "example" { - name = "example" -} -``` - -## Argument Reference - -* `name` - (Required) Name of thing. - -## Attribute Reference - -* `id` - Name of thing. diff --git a/internal/provider/validate_test.go b/internal/provider/validate_test.go index 3458f8a..3e8d8ae 100644 --- a/internal/provider/validate_test.go +++ b/internal/provider/validate_test.go @@ -185,8 +185,12 @@ func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { } got := v.validateStaticDocs("docs") + if got == nil && testCase.ExpectedError != "" { + t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) + } + if got != nil && got.Error() != testCase.ExpectedError { - t.Errorf("expected error: %s, got error: %s", testCase.ExpectedError, got) + t.Errorf("Unexpected response (+wanted, -got): %s", cmp.Diff(testCase.ExpectedError, got.Error())) } }) } @@ -379,8 +383,8 @@ func TestValidateStaticDocs_FileChecks(t *testing.T) { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) } - if diff := cmp.Diff(got.Error(), testCase.ExpectedError); diff != "" { - t.Errorf("Unexpected response (+wanted, -got): %s", diff) + if got != nil && got.Error() != testCase.ExpectedError { + t.Errorf("Unexpected response (+wanted, -got): %s", cmp.Diff(testCase.ExpectedError, got.Error())) } }) } @@ -390,7 +394,6 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { t.Parallel() testCases := map[string]struct { ProviderFS fs.FS - ExpectError bool ExpectedError string }{ "valid legacy directories": { @@ -458,7 +461,6 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { Data: encodeYAML(t, &ValidLegacyIndexFrontMatter), }, }, - ExpectError: true, ExpectedError: "invalid Terraform Provider documentation directory found: " + filepath.Join("website", "docs", "d", "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") + @@ -480,16 +482,12 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { } got := v.validateLegacyWebsite("website/docs") - if got == nil && testCase.ExpectError { - t.Errorf("expected error, got no error") - } - - if got != nil && !testCase.ExpectError { - t.Errorf("expected no error, got error: %s", got) + if got == nil && testCase.ExpectedError != "" { + t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) } if got != nil && got.Error() != testCase.ExpectedError { - t.Errorf("expected error: %s, got error: %s", testCase.ExpectedError, got) + t.Errorf("Unexpected response (+wanted, -got): %s", cmp.Diff(testCase.ExpectedError, got.Error())) } }) } @@ -690,8 +688,8 @@ func TestValidateLegacyWebsite_FileChecks(t *testing.T) { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) } - if diff := cmp.Diff(got.Error(), testCase.ExpectedError); diff != "" { - t.Errorf("Unexpected response (+wanted, -got): %s", diff) + if got != nil && got.Error() != testCase.ExpectedError { + t.Errorf("Unexpected response (+wanted, -got): %s", cmp.Diff(testCase.ExpectedError, got.Error())) } }) } From 71cb71da88fe913c2470b0d31202d08faf9f016b Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 15:43:20 -0400 Subject: [PATCH 04/14] Add tests for file mismatch check --- internal/provider/validate_test.go | 251 +++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) diff --git a/internal/provider/validate_test.go b/internal/provider/validate_test.go index 3e8d8ae..97386c4 100644 --- a/internal/provider/validate_test.go +++ b/internal/provider/validate_test.go @@ -13,6 +13,7 @@ import ( "github.com/bmatcuk/doublestar/v4" "github.com/google/go-cmp/cmp" "github.com/hashicorp/cli" + tfjson "github.com/hashicorp/terraform-json" "gopkg.in/yaml.v3" ) @@ -390,6 +391,131 @@ func TestValidateStaticDocs_FileChecks(t *testing.T) { } } +func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { + t.Parallel() + testCases := map[string]struct { + ProviderFS fs.FS + ProviderSchema *tfjson.ProviderSchema + ExpectedError string + }{ + "valid - no mismatch": { + ProviderSchema: &tfjson.ProviderSchema{ + DataSourceSchemas: map[string]*tfjson.Schema{ + "test_pet": {}, + }, + ResourceSchemas: map[string]*tfjson.Schema{ + "test_id": {}, + }, + Functions: map[string]*tfjson.FunctionSignature{ + "parse_id": {}, + }, + }, + ProviderFS: fstest.MapFS{ + "docs/data-sources/pet.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/functions/parse_id.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/resources/id.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + }, + }, + "invalid - missing files": { + ProviderSchema: &tfjson.ProviderSchema{ + DataSourceSchemas: map[string]*tfjson.Schema{ + "test_pet": {}, + "test_pet2": {}, + }, + ResourceSchemas: map[string]*tfjson.Schema{ + "test_id": {}, + "test_id2": {}, + }, + Functions: map[string]*tfjson.FunctionSignature{ + "parse_id": {}, + "parse_id2": {}, + }, + }, + ProviderFS: fstest.MapFS{ + "docs/data-sources/pet.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/functions/parse_id.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/resources/id.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + }, + ExpectedError: "missing documentation file for resource: test_id2\n" + + "missing documentation file for datasource: test_pet2\n" + + "missing documentation file for function: parse_id2", + }, + "invalid - extra files": { + ProviderSchema: &tfjson.ProviderSchema{ + DataSourceSchemas: map[string]*tfjson.Schema{ + "test_pet": {}, + }, + ResourceSchemas: map[string]*tfjson.Schema{ + "test_id": {}, + }, + Functions: map[string]*tfjson.FunctionSignature{ + "parse_id": {}, + }, + }, + ProviderFS: fstest.MapFS{ + "docs/data-sources/pet.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/data-sources/pet2.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/functions/parse_id.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/functions/parse_id2.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/resources/id.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + "docs/resources/id2.md": { + Data: encodeYAML(t, &ValidRegistryResourceFrontMatter), + }, + }, + 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", + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + v := &validator{ + providerSchema: testCase.ProviderSchema, + providerFS: testCase.ProviderFS, + providerName: "terraform-provider-test", + + logger: NewLogger(cli.NewMockUi()), + } + got := v.validateStaticDocs("docs") + + if got == nil && testCase.ExpectedError != "" { + t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) + } + + if got != nil && got.Error() != testCase.ExpectedError { + t.Errorf("Unexpected response (+wanted, -got): %s", cmp.Diff(testCase.ExpectedError, got.Error())) + } + }) + } +} + func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { t.Parallel() testCases := map[string]struct { @@ -695,6 +821,131 @@ func TestValidateLegacyWebsite_FileChecks(t *testing.T) { } } +func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { + t.Parallel() + testCases := map[string]struct { + ProviderFS fs.FS + ProviderSchema *tfjson.ProviderSchema + ExpectedError string + }{ + "valid - no mismatch": { + ProviderSchema: &tfjson.ProviderSchema{ + DataSourceSchemas: map[string]*tfjson.Schema{ + "test_pet": {}, + }, + ResourceSchemas: map[string]*tfjson.Schema{ + "test_id": {}, + }, + Functions: map[string]*tfjson.FunctionSignature{ + "parse_id": {}, + }, + }, + ProviderFS: fstest.MapFS{ + "website/docs/d/pet.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/functions/parse_id.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/r/id.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + }, + }, + "invalid - missing files": { + ProviderSchema: &tfjson.ProviderSchema{ + DataSourceSchemas: map[string]*tfjson.Schema{ + "test_pet": {}, + "test_pet2": {}, + }, + ResourceSchemas: map[string]*tfjson.Schema{ + "test_id": {}, + "test_id2": {}, + }, + Functions: map[string]*tfjson.FunctionSignature{ + "parse_id": {}, + "parse_id2": {}, + }, + }, + ProviderFS: fstest.MapFS{ + "website/docs/d/pet.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/functions/parse_id.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/r/id.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + }, + ExpectedError: "missing documentation file for resource: test_id2\n" + + "missing documentation file for datasource: test_pet2\n" + + "missing documentation file for function: parse_id2", + }, + "invalid - extra files": { + ProviderSchema: &tfjson.ProviderSchema{ + DataSourceSchemas: map[string]*tfjson.Schema{ + "test_pet": {}, + }, + ResourceSchemas: map[string]*tfjson.Schema{ + "test_id": {}, + }, + Functions: map[string]*tfjson.FunctionSignature{ + "parse_id": {}, + }, + }, + ProviderFS: fstest.MapFS{ + "website/docs/d/pet.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/d/pet2.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/functions/parse_id.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/functions/parse_id2.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/r/id.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + "website/docs/r/id2.html.markdown": { + Data: encodeYAML(t, &ValidLegacyResourceFrontMatter), + }, + }, + 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", + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + v := &validator{ + providerSchema: testCase.ProviderSchema, + providerFS: testCase.ProviderFS, + providerName: "terraform-provider-test", + + logger: NewLogger(cli.NewMockUi()), + } + got := v.validateLegacyWebsite("website/docs") + + if got == nil && testCase.ExpectedError != "" { + t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) + } + + if got != nil && got.Error() != testCase.ExpectedError { + t.Errorf("Unexpected response (+wanted, -got): %s", cmp.Diff(testCase.ExpectedError, got.Error())) + } + }) + } +} + func TestDocumentationDirGlobPattern(t *testing.T) { t.Parallel() testCases := map[string]struct { From 886487348060a60f769f86855c963f71de434fd9 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 16:35:38 -0400 Subject: [PATCH 05/14] Fix `unparam` lints --- internal/provider/validate.go | 12 ++++++------ internal/provider/validate_test.go | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/provider/validate.go b/internal/provider/validate.go index 241a628..9500354 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -168,21 +168,21 @@ func (v *validator) validate(ctx context.Context) error { if dirExists(v.providerFS, "docs") { v.logger.infof("detected static docs directory, running checks") - err = v.validateStaticDocs("docs") + err = v.validateStaticDocs() result = errors.Join(result, err) } if dirExists(v.providerFS, "website/docs") { v.logger.infof("detected legacy website directory, running checks") - err = v.validateLegacyWebsite("website/docs") + err = v.validateLegacyWebsite() result = errors.Join(result, err) } return result } -func (v *validator) validateStaticDocs(dir string) error { - +func (v *validator) validateStaticDocs() error { + dir := "docs" var result error options := &check.ProviderFileOptions{ @@ -262,8 +262,8 @@ func (v *validator) validateStaticDocs(dir string) error { return result } -func (v *validator) validateLegacyWebsite(dir string) error { - +func (v *validator) validateLegacyWebsite() error { + dir := "website/docs" var result error options := &check.ProviderFileOptions{ diff --git a/internal/provider/validate_test.go b/internal/provider/validate_test.go index 97386c4..a6ada21 100644 --- a/internal/provider/validate_test.go +++ b/internal/provider/validate_test.go @@ -184,7 +184,7 @@ func TestValidateStaticDocs_DirectoryChecks(t *testing.T) { logger: NewLogger(cli.NewMockUi()), } - got := v.validateStaticDocs("docs") + got := v.validateStaticDocs() if got == nil && testCase.ExpectedError != "" { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) @@ -378,7 +378,7 @@ func TestValidateStaticDocs_FileChecks(t *testing.T) { logger: NewLogger(cli.NewMockUi()), } - got := v.validateStaticDocs("docs") + got := v.validateStaticDocs() if got == nil && testCase.ExpectedError != "" { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) @@ -503,7 +503,7 @@ func TestValidateStaticDocs_FileMismatchCheck(t *testing.T) { logger: NewLogger(cli.NewMockUi()), } - got := v.validateStaticDocs("docs") + got := v.validateStaticDocs() if got == nil && testCase.ExpectedError != "" { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) @@ -606,7 +606,7 @@ func TestValidateLegacyWebsite_DirectoryChecks(t *testing.T) { logger: NewLogger(cli.NewMockUi()), } - got := v.validateLegacyWebsite("website/docs") + got := v.validateLegacyWebsite() if got == nil && testCase.ExpectedError != "" { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) @@ -808,7 +808,7 @@ func TestValidateLegacyWebsite_FileChecks(t *testing.T) { logger: NewLogger(cli.NewMockUi()), } - got := v.validateLegacyWebsite("website/docs") + got := v.validateLegacyWebsite() if got == nil && testCase.ExpectedError != "" { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) @@ -933,7 +933,7 @@ func TestValidateLegacyWebsite_FileMismatchCheck(t *testing.T) { logger: NewLogger(cli.NewMockUi()), } - got := v.validateLegacyWebsite("website/docs") + got := v.validateLegacyWebsite() if got == nil && testCase.ExpectedError != "" { t.Fatalf("expected error: %s, but got no error", testCase.ExpectedError) From aeb110589f4a9f6ab7ea48eac048e6241b59369f Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 16:46:40 -0400 Subject: [PATCH 06/14] Add changelog entries --- .changes/unreleased/BUG FIXES-20241022-163805.yaml | 5 +++++ .changes/unreleased/BUG FIXES-20241022-164013.yaml | 5 +++++ .changes/unreleased/BUG FIXES-20241022-164107.yaml | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 .changes/unreleased/BUG FIXES-20241022-163805.yaml create mode 100644 .changes/unreleased/BUG FIXES-20241022-164013.yaml create mode 100644 .changes/unreleased/BUG FIXES-20241022-164107.yaml diff --git a/.changes/unreleased/BUG FIXES-20241022-163805.yaml b/.changes/unreleased/BUG FIXES-20241022-163805.yaml new file mode 100644 index 0000000..a35ff8b --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20241022-163805.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'validate: File extension check now runs on `index.*` files instead of just `index.md` files.' +time: 2024-10-22T16:38:05.530944-04:00 +custom: + Issue: "413" diff --git a/.changes/unreleased/BUG FIXES-20241022-164013.yaml b/.changes/unreleased/BUG FIXES-20241022-164013.yaml new file mode 100644 index 0000000..193336c --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20241022-164013.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'validate: File extension check now specifies the correct valid extensions in the error message.' +time: 2024-10-22T16:40:13.832638-04:00 +custom: + Issue: "413" diff --git a/.changes/unreleased/BUG FIXES-20241022-164107.yaml b/.changes/unreleased/BUG FIXES-20241022-164107.yaml new file mode 100644 index 0000000..584931b --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20241022-164107.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'validate: Front matter check now runs with the correct options on legacy index files.' +time: 2024-10-22T16:41:07.726856-04:00 +custom: + Issue: "413" From 9c92c3e08a665e7e43322902c4876a9c84277d7d Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 16:49:55 -0400 Subject: [PATCH 07/14] Use `filepath.Join` instead of `website/docs` for windows compatability. --- internal/provider/migrate.go | 4 ++-- internal/provider/validate.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/provider/migrate.go b/internal/provider/migrate.go index babe212..3ae1af1 100644 --- a/internal/provider/migrate.go +++ b/internal/provider/migrate.go @@ -381,7 +381,7 @@ func (m *migrator) ProviderExamplesDir() string { func determineWebsiteDir(providerDir string) (string, error) { // Check for legacy website directory - providerWebsiteDirFileInfo, err := os.Stat(filepath.Join(providerDir, "website/docs")) + providerWebsiteDirFileInfo, err := os.Stat(filepath.Join(providerDir, "website", "docs")) if err != nil { if os.IsNotExist(err) { @@ -390,7 +390,7 @@ func determineWebsiteDir(providerDir string) (string, error) { return "", fmt.Errorf("error getting information for provider website directory %q: %w", providerDir, err) } } else if providerWebsiteDirFileInfo.IsDir() { - return "website/docs", nil + return filepath.Join("website", "docs"), nil } // Check for docs directory diff --git a/internal/provider/validate.go b/internal/provider/validate.go index 9500354..9448d53 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -172,7 +172,7 @@ func (v *validator) validate(ctx context.Context) error { result = errors.Join(result, err) } - if dirExists(v.providerFS, "website/docs") { + if dirExists(v.providerFS, filepath.Join("website", "docs")) { v.logger.infof("detected legacy website directory, running checks") err = v.validateLegacyWebsite() result = errors.Join(result, err) @@ -263,7 +263,7 @@ func (v *validator) validateStaticDocs() error { } func (v *validator) validateLegacyWebsite() error { - dir := "website/docs" + dir := filepath.Join("website", "docs") var result error options := &check.ProviderFileOptions{ From 48ecdbf46248807b0ec6b9c43908ac4f40c6a04c Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 17:03:05 -0400 Subject: [PATCH 08/14] Revert "Use `filepath.Join` instead of `website/docs` for windows compatability." This reverts commit 9c92c3e08a665e7e43322902c4876a9c84277d7d. --- internal/provider/migrate.go | 4 ++-- internal/provider/validate.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/provider/migrate.go b/internal/provider/migrate.go index 3ae1af1..babe212 100644 --- a/internal/provider/migrate.go +++ b/internal/provider/migrate.go @@ -381,7 +381,7 @@ func (m *migrator) ProviderExamplesDir() string { func determineWebsiteDir(providerDir string) (string, error) { // Check for legacy website directory - providerWebsiteDirFileInfo, err := os.Stat(filepath.Join(providerDir, "website", "docs")) + providerWebsiteDirFileInfo, err := os.Stat(filepath.Join(providerDir, "website/docs")) if err != nil { if os.IsNotExist(err) { @@ -390,7 +390,7 @@ func determineWebsiteDir(providerDir string) (string, error) { return "", fmt.Errorf("error getting information for provider website directory %q: %w", providerDir, err) } } else if providerWebsiteDirFileInfo.IsDir() { - return filepath.Join("website", "docs"), nil + return "website/docs", nil } // Check for docs directory diff --git a/internal/provider/validate.go b/internal/provider/validate.go index 9448d53..9500354 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -172,7 +172,7 @@ func (v *validator) validate(ctx context.Context) error { result = errors.Join(result, err) } - if dirExists(v.providerFS, filepath.Join("website", "docs")) { + if dirExists(v.providerFS, "website/docs") { v.logger.infof("detected legacy website directory, running checks") err = v.validateLegacyWebsite() result = errors.Join(result, err) @@ -263,7 +263,7 @@ func (v *validator) validateStaticDocs() error { } func (v *validator) validateLegacyWebsite() error { - dir := filepath.Join("website", "docs") + dir := "website/docs" var result error options := &check.ProviderFileOptions{ From 788389bb1de5b57368d7154baedec2e526509f81 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 17:10:08 -0400 Subject: [PATCH 09/14] Remove `filepath.Join()` usages and `/` separator conversions. --- internal/provider/validate.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/internal/provider/validate.go b/internal/provider/validate.go index 9500354..df887d8 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -198,7 +198,7 @@ func (v *validator) validateStaticDocs() error { return fmt.Errorf("error walking directory %q: %w", dir, err) } if d.IsDir() { - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationDirGlobPattern), path) + match, err := doublestar.PathMatch(DocumentationDirGlobPattern, path) if err != nil { return err } @@ -210,7 +210,7 @@ func (v *validator) validateStaticDocs() error { result = errors.Join(result, check.InvalidDirectoriesCheck(path)) return nil } - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationGlobPattern), path) + match, err := doublestar.PathMatch(DocumentationGlobPattern, path) if err != nil { return err } @@ -221,7 +221,7 @@ func (v *validator) validateStaticDocs() error { // Configure FrontMatterOptions based on file type if removeAllExt(d.Name()) == "index" { options.FrontMatter = RegistryIndexFrontMatterOptions - } else if _, relErr := filepath.Rel(filepath.Join(dir, "guides"), path); relErr == nil { + } else if _, relErr := filepath.Rel(dir+"/guides", path); relErr == nil { options.FrontMatter = RegistryGuideFrontMatterOptions } else { options.FrontMatter = RegistryFrontMatterOptions @@ -241,16 +241,16 @@ func (v *validator) validateStaticDocs() error { Schema: v.providerSchema, } - if dirExists(v.providerFS, filepath.Join(dir, "data-sources")) { - dataSourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "data-sources")) + if dirExists(v.providerFS, dir+"/data-sources") { + dataSourceFiles, _ := fs.ReadDir(v.providerFS, dir+"/data-sources") mismatchOpt.DatasourceEntries = dataSourceFiles } - if dirExists(v.providerFS, filepath.Join(dir, "resources")) { - resourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "resources")) + if dirExists(v.providerFS, dir+"/resources") { + resourceFiles, _ := fs.ReadDir(v.providerFS, dir+"/resources") mismatchOpt.ResourceEntries = resourceFiles } - if dirExists(v.providerFS, filepath.Join(dir, "functions")) { - functionFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "functions")) + if dirExists(v.providerFS, dir+"/functions") { + functionFiles, _ := fs.ReadDir(v.providerFS, dir+"/functions") mismatchOpt.FunctionEntries = functionFiles } @@ -278,7 +278,7 @@ func (v *validator) validateLegacyWebsite() error { return fmt.Errorf("error walking directory %q: %w", dir, err) } if d.IsDir() { - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationDirGlobPattern), path) + match, err := doublestar.PathMatch(DocumentationDirGlobPattern, path) if err != nil { return err } @@ -291,7 +291,7 @@ func (v *validator) validateLegacyWebsite() error { return nil } - match, err := doublestar.PathMatch(filepath.FromSlash(DocumentationGlobPattern), path) + match, err := doublestar.PathMatch(DocumentationGlobPattern, path) if err != nil { return err } @@ -320,16 +320,16 @@ func (v *validator) validateLegacyWebsite() error { Schema: v.providerSchema, } - if dirExists(v.providerFS, filepath.Join(dir, "d")) { - dataSourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "d")) + if dirExists(v.providerFS, dir+"/d") { + dataSourceFiles, _ := fs.ReadDir(v.providerFS, dir+"/d") mismatchOpt.DatasourceEntries = dataSourceFiles } - if dirExists(v.providerFS, filepath.Join(dir, "r")) { - resourceFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "r")) + if dirExists(v.providerFS, dir+"/r") { + resourceFiles, _ := fs.ReadDir(v.providerFS, dir+"/r") mismatchOpt.ResourceEntries = resourceFiles } - if dirExists(v.providerFS, filepath.Join(dir, "functions")) { - functionFiles, _ := fs.ReadDir(v.providerFS, filepath.Join(dir, "functions")) + if dirExists(v.providerFS, dir+"/functions") { + functionFiles, _ := fs.ReadDir(v.providerFS, dir+"/functions") mismatchOpt.FunctionEntries = functionFiles } From 2668fc7422286749ef6938325b2b724c5496a6fd Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 17:21:25 -0400 Subject: [PATCH 10/14] Remove `filepath.fromSlash()` usages --- internal/check/directory.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/check/directory.go b/internal/check/directory.go index 3c3183b..01ca872 100644 --- a/internal/check/directory.go +++ b/internal/check/directory.go @@ -120,7 +120,7 @@ func MixedDirectoriesCheck(docFiles []string) error { func IsValidLegacyDirectory(directory string) bool { for _, validLegacyDirectory := range ValidLegacyDirectories { - if directory == filepath.FromSlash(validLegacyDirectory) { + if directory == validLegacyDirectory { return true } } @@ -130,7 +130,7 @@ func IsValidLegacyDirectory(directory string) bool { func IsValidRegistryDirectory(directory string) bool { for _, validRegistryDirectory := range ValidRegistryDirectories { - if directory == filepath.FromSlash(validRegistryDirectory) { + if directory == validRegistryDirectory { return true } } @@ -139,32 +139,32 @@ func IsValidRegistryDirectory(directory string) bool { } func IsValidCdktfDirectory(directory string) bool { - if directory == filepath.FromSlash(fmt.Sprintf("%s/%s", LegacyIndexDirectory, CdktfIndexDirectory)) { + if directory == fmt.Sprintf("%s/%s", LegacyIndexDirectory, CdktfIndexDirectory) { return true } - if directory == filepath.FromSlash(fmt.Sprintf("%s/%s", RegistryIndexDirectory, CdktfIndexDirectory)) { + if directory == fmt.Sprintf("%s/%s", RegistryIndexDirectory, CdktfIndexDirectory) { return true } for _, validCdktfLanguage := range ValidCdktfLanguages { - if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage)) { + if directory == fmt.Sprintf("%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage) { return true } - if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage)) { + if directory == fmt.Sprintf("%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage) { return true } for _, validLegacySubdirectory := range ValidLegacySubdirectories { - if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validLegacySubdirectory)) { + if directory == fmt.Sprintf("%s/%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validLegacySubdirectory) { return true } } for _, validRegistrySubdirectory := range ValidRegistrySubdirectories { - if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validRegistrySubdirectory)) { + if directory == fmt.Sprintf("%s/%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validRegistrySubdirectory) { return true } } From a8a866484aa10e15e4fa011025fd9e97d6f9fb70 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 22 Oct 2024 17:46:49 -0400 Subject: [PATCH 11/14] Use `path.Dir()` instead of `filepath.Dir()` --- internal/check/directory.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/check/directory.go b/internal/check/directory.go index 01ca872..27f106e 100644 --- a/internal/check/directory.go +++ b/internal/check/directory.go @@ -6,7 +6,7 @@ package check import ( "fmt" "log" - "path/filepath" + "path" ) const ( @@ -92,7 +92,7 @@ func MixedDirectoriesCheck(docFiles []string) error { err := fmt.Errorf("mixed Terraform Provider documentation directory layouts found, must use only legacy or registry layout") for _, file := range docFiles { - directory := filepath.Dir(file) + directory := path.Dir(file) log.Printf("[DEBUG] Found directory: %s", directory) // Allow docs/ with other files From d362d767a8bdeb32a499c44a5078f4198d888982 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 29 Oct 2024 15:32:52 -0400 Subject: [PATCH 12/14] Use `doublestar.Match()` instead of `doublestar.PathMatch()` --- internal/provider/validate.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/provider/validate.go b/internal/provider/validate.go index df887d8..f7751a0 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -198,7 +198,7 @@ func (v *validator) validateStaticDocs() error { return fmt.Errorf("error walking directory %q: %w", dir, err) } if d.IsDir() { - match, err := doublestar.PathMatch(DocumentationDirGlobPattern, path) + match, err := doublestar.Match(DocumentationDirGlobPattern, path) if err != nil { return err } @@ -210,7 +210,7 @@ func (v *validator) validateStaticDocs() error { result = errors.Join(result, check.InvalidDirectoriesCheck(path)) return nil } - match, err := doublestar.PathMatch(DocumentationGlobPattern, path) + match, err := doublestar.Match(DocumentationGlobPattern, path) if err != nil { return err } @@ -278,7 +278,7 @@ func (v *validator) validateLegacyWebsite() error { return fmt.Errorf("error walking directory %q: %w", dir, err) } if d.IsDir() { - match, err := doublestar.PathMatch(DocumentationDirGlobPattern, path) + match, err := doublestar.Match(DocumentationDirGlobPattern, path) if err != nil { return err } @@ -291,7 +291,7 @@ func (v *validator) validateLegacyWebsite() error { return nil } - match, err := doublestar.PathMatch(DocumentationGlobPattern, path) + match, err := doublestar.Match(DocumentationGlobPattern, path) if err != nil { return err } From 00ecc45e35f63f44cf366dce68e60b980084f355 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 29 Oct 2024 15:38:27 -0400 Subject: [PATCH 13/14] Convert path slashes to os separators in error messages --- internal/check/provider_file.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/check/provider_file.go b/internal/check/provider_file.go index 8bc94ac..cae52a9 100644 --- a/internal/check/provider_file.go +++ b/internal/check/provider_file.go @@ -7,6 +7,7 @@ import ( "fmt" "io/fs" "log" + "path/filepath" ) type ProviderFileOptions struct { @@ -48,21 +49,21 @@ func (check *ProviderFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := FileExtensionCheck(path, check.Options.ValidExtensions); err != nil { - return fmt.Errorf("%s: error checking file extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", filepath.FromSlash(path), err) } if err := FileSizeCheck(check.ProviderFs, path); err != nil { - return fmt.Errorf("%s: error checking file size: %w", path, err) + return fmt.Errorf("%s: error checking file size: %w", filepath.FromSlash(path), err) } content, err := fs.ReadFile(check.ProviderFs, path) if err != nil { - return fmt.Errorf("%s: error reading file: %w", path, err) + return fmt.Errorf("%s: error reading file: %w", filepath.FromSlash(path), err) } if err := NewFrontMatterCheck(check.Options.FrontMatter).Run(content); err != nil { - return fmt.Errorf("%s: error checking file frontmatter: %w", path, err) + return fmt.Errorf("%s: error checking file frontmatter: %w", filepath.FromSlash(path), err) } return nil From 58e1a6ae35e1e81d52a91f45929969095d092341 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 29 Oct 2024 15:44:15 -0400 Subject: [PATCH 14/14] Convert path slashes to os separators in invalid directory check error messages --- internal/check/directory.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/check/directory.go b/internal/check/directory.go index 27f106e..17c16d4 100644 --- a/internal/check/directory.go +++ b/internal/check/directory.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "path" + "path/filepath" ) const ( @@ -82,7 +83,7 @@ func InvalidDirectoriesCheck(dirPath string) error { return nil } - return fmt.Errorf("invalid Terraform Provider documentation directory found: %s", dirPath) + return fmt.Errorf("invalid Terraform Provider documentation directory found: %s", filepath.FromSlash(dirPath)) }