Skip to content

Commit 6c67ef2

Browse files
authored
Validate: refactor internal methods to use fs.FS interface for file handling (#413)
* Refactor `validateStaticDocs()` and `validateLegacyWebsite()` to use a `fs.FS` interface for walking. * Refactor `validate_test.go` to use `fstest.MapFS` * Refactor `directory_test.go` to use `fstest.MapFS` * Add tests for file mismatch check * Fix `unparam` lints * Add changelog entries * Use `filepath.Join` instead of `website/docs` for windows compatability. * Revert "Use `filepath.Join` instead of `website/docs` for windows compatability." This reverts commit 9c92c3e. * Remove `filepath.Join()` usages and `/` separator conversions. * Remove `filepath.fromSlash()` usages * Use `path.Dir()` instead of `filepath.Dir()` * Use `doublestar.Match()` instead of `doublestar.PathMatch()` * Convert path slashes to os separators in error messages * Convert path slashes to os separators in invalid directory check error messages
1 parent d70aced commit 6c67ef2

File tree

83 files changed

+1064
-1436
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1064
-1436
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: BUG FIXES
2+
body: 'validate: File extension check now runs on `index.*` files instead of just `index.md` files.'
3+
time: 2024-10-22T16:38:05.530944-04:00
4+
custom:
5+
Issue: "413"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: BUG FIXES
2+
body: 'validate: File extension check now specifies the correct valid extensions in the error message.'
3+
time: 2024-10-22T16:40:13.832638-04:00
4+
custom:
5+
Issue: "413"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: BUG FIXES
2+
body: 'validate: Front matter check now runs with the correct options on legacy index files.'
3+
time: 2024-10-22T16:41:07.726856-04:00
4+
custom:
5+
Issue: "413"

internal/check/directory.go

+11-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package check
66
import (
77
"fmt"
88
"log"
9+
"path"
910
"path/filepath"
1011
)
1112

@@ -82,7 +83,7 @@ func InvalidDirectoriesCheck(dirPath string) error {
8283
return nil
8384
}
8485

85-
return fmt.Errorf("invalid Terraform Provider documentation directory found: %s", dirPath)
86+
return fmt.Errorf("invalid Terraform Provider documentation directory found: %s", filepath.FromSlash(dirPath))
8687

8788
}
8889

