Skip to content

Commit 0b04c12

Browse files
authored
feat: conditionally disable external CI pipeline when doing periodic evaluation (#96)
* feat: conditionally disable external CI pipeline when doing periodic evaluation Specifically when the HEAD MR CI pipeline is in a failed state, as this can trigger GitLab to send 'your CI pipeline failed' emails every time the evaluation process runs, which is undesirable * chore: shorten var back down
1 parent c12daf0 commit 0b04c12

File tree

5 files changed

+63
-4
lines changed

5 files changed

+63
-4
lines changed

.golangci.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,15 @@ linters-settings:
174174
check-return: true
175175
check-type-param: true
176176
ignore-names:
177-
- tt
178177
- err
179178
- i
180179
- id
180+
- mr
181181
- ok
182-
- wg
183182
- r
183+
- tt
184184
- w
185+
- wg
185186

186187
tagalign:
187188
# Align and sort can be used together or separately.

cmd/gitlab_server_periodic.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ func startPeriodicEvaluation(ctx context.Context, interval time.Duration, filter
8383
ctx = state.WithMergeRequestID(ctx, mergeRequest.MergeRequestID)
8484
ctx = state.WithProjectID(ctx, mergeRequest.Project)
8585

86+
if !mergeRequest.UpdatePipeline {
87+
slogctx.Info(ctx, "Disabling CI pipeline commit status updating since the MR HEAD CI pipeline is in a failed state")
88+
89+
ctx = state.WithUpdatePipeline(ctx, false, "")
90+
}
91+
8692
if len(mergeRequest.ConfigBlob) == 0 {
8793
slogctx.Warn(ctx, "Could not find the scm-engine configuration file in the repository, skipping...")
8894

pkg/scm/gitlab/client.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log/slog"
88
"net/http"
99
"net/url"
10+
"slices"
1011
"strconv"
1112
"strings"
1213
"time"
@@ -22,6 +23,36 @@ import (
2223

2324
var pipelineName = scm.Ptr("scm-engine")
2425

26+
// Skip the "update external pipeline" step if the HEAD pipeline is any
27+
// of the configured options
28+
//
29+
// Disable updating CI pipelines when running periodic evaluations in the background
30+
// to avoid sending "CI pipeline failed" notification emails to users
31+
//
32+
// If the HEAD CI pipeline for a MR is in "failed" mode and we update the external
33+
// pipeline, GitLab will send the user (if configured in their profile) a 'your pipeline failed'
34+
// email every time the background evaluation process runs.
35+
//
36+
// Possible values:
37+
//
38+
// - CANCELED
39+
// - CANCELING
40+
// - CREATED
41+
// - FAILED
42+
// - MANUAL
43+
// - PENDING
44+
// - PREPARING
45+
// - RUNNING
46+
// - SCHEDULED
47+
// - SKIPPED
48+
// - SUCCESS
49+
// - WAITING_FOR_CALLBACK
50+
// - WAITING_FOR_RESOURCE
51+
var SkipPipelineUpdateIfPeriodicAndPipelineStatusIs = []string{
52+
"FAILED",
53+
"SKIPPED",
54+
}
55+
2556
// Ensure the GitLab client implements the [scm.Client]
2657
var _ scm.Client = (*Client)(nil)
2758

@@ -74,6 +105,9 @@ func (client *Client) FindMergeRequestsForPeriodicEvaluation(ctx context.Context
74105

75106
var result []scm.PeriodicEvaluationMergeRequest
76107

108+
// Check if the evaluation should update CI pipelines by default
109+
updatePipeline, _ := state.ShouldUpdatePipeline(ctx)
110+
77111
for _, project := range response.Projects.Nodes {
78112
slogctx.Debug(ctx, fmt.Sprintf("Project %s has %d Merge Requests", project.FullPath, len(project.MergeRequests.Nodes)))
79113

@@ -82,6 +116,14 @@ func (client *Client) FindMergeRequestsForPeriodicEvaluation(ctx context.Context
82116
Project: project.FullPath,
83117
MergeRequestID: mr.IID,
84118
SHA: mr.SHA,
119+
UpdatePipeline: updatePipeline,
120+
}
121+
122+
// If periodic evaluation are updating CI pipelines, check if the status of the HEAD pipeline
123+
// is in a state where re-triggering the external CI pipeline would potentially send the MR creator
124+
// a "Your CI pipeline failed" e-mail every time we evaluate the MR in the background (spammy!)
125+
if item.UpdatePipeline && mr.HeadPipeline != nil && slices.Contains(SkipPipelineUpdateIfPeriodicAndPipelineStatusIs, mr.HeadPipeline.Status) {
126+
item.UpdatePipeline = false
85127
}
86128

87129
// Only set the ConfigBlob struct if the config file exists in the repository

pkg/scm/gitlab/structs.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ package gitlab
3737
// nodes {
3838
// iid
3939
// diffHeadSha
40+
//
41+
// headPipeline {
42+
// status
43+
// }
4044
// }
4145
// }
4246
// }
@@ -75,8 +79,13 @@ type PeriodicEvaluationRepository struct {
7579
}
7680

7781
type PeriodicEvaluationMergeRequestNode struct {
78-
IID string `graphql:"iid"`
79-
SHA string `graphql:"diffHeadSha"`
82+
IID string `graphql:"iid"`
83+
SHA string `graphql:"diffHeadSha"`
84+
HeadPipeline *PipelineNode `graphql:"headPipeline"`
85+
}
86+
87+
type PipelineNode struct {
88+
Status string `graphql:"status"`
8089
}
8190

8291
type BlobNode struct {

pkg/scm/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ type PeriodicEvaluationMergeRequest struct {
182182
MergeRequestID string
183183
SHA string
184184
ConfigBlob string
185+
UpdatePipeline bool
185186
}
186187

187188
type EvalContextualizer struct{}

0 commit comments

Comments
 (0)