diff --git a/CHANGELOG.md b/CHANGELOG.md index 3572310..ca3b902 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS * check: Verify number of documentation files for Terraform Registry storage limits +* check: Verify size of documentation files for Terraform Registry storage limits # v0.1.2 diff --git a/README.md b/README.md index 27c9343..2d484c9 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ The `tfproviderdocs check` command verifies the Terraform Provider documentation The validity of files is checked with the following rules: - Proper file extensions are used (e.g. `.md` for Terraform Registry). +- Verifies size of file is below Terraform Registry storage limits. - YAML frontmatter can be parsed and matches expectations. The YAML frontmatter checks include some defaults (e.g. no `layout` field for Terraform Registry), but there are some useful flags that can be passed to the command to tune the behavior, especially for larger Terraform Providers. diff --git a/check/check.go b/check/check.go index 33f3fe4..cfd7838 100644 --- a/check/check.go +++ b/check/check.go @@ -10,6 +10,7 @@ const ( // Terraform Registry Storage Limits // https://www.terraform.io/docs/registry/providers/docs.html#storage-limits RegistryMaximumNumberOfFiles = 1000 + RegistryMaximumSizeOfFile = 500000 // 500KB ) type Check struct { diff --git a/check/file.go b/check/file.go index 1f5baf8..bfc0611 100644 --- a/check/file.go +++ b/check/file.go @@ -1,6 +1,9 @@ package check import ( + "fmt" + "log" + "os" "path/filepath" ) @@ -20,3 +23,19 @@ func (opts *FileOptions) FullPath(path string) string { return path } + +// FileSizeCheck verifies that documentation file is below the Terraform Registry storage limit. +func FileSizeCheck(fullpath string) error { + fi, err := os.Stat(fullpath) + + if err != nil { + return err + } + + log.Printf("[DEBUG] File %s size: %d (limit: %d)", fullpath, 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()) + } + + return nil +} diff --git a/check/file_test.go b/check/file_test.go index 4dfea82..08bbac5 100644 --- a/check/file_test.go +++ b/check/file_test.go @@ -1,9 +1,60 @@ package check import ( + "io/ioutil" + "os" "testing" ) +func TestFileSizeCheck(t *testing.T) { + testCases := []struct { + Name string + Size int64 + ExpectError bool + }{ + { + Name: "under limit", + Size: RegistryMaximumSizeOfFile - 1, + }, + { + Name: "on limit", + Size: RegistryMaximumSizeOfFile, + ExpectError: true, + }, + { + Name: "over limit", + Size: RegistryMaximumSizeOfFile + 1, + ExpectError: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + file, err := ioutil.TempFile(os.TempDir(), "TestFileSizeCheck") + + if err != nil { + t.Fatalf("error creating temporary file: %s", err) + } + + defer os.Remove(file.Name()) + + if err := file.Truncate(testCase.Size); err != nil { + t.Fatalf("error writing temporary file: %s", err) + } + + got := FileSizeCheck(file.Name()) + + 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) + } + }) + } +} + func TestFullPath(t *testing.T) { testCases := []struct { Name string @@ -14,16 +65,16 @@ func TestFullPath(t *testing.T) { { Name: "without base path", FileOptions: &FileOptions{}, - Path: "docs/resource/thing.md", - Expect: "docs/resource/thing.md", + Path: "docs/resources/thing.md", + Expect: "docs/resources/thing.md", }, { Name: "without base path", FileOptions: &FileOptions{ BasePath: "/full/path/to", }, - Path: "docs/resource/thing.md", - Expect: "/full/path/to/docs/resource/thing.md", + Path: "docs/resources/thing.md", + Expect: "/full/path/to/docs/resources/thing.md", }, } diff --git a/check/legacy_data_source_file.go b/check/legacy_data_source_file.go index adec008..c1baf6e 100644 --- a/check/legacy_data_source_file.go +++ b/check/legacy_data_source_file.go @@ -50,7 +50,11 @@ func (check *LegacyDataSourceFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := LegacyFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/legacy_guide_file.go b/check/legacy_guide_file.go index c0521fd..b90b22b 100644 --- a/check/legacy_guide_file.go +++ b/check/legacy_guide_file.go @@ -50,7 +50,11 @@ func (check *LegacyGuideFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := LegacyFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/legacy_index_file.go b/check/legacy_index_file.go index 1454791..3380ff5 100644 --- a/check/legacy_index_file.go +++ b/check/legacy_index_file.go @@ -51,7 +51,11 @@ func (check *LegacyIndexFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := LegacyFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/legacy_resource_file.go b/check/legacy_resource_file.go index d8b0e5c..e3f91c6 100644 --- a/check/legacy_resource_file.go +++ b/check/legacy_resource_file.go @@ -50,7 +50,11 @@ func (check *LegacyResourceFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := LegacyFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/registry_data_source_file.go b/check/registry_data_source_file.go index b31f864..d6ca798 100644 --- a/check/registry_data_source_file.go +++ b/check/registry_data_source_file.go @@ -48,7 +48,11 @@ func (check *RegistryDataSourceFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := RegistryFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/registry_guide_file.go b/check/registry_guide_file.go index a2c592f..6843de7 100644 --- a/check/registry_guide_file.go +++ b/check/registry_guide_file.go @@ -49,7 +49,11 @@ func (check *RegistryGuideFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := RegistryFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/registry_index_file.go b/check/registry_index_file.go index d01cf0c..5494ab7 100644 --- a/check/registry_index_file.go +++ b/check/registry_index_file.go @@ -49,7 +49,11 @@ func (check *RegistryIndexFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := RegistryFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath) diff --git a/check/registry_resource_file.go b/check/registry_resource_file.go index 3461bb3..b2f41c2 100644 --- a/check/registry_resource_file.go +++ b/check/registry_resource_file.go @@ -48,7 +48,11 @@ func (check *RegistryResourceFileCheck) Run(path string) error { log.Printf("[DEBUG] Checking file: %s", fullpath) if err := RegistryFileExtensionCheck(path); err != nil { - return fmt.Errorf("error checking file (%s) extension: %w", path, err) + return fmt.Errorf("%s: error checking file extension: %w", path, err) + } + + if err := FileSizeCheck(fullpath); err != nil { + return fmt.Errorf("%s: error checking file size: %w", path, err) } content, err := ioutil.ReadFile(fullpath)