diff --git a/cmd/readmevalidation/coderResources.go b/cmd/readmevalidation/coderResources.go index 374edbb5..76e44092 100644 --- a/cmd/readmevalidation/coderResources.go +++ b/cmd/readmevalidation/coderResources.go @@ -19,11 +19,12 @@ type coderResourceFrontmatter struct { // coderResource represents a generic concept for a Terraform resource used to // help create Coder workspaces. As of 2025-04-15, this encapsulates both -// Coder Modules and Coder Templates. +// Coder Modules and Coder Templates. If the newReadmeBody and newFrontmatter +// fields are nil, that represents that the file has been deleted type coderResource struct { name string filePath string - readmeBody string + newReadmeBody *string oldFrontmatter *coderResourceFrontmatter newFrontmatter *coderResourceFrontmatter oldIsVerified bool @@ -124,7 +125,8 @@ func validateCoderResourceVerifiedStatus(oldVerified bool, newVerified bool, act // Todo: once we decide on how we want the README frontmatter to be formatted // for the Embedded Registry work, update this function to validate that the // correct Terraform code snippets are included in the README and are actually -// valid Terraform +// valid Terraform. Might also want to validate that each header follows proper +// hierarchy (i.e., not jumping from h1 to h3 because you think it looks nicer) func validateCoderResourceReadmeBody(body string) error { trimmed := strings.TrimSpace(body) if !strings.HasPrefix(trimmed, "# ") { @@ -133,6 +135,45 @@ func validateCoderResourceReadmeBody(body string) error { return nil } -func validateCoderResource(resource coderResource) []error { +func validateCoderResourceChanges(resource coderResource, actorOrgStatus github.OrgStatus) []error { + var problems []error + + if resource.newReadmeBody != nil { + if err := validateCoderResourceReadmeBody(*resource.newReadmeBody); err != nil { + problems = append(problems, addFilePathToError(resource.filePath, err)) + } + } + + if resource.newFrontmatter != nil { + if err := validateCoderResourceDisplayName(resource.newFrontmatter.DisplayName); err != nil { + problems = append(problems, addFilePathToError(resource.filePath, err)) + } + if err := validateCoderResourceDescription(resource.newFrontmatter.Description); err != nil { + problems = append(problems, addFilePathToError(resource.filePath, err)) + } + if err := validateCoderResourceTags(resource.newFrontmatter.Tags); err != nil { + problems = append(problems, addFilePathToError(resource.filePath, err)) + } + if err := validateCoderResourceVerifiedStatus(resource.oldIsVerified, resource.newIsVerified, actorOrgStatus); err != nil { + problems = append(problems, addFilePathToError(resource.filePath, err)) + } + + for _, err := range validateCoderResourceIconURL(resource.newFrontmatter.IconURL) { + problems = append(problems, addFilePathToError(resource.filePath, err)) + } + } + + return problems +} + +func parseCoderResourceFiles(oldReadmeFiles []readme, newReadmeFiles []readme) (map[string]coderResource, error) { + return nil, nil +} + +func validateCoderResourceRelativeUrls(map[string]coderResource) []error { return nil } + +func aggregateCoderResourceReadmeFiles() ([]readme, error) { + return nil, nil +} diff --git a/cmd/readmevalidation/contributors.go b/cmd/readmevalidation/contributors.go index 177340c4..782cc0c9 100644 --- a/cmd/readmevalidation/contributors.go +++ b/cmd/readmevalidation/contributors.go @@ -334,9 +334,7 @@ func aggregateContributorReadmeFiles() ([]readme, error) { return allReadmeFiles, nil } -func validateContributorRelativeUrls( - contributors map[string]contributorProfile, -) error { +func validateContributorRelativeUrls(contributors map[string]contributorProfile) error { // This function only validates relative avatar URLs for now, but it can be // beefed up to validate more in the future problems := []error{} diff --git a/cmd/readmevalidation/main.go b/cmd/readmevalidation/main.go index d0d7ac34..28fdb503 100644 --- a/cmd/readmevalidation/main.go +++ b/cmd/readmevalidation/main.go @@ -9,6 +9,8 @@ package main import ( "fmt" "log" + "os" + "sync" "coder.com/coder-registry/cmd/github" "github.com/joho/godotenv" @@ -60,30 +62,64 @@ func main() { log.Println("Starting README validation") // Validate file structure of main README directory + log.Println("Validating directory structure of the README directory") err = validateRepoStructure() if err != nil { log.Panic(err) } + // Set up concurrency for validating each category of README file + var readmeValidationErrors []error + errChan := make(chan error, 1) + wg := sync.WaitGroup{} + go func() { + for err := range errChan { + readmeValidationErrors = append(readmeValidationErrors, err) + } + }() + // Validate contributor README files - allReadmeFiles, err := aggregateContributorReadmeFiles() - if err != nil { - log.Panic(err) - } - log.Printf("Processing %d README files\n", len(allReadmeFiles)) - contributors, err := parseContributorFiles(allReadmeFiles) - log.Printf("Processed %d README files as valid contributor profiles", len(contributors)) - if err != nil { - log.Panic(err) - } - err = validateContributorRelativeUrls(contributors) - if err != nil { - log.Panic(err) - } - log.Println("All relative URLs for READMEs are valid") - log.Printf("Processed all READMEs in the %q directory\n", rootRegistryPath) + wg.Add(1) + go func() { + defer wg.Done() + + allReadmeFiles, err := aggregateContributorReadmeFiles() + if err != nil { + log.Panic(err) + } + log.Printf("Processing %d README files\n", len(allReadmeFiles)) + contributors, err := parseContributorFiles(allReadmeFiles) + log.Printf("Processed %d README files as valid contributor profiles", len(contributors)) + if err != nil { + log.Panic(err) + } + err = validateContributorRelativeUrls(contributors) + if err != nil { + log.Panic(err) + } + log.Println("All relative URLs for READMEs are valid") + log.Printf("Processed all READMEs in the %q directory\n", rootRegistryPath) + }() // Validate modules + wg.Add(1) + go func() { + defer wg.Done() + }() // Validate templates + wg.Add(1) + go func() { + defer wg.Done() + }() + + // Clean up and log errors + wg.Wait() + close(errChan) + for _, err := range readmeValidationErrors { + log.Println(err) + } + if len(readmeValidationErrors) != 0 { + os.Exit(1) + } }