From 3fa316dc3785d5352ee7d0e5dbeb207ae0b03f64 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Tue, 15 Apr 2025 14:54:30 +0000 Subject: [PATCH] wip: get basic GH API call stuff working --- cmd/github/github.go | 29 +++++++++++++++------------- cmd/readmevalidation/contributors.go | 2 +- cmd/readmevalidation/main.go | 12 +++++++----- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/cmd/github/github.go b/cmd/github/github.go index 68b40f14..00b3f3a7 100644 --- a/cmd/github/github.go +++ b/cmd/github/github.go @@ -149,25 +149,28 @@ func (s OrgStatus) String() string { } // GetUserOrgStatus takes a GitHub username, and checks the GitHub API to see -// whether that member is part of the Coder organization -func (gc *Client) GetUserOrgStatus(org string, username string) (OrgStatus, error) { +// whether that member is part of the provided organization +func (gc *Client) GetUserOrgStatus(orgName string, username string) (OrgStatus, error) { // This API endpoint is really annoying, because it's able to produce false - // negatives. Any user can be a public member of Coder, a private member of - // Coder, or a non-member. + // negatives. Any user can be: + // 1. A public member of an organization + // 2. A private member of an organization + // 3. Not a member of an organization // // So if the function returns status 200, you can always trust that. But if // it returns any 400 code, that could indicate a few things: - // 1. The user being checked is not part of the organization, but the user - // associated with the token is. - // 2. The user being checked is a member of the organization, but their - // status is private, and the token being used to check belongs to a user - // who is not part of the Coder organization. + // 1. The user associated with the token is a member of the organization, + // and the user being checked is not. + // 2. The user associated with the token is NOT a member of the + // organization, and the member being checked is a private member. The + // token user will have no way to view the private member's status. // 3. Neither the user being checked nor the user associated with the token - // are members of the organization + // are members of the organization. // - // The best option is to make sure that the token being used belongs to a - // member of the Coder organization - req, err := http.NewRequest("GET", fmt.Sprintf("%sorgs/%s/%s", gc.baseURL, org, username), nil) + // The best option to avoid false positives is to make sure that the token + // being used belongs to a member of the organization being checked. + url := fmt.Sprintf("%sorgs/%s/members/%s", gc.baseURL, orgName, username) + req, err := http.NewRequest("GET", url, nil) if err != nil { return OrgStatusIndeterminate, err } diff --git a/cmd/readmevalidation/contributors.go b/cmd/readmevalidation/contributors.go index 02823f26..0d081bb6 100644 --- a/cmd/readmevalidation/contributors.go +++ b/cmd/readmevalidation/contributors.go @@ -405,7 +405,7 @@ func aggregateContributorReadmeFiles() ([]readme, error) { return allReadmeFiles, nil } -func validateRelativeUrls( +func validateContributorRelativeUrls( contributors map[string]contributorProfile, ) error { // This function only validates relative avatar URLs for now, but it can be diff --git a/cmd/readmevalidation/main.go b/cmd/readmevalidation/main.go index 9a5aaf97..f14ed121 100644 --- a/cmd/readmevalidation/main.go +++ b/cmd/readmevalidation/main.go @@ -15,6 +15,7 @@ import ( ) func main() { + // Do basic setup log.Println("Beginning README file validation") err := godotenv.Load() if err != nil { @@ -30,6 +31,8 @@ func main() { } log.Printf("Using branch %q for validation comparison", baseRef) + // Retrieve data necessary from the GitHub API to help determine whether + // certain field changes are allowed log.Printf("Using GitHub API to determine what fields can be set by user %q\n", actorUsername) client, err := github.NewClient() if err != nil { @@ -49,28 +52,27 @@ func main() { if err != nil { log.Panic(err) } + } else { + log.Println("Provided API token does not belong to a Coder employee. Some README validation steps will be skipped compared to when they run in CI.") } - fmt.Printf("actor %q is %s\n", actorUsername, actorOrgStatus.String()) log.Println("Starting README validation") + 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 = validateRelativeUrls(contributors) + 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) }