-
Notifications
You must be signed in to change notification settings - Fork 5
/
template.go
127 lines (107 loc) · 3.22 KB
/
template.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium
package checklist
import (
"fmt"
"os"
"regexp"
"strconv"
"strings"
gh "github.com/google/go-github/v50/github"
"golang.org/x/mod/semver"
)
var (
orderedSubstitutions = []string{
"X.Y.Z-rc.W",
"X.Y.Z-pre.N",
"X.Y.Z",
"X.Y.W",
"X.Y-1",
"X.Y+1",
"X.Y",
}
)
func fetchTemplate(cfg ChecklistConfig) ([]byte, error) {
if len(cfg.TemplatePath) > 0 {
return os.ReadFile(cfg.TemplatePath)
}
return nil, fmt.Errorf("No template configuration found")
}
func assembleVersionSubstitutions(version string) ([]string, error) {
var patchVer string
versionSub := make(map[string]string)
if semver.Prerelease(version) == "" {
versionSub["X.Y.Z"] = version
patchVer = version
} else {
versionSub["X.Y.Z-rc.W"] = version
versionSub["X.Y.Z-pre.N"] = version
patchVer, _, _ = strings.Cut(version, "-")
versionSub["X.Y.Z"] = patchVer
}
splits := strings.Split(patchVer, ".")
if len(splits) != 3 {
return nil, fmt.Errorf("unexpected version string %s", version)
}
minor, err := strconv.Atoi(splits[1])
if err != nil {
return nil, err
}
patch, err := strconv.Atoi(splits[2])
if err != nil {
return nil, err
}
versionSub["X.Y.W"] = semver.MajorMinor(version) + "." + strconv.Itoa(patch+1)
versionSub["X.Y-1"] = semver.Major(version) + "." + strconv.Itoa(minor-1)
versionSub["X.Y+1"] = semver.Major(version) + "." + strconv.Itoa(minor+1)
versionSub["X.Y"] = semver.MajorMinor(version)
// Now we have a nice map of keys -> values, convert into a list of
// key,value pairs that will be respected by strings.NewReplacer().
result := make([]string, 0, len(orderedSubstitutions)*2)
for _, p := range orderedSubstitutions {
version = versionSub[p]
result = append(result, p)
result = append(result, strings.TrimPrefix(version, "v"))
//fmt.Fprintf(os.Stderr, "Replacing %q with %q...\n", p, version)
}
return result, nil
}
func prepareChecklist(cfg ChecklistConfig) (string, error) {
tmpl, err := fetchTemplate(cfg)
if err != nil {
return "", fmt.Errorf("Failed to fetch template: %w", err)
}
patterns, err := assembleVersionSubstitutions(cfg.TargetVer)
if err != nil {
return "", fmt.Errorf("Error while parsing version %q: %w", cfg.TargetVer, err)
}
// Now, substitute version strings into the template
replacer := strings.NewReplacer(patterns...)
checklist := replacer.Replace(string(tmpl))
return checklist, nil
}
func templateToRequest(tmpl string) (*gh.IssueRequest, error) {
segments := strings.Split(tmpl, "---")
if len(segments) < 3 {
return nil, fmt.Errorf("unable to find metadata, body in issue template, check form of %s", cfg.TemplatePath)
}
meta := segments[1]
body := segments[2]
titleRe := regexp.MustCompile(`title: '(.*)'\n`)
match := titleRe.FindStringSubmatch(meta)
if len(match) < 2 {
return nil, fmt.Errorf("unable to find title in issue metadata:\n%s", meta)
}
title := string(match[1])
labelsRe := regexp.MustCompile(`labels: (.*)\n`)
match = labelsRe.FindStringSubmatch(meta)
if len(match) < 2 {
return nil, fmt.Errorf("unable to find labels in issue metadata:\n%s", meta)
}
labels := strings.Split(match[1], ",")
return &gh.IssueRequest{
Title: &title,
Body: &body,
Labels: &labels,
}, nil
}