Skip to content

Commit e6efd71

Browse files
committed
wip: more progress
1 parent f10f5a4 commit e6efd71

File tree

4 files changed

+170
-54
lines changed

4 files changed

+170
-54
lines changed

cmd/readmevalidation/coderResources.go

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111

1212
"coder.com/coder-registry/cmd/github"
13+
"gopkg.in/yaml.v3"
1314
)
1415

1516
// dummyGitDirectory is the directory that a full version of the Registry will
@@ -34,7 +35,7 @@ type coderResourceFrontmatter struct {
3435
// Coder Modules and Coder Templates. If the newReadmeBody and newFrontmatter
3536
// fields are nil, that represents that the file has been deleted
3637
type coderResource struct {
37-
name string
38+
resourceType string
3839
filePath string
3940
newReadmeBody *string
4041
oldFrontmatter *coderResourceFrontmatter
@@ -178,10 +179,77 @@ func validateCoderResourceChanges(resource coderResource, actorOrgStatus github.
178179
return problems
179180
}
180181

181-
func parseCoderResourceFiles(oldReadmeFiles []readme, newReadmeFiles []readme, actorOrgStatus github.OrgStatus) (map[string]coderResource, error) {
182-
return nil, nil
182+
func parseCoderResourceFiles(resourceType string, oldReadmeFiles []readme, newReadmeFiles []readme, actorOrgStatus github.OrgStatus) (map[string]coderResource, error) {
183+
if !slices.Contains(supportedResourceTypes, resourceType) {
184+
return nil, fmt.Errorf("resource type %q is not in supported list [%s]", resourceType, strings.Join(supportedResourceTypes, ", "))
185+
}
186+
187+
var errs []error
188+
resourcesByFilePath := map[string]coderResource{}
189+
zipped := zipReadmes(oldReadmeFiles, newReadmeFiles)
190+
191+
for filePath, z := range zipped {
192+
resource := coderResource{
193+
resourceType: resourceType,
194+
filePath: filePath,
195+
}
196+
197+
if z.new != nil {
198+
fm, body, err := separateFrontmatter(z.new.rawText)
199+
if err != nil {
200+
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
201+
} else {
202+
resource.newReadmeBody = &body
203+
var newFm coderResourceFrontmatter
204+
if err := yaml.Unmarshal([]byte(fm), &newFm); err != nil {
205+
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
206+
} else {
207+
resource.newFrontmatter = &newFm
208+
if newFm.Verified != nil && *newFm.Verified {
209+
resource.newIsVerified = true
210+
}
211+
}
212+
}
213+
}
214+
215+
if z.old != nil {
216+
fm, _, err := separateFrontmatter(z.old.rawText)
217+
if err != nil {
218+
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
219+
} else {
220+
var oldFm coderResourceFrontmatter
221+
if err := yaml.Unmarshal([]byte(fm), &oldFm); err != nil {
222+
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
223+
} else {
224+
resource.oldFrontmatter = &oldFm
225+
if oldFm.Verified != nil && *oldFm.Verified {
226+
resource.oldIsVerified = true
227+
}
228+
}
229+
}
230+
}
231+
232+
if z.old != nil || z.new != nil {
233+
resourcesByFilePath[filePath] = resource
234+
}
235+
}
236+
237+
for _, r := range resourcesByFilePath {
238+
errs = append(errs, validateCoderResourceChanges(r, actorOrgStatus)...)
239+
}
240+
241+
if len(errs) != 0 {
242+
return nil, validationPhaseError{
243+
phase: validationPhaseReadmeParsing,
244+
errors: errs,
245+
}
246+
}
247+
return resourcesByFilePath, nil
183248
}
184249

250+
// Todo: because Coder Resource READMEs will have their full contents
251+
// (frontmatter and body) rendered on the Registry site, we need to make sure
252+
// that all image references in the body are valid, too
185253
func validateCoderResourceRelativeUrls(map[string]coderResource) []error {
186254
return nil
187255
}

cmd/readmevalidation/main.go

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ import (
1313
"sync"
1414

1515
"coder.com/coder-registry/cmd/github"
16-
"github.com/go-git/go-git/v5"
17-
"github.com/go-git/go-git/v5/plumbing"
18-
"github.com/go-git/go-git/v5/plumbing/transport/http"
1916
"github.com/joho/godotenv"
2017
)
2118

@@ -104,53 +101,56 @@ func main() {
104101
go func() {
105102
defer wg.Done()
106103

107-
refactorLater := func() error {
104+
moveToOuterScopeLater := func() error {
108105
baseRefReadmeFiles, err := aggregateCoderResourceReadmeFiles("modules")
109106
if err != nil {
110107
return err
111108
}
112-
fmt.Printf("------ got %d back\n", len(baseRefReadmeFiles))
113-
114-
repo, err := git.PlainClone(dummyGitDirectory, true, &git.CloneOptions{
115-
URL: "https://github.com/coder/registry",
116-
Auth: &http.BasicAuth{},
117-
})
118-
if err != nil {
119-
return err
120-
}
121-
122-
head, err := repo.Head()
123-
if err != nil {
124-
return err
125-
}
126-
activeBranchName := head.Name().Short()
127-
128-
tree, err := repo.Worktree()
109+
parsed, err := parseCoderResourceFiles("modules", baseRefReadmeFiles, baseRefReadmeFiles, actorOrgStatus)
129110
if err != nil {
130111
return err
131112
}
132-
err = tree.Checkout(&git.CheckoutOptions{
133-
Branch: plumbing.NewBranchReferenceName(activeBranchName),
134-
Create: false,
135-
Force: false,
136-
Keep: true,
137-
})
138-
if err != nil {
139-
return err
140-
}
141-
142-
fmt.Println("Got here!")
143-
files, _ := tree.Filesystem.ReadDir(".")
144-
for _, f := range files {
145-
if f.IsDir() {
146-
fmt.Println(f.Name())
147-
}
148-
}
113+
fmt.Printf("------ got %d back\n", len(parsed))
114+
115+
// repo, err := git.PlainClone(dummyGitDirectory, true, &git.CloneOptions{
116+
// URL: "https://github.com/coder/registry",
117+
// Auth: &http.BasicAuth{},
118+
// })
119+
// if err != nil {
120+
// return err
121+
// }
122+
123+
// head, err := repo.Head()
124+
// if err != nil {
125+
// return err
126+
// }
127+
// activeBranchName := head.Name().Short()
128+
129+
// tree, err := repo.Worktree()
130+
// if err != nil {
131+
// return err
132+
// }
133+
// err = tree.Checkout(&git.CheckoutOptions{
134+
// Branch: plumbing.NewBranchReferenceName(activeBranchName),
135+
// Create: false,
136+
// Force: false,
137+
// Keep: true,
138+
// })
139+
// if err != nil {
140+
// return err
141+
// }
142+
143+
// files, _ := tree.Filesystem.ReadDir(".")
144+
// for _, f := range files {
145+
// if f.IsDir() {
146+
// fmt.Println(f.Name())
147+
// }
148+
// }
149149

150150
return nil
151151
}
152152

153-
if err := refactorLater(); err != nil {
153+
if err := moveToOuterScopeLater(); err != nil {
154154
errChan <- fmt.Errorf("module validation: %v", err)
155155
}
156156

cmd/readmevalidation/readmes.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,48 @@ func (p validationPhase) String() string {
108108
return "Unknown validation phase"
109109
}
110110
}
111+
112+
type zippedReadmes struct {
113+
old *readme
114+
new *readme
115+
}
116+
117+
// zipReadmes takes two slices of README files, and combines them into a map,
118+
// where each key is a file path, and each value is a struct containing the old
119+
// value for the path, and the new value for the path. If the old value exists
120+
// but the new one doesn't, that indicates that a file has been deleted. If the
121+
// new value exists, but the old one doesn't, that indicates that the file was
122+
// created.
123+
func zipReadmes(prevReadmes []readme, newReadmes []readme) map[string]zippedReadmes {
124+
oldMap := map[string]readme{}
125+
for _, rm := range prevReadmes {
126+
oldMap[rm.filePath] = rm
127+
}
128+
129+
zipped := map[string]zippedReadmes{}
130+
for _, rm := range newReadmes {
131+
old, ok := oldMap[rm.filePath]
132+
if ok {
133+
zipped[rm.filePath] = zippedReadmes{
134+
old: &old,
135+
new: &rm,
136+
}
137+
} else {
138+
zipped[rm.filePath] = zippedReadmes{
139+
old: nil,
140+
new: &rm,
141+
}
142+
}
143+
}
144+
for _, old := range oldMap {
145+
_, ok := zipped[old.filePath]
146+
if !ok {
147+
zipped[old.filePath] = zippedReadmes{
148+
old: &old,
149+
new: nil,
150+
}
151+
}
152+
}
153+
154+
return zipped
155+
}

cmd/readmevalidation/repoStructure.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,24 @@ func validateCoderResourceSubdirectory(dirPath string) []error {
3737

3838
resourceReadmePath := path.Join(dirPath, f.Name(), "README.md")
3939
_, err := os.Stat(resourceReadmePath)
40-
if err == nil {
41-
continue
40+
if err != nil {
41+
if errors.Is(err, os.ErrNotExist) {
42+
errs = append(errs, fmt.Errorf("%q: README file does not exist", resourceReadmePath))
43+
} else {
44+
errs = append(errs, addFilePathToError(resourceReadmePath, err))
45+
}
4246
}
4347

44-
if errors.Is(err, os.ErrNotExist) {
45-
errs = append(errs, fmt.Errorf("%q: README file does not exist", resourceReadmePath))
46-
} else {
47-
errs = append(errs, addFilePathToError(resourceReadmePath, err))
48+
mainTerraformPath := path.Join(dirPath, f.Name(), "main.tf")
49+
_, err = os.Stat(mainTerraformPath)
50+
if err != nil {
51+
if errors.Is(err, os.ErrNotExist) {
52+
errs = append(errs, fmt.Errorf("%q: 'main.tf' file does not exist", mainTerraformPath))
53+
} else {
54+
errs = append(errs, addFilePathToError(mainTerraformPath, err))
55+
}
4856
}
57+
4958
}
5059

5160
return errs
@@ -71,12 +80,6 @@ func validateRegistryDirectory() []error {
7180
problems = append(problems, err)
7281
}
7382

74-
mainTerraformPath := path.Join(dirPath, "main.tf")
75-
_, err = os.Stat(mainTerraformPath)
76-
if err != nil {
77-
problems = append(problems, err)
78-
}
79-
8083
for _, rType := range supportedResourceTypes {
8184
resourcePath := path.Join(dirPath, rType)
8285
if errs := validateCoderResourceSubdirectory(resourcePath); len(errs) != 0 {

0 commit comments

Comments
 (0)