Skip to content

Commit

Permalink
Add pull request support to SCM generator
Browse files Browse the repository at this point in the history
This commit adds pull request support to SCM generator so the generator
can create ArgoCD apps for PRs as well.

Fixes argoproj#466

Signed-off-by: Fardin Khanjani <[email protected]>
  • Loading branch information
fardin01 committed Jan 20, 2022
1 parent c8fb714 commit a9db23f
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 32 deletions.
2 changes: 2 additions & 0 deletions api/v1alpha1/applicationset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ type SCMProviderGeneratorGithub struct {
TokenRef *SecretRef `json:"tokenRef,omitempty"`
// Scan all branches instead of just the default branch.
AllBranches bool `json:"allBranches,omitempty"`
// Scan all pull requests
AllPullRequests bool `json:"allPullRequests,omitempty"`
}

// SCMProviderGeneratorGitlab defines a connection info specific to Gitlab.
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions manifests/crds/argoproj.io_applicationsets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3890,6 +3890,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -5706,6 +5708,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -6347,6 +6351,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -9609,6 +9615,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -11425,6 +11433,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -12066,6 +12076,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -12973,6 +12985,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down
14 changes: 14 additions & 0 deletions manifests/install-with-argo-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5707,6 +5707,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -7523,6 +7525,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -8164,6 +8168,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -11426,6 +11432,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -13242,6 +13250,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -13883,6 +13893,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -14790,6 +14802,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down
14 changes: 14 additions & 0 deletions manifests/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3889,6 +3889,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -5705,6 +5707,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -6346,6 +6350,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -9608,6 +9614,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -11424,6 +11432,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -12065,6 +12075,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down Expand Up @@ -12972,6 +12984,8 @@ spec:
properties:
allBranches:
type: boolean
allPullRequests:
type: boolean
api:
type: string
organization:
Expand Down
4 changes: 2 additions & 2 deletions pkg/generators/scm_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
if err != nil {
return nil, fmt.Errorf("error fetching Github token: %v", err)
}
provider, err = scm_provider.NewGithubProvider(ctx, providerConfig.Github.Organization, token, providerConfig.Github.API, providerConfig.Github.AllBranches)
provider, err = scm_provider.NewGithubProvider(ctx, providerConfig.Github.Organization, token, providerConfig.Github.API, providerConfig.Github.AllBranches, providerConfig.Github.AllPullRequests)
if err != nil {
return nil, fmt.Errorf("error initializing Github service: %v", err)
}
Expand Down Expand Up @@ -92,7 +92,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
"organization": repo.Organization,
"repository": repo.Repository,
"url": repo.URL,
"branch": repo.Branch,
"revision": repo.Revision,
"sha": repo.SHA,
"labels": strings.Join(repo.Labels, ","),
})
Expand Down
6 changes: 3 additions & 3 deletions pkg/generators/scm_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ func TestSCMProviderGenerateParams(t *testing.T) {
Organization: "myorg",
Repository: "repo1",
URL: "[email protected]:myorg/repo1.git",
Branch: "main",
Revision: "main",
SHA: "abcd1234",
Labels: []string{"prod", "staging"},
},
{
Organization: "myorg",
Repository: "repo2",
URL: "[email protected]:myorg/repo2.git",
Branch: "main",
Revision: "main",
SHA: "00000000",
},
},
Expand All @@ -108,7 +108,7 @@ func TestSCMProviderGenerateParams(t *testing.T) {
assert.Equal(t, "myorg", params[0]["organization"])
assert.Equal(t, "repo1", params[0]["repository"])
assert.Equal(t, "[email protected]:myorg/repo1.git", params[0]["url"])
assert.Equal(t, "main", params[0]["branch"])
assert.Equal(t, "main", params[0]["revision"])
assert.Equal(t, "abcd1234", params[0]["sha"])
assert.Equal(t, "prod,staging", params[0]["labels"])
assert.Equal(t, "repo2", params[1]["repository"])
Expand Down
61 changes: 54 additions & 7 deletions pkg/services/scm_provider/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ import (
"context"
"fmt"
"os"
"strconv"

"github.com/google/go-github/v35/github"
"golang.org/x/oauth2"
)

type GithubProvider struct {
client *github.Client
organization string
allBranches bool
client *github.Client
organization string
allBranches bool
allPullRequests bool
}

var _ SCMProviderService = &GithubProvider{}

func NewGithubProvider(ctx context.Context, organization string, token string, url string, allBranches bool) (*GithubProvider, error) {
func NewGithubProvider(ctx context.Context, organization string, token string, url string, allBranches bool, allPullRequests bool) (*GithubProvider, error) {
var ts oauth2.TokenSource
// Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits.
if token == "" {
Expand All @@ -39,7 +41,8 @@ func NewGithubProvider(ctx context.Context, organization string, token string, u
return nil, err
}
}
return &GithubProvider{client: client, organization: organization, allBranches: allBranches}, nil

return &GithubProvider{client: client, organization: organization, allBranches: allBranches, allPullRequests: allPullRequests}, nil
}

func (g *GithubProvider) ListRepos(ctx context.Context, cloneProtocol string) ([]*Repository, error) {
Expand Down Expand Up @@ -74,11 +77,29 @@ func (g *GithubProvider) ListRepos(ctx context.Context, cloneProtocol string) ([
Organization: githubRepo.Owner.GetLogin(),
Repository: githubRepo.GetName(),
URL: url,
Branch: branch.GetName(),
Revision: branch.GetName(),
SHA: branch.GetCommit().GetSHA(),
Labels: githubRepo.Topics,
})
}

if g.allPullRequests {
pullRequests, err := g.listPullRequests(ctx, githubRepo)
if err != nil {
return nil, fmt.Errorf("error listing pull requests for %s/%s: %v", githubRepo.Owner.GetLogin(), githubRepo.GetName(), err)
}

for _, pr := range pullRequests {
repos = append(repos, &Repository{
Organization: githubRepo.Owner.GetLogin(),
Repository: githubRepo.GetName(),
URL: url,
Revision: strconv.FormatInt(int64(pr.GetNumber()), 10), // PR number is an int
SHA: pr.GetHead().GetSHA(),
Labels: githubRepo.Topics,
})
}
}
}
if resp.NextPage == 0 {
break
Expand All @@ -90,7 +111,7 @@ func (g *GithubProvider) ListRepos(ctx context.Context, cloneProtocol string) ([

func (g *GithubProvider) RepoHasPath(ctx context.Context, repo *Repository, path string) (bool, error) {
_, _, resp, err := g.client.Repositories.GetContents(ctx, repo.Organization, repo.Repository, path, &github.RepositoryContentGetOptions{
Ref: repo.Branch,
Ref: repo.SHA,
})
// 404s are not an error here, just a normal false.
if resp != nil && resp.StatusCode == 404 {
Expand Down Expand Up @@ -132,3 +153,29 @@ func (g *GithubProvider) listBranches(ctx context.Context, repo *github.Reposito
}
return branches, nil
}

func (g *GithubProvider) listPullRequests(ctx context.Context, repo *github.Repository) ([]github.PullRequest, error) {
opt := &github.PullRequestListOptions{
ListOptions: github.ListOptions{PerPage: 100},
}

pullRequests := []github.PullRequest{}

for {
allPullRequests, resp, err := g.client.PullRequests.List(ctx, repo.Owner.GetLogin(), repo.GetName(), opt)
if err != nil {
return nil, err
}

for _, pr := range allPullRequests {
pullRequests = append(pullRequests, *pr)
}

if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}

return pullRequests, nil
}
Loading

0 comments on commit a9db23f

Please sign in to comment.