Skip to content

Commit 06bdf35

Browse files
authored
fix: do not send setStatut + add memory cache on commit status list (#5059)
1 parent 268c001 commit 06bdf35

File tree

7 files changed

+249
-170
lines changed

7 files changed

+249
-170
lines changed

engine/api/event/publish.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,6 @@ func publishEvent(ctx context.Context, e sdk.Event) error {
2020
if err := store.Enqueue("events", e); err != nil {
2121
return err
2222
}
23-
24-
// send to cache for cds repositories manager
25-
var toSkipSendReposManager bool
26-
// the StatusWaiting is not useful to be sent on repomanager.
27-
// the building status (or success / failed) is already sent just after
28-
if e.EventType == fmt.Sprintf("%T", sdk.EventRunWorkflowNode{}) && e.Status == sdk.StatusWaiting {
29-
toSkipSendReposManager = true
30-
}
31-
if !toSkipSendReposManager {
32-
if err := store.Enqueue("events_repositoriesmanager", e); err != nil {
33-
return err
34-
}
35-
}
36-
3723
b, err := json.Marshal(e)
3824
if err != nil {
3925
return sdk.WrapError(err, "Cannot marshal event %+v", e)

engine/api/workflow/workflow_run_event.go

Lines changed: 105 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616
"github.com/ovh/cds/sdk/log"
1717
)
1818

19+
type VCSEventMessenger struct {
20+
commitsStatuses map[string][]sdk.VCSCommitStatus
21+
vcsClient sdk.VCSAuthorizedClient
22+
}
23+
1924
// ResyncCommitStatus resync commit status for a workflow run
2025
func ResyncCommitStatus(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sdk.Project, wr *sdk.WorkflowRun) error {
2126
_, end := observability.Span(ctx, "workflow.resyncCommitStatus",
@@ -24,91 +29,108 @@ func ResyncCommitStatus(ctx context.Context, db gorp.SqlExecutor, store cache.St
2429
)
2530
defer end()
2631

27-
for nodeID, nodeRuns := range wr.WorkflowNodeRuns {
32+
eventMessenger := &VCSEventMessenger{commitsStatuses: make(map[string][]sdk.VCSCommitStatus)}
33+
for _, nodeRuns := range wr.WorkflowNodeRuns {
2834
sort.Slice(nodeRuns, func(i, j int) bool {
2935
return nodeRuns[i].SubNumber >= nodeRuns[j].SubNumber
3036
})
3137
nodeRun := nodeRuns[0]
3238

33-
if !sdk.StatusIsTerminated(nodeRun.Status) {
34-
continue
39+
if err := eventMessenger.SendVCSEvent(ctx, db, store, proj, *wr, nodeRun); err != nil {
40+
log.Error(ctx, "resyncCommitStatus > unable to send vcs event: %v", err)
3541
}
42+
}
43+
44+
return nil
45+
}
46+
47+
func (e *VCSEventMessenger) SendVCSEvent(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sdk.Project, wr sdk.WorkflowRun, nodeRun sdk.WorkflowNodeRun) error {
48+
if nodeRun.Status == sdk.StatusWaiting {
49+
return nil
50+
}
51+
52+
if e.commitsStatuses == nil {
53+
e.commitsStatuses = make(map[string][]sdk.VCSCommitStatus)
54+
}
3655

37-
node := wr.Workflow.WorkflowData.NodeByID(nodeID)
38-
if !node.IsLinkedToRepo(&wr.Workflow) {
56+
node := wr.Workflow.WorkflowData.NodeByID(nodeRun.WorkflowNodeID)
57+
if !node.IsLinkedToRepo(&wr.Workflow) {
58+
return nil
59+
}
60+
61+
var notif *sdk.WorkflowNotification
62+
// browse notification to find vcs one
63+
loopNotif:
64+
for _, n := range wr.Workflow.Notifications {
65+
if n.Type != sdk.VCSUserNotification {
3966
continue
4067
}
41-
42-
var notif *sdk.WorkflowNotification
43-
// browse notification to find vcs one
44-
loopNotif:
45-
for _, n := range wr.Workflow.Notifications {
46-
if n.Type != sdk.VCSUserNotification {
47-
continue
48-
}
49-
// If list of node is nill, send notification to all of them
50-
if len(n.NodeIDs) == 0 {
68+
// If list of node is nill, send notification to all of them
69+
if len(n.NodeIDs) == 0 {
70+
notif = &n
71+
break
72+
}
73+
// browser source node id
74+
for _, src := range n.NodeIDs {
75+
if src == node.ID {
5176
notif = &n
52-
break
53-
}
54-
// browser source node id
55-
for _, src := range n.NodeIDs {
56-
if src == node.ID {
57-
notif = &n
58-
break loopNotif
59-
}
77+
break loopNotif
6078
}
6179
}
80+
}
6281

63-
vcsServerName := wr.Workflow.Applications[node.Context.ApplicationID].VCSServer
64-
repoFullName := wr.Workflow.Applications[node.Context.ApplicationID].RepositoryFullname
82+
if notif == nil {
83+
return nil
84+
}
6585

66-
vcsServer := repositoriesmanager.GetProjectVCSServer(proj, vcsServerName)
67-
if vcsServer == nil {
68-
return nil
69-
}
86+
vcsServerName := wr.Workflow.Applications[node.Context.ApplicationID].VCSServer
87+
repoFullName := wr.Workflow.Applications[node.Context.ApplicationID].RepositoryFullname
7088

71-
details := fmt.Sprintf("on project:%s workflow:%s node:%s num:%d sub:%d vcs:%s", proj.Name, wr.Workflow.Name, nodeRun.WorkflowNodeName, nodeRun.Number, nodeRun.SubNumber, vcsServer.Name)
89+
vcsServer := repositoriesmanager.GetProjectVCSServer(proj, vcsServerName)
90+
if vcsServer == nil {
91+
return nil
92+
}
7293

73-
//Get the RepositoriesManager Client
74-
client, errClient := repositoriesmanager.AuthorizedClient(ctx, db, store, proj.Key, vcsServer)
75-
if errClient != nil {
76-
return sdk.WrapError(errClient, "resyncCommitStatus> Cannot get client %s", details)
94+
//Get the RepositoriesManager Client
95+
if e.vcsClient == nil {
96+
var err error
97+
e.vcsClient, err = repositoriesmanager.AuthorizedClient(ctx, db, store, proj.Key, vcsServer)
98+
if err != nil {
99+
return err
77100
}
101+
}
78102

79-
ref := nodeRun.VCSHash
80-
if nodeRun.VCSTag != "" {
81-
ref = nodeRun.VCSTag
82-
}
103+
ref := nodeRun.VCSHash
104+
if nodeRun.VCSTag != "" {
105+
ref = nodeRun.VCSTag
106+
}
83107

84-
statuses, errStatuses := client.ListStatuses(ctx, repoFullName, ref)
85-
if errStatuses != nil {
86-
return sdk.WrapError(errStatuses, "resyncCommitStatus> Cannot get statuses %s", details)
108+
statuses, ok := e.commitsStatuses[ref]
109+
if !ok {
110+
var err error
111+
statuses, err = e.vcsClient.ListStatuses(ctx, repoFullName, ref)
112+
if err != nil {
113+
return err
87114
}
88-
89-
var statusFound *sdk.VCSCommitStatus
90-
expected := sdk.VCSCommitStatusDescription(proj.Key, wr.Workflow.Name, sdk.EventRunWorkflowNode{
91-
NodeName: nodeRun.WorkflowNodeName,
92-
})
93-
94-
for i, status := range statuses {
95-
if status.Decription == expected {
96-
statusFound = &statuses[i]
97-
break
98-
}
115+
e.commitsStatuses[ref] = statuses
116+
}
117+
expected := sdk.VCSCommitStatusDescription(proj.Key, wr.Workflow.Name, sdk.EventRunWorkflowNode{
118+
NodeName: nodeRun.WorkflowNodeName,
119+
})
120+
121+
var statusFound *sdk.VCSCommitStatus
122+
for i, status := range statuses {
123+
if status.Decription == expected {
124+
statusFound = &statuses[i]
125+
break
99126
}
127+
}
100128

101-
if statusFound == nil || statusFound.State == "" {
102-
if err := sendVCSEventStatus(ctx, db, store, proj, wr, &nodeRun, notif); err != nil {
103-
log.Error(ctx, "resyncCommitStatus> Error sending status %s err: %v", details, err)
104-
}
105-
106-
if err := sendVCSPullRequestComment(ctx, db, store, proj, wr, &nodeRun, notif); err != nil {
107-
log.Error(ctx, "resyncCommitStatus> Error sending pr comments %s %s err:%v", statusFound.State, details, err)
108-
}
109-
continue
129+
if statusFound == nil || statusFound.State == "" {
130+
if err := e.sendVCSEventStatus(ctx, db, store, proj.Key, wr, &nodeRun, notif, vcsServer.Name); err != nil {
131+
return err
110132
}
111-
133+
} else {
112134
skipStatus := false
113135
switch statusFound.State {
114136
case sdk.StatusSuccess:
@@ -130,21 +152,20 @@ func ResyncCommitStatus(ctx context.Context, db gorp.SqlExecutor, store cache.St
130152
}
131153

132154
if !skipStatus {
133-
if err := sendVCSEventStatus(ctx, db, store, proj, wr, &nodeRun, notif); err != nil {
134-
log.Error(ctx, "resyncCommitStatus> Error sending status %s %s err:%v", statusFound.State, details, err)
155+
if err := e.sendVCSEventStatus(ctx, db, store, proj.Key, wr, &nodeRun, notif, vcsServer.Name); err != nil {
156+
return err
135157
}
136158
}
159+
}
137160

138-
if err := sendVCSPullRequestComment(ctx, db, store, proj, wr, &nodeRun, notif); err != nil {
139-
log.Error(ctx, "resyncCommitStatus> Error sending pr comments %s %s err:%v", statusFound.State, details, err)
140-
}
141-
161+
if err := e.sendVCSPullRequestComment(ctx, db, wr, &nodeRun, notif, vcsServer.Name); err != nil {
162+
return err
142163
}
143164
return nil
144165
}
145166

146167
// sendVCSEventStatus send status
147-
func sendVCSEventStatus(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sdk.Project, wr *sdk.WorkflowRun, nodeRun *sdk.WorkflowNodeRun, notif *sdk.WorkflowNotification) error {
168+
func (e *VCSEventMessenger) sendVCSEventStatus(ctx context.Context, db gorp.SqlExecutor, store cache.Store, projectKey string, wr sdk.WorkflowRun, nodeRun *sdk.WorkflowNodeRun, notif *sdk.WorkflowNotification, vcsServerName string) error {
148169
if notif == nil || notif.Settings.Template == nil || (notif.Settings.Template.DisableStatus != nil && *notif.Settings.Template.DisableStatus) {
149170
return nil
150171
}
@@ -166,17 +187,6 @@ func sendVCSEventStatus(ctx context.Context, db gorp.SqlExecutor, store cache.St
166187
env = wr.Workflow.Environments[node.Context.EnvironmentID]
167188
}
168189

169-
vcsServer := repositoriesmanager.GetProjectVCSServer(proj, app.VCSServer)
170-
if vcsServer == nil {
171-
return nil
172-
}
173-
174-
//Get the RepositoriesManager Client
175-
client, errClient := repositoriesmanager.AuthorizedClient(ctx, db, store, proj.Key, vcsServer)
176-
if errClient != nil {
177-
return sdk.WrapError(errClient, "sendVCSEventStatus> Cannot get client")
178-
}
179-
180190
var eventWNR = sdk.EventRunWorkflowNode{
181191
ID: nodeRun.ID,
182192
Number: nodeRun.Number,
@@ -214,12 +224,11 @@ func sendVCSEventStatus(ctx context.Context, db gorp.SqlExecutor, store cache.St
214224

215225
report, err := nodeRun.Report()
216226
if err != nil {
217-
log.Error(ctx, "sendVCSEventStatus> unable to compute node run report%v", err)
218-
return nil
227+
return err
219228
}
220229

221230
// Check if it's a gerrit or not
222-
vcsConf, err := repositoriesmanager.LoadByName(ctx, db, vcsServer.Name)
231+
vcsConf, err := repositoriesmanager.LoadByName(ctx, db, vcsServerName)
223232
if err != nil {
224233
return err
225234
}
@@ -266,24 +275,24 @@ func sendVCSEventStatus(ctx context.Context, db gorp.SqlExecutor, store cache.St
266275
EventType: fmt.Sprintf("%T", eventWNR),
267276
Payload: payload,
268277
Timestamp: time.Now(),
269-
ProjectKey: proj.Key,
278+
ProjectKey: projectKey,
270279
WorkflowName: wr.Workflow.Name,
271280
PipelineName: pipName,
272281
ApplicationName: appName,
273282
EnvironmentName: envName,
274283
}
275284

276-
if err := client.SetStatus(ctx, evt); err != nil {
285+
if err := e.vcsClient.SetStatus(ctx, evt); err != nil {
277286
if err2 := repositoriesmanager.RetryEvent(&evt, err, store); err2 != nil {
278-
log.Error(ctx, "sendEvent>processEvent> err while retry event: %v", err2)
287+
return err2
279288
}
280-
log.Error(ctx, "sendEvent> err:%v", err)
289+
return err
281290
}
282291

283292
return nil
284293
}
285294

286-
func sendVCSPullRequestComment(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sdk.Project, wr *sdk.WorkflowRun, nodeRun *sdk.WorkflowNodeRun, notif *sdk.WorkflowNotification) error {
295+
func (e *VCSEventMessenger) sendVCSPullRequestComment(ctx context.Context, db gorp.SqlExecutor, wr sdk.WorkflowRun, nodeRun *sdk.WorkflowNodeRun, notif *sdk.WorkflowNotification, vcsServerName string) error {
287296
if notif == nil || notif.Settings.Template == nil || (notif.Settings.Template.DisableComment != nil && *notif.Settings.Template.DisableComment) {
288297
return nil
289298
}
@@ -308,23 +317,11 @@ func sendVCSPullRequestComment(ctx context.Context, db gorp.SqlExecutor, store c
308317

309318
report, err := nodeRun.Report()
310319
if err != nil {
311-
log.Error(ctx, "sendVCSPullRequestComment> unable to compute node run report%v", err)
312-
return nil
313-
}
314-
315-
vcsServer := repositoriesmanager.GetProjectVCSServer(proj, app.VCSServer)
316-
if vcsServer == nil {
317-
return nil
318-
}
319-
320-
//Get the RepositoriesManager Client
321-
client, errClient := repositoriesmanager.AuthorizedClient(ctx, db, store, proj.Key, vcsServer)
322-
if errClient != nil {
323-
return errClient
320+
return err
324321
}
325322

326323
// Check if it's a gerrit or not
327-
vcsConf, err := repositoriesmanager.LoadByName(ctx, db, vcsServer.Name)
324+
vcsConf, err := repositoriesmanager.LoadByName(ctx, db, vcsServerName)
328325
if err != nil {
329326
return err
330327
}
@@ -347,31 +344,26 @@ func sendVCSPullRequestComment(ctx context.Context, db gorp.SqlExecutor, store c
347344
// If we are on Gerrit
348345
if changeID != "" && vcsConf.Type == "gerrit" {
349346
reqComment.ChangeID = changeID
350-
if err := client.PullRequestComment(ctx, app.RepositoryFullname, reqComment); err != nil {
351-
log.Error(ctx, "sendVCSPullRequestComment> unable to send PR report:%v", err)
352-
return nil
347+
if err := e.vcsClient.PullRequestComment(ctx, app.RepositoryFullname, reqComment); err != nil {
348+
return err
353349
}
354350
} else if vcsConf.Type != "gerrit" {
355351
//Check if this branch and this commit is a pullrequest
356-
prs, err := client.PullRequests(ctx, app.RepositoryFullname)
352+
prs, err := e.vcsClient.PullRequests(ctx, app.RepositoryFullname)
357353
if err != nil {
358-
log.Error(ctx, "sendVCSPullRequestComment> unable to get pull requests on repo %s: %v", app.RepositoryFullname, err)
359-
return nil
354+
return err
360355
}
361356

362357
//Send comment on pull request
363358
for _, pr := range prs {
364359
if pr.Head.Branch.DisplayID == nodeRun.VCSBranch && pr.Head.Branch.LatestCommit == nodeRun.VCSHash && !pr.Merged && !pr.Closed {
365360
reqComment.ID = pr.ID
366-
if err := client.PullRequestComment(ctx, app.RepositoryFullname, reqComment); err != nil {
367-
log.Error(ctx, "sendVCSPullRequestComment> unable to send PR report:%v", err)
368-
return nil
361+
if err := e.vcsClient.PullRequestComment(ctx, app.RepositoryFullname, reqComment); err != nil {
362+
return err
369363
}
370-
// if we found the pull request for head branch we can break (only one PR for the branch should exist)
371364
break
372365
}
373366
}
374367
}
375-
376368
return nil
377369
}

0 commit comments

Comments
 (0)