From afe5b40567603d0282f8824edf4c3eeeb8089ece Mon Sep 17 00:00:00 2001 From: Azeem Shaikh Date: Wed, 1 Sep 2021 19:32:26 -0700 Subject: [PATCH] Make RepoClient as default interface for Scorecard (#951) Co-authored-by: Azeem Shaikh --- checker/check_request.go | 7 ---- checks/cii_best_practices.go | 2 +- checks/fuzzing.go | 9 +++- checks/security_policy.go | 8 +++- clients/githubrepo/client.go | 26 +++++++++++- .../githubrepo/roundtripper}/census.go | 0 .../githubrepo/roundtripper}/rate_limit.go | 0 .../githubrepo/roundtripper}/roundtripper.go | 4 +- .../{ => roundtripper}/transport.go | 10 +++-- clients/githubrepo/{ => stats}/stats.go | 2 +- cmd/root.go | 28 ++++--------- cmd/serve.go | 19 ++------- cron/worker/main.go | 41 +++++-------------- e2e/binary_artifacts_test.go | 28 ++++++------- e2e/branch_protection_test.go | 31 ++++++-------- e2e/ci_tests_test.go | 15 +++---- e2e/cii_best_practices_test.go | 13 +++--- e2e/code_review_test.go | 15 +++---- e2e/contributors_test.go | 30 ++++++-------- e2e/dependency_update_tool_test.go | 28 ++++++------- e2e/e2e_suite_test.go | 34 ++------------- e2e/fuzzing_test.go | 15 +++---- e2e/maintained_test.go | 15 +++---- e2e/packaging_test.go | 15 +++---- e2e/permissions_test.go | 15 +++---- e2e/pinned_dependencies_test.go | 15 +++---- e2e/sast_test.go | 16 +++----- e2e/security_policy_test.go | 30 ++++++-------- e2e/signedreleases_test.go | 15 +++---- e2e/vulnerabilities_test.go | 31 ++++++-------- pkg/scorecard.go | 24 +++-------- 31 files changed, 211 insertions(+), 330 deletions(-) rename {roundtripper => clients/githubrepo/roundtripper}/census.go (100%) rename {roundtripper => clients/githubrepo/roundtripper}/rate_limit.go (100%) rename {roundtripper => clients/githubrepo/roundtripper}/roundtripper.go (94%) rename clients/githubrepo/{ => roundtripper}/transport.go (86%) rename clients/githubrepo/{ => stats}/stats.go (98%) diff --git a/checker/check_request.go b/checker/check_request.go index 58351f95..38dc9627 100644 --- a/checker/check_request.go +++ b/checker/check_request.go @@ -16,10 +16,6 @@ package checker import ( "context" - "net/http" - - "github.com/google/go-github/v38/github" - "github.com/shurcooL/githubv4" "github.com/ossf/scorecard/v2/clients" ) @@ -27,9 +23,6 @@ import ( // CheckRequest struct encapsulates all data to be passed into a CheckFn. type CheckRequest struct { Ctx context.Context - Client *github.Client - GraphClient *githubv4.Client - HTTPClient *http.Client RepoClient clients.RepoClient Dlogger DetailLogger Owner, Repo string diff --git a/checks/cii_best_practices.go b/checks/cii_best_practices.go index 90607cd9..0dafa695 100644 --- a/checks/cii_best_practices.go +++ b/checks/cii_best_practices.go @@ -46,7 +46,7 @@ func CIIBestPractices(c *checker.CheckRequest) checker.CheckResult { e := sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("http.NewRequestWithContext: %v", err)) return checker.CreateRuntimeErrorResult(CheckCIIBestPractices, e) } - resp, err := c.HTTPClient.Do(req) + resp, err := http.DefaultClient.Do(req) if err != nil { e := sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("HTTPClient.Do: %v", err)) return checker.CreateRuntimeErrorResult(CheckCIIBestPractices, e) diff --git a/checks/fuzzing.go b/checks/fuzzing.go index 66d3ca0a..2ebfafc4 100644 --- a/checks/fuzzing.go +++ b/checks/fuzzing.go @@ -18,6 +18,8 @@ import ( "fmt" "sync" + "go.uber.org/zap" + "github.com/ossf/scorecard/v2/checker" "github.com/ossf/scorecard/v2/clients" "github.com/ossf/scorecard/v2/clients/githubrepo" @@ -30,6 +32,7 @@ const CheckFuzzing = "Fuzzing" var ( ossFuzzRepo clients.RepoClient errOssFuzzRepo error + logger *zap.Logger once sync.Once ) @@ -41,7 +44,11 @@ func init() { // Fuzzing runs Fuzzing check. func Fuzzing(c *checker.CheckRequest) checker.CheckResult { once.Do(func() { - ossFuzzRepo = githubrepo.CreateGithubRepoClient(c.Ctx, c.Client, c.GraphClient) + logger, errOssFuzzRepo = githubrepo.NewLogger(zap.InfoLevel) + if errOssFuzzRepo != nil { + return + } + ossFuzzRepo = githubrepo.CreateGithubRepoClient(c.Ctx, logger) errOssFuzzRepo = ossFuzzRepo.InitRepo("google", "oss-fuzz") }) if errOssFuzzRepo != nil { diff --git a/checks/security_policy.go b/checks/security_policy.go index 7bf596df..6f207761 100644 --- a/checks/security_policy.go +++ b/checks/security_policy.go @@ -18,6 +18,8 @@ import ( "errors" "strings" + "go.uber.org/zap" + "github.com/ossf/scorecard/v2/checker" "github.com/ossf/scorecard/v2/clients/githubrepo" sce "github.com/ossf/scorecard/v2/errors" @@ -72,7 +74,11 @@ func SecurityPolicy(c *checker.CheckRequest) checker.CheckResult { // https://docs.github.com/en/github/building-a-strong-community/creating-a-default-community-health-file dotGitHub := c dotGitHub.Repo = ".github" - dotGitHubClient := githubrepo.CreateGithubRepoClient(c.Ctx, c.Client, c.GraphClient) + logger, err := githubrepo.NewLogger(zap.InfoLevel) + if err != nil { + return checker.CreateRuntimeErrorResult(CheckSecurityPolicy, err) + } + dotGitHubClient := githubrepo.CreateGithubRepoClient(c.Ctx, logger) err = dotGitHubClient.InitRepo(c.Owner, c.Repo) switch { diff --git a/clients/githubrepo/client.go b/clients/githubrepo/client.go index cf421b69..1df35a28 100644 --- a/clients/githubrepo/client.go +++ b/clients/githubrepo/client.go @@ -18,11 +18,15 @@ package githubrepo import ( "context" "fmt" + "net/http" "github.com/google/go-github/v38/github" "github.com/shurcooL/githubv4" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" "github.com/ossf/scorecard/v2/clients" + "github.com/ossf/scorecard/v2/clients/githubrepo/roundtripper" sce "github.com/ossf/scorecard/v2/errors" ) @@ -164,8 +168,15 @@ func (client *Client) Close() error { } // CreateGithubRepoClient returns a Client which implements RepoClient interface. -func CreateGithubRepoClient(ctx context.Context, - client *github.Client, graphClient *githubv4.Client) clients.RepoClient { +func CreateGithubRepoClient(ctx context.Context, logger *zap.Logger) clients.RepoClient { + // Use our custom roundtripper + rt := roundtripper.NewTransport(ctx, logger.Sugar()) + httpClient := &http.Client{ + Transport: rt, + } + client := github.NewClient(httpClient) + graphClient := githubv4.NewClient(httpClient) + return &Client{ ctx: ctx, repoClient: client, @@ -196,3 +207,14 @@ func CreateGithubRepoClient(ctx context.Context, }, } } + +// NewLogger creates an instance of *zap.Logger. +func NewLogger(logLevel zapcore.Level) (*zap.Logger, error) { + cfg := zap.NewProductionConfig() + cfg.Level.SetLevel(logLevel) + logger, err := cfg.Build() + if err != nil { + return nil, fmt.Errorf("cfg.Build: %w", err) + } + return logger, nil +} diff --git a/roundtripper/census.go b/clients/githubrepo/roundtripper/census.go similarity index 100% rename from roundtripper/census.go rename to clients/githubrepo/roundtripper/census.go diff --git a/roundtripper/rate_limit.go b/clients/githubrepo/roundtripper/rate_limit.go similarity index 100% rename from roundtripper/rate_limit.go rename to clients/githubrepo/roundtripper/rate_limit.go diff --git a/roundtripper/roundtripper.go b/clients/githubrepo/roundtripper/roundtripper.go similarity index 94% rename from roundtripper/roundtripper.go rename to clients/githubrepo/roundtripper/roundtripper.go index b7ac7c35..fa700f45 100644 --- a/roundtripper/roundtripper.go +++ b/clients/githubrepo/roundtripper/roundtripper.go @@ -25,8 +25,6 @@ import ( "github.com/bradleyfalzon/ghinstallation" "go.uber.org/zap" - - "github.com/ossf/scorecard/v2/clients/githubrepo" ) // GithubAuthTokens are for making requests to GiHub's API. @@ -58,7 +56,7 @@ func NewTransport(ctx context.Context, logger *zap.SugaredLogger) http.RoundTrip // nolint if token, exists := readGitHubTokens(); exists { // Use GitHub PAT - transport = githubrepo.MakeGitHubTransport(transport, strings.Split(token, ",")) + transport = MakeGitHubTransport(transport, strings.Split(token, ",")) } else if keyPath := os.Getenv(GithubAppKeyPath); keyPath != "" { // Also try a GITHUB_APP appID, err := strconv.Atoi(os.Getenv(GithubAppID)) if err != nil { diff --git a/clients/githubrepo/transport.go b/clients/githubrepo/roundtripper/transport.go similarity index 86% rename from clients/githubrepo/transport.go rename to clients/githubrepo/roundtripper/transport.go index b99c8501..6905af54 100644 --- a/clients/githubrepo/transport.go +++ b/clients/githubrepo/roundtripper/transport.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package githubrepo +package roundtripper import ( "fmt" @@ -22,6 +22,8 @@ import ( "go.opencensus.io/stats" "go.opencensus.io/tag" + + githubstats "github.com/ossf/scorecard/v2/clients/githubrepo/stats" ) // MakeGitHubTransport wraps input RoundTripper with GitHub authorization logic. @@ -52,13 +54,13 @@ func (gt *githubTransport) RoundTrip(r *http.Request) (*http.Response, error) { if err != nil { return nil, fmt.Errorf("error in HTTP: %w", err) } - ctx, err := tag.New(r.Context(), tag.Upsert(ResourceType, resp.Header.Get("X-RateLimit-Resource"))) + ctx, err := tag.New(r.Context(), tag.Upsert(githubstats.ResourceType, resp.Header.Get("X-RateLimit-Resource"))) if err != nil { return nil, fmt.Errorf("error updating context: %w", err) } remaining, err := strconv.Atoi(resp.Header.Get("X-RateLimit-Remaining")) if err == nil { - stats.Record(ctx, RemainingTokens.M(int64(remaining))) + stats.Record(ctx, githubstats.RemainingTokens.M(int64(remaining))) } return resp, nil } @@ -79,7 +81,7 @@ func (roundRobin *roundRobinAccessor) next(r *http.Request) (string, error) { l := len(roundRobin.accessTokens) index := c % uint64(l) - ctx, err := tag.New(r.Context(), tag.Upsert(TokenIndex, fmt.Sprint(index))) + ctx, err := tag.New(r.Context(), tag.Upsert(githubstats.TokenIndex, fmt.Sprint(index))) if err != nil { return "", fmt.Errorf("error updating context: %w", err) } diff --git a/clients/githubrepo/stats.go b/clients/githubrepo/stats/stats.go similarity index 98% rename from clients/githubrepo/stats.go rename to clients/githubrepo/stats/stats.go index 0b7e8890..304b8d98 100644 --- a/clients/githubrepo/stats.go +++ b/clients/githubrepo/stats/stats.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package githubrepo +package stats import ( "go.opencensus.io/stats" diff --git a/cmd/root.go b/cmd/root.go index d56f9849..db29a356 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -27,8 +27,6 @@ import ( "strings" "time" - "github.com/google/go-github/v38/github" - "github.com/shurcooL/githubv4" "github.com/spf13/cobra" "go.uber.org/zap" @@ -39,7 +37,6 @@ import ( sce "github.com/ossf/scorecard/v2/errors" "github.com/ossf/scorecard/v2/pkg" "github.com/ossf/scorecard/v2/repos" - "github.com/ossf/scorecard/v2/roundtripper" ) var ( @@ -73,15 +70,6 @@ or ./scorecard --{npm,pypi,rubgems}= [--checks=check1,...] [--show if _, v3 = os.LookupEnv("SCORECARD_V3"); v3 { fmt.Printf("**** Using SCORECARD_V3 code ***** \n\n") } - cfg := zap.NewProductionConfig() - cfg.Level.SetLevel(*logLevel) - logger, err := cfg.Build() - if err != nil { - log.Fatalf("unable to construct logger: %v", err) - } - // nolint - defer logger.Sync() // flushes buffer, if any - sugar := logger.Sugar() if npm != "" { if git, err := fetchGitRepositoryFromNPM(npm); err != nil { @@ -134,15 +122,17 @@ or ./scorecard --{npm,pypi,rubgems}= [--checks=check1,...] [--show } ctx := context.Background() - rt := roundtripper.NewTransport(ctx, sugar) - httpClient := &http.Client{ - Transport: rt, + logger, err := githubrepo.NewLogger(*logLevel) + if err != nil { + panic(err) } - githubClient := github.NewClient(httpClient) - graphClient := githubv4.NewClient(httpClient) - repoClient := githubrepo.CreateGithubRepoClient(ctx, githubClient, graphClient) + // nolint + defer logger.Sync() // flushes buffer, if any - repoResult, err := pkg.RunScorecards(ctx, repo, enabledChecks, repoClient, httpClient, githubClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(ctx, logger) + defer repoClient.Close() + + repoResult, err := pkg.RunScorecards(ctx, repo, enabledChecks, repoClient) if err != nil { log.Fatal(err) } diff --git a/cmd/serve.go b/cmd/serve.go index 9b7a87dc..89fc1a24 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -22,16 +22,12 @@ import ( "os" "strings" - "github.com/google/go-github/v38/github" - "github.com/shurcooL/githubv4" "github.com/spf13/cobra" - "go.uber.org/zap" "github.com/ossf/scorecard/v2/checks" "github.com/ossf/scorecard/v2/clients/githubrepo" "github.com/ossf/scorecard/v2/pkg" "github.com/ossf/scorecard/v2/repos" - "github.com/ossf/scorecard/v2/roundtripper" ) //nolint:gochecknoinits @@ -44,9 +40,7 @@ var serveCmd = &cobra.Command{ Short: "Serve the scorecard program over http", Long: ``, Run: func(cmd *cobra.Command, args []string) { - cfg := zap.NewProductionConfig() - cfg.Level.SetLevel(*logLevel) - logger, err := cfg.Build() + logger, err := githubrepo.NewLogger(*logLevel) if err != nil { log.Fatalf("unable to construct logger: %v", err) } @@ -69,16 +63,9 @@ var serveCmd = &cobra.Command{ if err := repo.Set(repoParam); err != nil { rw.WriteHeader(http.StatusBadRequest) } - sugar.Info(repoParam) ctx := r.Context() - rt := roundtripper.NewTransport(ctx, sugar) - httpClient := &http.Client{ - Transport: rt, - } - githubClient := github.NewClient(httpClient) - graphClient := githubv4.NewClient(httpClient) - repoClient := githubrepo.CreateGithubRepoClient(ctx, githubClient, graphClient) - repoResult, err := pkg.RunScorecards(ctx, repo, checks.AllChecks, repoClient, httpClient, githubClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(ctx, logger) + repoResult, err := pkg.RunScorecards(ctx, repo, checks.AllChecks, repoClient) if err != nil { sugar.Error(err) rw.WriteHeader(http.StatusInternalServerError) diff --git a/cron/worker/main.go b/cron/worker/main.go index 63153dc8..4e50d16d 100644 --- a/cron/worker/main.go +++ b/cron/worker/main.go @@ -27,8 +27,6 @@ import ( // nolint:gosec _ "net/http/pprof" - "github.com/google/go-github/v38/github" - "github.com/shurcooL/githubv4" "go.opencensus.io/stats/view" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -37,6 +35,7 @@ import ( "github.com/ossf/scorecard/v2/checks" "github.com/ossf/scorecard/v2/clients" "github.com/ossf/scorecard/v2/clients/githubrepo" + githubstats "github.com/ossf/scorecard/v2/clients/githubrepo/stats" "github.com/ossf/scorecard/v2/cron/config" "github.com/ossf/scorecard/v2/cron/data" "github.com/ossf/scorecard/v2/cron/monitoring" @@ -44,7 +43,6 @@ import ( sce "github.com/ossf/scorecard/v2/errors" "github.com/ossf/scorecard/v2/pkg" "github.com/ossf/scorecard/v2/repos" - "github.com/ossf/scorecard/v2/roundtripper" "github.com/ossf/scorecard/v2/stats" ) @@ -53,8 +51,7 @@ var ignoreRuntimeErrors = flag.Bool("ignoreRuntimeErrors", false, "if set to tru func processRequest(ctx context.Context, batchRequest *data.ScorecardBatchRequest, checksToRun checker.CheckNameToFnMap, bucketURL, bucketURL2 string, - repoClient clients.RepoClient, - httpClient *http.Client, githubClient *github.Client, graphClient *githubv4.Client) error { + repoClient clients.RepoClient) error { filename := data.GetBlobFilename( fmt.Sprintf("shard-%05d", batchRequest.GetShardNum()), batchRequest.GetJobTime().AsTime()) @@ -91,7 +88,7 @@ func processRequest(ctx context.Context, // TODO: run Scorecard for each repo in a separate thread. for _, repoURL := range repoURLs { log.Printf("Running Scorecard for repo: %s", repoURL.URL()) - result, err := pkg.RunScorecards(ctx, repoURL, checksToRun, repoClient, httpClient, githubClient, graphClient) + result, err := pkg.RunScorecards(ctx, repoURL, checksToRun, repoClient) if errors.Is(err, sce.ErrRepoUnreachable) { // Not accessible repo - continue. continue @@ -133,28 +130,6 @@ func processRequest(ctx context.Context, return nil } -func createNetClients(ctx context.Context) ( - repoClient clients.RepoClient, - httpClient *http.Client, - githubClient *github.Client, graphClient *githubv4.Client, logger *zap.Logger) { - cfg := zap.NewProductionConfig() - cfg.Level.SetLevel(zap.InfoLevel) - logger, err := cfg.Build() - if err != nil { - panic(err) - } - sugar := logger.Sugar() - // Use our custom roundtripper - rt := roundtripper.NewTransport(ctx, sugar) - httpClient = &http.Client{ - Transport: rt, - } - githubClient = github.NewClient(httpClient) - graphClient = githubv4.NewClient(httpClient) - repoClient = githubrepo.CreateGithubRepoClient(ctx, githubClient, graphClient) - return -} - func startMetricsExporter() (monitoring.Exporter, error) { exporter, err := monitoring.GetExporter() if err != nil { @@ -169,7 +144,7 @@ func startMetricsExporter() (monitoring.Exporter, error) { &stats.CheckErrorCount, &stats.RepoRuntime, &stats.OutgoingHTTPRequests, - &githubrepo.GithubTokens); err != nil { + &githubstats.GithubTokens); err != nil { return nil, fmt.Errorf("error during view.Register: %w", err) } return exporter, nil @@ -199,7 +174,11 @@ func main() { panic(err) } - repoClient, httpClient, githubClient, graphClient, logger := createNetClients(ctx) + logger, err := githubrepo.NewLogger(zap.InfoLevel) + if err != nil { + panic(err) + } + repoClient := githubrepo.CreateGithubRepoClient(ctx, logger) exporter, err := startMetricsExporter() if err != nil { @@ -229,7 +208,7 @@ func main() { break } if err := processRequest(ctx, req, checksToRun, bucketURL, bucketURL2, - repoClient, httpClient, githubClient, graphClient); err != nil { + repoClient); err != nil { log.Printf("error processing request: %v", err) // Nack the message so that another worker can retry. subscriber.Nack() diff --git a/e2e/binary_artifacts_test.go b/e2e/binary_artifacts_test.go index dd191387..e3992c20 100644 --- a/e2e/binary_artifacts_test.go +++ b/e2e/binary_artifacts_test.go @@ -33,18 +33,16 @@ var _ = Describe("E2E TEST:"+checks.CheckBinaryArtifacts, func() { Context("E2E TEST:Binary artifacts are not present in source code", func() { It("Should return not binary artifacts in source code", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf", "scorecard") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - RepoClient: repoClient, - Owner: "ossf", - Repo: "scorecard", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf", + Repo: "scorecard", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, @@ -64,18 +62,16 @@ var _ = Describe("E2E TEST:"+checks.CheckBinaryArtifacts, func() { }) It("Should return binary artifacts present in source code", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-binary-artifacts-e2e") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-binary-artifacts-e2e", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-binary-artifacts-e2e", + Dlogger: &dl, } // TODO: upload real binaries to the repo as well. expected := scut.TestReturn{ diff --git a/e2e/branch_protection_test.go b/e2e/branch_protection_test.go index c39b1040..c44cd7bb 100644 --- a/e2e/branch_protection_test.go +++ b/e2e/branch_protection_test.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// nolint: dupl package e2e import ( @@ -31,18 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckBranchProtection, func() { Context("E2E TEST:Validating branch protection", func() { It("Should fail to return branch protection on other repositories", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("apache", "airflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "apache", - Repo: "airflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "apache", + Repo: "airflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, @@ -62,18 +58,15 @@ var _ = Describe("E2E TEST:"+checks.CheckBranchProtection, func() { Context("E2E TEST:Validating branch protection", func() { It("Should fail to return branch protection on other repositories", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-branch-protection-e2e") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-branch-protection-e2e", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-branch-protection-e2e", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/ci_tests_test.go b/e2e/ci_tests_test.go index 14b29de9..37b86e40 100644 --- a/e2e/ci_tests_test.go +++ b/e2e/ci_tests_test.go @@ -31,18 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckCITests, func() { Context("E2E TEST:Validating use of CI tests", func() { It("Should return use of CI tests", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("apache", "airflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "apache", - Repo: "airflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "apache", + Repo: "airflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/cii_best_practices_test.go b/e2e/cii_best_practices_test.go index 11004978..8e58df1a 100644 --- a/e2e/cii_best_practices_test.go +++ b/e2e/cii_best_practices_test.go @@ -30,14 +30,11 @@ var _ = Describe("E2E TEST:CIIBestPractices", func() { It("Should return use of CII Best Practices", func() { dl := scut.TestDetailLogger{} req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: nil, - Owner: "tensorflow", - Repo: "tensorflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: nil, + Owner: "tensorflow", + Repo: "tensorflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/code_review_test.go b/e2e/code_review_test.go index 6c72bc38..a15a67f8 100644 --- a/e2e/code_review_test.go +++ b/e2e/code_review_test.go @@ -33,19 +33,16 @@ var _ = Describe("E2E TEST:CodeReview", func() { Context("E2E TEST:Validating use of code reviews", func() { It("Should return use of code reviews", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("apache", "airflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "apache", - Repo: "airflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "apache", + Repo: "airflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/contributors_test.go b/e2e/contributors_test.go index 3b52dd7a..7886538e 100644 --- a/e2e/contributors_test.go +++ b/e2e/contributors_test.go @@ -31,18 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckContributors, func() { Context("E2E TEST:Validating project contributors", func() { It("Should return valid project contributors", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf", "scorecard") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf", - Repo: "scorecard", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf", + Repo: "scorecard", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, @@ -61,18 +58,15 @@ var _ = Describe("E2E TEST:"+checks.CheckContributors, func() { }) It("Should return valid project contributors", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("apache", "airflow") Expect(err).Should(BeNil()) checkRequest := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "apache", - Repo: "airflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "apache", + Repo: "airflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/dependency_update_tool_test.go b/e2e/dependency_update_tool_test.go index 6745dcd6..dff221b3 100644 --- a/e2e/dependency_update_tool_test.go +++ b/e2e/dependency_update_tool_test.go @@ -33,18 +33,16 @@ var _ = Describe("E2E TEST:"+checks.CheckDependencyUpdateTool, func() { Context("E2E TEST:Validating dependencies are updated with a tool", func() { It("Should return repo uses dependabot", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf", "scorecard") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - RepoClient: repoClient, - Owner: "ossf", - Repo: "scorecard", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf", + Repo: "scorecard", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, @@ -64,18 +62,16 @@ var _ = Describe("E2E TEST:"+checks.CheckDependencyUpdateTool, func() { }) It("Should return repo uses renovatebot", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("netlify", "netlify-cms") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - RepoClient: repoClient, - Owner: "netlify", - Repo: "netlify-cms", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "netlify", + Repo: "netlify-cms", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/e2e_suite_test.go b/e2e/e2e_suite_test.go index 20c3ede9..6fa25564 100644 --- a/e2e/e2e_suite_test.go +++ b/e2e/e2e_suite_test.go @@ -15,25 +15,17 @@ package e2e import ( - "context" - "net/http" "os" "testing" - "github.com/google/go-github/v38/github" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/shurcooL/githubv4" "go.uber.org/zap" - "github.com/ossf/scorecard/v2/roundtripper" + "github.com/ossf/scorecard/v2/clients/githubrepo" ) -var ( - ghClient *github.Client - graphClient *githubv4.Client - httpClient *http.Client -) +var logger *zap.Logger func TestE2e(t *testing.T) { t.Parallel() @@ -49,27 +41,9 @@ var _ = BeforeSuite(func() { "GITHUB_AUTH_TOKEN env variable is not set.The GITHUB_AUTH_TOKEN env variable has to be set to run e2e test.") Expect(len(token)).ShouldNot(BeZero(), "Length of the GITHUB_AUTH_TOKEN env variable is zero.") - ctx := context.TODO() - - logLevel := zap.LevelFlag("verbosity", zap.InfoLevel, "override the default log level") - cfg := zap.NewProductionConfig() - cfg.Level.SetLevel(*logLevel) - logger, err := cfg.Build() + l, err := githubrepo.NewLogger(zap.InfoLevel) Expect(err).Should(BeNil()) - - sugar := logger.Sugar() - // nolint - defer logger.Sync() // flushes buffer, if any - Expect(sugar).ShouldNot(BeNil()) - - rt := roundtripper.NewTransport(ctx, sugar) - - httpClient = &http.Client{ - Transport: rt, - } - - ghClient = github.NewClient(httpClient) - graphClient = githubv4.NewClient(httpClient) + logger = l }) var _ = AfterSuite(func() { diff --git a/e2e/fuzzing_test.go b/e2e/fuzzing_test.go index 25983723..274ab470 100644 --- a/e2e/fuzzing_test.go +++ b/e2e/fuzzing_test.go @@ -31,18 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() { Context("E2E TEST:Validating use of fuzzing tools", func() { It("Should return use of fuzzing tools", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("tensorflow", "tensorflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "tensorflow", - Repo: "tensorflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "tensorflow", + Repo: "tensorflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/maintained_test.go b/e2e/maintained_test.go index a7a270eb..76fb0f3b 100644 --- a/e2e/maintained_test.go +++ b/e2e/maintained_test.go @@ -31,18 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckMaintained, func() { Context("E2E TEST:Validating maintained status", func() { It("Should return valid maintained status", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("apache", "airflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "apache", - Repo: "airflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "apache", + Repo: "airflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/packaging_test.go b/e2e/packaging_test.go index d7383dd6..68643a8f 100644 --- a/e2e/packaging_test.go +++ b/e2e/packaging_test.go @@ -31,18 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckPackaging, func() { Context("E2E TEST:Validating use of packaging in CI/CD", func() { It("Should return use of packaging in CI/CD", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-packaging-e2e") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-packaging-e2e", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-packaging-e2e", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/permissions_test.go b/e2e/permissions_test.go index fe23bbf1..9cc3eaca 100644 --- a/e2e/permissions_test.go +++ b/e2e/permissions_test.go @@ -30,18 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckTokenPermissions, func() { Context("E2E TEST:Validating token permission check", func() { It("Should return token permission works", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-token-permissions-e2e") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-token-permissions-e2e", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-token-permissions-e2e", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/pinned_dependencies_test.go b/e2e/pinned_dependencies_test.go index 9cd4d79f..91f87ef0 100644 --- a/e2e/pinned_dependencies_test.go +++ b/e2e/pinned_dependencies_test.go @@ -32,19 +32,16 @@ var _ = Describe("E2E TEST:"+checks.CheckPinnedDependencies, func() { Context("E2E TEST:Validating dependencies check is working", func() { It("Should return dependencies check is working", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-pinned-dependencies-e2e") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-pinned-dependencies-e2e", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-pinned-dependencies-e2e", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/sast_test.go b/e2e/sast_test.go index c75623c4..651f00d1 100644 --- a/e2e/sast_test.go +++ b/e2e/sast_test.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// nolint: dupl package e2e import ( @@ -31,18 +30,15 @@ var _ = Describe("E2E TEST:"+checks.CheckSAST, func() { Context("E2E TEST:Validating use of SAST tools", func() { It("Should return use of SAST tools", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("apache", "airflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "apache", - Repo: "airflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "apache", + Repo: "airflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/security_policy_test.go b/e2e/security_policy_test.go index d2e73b39..29b8009c 100644 --- a/e2e/security_policy_test.go +++ b/e2e/security_policy_test.go @@ -30,19 +30,16 @@ var _ = Describe("E2E TEST:SecurityPolicy", func() { Context("E2E TEST:Validating security policy", func() { It("Should return valid security policy", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("tensorflow", "tensorflow") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "tensorflow", - Repo: "tensorflow", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "tensorflow", + Repo: "tensorflow", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, @@ -61,19 +58,16 @@ var _ = Describe("E2E TEST:SecurityPolicy", func() { }) It("Should return valid security policy for rust repositories", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("randombit", "botan") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "randombit", - Repo: "botan", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "randombit", + Repo: "botan", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/signedreleases_test.go b/e2e/signedreleases_test.go index cd840456..b02c3f57 100644 --- a/e2e/signedreleases_test.go +++ b/e2e/signedreleases_test.go @@ -31,18 +31,15 @@ var _ = Describe("E2E TEST:"+checks.CheckSignedReleases, func() { Context("E2E TEST:Validating signed releases", func() { It("Should return valid signed releases", func() { dl := scut.TestDetailLogger{} - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-signed-releases-e2e") Expect(err).Should(BeNil()) req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-signed-releases-e2e", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-signed-releases-e2e", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/e2e/vulnerabilities_test.go b/e2e/vulnerabilities_test.go index 71b69dbf..b9c8d029 100644 --- a/e2e/vulnerabilities_test.go +++ b/e2e/vulnerabilities_test.go @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//nolint:dupl // repeating test cases that are slightly different is acceptable package e2e import ( @@ -30,20 +29,17 @@ import ( var _ = Describe("E2E TEST:Vulnerabilities", func() { Context("E2E TEST:Validating vulnerabilities status", func() { It("Should return that there are no vulnerabilities", func() { - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf", "scorecard") Expect(err).Should(BeNil()) dl := scut.TestDetailLogger{} req := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf", - Repo: "scorecard", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf", + Repo: "scorecard", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, @@ -62,20 +58,17 @@ var _ = Describe("E2E TEST:Vulnerabilities", func() { }) It("Should return that there are vulnerabilities", func() { - repoClient := githubrepo.CreateGithubRepoClient(context.Background(), ghClient, graphClient) + repoClient := githubrepo.CreateGithubRepoClient(context.Background(), logger) err := repoClient.InitRepo("ossf-tests", "scorecard-check-vulnerabilities-open62541") Expect(err).Should(BeNil()) dl := scut.TestDetailLogger{} checkRequest := checker.CheckRequest{ - Ctx: context.Background(), - Client: ghClient, - HTTPClient: httpClient, - RepoClient: repoClient, - Owner: "ossf-tests", - Repo: "scorecard-check-vulnerabilities-open62541", - GraphClient: graphClient, - Dlogger: &dl, + Ctx: context.Background(), + RepoClient: repoClient, + Owner: "ossf-tests", + Repo: "scorecard-check-vulnerabilities-open62541", + Dlogger: &dl, } expected := scut.TestReturn{ Error: nil, diff --git a/pkg/scorecard.go b/pkg/scorecard.go index cc986dcc..388b37ff 100644 --- a/pkg/scorecard.go +++ b/pkg/scorecard.go @@ -18,12 +18,9 @@ package pkg import ( "context" "fmt" - "net/http" "sync" "time" - "github.com/google/go-github/v38/github" - "github.com/shurcooL/githubv4" opencensusstats "go.opencensus.io/stats" "go.opencensus.io/tag" @@ -41,16 +38,12 @@ func logStats(ctx context.Context, startTime time.Time) { func runEnabledChecks(ctx context.Context, repo repos.RepoURL, checksToRun checker.CheckNameToFnMap, repoClient clients.RepoClient, - httpClient *http.Client, githubClient *github.Client, graphClient *githubv4.Client, resultsCh chan checker.CheckResult) { request := checker.CheckRequest{ - Ctx: ctx, - Client: githubClient, - RepoClient: repoClient, - HTTPClient: httpClient, - Owner: repo.Owner, - Repo: repo.Repo, - GraphClient: graphClient, + Ctx: ctx, + RepoClient: repoClient, + Owner: repo.Owner, + Repo: repo.Repo, } wg := sync.WaitGroup{} for checkName, checkFn := range checksToRun { @@ -75,10 +68,7 @@ func runEnabledChecks(ctx context.Context, func RunScorecards(ctx context.Context, repo repos.RepoURL, checksToRun checker.CheckNameToFnMap, - repoClient clients.RepoClient, - httpClient *http.Client, - githubClient *github.Client, - graphClient *githubv4.Client) (ScorecardResult, error) { + repoClient clients.RepoClient) (ScorecardResult, error) { ctx, err := tag.New(ctx, tag.Upsert(stats.Repo, repo.URL())) if err != nil { //nolint:wrapcheck @@ -113,9 +103,7 @@ func RunScorecards(ctx context.Context, Date: time.Now(), } resultsCh := make(chan checker.CheckResult) - go runEnabledChecks(ctx, repo, checksToRun, repoClient, - httpClient, githubClient, graphClient, - resultsCh) + go runEnabledChecks(ctx, repo, checksToRun, repoClient, resultsCh) for result := range resultsCh { ret.Checks = append(ret.Checks, result) }