Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip empty repositories for Allstar policy enforcement #471

Merged
merged 4 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions pkg/enforce/enforce.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package enforce
import (
"context"
"fmt"
"net/http"
"sync"
"time"

Expand Down Expand Up @@ -48,6 +49,7 @@ var getAppInstallationRepos func(context.Context, *github.Client) ([]*github.Rep
var runPolicies func(context.Context, *github.Client, string, string, bool, string) (EnforceRepoResults, error)
var deleteInstallation func(context.Context, *github.Client, int64) (*github.Response, error)
var listInstallations func(context.Context, *github.Client) ([]*github.Installation, error)
var isRepositoryEmpty func(context.Context, *github.Client, string, string, string) (bool, error)

func init() {
policiesGetPolicies = policies.GetPolicies
Expand All @@ -59,6 +61,7 @@ func init() {
runPolicies = runPoliciesReal
deleteInstallation = deleteInstallationReal
listInstallations = listInstallationsReal
isRepositoryEmpty = isRepositoryEmptyReal
}

// EnforceAll iterates through all available installations and repos Allstar
Expand Down Expand Up @@ -318,6 +321,25 @@ func EnforceJob(ctx context.Context, ghc *ghclients.GHClients, d time.Duration,
}
}

// returns true if the repository has content and false if it's empty
func isRepositoryEmptyReal(ctx context.Context, c *github.Client, owner, repo, policy string) (bool, error) {
opts := github.RepositoryContentGetOptions{}
file, dirs, resp, err := c.Repositories.GetContents(ctx, owner, repo, "", &opts)
if err != nil && resp.StatusCode != http.StatusNotFound {
return false, err
}
if file == nil && len(dirs) == 0 {
log.Info().
Str("org", owner).
Str("repo", repo).
Str("area", policy).
Msg("Repository is empty, skipping")
return true, nil
}

return false, nil
}

// runPoliciesReal enforces policies on the provided repo. It is meant to be called
// from either jobs, webhooks, or delayed checks. TODO: implement concurrency
// check to only run a single instance per repo at a time.
Expand Down Expand Up @@ -350,6 +372,16 @@ func runPoliciesReal(ctx context.Context, c *github.Client, owner, repo string,
Msg("Policy run skipped as repo is not enabled and doNothingOnOptOut is configured.")
continue
}

isEmpty, err := isRepositoryEmpty(ctx, c, owner, repo, p.Name())
if err != nil {
return nil, err
}

if isEmpty {
continue
}

r, err := p.Check(ctx, c, owner, repo)
if err != nil {
return nil, err
Expand Down
39 changes: 39 additions & 0 deletions pkg/enforce/enforce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,42 @@ func (m MockGhClients) Get(i int64) (*github.Client, error) {

func (m MockGhClients) LogCacheSize() {}

func TestSkipEmptyRepositories(t *testing.T) {
policiesGetPolicies = func() []policydef.Policy {
return []policydef.Policy{
pol{},
}
}

isRepositoryEmpty = func(ctx context.Context, c *github.Client, s1, s2, s3 string) (bool, error) {
return true, nil
}

repo := "fake-repo"

tests := []struct {
Desc string
}{
{
Desc: "test skip a single empty repository",
},
}

for _, test := range tests {
t.Run(test.Desc, func(t *testing.T) {
enforceResults, err := runPoliciesReal(context.Background(), nil, "", repo, true, "")

if err != nil {
t.Fatalf("Unexpected error: %v", err)
}

if len(enforceResults) != 0 {
t.Errorf("expected no policy results, got %+v\n", enforceResults)
}
})
}
}

func TestRunPolicies(t *testing.T) {
policiesGetPolicies = func() []policydef.Policy {
return []policydef.Policy{
Expand All @@ -107,6 +143,9 @@ func TestRunPolicies(t *testing.T) {
closeCalled = true
return nil
}
isRepositoryEmpty = func(ctx context.Context, c *github.Client, s1, s2, s3 string) (bool, error) {
return false, nil
}
repo := "fake-repo"
tests := []struct {
Name string
Expand Down