Skip to content

Commit 19226af

Browse files
committed
wip: commit more progress
1 parent e888506 commit 19226af

File tree

8 files changed

+266
-75
lines changed

8 files changed

+266
-75
lines changed

.env.example

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
# can set this to your GitHub username.
55
CI_ACTOR=
66

7-
# This is the Git ref that you want to merge into the main branch. In local
8-
# development, this should be set to the value of the branch you're working from
9-
CI_BASE_REF=
10-
117
# This is the configurable base URL for accessing the GitHub REST API. This
128
# value will be injected by the CI script's Actions context, but if the value is
139
# not defined (either in CI or when running locally), "https://api.github.com/"

cmd/github/github.go

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,12 @@ import (
77
"errors"
88
"fmt"
99
"io"
10-
"log"
1110
"net/http"
12-
"os"
1311
"time"
1412
)
1513

1614
const defaultGithubAPIBaseRoute = "https://api.github.com/"
1715

18-
const (
19-
actionsActorKey = "CI_ACTOR"
20-
actionsBaseRefKey = "CI_BASE_REF"
21-
)
22-
23-
const (
24-
githubAPIURLKey = "GITHUB_API_URL"
25-
githubAPITokenKey = "GITHUB_API_TOKEN"
26-
)
27-
28-
// ActionsActor returns the username of the GitHub user who triggered the
29-
// current CI run as part of GitHub Actions. The value must be loaded into the
30-
// env as part of the Github Actions YAML file, or else the function fails.
31-
func ActionsActor() (string, error) {
32-
username := os.Getenv(actionsActorKey)
33-
if username == "" {
34-
return "", fmt.Errorf("value for %q is not in env. If running from CI, please add value via ci.yaml file", actionsActorKey)
35-
}
36-
return username, nil
37-
}
38-
39-
// BaseRef returns the name of the base ref for the Git branch that will be
40-
// merged into the main branch.
41-
func BaseRef() (string, error) {
42-
baseRef := os.Getenv(actionsBaseRefKey)
43-
if baseRef == "" {
44-
return "", fmt.Errorf("value for %q is not in env. If running from CI, please add value via ci.yaml file", actionsBaseRefKey)
45-
}
46-
47-
return baseRef, nil
48-
}
49-
5016
// Client is a reusable REST client for making requests to the GitHub API.
5117
// It should be instantiated via NewGithubClient
5218
type Client struct {
@@ -55,19 +21,25 @@ type Client struct {
5521
httpClient http.Client
5622
}
5723

58-
// NewClient instantiates a GitHub client
59-
func NewClient() (*Client, error) {
24+
// ClientInit is used to instantiate a new client. If the value of BaseURL is
25+
// not defined, a default value of "https://api.github.com/" is used instead
26+
type ClientInit struct {
27+
BaseURL string
28+
APIToken string
29+
}
30+
31+
// NewClient instantiates a GitHub client. If the baseURL is
32+
func NewClient(init ClientInit) (*Client, error) {
6033
// Considered letting the user continue on with no token and more aggressive
6134
// rate-limiting, but from experimentation, the non-authenticated experience
6235
// hit the rate limits really quickly, and had a lot of restrictions
63-
apiToken := os.Getenv(githubAPITokenKey)
36+
apiToken := init.APIToken
6437
if apiToken == "" {
65-
return nil, fmt.Errorf("missing env variable %q", githubAPITokenKey)
38+
return nil, errors.New("API token is missing")
6639
}
6740

68-
baseURL := os.Getenv(githubAPIURLKey)
41+
baseURL := init.BaseURL
6942
if baseURL == "" {
70-
log.Printf("env variable %q is not defined. Falling back to %q\n", githubAPIURLKey, defaultGithubAPIBaseRoute)
7143
baseURL = defaultGithubAPIBaseRoute
7244
}
7345

@@ -129,9 +101,11 @@ const (
129101
// could not be determined. It is the zero value of the OrgStatus type, and
130102
// any users with this value should be treated as completely untrusted
131103
OrgStatusIndeterminate = iota
104+
132105
// OrgStatusNonMember indicates when a user is definitely NOT part of an
133106
// organization
134107
OrgStatusNonMember
108+
135109
// OrgStatusMember indicates when a user is a member of a Github
136110
// organization
137111
OrgStatusMember

cmd/readmevalidation/coderResources.go

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import (
44
"errors"
55
"fmt"
66
"net/url"
7+
"os"
8+
"path"
9+
"slices"
710
"strings"
811

912
"coder.com/coder-registry/cmd/github"
1013
)
1114

15+
var supportedResourceTypes = []string{"modules", "templates"}
16+
1217
type coderResourceFrontmatter struct {
1318
Description string `yaml:"description"`
1419
IconURL string `yaml:"icon"`
@@ -166,14 +171,68 @@ func validateCoderResourceChanges(resource coderResource, actorOrgStatus github.
166171
return problems
167172
}
168173

169-
func parseCoderResourceFiles(oldReadmeFiles []readme, newReadmeFiles []readme) (map[string]coderResource, error) {
174+
func parseCoderResourceFiles(oldReadmeFiles []readme, newReadmeFiles []readme, actorOrgStatus github.OrgStatus) (map[string]coderResource, error) {
170175
return nil, nil
171176
}
172177

173178
func validateCoderResourceRelativeUrls(map[string]coderResource) []error {
174179
return nil
175180
}
176181

177-
func aggregateCoderResourceReadmeFiles() ([]readme, error) {
178-
return nil, nil
182+
func aggregateCoderResourceReadmeFiles(resourceDirectoryName string) ([]readme, error) {
183+
if !slices.Contains(supportedResourceTypes, resourceDirectoryName) {
184+
return nil, fmt.Errorf("%q is not a supported resource type. Must be one of [%s]", resourceDirectoryName, strings.Join(supportedResourceTypes, ", "))
185+
}
186+
187+
registryFiles, err := os.ReadDir(rootRegistryPath)
188+
if err != nil {
189+
return nil, err
190+
}
191+
192+
var allReadmeFiles []readme
193+
var problems []error
194+
for _, f := range registryFiles {
195+
if !f.IsDir() {
196+
continue
197+
}
198+
199+
resourceDirPath := path.Join(rootRegistryPath, f.Name(), resourceDirectoryName)
200+
resourceFiles, err := os.ReadDir(resourceDirPath)
201+
if err != nil {
202+
if !errors.Is(err, os.ErrNotExist) {
203+
problems = append(problems, err)
204+
}
205+
continue
206+
}
207+
208+
for _, resFile := range resourceFiles {
209+
// Not sure if we want to allow non-directories to live inside of
210+
// main directories like /modules or /templates, but we can tighten
211+
// things up later
212+
if !resFile.IsDir() {
213+
continue
214+
}
215+
216+
readmePath := path.Join(resourceDirPath, resFile.Name(), "README.md")
217+
rawRm, err := os.ReadFile(readmePath)
218+
if err != nil {
219+
problems = append(problems, err)
220+
continue
221+
}
222+
allReadmeFiles = append(allReadmeFiles, readme{
223+
filePath: readmePath,
224+
rawText: string(rawRm),
225+
})
226+
227+
}
228+
}
229+
230+
if len(problems) != 0 {
231+
return nil, validationPhaseError{
232+
phase: validationPhaseFileLoad,
233+
errors: problems,
234+
}
235+
}
236+
237+
return allReadmeFiles, nil
179238
}

cmd/readmevalidation/github.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
)
7+
8+
const actionsActorKey = "CI_ACTOR"
9+
10+
const (
11+
githubAPIBaseURLKey = "GITHUB_API_URL"
12+
githubAPITokenKey = "GITHUB_API_TOKEN"
13+
)
14+
15+
// actionsActor returns the username of the GitHub user who triggered the
16+
// current CI run as part of GitHub Actions. It is expected that this value be
17+
// set using a local .env file in local development, and set via GitHub Actions
18+
// context during CI.
19+
func actionsActor() (string, error) {
20+
username := os.Getenv(actionsActorKey)
21+
if username == "" {
22+
return "", fmt.Errorf("value for %q is not in env. If running from CI, please add value via ci.yaml file", actionsActorKey)
23+
}
24+
return username, nil
25+
}
26+
27+
func githubAPIToken() (string, error) {
28+
token := os.Getenv(githubAPITokenKey)
29+
if token == "" {
30+
return "", fmt.Errorf("value for %q is not in env. If running from CI, please add value via ci.yaml file", githubAPITokenKey)
31+
}
32+
return token, nil
33+
}

cmd/readmevalidation/main.go

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,34 @@ import (
1313
"sync"
1414

1515
"coder.com/coder-registry/cmd/github"
16+
"github.com/go-git/go-git/v5"
1617
"github.com/joho/godotenv"
1718
)
1819

1920
func main() {
20-
// Do basic setup
2121
log.Println("Beginning README file validation")
22+
23+
// Do basic setup
2224
err := godotenv.Load()
2325
if err != nil {
2426
log.Panic(err)
2527
}
26-
actorUsername, err := github.ActionsActor()
28+
actorUsername, err := actionsActor()
2729
if err != nil {
2830
log.Panic(err)
2931
}
30-
baseRef, err := github.BaseRef()
32+
ghAPIToken, err := githubAPIToken()
3133
if err != nil {
3234
log.Panic(err)
3335
}
34-
log.Printf("Using branch %q for validation comparison", baseRef)
3536

3637
// Retrieve data necessary from the GitHub API to help determine whether
3738
// certain field changes are allowed
3839
log.Printf("Using GitHub API to determine what fields can be set by user %q\n", actorUsername)
39-
client, err := github.NewClient()
40+
client, err := github.NewClient(github.ClientInit{
41+
BaseURL: os.Getenv(githubAPIBaseURLKey),
42+
APIToken: ghAPIToken,
43+
})
4044
if err != nil {
4145
log.Panic(err)
4246
}
@@ -59,6 +63,7 @@ func main() {
5963
}
6064
fmt.Printf("Script GitHub actor %q has Coder organization status %q\n", actorUsername, actorOrgStatus.String())
6165

66+
// Start main validation
6267
log.Println("Starting README validation")
6368

6469
// Validate file structure of main README directory
@@ -85,17 +90,20 @@ func main() {
8590

8691
allReadmeFiles, err := aggregateContributorReadmeFiles()
8792
if err != nil {
88-
log.Panic(err)
93+
errChan <- err
94+
return
8995
}
9096
log.Printf("Processing %d README files\n", len(allReadmeFiles))
9197
contributors, err := parseContributorFiles(allReadmeFiles)
9298
log.Printf("Processed %d README files as valid contributor profiles", len(contributors))
9399
if err != nil {
94-
log.Panic(err)
100+
errChan <- err
101+
return
95102
}
96103
err = validateContributorRelativeUrls(contributors)
97104
if err != nil {
98-
log.Panic(err)
105+
errChan <- err
106+
return
99107
}
100108
log.Println("All relative URLs for READMEs are valid")
101109
log.Printf("Processed all READMEs in the %q directory\n", rootRegistryPath)
@@ -105,6 +113,30 @@ func main() {
105113
wg.Add(1)
106114
go func() {
107115
defer wg.Done()
116+
117+
baseRefReadmeFiles, err := aggregateCoderResourceReadmeFiles("modules")
118+
if err != nil {
119+
errChan <- err
120+
return
121+
}
122+
fmt.Printf("------ got %d back\n", len(baseRefReadmeFiles))
123+
124+
repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{
125+
DetectDotGit: false,
126+
EnableDotGitCommonDir: false,
127+
})
128+
if err != nil {
129+
errChan <- err
130+
return
131+
}
132+
133+
head, err := repo.Head()
134+
if err != nil {
135+
errChan <- err
136+
return
137+
}
138+
activeBranchName := head.Name().Short()
139+
fmt.Println("-----", activeBranchName)
108140
}()
109141

110142
// Validate templates

0 commit comments

Comments
 (0)