Skip to content

Commit 668b430

Browse files
committed
auto apply xerrors and comment full sentence changes
Signed-off-by: Callum Styan <[email protected]>
1 parent 37481dd commit 668b430

File tree

5 files changed

+69
-65
lines changed

5 files changed

+69
-65
lines changed

cmd/readmevalidation/coderresources.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"bufio"
55
"errors"
6-
"fmt"
76
"log"
87
"net/url"
98
"os"
@@ -12,6 +11,7 @@ import (
1211
"slices"
1312
"strings"
1413

14+
"golang.org/x/xerrors"
1515
"gopkg.in/yaml.v3"
1616
)
1717

@@ -27,7 +27,7 @@ type coderResourceFrontmatter struct {
2727

2828
// coderResourceReadme represents a README describing a Terraform resource used
2929
// to help create Coder workspaces. As of 2025-04-15, this encapsulates both
30-
// Coder Modules and Coder Templates
30+
// Coder Modules and Coder Templates.
3131
type coderResourceReadme struct {
3232
resourceType string
3333
filePath string
@@ -37,14 +37,14 @@ type coderResourceReadme struct {
3737

3838
func validateCoderResourceDisplayName(displayName *string) error {
3939
if displayName != nil && *displayName == "" {
40-
return errors.New("if defined, display_name must not be empty string")
40+
return xerrors.New("if defined, display_name must not be empty string")
4141
}
4242
return nil
4343
}
4444

4545
func validateCoderResourceDescription(description string) error {
4646
if description == "" {
47-
return errors.New("frontmatter description cannot be empty")
47+
return xerrors.New("frontmatter description cannot be empty")
4848
}
4949
return nil
5050
}
@@ -53,17 +53,17 @@ func validateCoderResourceIconURL(iconURL string) []error {
5353
problems := []error{}
5454

5555
if iconURL == "" {
56-
problems = append(problems, errors.New("icon URL cannot be empty"))
56+
problems = append(problems, xerrors.New("icon URL cannot be empty"))
5757
return problems
5858
}
5959

6060
isAbsoluteURL := !strings.HasPrefix(iconURL, ".") && !strings.HasPrefix(iconURL, "/")
6161
if isAbsoluteURL {
6262
if _, err := url.ParseRequestURI(iconURL); err != nil {
63-
problems = append(problems, errors.New("absolute icon URL is not correctly formatted"))
63+
problems = append(problems, xerrors.New("absolute icon URL is not correctly formatted"))
6464
}
6565
if strings.Contains(iconURL, "?") {
66-
problems = append(problems, errors.New("icon URLs cannot contain query parameters"))
66+
problems = append(problems, xerrors.New("icon URLs cannot contain query parameters"))
6767
}
6868
return problems
6969
}
@@ -75,15 +75,15 @@ func validateCoderResourceIconURL(iconURL string) []error {
7575
strings.HasPrefix(iconURL, "/") ||
7676
strings.HasPrefix(iconURL, "../../../../.icons")
7777
if !isPermittedRelativeURL {
78-
problems = append(problems, fmt.Errorf("relative icon URL %q must either be scoped to that module's directory, or the top-level /.icons directory (this can usually be done by starting the path with \"../../../.icons\")", iconURL))
78+
problems = append(problems, xerrors.Errorf("relative icon URL %q must either be scoped to that module's directory, or the top-level /.icons directory (this can usually be done by starting the path with \"../../../.icons\")", iconURL))
7979
}
8080

8181
return problems
8282
}
8383

8484
func validateCoderResourceTags(tags []string) error {
8585
if tags == nil {
86-
return errors.New("provided tags array is nil")
86+
return xerrors.New("provided tags array is nil")
8787
}
8888
if len(tags) == 0 {
8989
return nil
@@ -100,7 +100,7 @@ func validateCoderResourceTags(tags []string) error {
100100
}
101101

102102
if len(invalidTags) != 0 {
103-
return fmt.Errorf("found invalid tags (tags that cannot be used for filter state in the Registry website): [%s]", strings.Join(invalidTags, ", "))
103+
return xerrors.Errorf("found invalid tags (tags that cannot be used for filter state in the Registry website): [%s]", strings.Join(invalidTags, ", "))
104104
}
105105
return nil
106106
}
@@ -147,7 +147,7 @@ func validateCoderResourceReadmeBody(body string) []error {
147147
terraformCodeBlockCount++
148148
}
149149
if strings.HasPrefix(nextLine, "```hcl") {
150-
errs = append(errs, errors.New("all .hcl language references must be converted to .tf"))
150+
errs = append(errs, xerrors.New("all .hcl language references must be converted to .tf"))
151151
}
152152
continue
153153
}
@@ -174,20 +174,20 @@ func validateCoderResourceReadmeBody(body string) []error {
174174
}
175175

176176
if terraformCodeBlockCount == 0 {
177-
errs = append(errs, errors.New("did not find Terraform code block within h1 section"))
177+
errs = append(errs, xerrors.New("did not find Terraform code block within h1 section"))
178178
} else {
179179
if terraformCodeBlockCount > 1 {
180-
errs = append(errs, errors.New("cannot have more than one Terraform code block in h1 section"))
180+
errs = append(errs, xerrors.New("cannot have more than one Terraform code block in h1 section"))
181181
}
182182
if !foundTerraformVersionRef {
183-
errs = append(errs, errors.New("did not find Terraform code block that specifies 'version' field"))
183+
errs = append(errs, xerrors.New("did not find Terraform code block that specifies 'version' field"))
184184
}
185185
}
186186
if !foundParagraph {
187-
errs = append(errs, errors.New("did not find paragraph within h1 section"))
187+
errs = append(errs, xerrors.New("did not find paragraph within h1 section"))
188188
}
189189
if isInsideCodeBlock {
190-
errs = append(errs, errors.New("code blocks inside h1 section do not all terminate before end of file"))
190+
errs = append(errs, xerrors.New("code blocks inside h1 section do not all terminate before end of file"))
191191
}
192192

193193
return errs
@@ -220,12 +220,12 @@ func validateCoderResourceReadme(rm coderResourceReadme) []error {
220220
func parseCoderResourceReadme(resourceType string, rm readme) (coderResourceReadme, error) {
221221
fm, body, err := separateFrontmatter(rm.rawText)
222222
if err != nil {
223-
return coderResourceReadme{}, fmt.Errorf("%q: failed to parse frontmatter: %v", rm.filePath, err)
223+
return coderResourceReadme{}, xerrors.Errorf("%q: failed to parse frontmatter: %v", rm.filePath, err)
224224
}
225225

226226
yml := coderResourceFrontmatter{}
227227
if err := yaml.Unmarshal([]byte(fm), &yml); err != nil {
228-
return coderResourceReadme{}, fmt.Errorf("%q: failed to parse: %v", rm.filePath, err)
228+
return coderResourceReadme{}, xerrors.Errorf("%q: failed to parse: %v", rm.filePath, err)
229229
}
230230

231231
return coderResourceReadme{
@@ -273,7 +273,7 @@ func parseCoderResourceReadmeFiles(resourceType string, rms []readme) (map[strin
273273
}
274274

275275
// Todo: Need to beef up this function by grabbing each image/video URL from
276-
// the body's AST
276+
// the body's AST.
277277
func validateCoderResourceRelativeUrls(resources map[string]coderResourceReadme) error {
278278
return nil
279279
}
@@ -330,7 +330,7 @@ func aggregateCoderResourceReadmeFiles(resourceType string) ([]readme, error) {
330330

331331
func validateAllCoderResourceFilesOfType(resourceType string) error {
332332
if !slices.Contains(supportedResourceTypes, resourceType) {
333-
return fmt.Errorf("resource type %q is not part of supported list [%s]", resourceType, strings.Join(supportedResourceTypes, ", "))
333+
return xerrors.Errorf("resource type %q is not part of supported list [%s]", resourceType, strings.Join(supportedResourceTypes, ", "))
334334
}
335335

336336
allReadmeFiles, err := aggregateCoderResourceReadmeFiles(resourceType)

cmd/readmevalidation/contributors.go

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package main
22

33
import (
4-
"errors"
5-
"fmt"
64
"log"
75
"net/url"
86
"os"
97
"path"
108
"slices"
119
"strings"
1210

11+
"golang.org/x/xerrors"
1312
"gopkg.in/yaml.v3"
1413
)
1514

@@ -35,7 +34,7 @@ type contributorProfileReadme struct {
3534

3635
func validateContributorDisplayName(displayName string) error {
3736
if displayName == "" {
38-
return fmt.Errorf("missing display_name")
37+
return xerrors.New("missing display_name")
3938
}
4039

4140
return nil
@@ -47,7 +46,7 @@ func validateContributorLinkedinURL(linkedinURL *string) error {
4746
}
4847

4948
if _, err := url.ParseRequestURI(*linkedinURL); err != nil {
50-
return fmt.Errorf("linkedIn URL %q is not valid: %v", *linkedinURL, err)
49+
return xerrors.Errorf("linkedIn URL %q is not valid: %v", *linkedinURL, err)
5150
}
5251

5352
return nil
@@ -66,28 +65,28 @@ func validateContributorSupportEmail(email *string) []error {
6665
// pipeline. Best we can do is verify the general structure
6766
username, server, ok := strings.Cut(*email, "@")
6867
if !ok {
69-
errs = append(errs, fmt.Errorf("email address %q is missing @ symbol", *email))
68+
errs = append(errs, xerrors.Errorf("email address %q is missing @ symbol", *email))
7069
return errs
7170
}
7271

7372
if username == "" {
74-
errs = append(errs, fmt.Errorf("email address %q is missing username", *email))
73+
errs = append(errs, xerrors.Errorf("email address %q is missing username", *email))
7574
}
7675

7776
domain, tld, ok := strings.Cut(server, ".")
7877
if !ok {
79-
errs = append(errs, fmt.Errorf("email address %q is missing period for server segment", *email))
78+
errs = append(errs, xerrors.Errorf("email address %q is missing period for server segment", *email))
8079
return errs
8180
}
8281

8382
if domain == "" {
84-
errs = append(errs, fmt.Errorf("email address %q is missing domain", *email))
83+
errs = append(errs, xerrors.Errorf("email address %q is missing domain", *email))
8584
}
8685
if tld == "" {
87-
errs = append(errs, fmt.Errorf("email address %q is missing top-level domain", *email))
86+
errs = append(errs, xerrors.Errorf("email address %q is missing top-level domain", *email))
8887
}
8988
if strings.Contains(*email, "?") {
90-
errs = append(errs, errors.New("email is not allowed to contain query parameters"))
89+
errs = append(errs, xerrors.New("email is not allowed to contain query parameters"))
9190
}
9291

9392
return errs
@@ -99,40 +98,40 @@ func validateContributorWebsite(websiteURL *string) error {
9998
}
10099

101100
if _, err := url.ParseRequestURI(*websiteURL); err != nil {
102-
return fmt.Errorf("linkedIn URL %q is not valid: %v", *websiteURL, err)
101+
return xerrors.Errorf("linkedIn URL %q is not valid: %v", *websiteURL, err)
103102
}
104103

105104
return nil
106105
}
107106

108107
func validateContributorStatus(status string) error {
109108
if !slices.Contains(validContributorStatuses, status) {
110-
return fmt.Errorf("contributor status %q is not valid", status)
109+
return xerrors.Errorf("contributor status %q is not valid", status)
111110
}
112111

113112
return nil
114113
}
115114

116115
// Can't validate the image actually leads to a valid resource in a pure
117-
// function, but can at least catch obvious problems
116+
// function, but can at least catch obvious problems.
118117
func validateContributorAvatarURL(avatarURL *string) []error {
119118
if avatarURL == nil {
120119
return nil
121120
}
122121

123122
errs := []error{}
124123
if *avatarURL == "" {
125-
errs = append(errs, errors.New("avatar URL must be omitted or non-empty string"))
124+
errs = append(errs, xerrors.New("avatar URL must be omitted or non-empty string"))
126125
return errs
127126
}
128127

129128
// Have to use .Parse instead of .ParseRequestURI because this is the
130129
// one field that's allowed to be a relative URL
131130
if _, err := url.Parse(*avatarURL); err != nil {
132-
errs = append(errs, fmt.Errorf("URL %q is not a valid relative or absolute URL", *avatarURL))
131+
errs = append(errs, xerrors.Errorf("URL %q is not a valid relative or absolute URL", *avatarURL))
133132
}
134133
if strings.Contains(*avatarURL, "?") {
135-
errs = append(errs, errors.New("avatar URL is not allowed to contain search parameters"))
134+
errs = append(errs, xerrors.New("avatar URL is not allowed to contain search parameters"))
136135
}
137136

138137
matched := false
@@ -145,7 +144,7 @@ func validateContributorAvatarURL(avatarURL *string) []error {
145144
if !matched {
146145
segments := strings.Split(*avatarURL, ".")
147146
fileExtension := segments[len(segments)-1]
148-
errs = append(errs, fmt.Errorf("avatar URL '.%s' does not end in a supported file format: [%s]", fileExtension, strings.Join(supportedAvatarFileFormats, ", ")))
147+
errs = append(errs, xerrors.Errorf("avatar URL '.%s' does not end in a supported file format: [%s]", fileExtension, strings.Join(supportedAvatarFileFormats, ", ")))
149148
}
150149

151150
return errs
@@ -180,12 +179,12 @@ func validateContributorReadme(rm contributorProfileReadme) []error {
180179
func parseContributorProfile(rm readme) (contributorProfileReadme, error) {
181180
fm, _, err := separateFrontmatter(rm.rawText)
182181
if err != nil {
183-
return contributorProfileReadme{}, fmt.Errorf("%q: failed to parse frontmatter: %v", rm.filePath, err)
182+
return contributorProfileReadme{}, xerrors.Errorf("%q: failed to parse frontmatter: %v", rm.filePath, err)
184183
}
185184

186185
yml := contributorProfileFrontmatter{}
187186
if err := yaml.Unmarshal([]byte(fm), &yml); err != nil {
188-
return contributorProfileReadme{}, fmt.Errorf("%q: failed to parse: %v", rm.filePath, err)
187+
return contributorProfileReadme{}, xerrors.Errorf("%q: failed to parse: %v", rm.filePath, err)
189188
}
190189

191190
return contributorProfileReadme{
@@ -206,7 +205,7 @@ func parseContributorFiles(readmeEntries []readme) (map[string]contributorProfil
206205
}
207206

208207
if prev, alreadyExists := profilesByNamespace[p.namespace]; alreadyExists {
209-
yamlParsingErrors = append(yamlParsingErrors, fmt.Errorf("%q: namespace %q conflicts with namespace from %q", p.filePath, p.namespace, prev.filePath))
208+
yamlParsingErrors = append(yamlParsingErrors, xerrors.Errorf("%q: namespace %q conflicts with namespace from %q", p.filePath, p.namespace, prev.filePath))
210209
continue
211210
}
212211
profilesByNamespace[p.namespace] = p
@@ -291,15 +290,15 @@ func validateContributorRelativeUrls(contributors map[string]contributorProfileR
291290
}
292291

293292
if strings.HasPrefix(*con.frontmatter.AvatarURL, "..") {
294-
errs = append(errs, fmt.Errorf("%q: relative avatar URLs cannot be placed outside a user's namespaced directory", con.filePath))
293+
errs = append(errs, xerrors.Errorf("%q: relative avatar URLs cannot be placed outside a user's namespaced directory", con.filePath))
295294
continue
296295
}
297296

298297
absolutePath := strings.TrimSuffix(con.filePath, "README.md") +
299298
*con.frontmatter.AvatarURL
300299
_, err := os.ReadFile(absolutePath)
301300
if err != nil {
302-
errs = append(errs, fmt.Errorf("%q: relative avatar path %q does not point to image in file system", con.filePath, *con.frontmatter.AvatarURL))
301+
errs = append(errs, xerrors.Errorf("%q: relative avatar path %q does not point to image in file system", con.filePath, *con.frontmatter.AvatarURL))
303302
}
304303
}
305304

cmd/readmevalidation/errors.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package main
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
6+
"golang.org/x/xerrors"
7+
)
48

59
// validationPhaseError represents an error that occurred during a specific
610
// phase of README validation. It should be used to collect ALL validation
@@ -24,5 +28,5 @@ func (vpe validationPhaseError) Error() string {
2428
}
2529

2630
func addFilePathToError(filePath string, err error) error {
27-
return fmt.Errorf("%q: %v", filePath, err)
31+
return xerrors.Errorf("%q: %v", filePath, err)
2832
}

0 commit comments

Comments
 (0)