From 3ca5631f29646a430531b4a4084cca2732dd7573 Mon Sep 17 00:00:00 2001 From: Mikhail Nacharov Date: Wed, 8 Feb 2023 12:29:31 +0400 Subject: [PATCH] feat: add notLabels to applicationset pullrequest generator (#12300) Signed-off-by: Mikhail Nacharov --- applicationset/generators/pull_request.go | 6 +-- .../services/pull_request/github.go | 43 +++++++++++++++---- .../services/pull_request/github_app.go | 11 ++--- .../services/pull_request/gitlab.go | 12 ++++-- .../v1alpha1/applicationset_types.go | 4 ++ 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/applicationset/generators/pull_request.go b/applicationset/generators/pull_request.go index 287a00be1ae81..c0bfaaeaf0820 100644 --- a/applicationset/generators/pull_request.go +++ b/applicationset/generators/pull_request.go @@ -112,7 +112,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera if err != nil { return nil, fmt.Errorf("error fetching Secret token: %v", err) } - return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState) + return pullrequest.NewGitLabService(ctx, token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.NotLabels, providerConfig.PullRequestState) } if generatorConfig.Gitea != nil { providerConfig := generatorConfig.Gitea @@ -144,7 +144,7 @@ func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alph if err != nil { return nil, fmt.Errorf("error getting GitHub App secret: %v", err) } - return pullrequest.NewGithubAppService(*auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels) + return pullrequest.NewGithubAppService(*auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, cfg.NotLabels) } // always default to token, even if not set (public access) @@ -152,7 +152,7 @@ func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alph if err != nil { return nil, fmt.Errorf("error fetching Secret token: %v", err) } - return pullrequest.NewGithubService(ctx, token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels) + return pullrequest.NewGithubService(ctx, token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, cfg.NotLabels) } // getSecretRef gets the value of the key for the specified Secret resource. diff --git a/applicationset/services/pull_request/github.go b/applicationset/services/pull_request/github.go index 011f1f2b71430..bec8f2ea677fa 100644 --- a/applicationset/services/pull_request/github.go +++ b/applicationset/services/pull_request/github.go @@ -10,15 +10,16 @@ import ( ) type GithubService struct { - client *github.Client - owner string - repo string - labels []string + client *github.Client + owner string + repo string + labels []string + notLabels []string } var _ PullRequestService = (*GithubService)(nil) -func NewGithubService(ctx context.Context, token, url, owner, repo string, labels []string) (PullRequestService, error) { +func NewGithubService(ctx context.Context, token, url, owner, repo string, labels []string, notLabels []string) (PullRequestService, 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 == "" { @@ -41,10 +42,11 @@ func NewGithubService(ctx context.Context, token, url, owner, repo string, label } } return &GithubService{ - client: client, - owner: owner, - repo: repo, - labels: labels, + client: client, + owner: owner, + repo: repo, + labels: labels, + notLabels: notLabels, }, nil } @@ -64,6 +66,9 @@ func (g *GithubService) List(ctx context.Context) ([]*PullRequest, error) { if !containLabels(g.labels, pull.Labels) { continue } + if !notContainLabels(g.notLabels, pull.Labels) { + continue + } pullRequests = append(pullRequests, &PullRequest{ Number: *pull.Number, Branch: *pull.Head.Ref, @@ -97,3 +102,23 @@ func containLabels(expectedLabels []string, gotLabels []*github.Label) bool { } return true } + +// notContainLabels returns true if gotLabels not contain exceptLabels +func notContainLabels(notLabels []string, gotLabels []*github.Label) bool { + for _, except := range notLabels { + found := false + for _, got := range gotLabels { + if got.Name == nil { + continue + } + if except == *got.Name { + found = true + break + } + } + if found { + return false + } + } + return true +} diff --git a/applicationset/services/pull_request/github_app.go b/applicationset/services/pull_request/github_app.go index 8879a777ad277..56800d48f4d8f 100644 --- a/applicationset/services/pull_request/github_app.go +++ b/applicationset/services/pull_request/github_app.go @@ -5,15 +5,16 @@ import ( "github.com/argoproj/argo-cd/v2/applicationset/services/internal/github_app" ) -func NewGithubAppService(g github_app_auth.Authentication, url, owner, repo string, labels []string) (PullRequestService, error) { +func NewGithubAppService(g github_app_auth.Authentication, url, owner, repo string, labels []string, notLabels []string) (PullRequestService, error) { client, err := github_app.Client(g, url) if err != nil { return nil, err } return &GithubService{ - client: client, - owner: owner, - repo: repo, - labels: labels, + client: client, + owner: owner, + repo: repo, + labels: labels, + notLabels: notLabels, }, nil } diff --git a/applicationset/services/pull_request/gitlab.go b/applicationset/services/pull_request/gitlab.go index 7d3b1138d7b8e..59ead99fe649f 100644 --- a/applicationset/services/pull_request/gitlab.go +++ b/applicationset/services/pull_request/gitlab.go @@ -12,12 +12,13 @@ type GitLabService struct { client *gitlab.Client project string labels []string + notLabels []string pullRequestState string } var _ PullRequestService = (*GitLabService)(nil) -func NewGitLabService(ctx context.Context, token, url, project string, labels []string, pullRequestState string) (PullRequestService, error) { +func NewGitLabService(ctx context.Context, token, url, project string, labels []string, notLabels []string, pullRequestState string) (PullRequestService, error) { var clientOptionFns []gitlab.ClientOptionFunc // Set a custom Gitlab base URL if one is provided @@ -38,6 +39,7 @@ func NewGitLabService(ctx context.Context, token, url, project string, labels [] client: client, project: project, labels: labels, + notLabels: notLabels, pullRequestState: pullRequestState, }, nil } @@ -45,16 +47,20 @@ func NewGitLabService(ctx context.Context, token, url, project string, labels [] func (g *GitLabService) List(ctx context.Context) ([]*PullRequest, error) { // Filter the merge requests on labels, if they are specified. - var labels *gitlab.Labels + var labels, notLabels *gitlab.Labels if len(g.labels) > 0 { labels = (*gitlab.Labels)(&g.labels) } + if len(g.notLabels) > 0 { + notLabels = (*gitlab.Labels)(&g.notLabels) + } opts := &gitlab.ListProjectMergeRequestsOptions{ ListOptions: gitlab.ListOptions{ PerPage: 100, }, - Labels: labels, + Labels: labels, + NotLabels: notLabels, } if g.pullRequestState != "" { diff --git a/pkg/apis/application/v1alpha1/applicationset_types.go b/pkg/apis/application/v1alpha1/applicationset_types.go index 9a46f98c62e13..d5015fc4c41d0 100644 --- a/pkg/apis/application/v1alpha1/applicationset_types.go +++ b/pkg/apis/application/v1alpha1/applicationset_types.go @@ -458,6 +458,8 @@ type PullRequestGeneratorGithub struct { AppSecretName string `json:"appSecretName,omitempty" protobuf:"bytes,5,opt,name=appSecretName"` // Labels is used to filter the PRs that you want to target Labels []string `json:"labels,omitempty" protobuf:"bytes,6,rep,name=labels"` + // Labels is used to filter out the PRs that you don't want to target + NotLabels []string `json:"notLabels,omitempty" protobuf:"bytes,6,rep,name=notLabels"` } // PullRequestGeneratorGitLab defines connection info specific to GitLab. @@ -470,6 +472,8 @@ type PullRequestGeneratorGitLab struct { TokenRef *SecretRef `json:"tokenRef,omitempty" protobuf:"bytes,3,opt,name=tokenRef"` // Labels is used to filter the MRs that you want to target Labels []string `json:"labels,omitempty" protobuf:"bytes,4,rep,name=labels"` + // Labels is used to filter out the PRs that you don't want to target + NotLabels []string `json:"notLabels,omitempty" protobuf:"bytes,4,rep,name=notLabels"` // PullRequestState is an additional MRs filter to get only those with a certain state. Default: "" (all states) PullRequestState string `json:"pullRequestState,omitempty" protobuf:"bytes,5,rep,name=pullRequestState"` }