From c2f21dc4d63dc639fbc5fa95e4b469896c0e9f22 Mon Sep 17 00:00:00 2001 From: Christian Winther Date: Fri, 30 Aug 2024 13:44:21 +0200 Subject: [PATCH] feat: allow limiting MRs to specific labels when doing async evaluation --- cmd/conventions.go | 35 ++++++++++++++++++----------------- cmd/gitlab.go | 7 +++++++ cmd/gitlab_server.go | 1 + cmd/gitlab_server_periodic.go | 5 +++++ pkg/scm/gitlab/structs.go | 2 +- pkg/scm/types.go | 14 ++++++++++---- 6 files changed, 42 insertions(+), 22 deletions(-) diff --git a/cmd/conventions.go b/cmd/conventions.go index f38c1d4..7118aab 100644 --- a/cmd/conventions.go +++ b/cmd/conventions.go @@ -1,21 +1,22 @@ package cmd const ( - FlagAPIToken = "api-token" - FlagCommitSHA = "commit" - FlagConfigFile = "config" - FlagDryRun = "dry-run" - FlagMergeRequestID = "id" - FlagSCMBaseURL = "base-url" - FlagSCMProject = "project" - FlagServerListenHost = "listen-host" - FlagServerListenPort = "listen-port" - FlagServerTimeout = "timeout" - FlagUpdatePipeline = "update-pipeline" - FlagUpdatePipelineURL = "update-pipeline-url" - FlagPeriodicEvaluationInterval = "periodic-evaluation-interval" - FlagPeriodicEvaluationIgnoreMergeRequestsWithLabel = "periodic-evaluation-ignore-mr-labels" - FlagPeriodicEvaluationOnlyProjectsWithTopics = "periodic-evaluation-project-topics" - FlagPeriodicEvaluationOnlyProjectsWithMembership = "periodic-evaluation-only-project-membership" - FlagWebhookSecret = "webhook-secret" + FlagAPIToken = "api-token" + FlagCommitSHA = "commit" + FlagConfigFile = "config" + FlagDryRun = "dry-run" + FlagMergeRequestID = "id" + FlagSCMBaseURL = "base-url" + FlagSCMProject = "project" + FlagServerListenHost = "listen-host" + FlagServerListenPort = "listen-port" + FlagServerTimeout = "timeout" + FlagUpdatePipeline = "update-pipeline" + FlagUpdatePipelineURL = "update-pipeline-url" + FlagPeriodicEvaluationInterval = "periodic-evaluation-interval" + FlagPeriodicEvaluationIgnoreMergeRequestsWithLabel = "periodic-evaluation-ignore-mr-labels" + FlagPeriodicEvaluationRequireMergeRequestsWithLabel = "periodic-evaluation-require-mr-labels" + FlagPeriodicEvaluationOnlyProjectsWithTopics = "periodic-evaluation-project-topics" + FlagPeriodicEvaluationOnlyProjectsWithMembership = "periodic-evaluation-only-project-membership" + FlagWebhookSecret = "webhook-secret" ) diff --git a/cmd/gitlab.go b/cmd/gitlab.go index bb51fdf..e071e7a 100644 --- a/cmd/gitlab.go +++ b/cmd/gitlab.go @@ -149,6 +149,13 @@ var GitLab = &cli.Command{ "SCM_ENGINE_PERIODIC_EVALUATION_IGNORE_MR_WITH_LABELS", }, }, + &cli.StringSliceFlag{ + Name: FlagPeriodicEvaluationRequireMergeRequestsWithLabel, + Usage: "(Optional) Only process MR with these labels", + EnvVars: []string{ + "SCM_ENGINE_PERIODIC_EVALUATION_REQUIRE_MR_WITH_LABELS", + }, + }, &cli.StringSliceFlag{ Name: FlagPeriodicEvaluationOnlyProjectsWithTopics, Usage: "(Optional) Only evaluate projects with these topics", diff --git a/cmd/gitlab_server.go b/cmd/gitlab_server.go index b9ab739..ab3e134 100644 --- a/cmd/gitlab_server.go +++ b/cmd/gitlab_server.go @@ -38,6 +38,7 @@ func Server(cCtx *cli.Context) error { filter := scm.MergeRequestListFilters{ IgnoreMergeRequestWithLabels: cCtx.StringSlice(FlagPeriodicEvaluationIgnoreMergeRequestsWithLabel), + OnlyMergeRequestsWithLabels: cCtx.StringSlice(FlagPeriodicEvaluationRequireMergeRequestsWithLabel), OnlyProjectsWithMembership: cCtx.Bool(FlagPeriodicEvaluationOnlyProjectsWithMembership), OnlyProjectsWithTopics: cCtx.StringSlice(FlagPeriodicEvaluationOnlyProjectsWithTopics), SCMConfigurationFilePath: cCtx.String(FlagConfigFile), diff --git a/cmd/gitlab_server_periodic.go b/cmd/gitlab_server_periodic.go index dc15e92..a894915 100644 --- a/cmd/gitlab_server_periodic.go +++ b/cmd/gitlab_server_periodic.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "fmt" "log/slog" "strings" "sync" @@ -71,6 +72,8 @@ func startPeriodicEvaluation(ctx context.Context, interval time.Duration, filter continue } + slogctx.Info(ctx, fmt.Sprintf("Found %d merge requests to evaluate", len(results)), slog.Int("number_of_projects", len(results))) + for _, mergeRequest := range results { ctx := ctx // make sure we define a fresh GC-able context per merge request so we don't append to the existing forever ctx = state.WithCommitSHA(ctx, mergeRequest.SHA) @@ -98,6 +101,8 @@ func startPeriodicEvaluation(ctx context.Context, interval time.Duration, filter continue } } // end loop results + + slogctx.Info(ctx, "Completed periodic evaluation cycle") } // end select } // end loop }(wg) diff --git a/pkg/scm/gitlab/structs.go b/pkg/scm/gitlab/structs.go index 7dc76d6..1fe19aa 100644 --- a/pkg/scm/gitlab/structs.go +++ b/pkg/scm/gitlab/structs.go @@ -35,7 +35,7 @@ type PeriodicEvaluationProjectNode struct { FullPath string `graphql:"fullPath"` // MergeRequests contains up to 100 merge requests, sorted by oldest update/last change first - MergeRequests graphqlNodesOf[PeriodicEvaluationMergeRequestNode] `graphql:"mergeRequests(first: 100, state: opened, not: {labels: $mr_ignore_labels}, sort: UPDATED_ASC)"` + MergeRequests graphqlNodesOf[PeriodicEvaluationMergeRequestNode] `graphql:"mergeRequests(first: 100, state: opened, not: {labels: $mr_ignore_labels}, labels: $mr_require_labels, sort: UPDATED_ASC)"` // Repository contains information about the git repository Repository PeriodicEvaluationRepository `graphql:"repository"` diff --git a/pkg/scm/types.go b/pkg/scm/types.go index 7fc9ce4..dc937be 100644 --- a/pkg/scm/types.go +++ b/pkg/scm/types.go @@ -204,27 +204,33 @@ type MergeRequestListFilters struct { IgnoreMergeRequestWithLabels []string OnlyProjectsWithMembership bool OnlyProjectsWithTopics []string + OnlyMergeRequestsWithLabels []string SCMConfigurationFilePath string } func (filter *MergeRequestListFilters) AsGraphqlVariables() map[string]any { output := map[string]any{ "mr_ignore_labels": filter.IgnoreMergeRequestWithLabels, + "mr_require_labels": filter.OnlyMergeRequestsWithLabels, "project_membership": filter.OnlyProjectsWithMembership, "project_topics": filter.OnlyProjectsWithTopics, "scm_config_file_path": filter.SCMConfigurationFilePath, } - if len(filter.SCMConfigurationFilePath) == 0 { - output["scm_config_file_path"] = ".scm-engine.yml" + if len(filter.IgnoreMergeRequestWithLabels) == 0 { + output["mr_ignore_labels"] = []string{} + } + + if len(filter.OnlyMergeRequestsWithLabels) == 0 { + output["mr_require_labels"] = []string{} } if len(filter.OnlyProjectsWithTopics) == 0 { output["project_topics"] = []string{} } - if len(filter.IgnoreMergeRequestWithLabels) == 0 { - output["mr_ignore_labels"] = []string{} + if len(filter.SCMConfigurationFilePath) == 0 { + output["scm_config_file_path"] = ".scm-engine.yml" } return output