forked from ldez/gha-mjolnir
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mjolnir.go
101 lines (82 loc) · 2.98 KB
/
mjolnir.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package main
import (
"context"
"fmt"
"log"
"regexp"
"strconv"
"strings"
"github.com/google/go-github/v44/github"
)
var (
globalFixesIssueRE = regexp.MustCompile(`(?i)(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)(\s+#\d+(?:[\s,]+#\d+)*(?:[\n\r\s,]|$))`)
fixesIssueRE = regexp.MustCompile(`[\s,]+#`)
cleanNumberRE = regexp.MustCompile(`[\n\r\s,]`)
)
// closeRelatedIssues Closes issues listed in the PR description.
func closeRelatedIssues(ctx context.Context, client *github.Client, owner string, repositoryName string, pr *github.PullRequest, dryRun bool) error {
log.Printf("Processing PR #%d targeting %s", pr.GetNumber(), pr.Base.GetRef())
issueNumbers := parseIssueFixes(pr.GetBody())
repo, _, err := client.Repositories.Get(ctx, owner, repositoryName)
if err != nil {
return fmt.Errorf("unable to access repository %s/%s: %w", owner, repositoryName, err)
}
for _, issueNumber := range issueNumbers {
log.Printf("PR #%d: closes issue #%d, add milestones %s", pr.GetNumber(), issueNumber, pr.Milestone.GetTitle())
if !dryRun {
err := closeIssue(ctx, client, owner, repositoryName, pr, issueNumber)
if err != nil {
return fmt.Errorf("unable to close issue #%d: %w", issueNumber, err)
}
}
// Add comment if needed
if pr.Base.GetRef() != repo.GetDefaultBranch() {
message := fmt.Sprintf("Closed by #%d.", pr.GetNumber())
log.Printf("PR #%d: issue #%d, add comment: %s", pr.GetNumber(), issueNumber, message)
if !dryRun {
err := addComment(ctx, client, owner, repositoryName, issueNumber, message)
if err != nil {
return fmt.Errorf("unable to add comment on issue #%d: %w", issueNumber, err)
}
}
}
}
return nil
}
func closeIssue(ctx context.Context, client *github.Client, owner string, repositoryName string, pr *github.PullRequest, issueNumber int) error {
var milestone *int
if pr.Milestone != nil {
milestone = pr.Milestone.Number
}
issueRequest := &github.IssueRequest{
Milestone: milestone,
State: github.String("closed"),
}
_, _, err := client.Issues.Edit(ctx, owner, repositoryName, issueNumber, issueRequest)
return err
}
func addComment(ctx context.Context, client *github.Client, owner string, repositoryName string, issueNumber int, message string) error {
issueComment := &github.IssueComment{
Body: github.String(message),
}
_, _, err := client.Issues.CreateComment(ctx, owner, repositoryName, issueNumber, issueComment)
return err
}
func parseIssueFixes(text string) []int {
var issueNumbers []int
submatch := globalFixesIssueRE.FindStringSubmatch(strings.ReplaceAll(text, ":", ""))
if len(submatch) != 0 {
issuesRaw := fixesIssueRE.Split(submatch[1], -1)
for _, issueRaw := range issuesRaw {
cleanIssueRaw := cleanNumberRE.ReplaceAllString(issueRaw, "")
if len(cleanIssueRaw) != 0 {
numb, err := strconv.ParseInt(cleanIssueRaw, 10, 16)
if err != nil {
log.Println(err)
}
issueNumbers = append(issueNumbers, int(numb))
}
}
}
return issueNumbers
}