-
Notifications
You must be signed in to change notification settings - Fork 17
/
blocker.go
83 lines (70 loc) · 2.65 KB
/
blocker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package main
import (
"context"
"fmt"
"slices"
"strings"
"github.com/chainguard-dev/clog"
"github.com/chainguard-dev/terraform-infra-common/modules/github-bots/sdk"
"github.com/google/go-github/v61/github"
)
// This bot is responsible for passing/failing a check run based on the presence of any "blocking/*" label.
//
// This check can be made required so that blockers block merging of PRs.
func New() sdk.Bot {
name := "blocker"
handler := sdk.PullRequestHandler(func(ctx context.Context, pre github.PullRequestEvent) error {
log := clog.FromContext(ctx)
cli := sdk.NewGitHubClient(ctx, *pre.Repo.Owner.Login, *pre.Repo.Name, name)
defer cli.Close(ctx)
owner, repo := *pre.Repo.Owner.Login, *pre.Repo.Name
hasBlockingLabel := slices.ContainsFunc(pre.PullRequest.Labels, func(l *github.Label) bool {
return strings.HasPrefix(*l.Name, "blocking/")
})
conclusion := "success"
if hasBlockingLabel {
conclusion = "failure"
log.Debug("PR %d has blocking label")
}
sha := *pre.PullRequest.Head.SHA
// If there are no check runs for the current head SHA, create one with the conclusion.
crs, _, err := cli.Client().Checks.ListCheckRunsForRef(ctx, owner, repo, sha, &github.ListCheckRunsOptions{CheckName: github.String(name)})
if err != nil {
return fmt.Errorf("listing check runs: %w", err)
}
if len(crs.CheckRuns) == 0 {
log.Infof("Creating CheckRun for PR %d sha %s with conclusion %s", *pre.PullRequest.Number, sha, conclusion)
if _, _, err := cli.Client().Checks.CreateCheckRun(ctx, owner, repo, github.CreateCheckRunOptions{
Name: name,
HeadSHA: sha,
Status: github.String("completed"),
Conclusion: &conclusion,
}); err != nil {
return fmt.Errorf("creating check run: %w", err)
}
return nil
}
// No change, nothing else to do.
if *crs.CheckRuns[0].Conclusion == conclusion {
log.Debugf("CheckRun for PR %d sha %s already has conclusion %s", *pre.Number, sha, conclusion)
return nil
}
// If there's already a check run, update its conclusion.
log.Infof("Updating CheckRun for PR %d sha %s with conclusion %s", *pre.Number, sha, conclusion)
if _, _, err = cli.Client().Checks.UpdateCheckRun(ctx, owner, repo, *crs.CheckRuns[0].ID, github.UpdateCheckRunOptions{
Name: name,
Status: github.String("completed"),
Conclusion: &conclusion,
Output: &github.CheckRunOutput{
Title: github.String("Blocking label check"),
Summary: github.String("This PR has a blocking label"),
},
}); err != nil {
return fmt.Errorf("updating check run %d: %w", *crs.CheckRuns[0].ID, err)
}
return nil
})
return sdk.NewBot(name,
sdk.BotWithHandler(handler),
)
}