@@ -92,7 +93,7 @@ func MixedDirectoriesCheck(docFiles []string) error {
9293
err := fmt.Errorf("mixed Terraform Provider documentation directory layouts found, must use only legacy or registry layout")
9394

9495
for _, file := range docFiles {
95-
directory := filepath.Dir(file)
96+
directory := path.Dir(file)
9697
log.Printf("[DEBUG] Found directory: %s", directory)
9798

9899
// Allow docs/ with other files
@@ -120,7 +121,7 @@ func MixedDirectoriesCheck(docFiles []string) error {
120121

121122
func IsValidLegacyDirectory(directory string) bool {
122123
for _, validLegacyDirectory := range ValidLegacyDirectories {
123-
if directory == filepath.FromSlash(validLegacyDirectory) {
124+
if directory == validLegacyDirectory {
124125
return true
125126
}
126127
}
@@ -130,7 +131,7 @@ func IsValidLegacyDirectory(directory string) bool {
130131

131132
func IsValidRegistryDirectory(directory string) bool {
132133
for _, validRegistryDirectory := range ValidRegistryDirectories {
133-
if directory == filepath.FromSlash(validRegistryDirectory) {
134+
if directory == validRegistryDirectory {
134135
return true
135136
}
136137
}
@@ -139,32 +140,32 @@ func IsValidRegistryDirectory(directory string) bool {
139140
}
140141

141142
func IsValidCdktfDirectory(directory string) bool {
142-
if directory == filepath.FromSlash(fmt.Sprintf("%s/%s", LegacyIndexDirectory, CdktfIndexDirectory)) {
143+
if directory == fmt.Sprintf("%s/%s", LegacyIndexDirectory, CdktfIndexDirectory) {
143144
return true
144145
}
145146

146-
if directory == filepath.FromSlash(fmt.Sprintf("%s/%s", RegistryIndexDirectory, CdktfIndexDirectory)) {
147+
if directory == fmt.Sprintf("%s/%s", RegistryIndexDirectory, CdktfIndexDirectory) {
147148
return true
148149
}
149150

150151
for _, validCdktfLanguage := range ValidCdktfLanguages {
151152

152-
if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage)) {
153+
if directory == fmt.Sprintf("%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage) {
153154
return true
154155
}
155156

156-
if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage)) {
157+
if directory == fmt.Sprintf("%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage) {
157158
return true
158159
}
159160

160161
for _, validLegacySubdirectory := range ValidLegacySubdirectories {
161-
if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validLegacySubdirectory)) {
162+
if directory == fmt.Sprintf("%s/%s/%s/%s", LegacyIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validLegacySubdirectory) {
162163
return true
163164
}
164165
}
165166

166167
for _, validRegistrySubdirectory := range ValidRegistrySubdirectories {
167-
if directory == filepath.FromSlash(fmt.Sprintf("%s/%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validRegistrySubdirectory)) {
168+
if directory == fmt.Sprintf("%s/%s/%s/%s", RegistryIndexDirectory, CdktfIndexDirectory, validCdktfLanguage, validRegistrySubdirectory) {
168169
return true
169170
}
170171
}

internal/check/directory_test.go

+76-10
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,94 @@
44
package check
55

66
import (
7-
"os"
8-
"path/filepath"
7+
"io/fs"
98
"testing"
9+
"testing/fstest"
1010

1111
"github.com/bmatcuk/doublestar/v4"
1212
)
1313

14-
var DocumentationGlobPattern = `{docs/index.md,docs/{,cdktf/}{data-sources,guides,resources,functions}/**/*,website/docs/**/*}`
14+
var DocumentationGlobPattern = `{docs/index.*,docs/{,cdktf/}{data-sources,guides,resources,functions}/**/*,website/docs/**/*}`
1515

1616
func TestMixedDirectoriesCheck(t *testing.T) {
1717
t.Parallel()
1818
testCases := map[string]struct {
19-
BasePath string
19+
ProviderFS fs.FS
2020
ExpectError bool
2121
}{
2222
"valid mixed directories": {
23-
BasePath: filepath.Join("testdata", "valid-mixed-directories"),
23+
ProviderFS: fstest.MapFS{
24+
"docs/nonregistrydocs/thing.md": {},
25+
"website/docs/index.md": {},
26+
},
2427
},
25-
"invalid mixed directories": {
26-
BasePath: filepath.Join("testdata", "invalid-mixed-directories"),
28+
"valid mixed directories - cdktf": {
29+
ProviderFS: fstest.MapFS{
30+
"docs/cdktf/typescript/index.md": {},
31+
"website/docs/index.md": {},
32+
},
33+
},
34+
"invalid mixed directories - registry data source": {
35+
ProviderFS: fstest.MapFS{
36+
"docs/data-sources/invalid.md": {},
37+
"website/docs/index.md": {},
38+
},
39+
ExpectError: true,
40+
},
41+
"invalid mixed directories - registry resource": {
42+
ProviderFS: fstest.MapFS{
43+
"docs/resources/invalid.md": {},
44+
"website/docs/index.md": {},
45+
},
46+
ExpectError: true,
47+
},
48+
"invalid mixed directories - registry guide": {
49+
ProviderFS: fstest.MapFS{
50+
"docs/guides/invalid.md": {},
51+
"website/docs/index.md": {},
52+
},
53+
ExpectError: true,
54+
},
55+
"invalid mixed directories - registry function": {
56+
ProviderFS: fstest.MapFS{
57+
"docs/functions/invalid.md": {},
58+
"website/docs/index.md": {},
59+
},
60+
ExpectError: true,
61+
},
62+
"invalid mixed directories - legacy data source": {
63+
ProviderFS: fstest.MapFS{
64+
"website/docs/d/invalid.html.markdown": {},
65+
"docs/resources/thing.md": {},
66+
},
67+
ExpectError: true,
68+
},
69+
"invalid mixed directories - legacy resource": {
70+
ProviderFS: fstest.MapFS{
71+
"website/docs/r/invalid.html.markdown": {},
72+
"docs/resources/thing.md": {},
73+
},
74+
ExpectError: true,
75+
},
76+
"invalid mixed directories - legacy guide": {
77+
ProviderFS: fstest.MapFS{
78+
"website/docs/guides/invalid.html.markdown": {},
79+
"docs/resources/thing.md": {},
80+
},
81+
ExpectError: true,
82+
},
83+
"invalid mixed directories - legacy function": {
84+
ProviderFS: fstest.MapFS{
85+
"website/docs/functions/invalid.html.markdown": {},
86+
"docs/resources/thing.md": {},
87+
},
88+
ExpectError: true,
89+
},
90+
"invalid mixed directories - legacy index": {
91+
ProviderFS: fstest.MapFS{
92+
"website/docs/index.html.markdown": {},
93+
"docs/resources/thing.md": {},
94+
},
2795
ExpectError: true,
2896
},
2997
}
@@ -34,9 +102,7 @@ func TestMixedDirectoriesCheck(t *testing.T) {
34102
t.Run(name, func(t *testing.T) {
35103
t.Parallel()
36104

37-
providerFs := os.DirFS(testCase.BasePath)
38-
39-
files, err := doublestar.Glob(providerFs, DocumentationGlobPattern)
105+
files, err := doublestar.Glob(testCase.ProviderFS, DocumentationGlobPattern)
40106
if err != nil {
41107
t.Fatalf("error finding documentation files: %s", err)
42108
}

internal/check/file.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ package check
55

66
import (
77
"fmt"
8+
"io/fs"
89
"log"
9-
"os"
1010
"path/filepath"
1111
)
1212

@@ -23,14 +23,14 @@ func (opts *FileOptions) FullPath(path string) string {
2323
}
2424

2525
// FileSizeCheck verifies that documentation file is below the Terraform Registry storage limit.
26-
func FileSizeCheck(fullpath string) error {
27-
fi, err := os.Stat(fullpath)
26+
func FileSizeCheck(providerFs fs.FS, path string) error {
27+
fi, err := fs.Stat(providerFs, path)
2828

2929
if err != nil {
3030
return err
3131
}
3232

33-
log.Printf("[DEBUG] File %s size: %d (limit: %d)", fullpath, fi.Size(), RegistryMaximumSizeOfFile)
33+
log.Printf("[DEBUG] File %s size: %d (limit: %d)", path, fi.Size(), RegistryMaximumSizeOfFile)
3434
if fi.Size() >= int64(RegistryMaximumSizeOfFile) {
3535
return fmt.Errorf("exceeded maximum (%d) size of documentation file for Terraform Registry: %d", RegistryMaximumSizeOfFile, fi.Size())
3636
}

internal/check/file_extension.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ var ValidRegistryFileExtensions = []string{
3030
// FileExtensionCheck checks if the file extension of the given path is valid.
3131
func FileExtensionCheck(path string, validExtensions []string) error {
3232
if !FilePathEndsWithExtensionFrom(path, validExtensions) {
33-
return fmt.Errorf("file does not end with a valid extension, valid extensions: %v", ValidLegacyFileExtensions)
33+
return fmt.Errorf("file does not end with a valid extension, valid extensions: %v", validExtensions)
3434
}
3535

3636
return nil

internal/check/file_test.go

+19-13
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,40 @@
44
package check
55

66
import (
7-
"os"
7+
"io/fs"
88
"path/filepath"
99
"testing"
10+
"testing/fstest"
1011
)
1112

1213
func TestFileSizeCheck(t *testing.T) {
1314
t.Parallel()
1415
testCases := map[string]struct {
16+
FileSystem fs.FS
1517
Size int64
1618
ExpectError bool
1719
}{
1820
"under limit": {
19-
Size: RegistryMaximumSizeOfFile - 1,
21+
FileSystem: fstest.MapFS{
22+
"file.md": {
23+
Data: make([]byte, RegistryMaximumSizeOfFile-1),
24+
},
25+
},
2026
},
2127
"on limit": {
22-
Size: RegistryMaximumSizeOfFile,
28+
FileSystem: fstest.MapFS{
29+
"file.md": {
30+
Data: make([]byte, RegistryMaximumSizeOfFile),
31+
},
32+
},
2333
ExpectError: true,
2434
},
2535
"over limit": {
26-
Size: RegistryMaximumSizeOfFile + 1,
36+
FileSystem: fstest.MapFS{
37+
"file.md": {
38+
Data: make([]byte, RegistryMaximumSizeOfFile+1),
39+
},
40+
},
2741
ExpectError: true,
2842
},
2943
}
@@ -34,15 +48,7 @@ func TestFileSizeCheck(t *testing.T) {
3448
t.Run(name, func(t *testing.T) {
3549
t.Parallel()
3650

37-
file, _ := os.CreateTemp(t.TempDir(), "TestFileSizeCheck")
38-
39-
defer file.Close()
40-
41-
if err := file.Truncate(testCase.Size); err != nil {
42-
t.Fatalf("error writing temporary file: %s", err)
43-
}
44-
45-
got := FileSizeCheck(file.Name())
51+
got := FileSizeCheck(testCase.FileSystem, "file.md")
4652

4753
if got == nil && testCase.ExpectError {
4854
t.Errorf("expected error, got no error")

internal/check/provider_file.go

+13-10
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ package check
55

66
import (
77
"fmt"
8+
"io/fs"
89
"log"
9-
"os"
10+
"path/filepath"
1011
)
1112

1213
type ProviderFileOptions struct {
@@ -17,12 +18,14 @@ type ProviderFileOptions struct {
1718
}
1819

1920
type ProviderFileCheck struct {
20-
Options *ProviderFileOptions
21+
Options *ProviderFileOptions
22+
ProviderFs fs.FS
2123
}
2224

23-
func NewProviderFileCheck(opts *ProviderFileOptions) *ProviderFileCheck {
25+
func NewProviderFileCheck(providerFs fs.FS, opts *ProviderFileOptions) *ProviderFileCheck {
2426
check := &ProviderFileCheck{
25-
Options: opts,
27+
Options: opts,
28+
ProviderFs: providerFs,
2629
}
2730

2831
if check.Options == nil {
@@ -46,21 +49,21 @@ func (check *ProviderFileCheck) Run(path string) error {
4649
log.Printf("[DEBUG] Checking file: %s", fullpath)
4750

4851
if err := FileExtensionCheck(path, check.Options.ValidExtensions); err != nil {
49-
return fmt.Errorf("%s: error checking file extension: %w", path, err)
52+
return fmt.Errorf("%s: error checking file extension: %w", filepath.FromSlash(path), err)
5053
}
5154

52-
if err := FileSizeCheck(fullpath); err != nil {
53-
return fmt.Errorf("%s: error checking file size: %w", path, err)
55+
if err := FileSizeCheck(check.ProviderFs, path); err != nil {
56+
return fmt.Errorf("%s: error checking file size: %w", filepath.FromSlash(path), err)
5457
}
5558

56-
content, err := os.ReadFile(fullpath)
59+
content, err := fs.ReadFile(check.ProviderFs, path)
5760

5861
if err != nil {
59-
return fmt.Errorf("%s: error reading file: %w", path, err)
62+
return fmt.Errorf("%s: error reading file: %w", filepath.FromSlash(path), err)
6063
}
6164

6265
if err := NewFrontMatterCheck(check.Options.FrontMatter).Run(content); err != nil {
63-
return fmt.Errorf("%s: error checking file frontmatter: %w", path, err)
66+
return fmt.Errorf("%s: error checking file frontmatter: %w", filepath.FromSlash(path), err)
6467
}
6568

6669
return nil

internal/check/testdata/invalid-mixed-directories/docs/resources/thing.md

-27
This file was deleted.

internal/check/testdata/invalid-mixed-directories/website/docs/r/thing.html.markdown

Whitespace-only changes.

0 commit comments

Comments
 (0)