Skip to content

Commit 92d664b

Browse files
Standard tools template
Add a script `update` that will keep it updated.
1 parent f3c3e94 commit 92d664b

File tree

167 files changed

+11169
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+11169
-0
lines changed

tools/changelog/changelog.go

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"os/exec"
8+
"regexp"
9+
"sort"
10+
"strings"
11+
)
12+
13+
var (
14+
mergeRequest = regexp.MustCompile(`Merge pull request #([\d]+)`)
15+
webconsoleBump = regexp.MustCompile(regexp.QuoteMeta("bump(github.com/openshift/origin-web-console): ") + `([\w]+)`)
16+
upstreamKube = regexp.MustCompile(`^UPSTREAM: (\d+)+:(.+)`)
17+
upstreamRepo = regexp.MustCompile(`^UPSTREAM: ([\w/-]+): (\d+)+:(.+)`)
18+
prefix = regexp.MustCompile(`^[\w-]: `)
19+
20+
assignments = []prefixAssignment{
21+
{"cluster up", "cluster"},
22+
{" pv ", "storage"},
23+
{"haproxy", "router"},
24+
{"router", "router"},
25+
{"route", "route"},
26+
{"authoriz", "auth"},
27+
{"rbac", "auth"},
28+
{"authent", "auth"},
29+
{"reconcil", "auth"},
30+
{"auth", "auth"},
31+
{"role", "auth"},
32+
{" dc ", "deploy"},
33+
{"deployment", "deploy"},
34+
{"rolling", "deploy"},
35+
{"security context constr", "security"},
36+
{"scc", "security"},
37+
{"pipeline", "build"},
38+
{"build", "build"},
39+
{"registry", "registry"},
40+
{"registries", "image"},
41+
{"image", "image"},
42+
{" arp ", "network"},
43+
{" cni ", "network"},
44+
{"egress", "network"},
45+
{"network", "network"},
46+
{"oc ", "cli"},
47+
{"template", "template"},
48+
{"etcd", "server"},
49+
{"pod", "node"},
50+
{"hack/", "hack"},
51+
{"e2e", "test"},
52+
{"integration", "test"},
53+
{"cluster", "cluster"},
54+
{"master", "server"},
55+
{"packages", "hack"},
56+
{"api", "server"},
57+
}
58+
)
59+
60+
type prefixAssignment struct {
61+
term string
62+
prefix string
63+
}
64+
65+
type commit struct {
66+
short string
67+
parents []string
68+
message string
69+
}
70+
71+
func contains(arr []string, value string) bool {
72+
for _, s := range arr {
73+
if s == value {
74+
return true
75+
}
76+
}
77+
return false
78+
}
79+
80+
func main() {
81+
log.SetFlags(0)
82+
if len(os.Args) != 3 {
83+
log.Fatalf("Must specify two arguments, FROM and TO")
84+
}
85+
from := os.Args[1]
86+
to := os.Args[2]
87+
88+
out, err := exec.Command("git", "log", "--topo-order", "--pretty=tformat:%h %p|%s", "--reverse", fmt.Sprintf("%s..%s", from, to)).CombinedOutput()
89+
if err != nil {
90+
log.Fatal(err)
91+
}
92+
93+
hide := make(map[string]struct{})
94+
var apiChanges []string
95+
var webconsole []string
96+
var commits []commit
97+
var upstreams []commit
98+
var bumps []commit
99+
for _, line := range strings.Split(string(out), "\n") {
100+
if len(strings.TrimSpace(line)) == 0 {
101+
continue
102+
}
103+
parts := strings.SplitN(line, "|", 2)
104+
hashes := strings.Split(parts[0], " ")
105+
c := commit{short: hashes[0], parents: hashes[1:], message: parts[1]}
106+
107+
if strings.HasPrefix(c.message, "UPSTREAM: ") {
108+
hide[c.short] = struct{}{}
109+
upstreams = append(upstreams, c)
110+
}
111+
if strings.HasPrefix(c.message, "bump(") {
112+
hide[c.short] = struct{}{}
113+
bumps = append(bumps, c)
114+
}
115+
116+
if len(c.parents) == 1 {
117+
commits = append(commits, c)
118+
continue
119+
}
120+
121+
matches := mergeRequest.FindStringSubmatch(line)
122+
if len(matches) == 0 {
123+
// this may have been a human pressing the merge button, we'll just record this as a direct push
124+
continue
125+
}
126+
127+
// split the accumulated commits into any that are force merges (assumed to be the initial set due
128+
// to --topo-order) from the PR commits as soon as we see any of our merge parents. Then print
129+
// any of the force merges
130+
var first int
131+
for i := range commits {
132+
first = i
133+
if contains(c.parents, commits[i].short) {
134+
first++
135+
break
136+
}
137+
}
138+
individual := commits[:first]
139+
merged := commits[first:]
140+
for _, commit := range individual {
141+
if len(commit.parents) > 1 {
142+
continue
143+
}
144+
if _, ok := hide[commit.short]; ok {
145+
continue
146+
}
147+
fmt.Printf("force-merge: %s %s\n", commit.message, commit.short)
148+
}
149+
150+
// try to find either the PR title or the first commit title from the merge commit
151+
out, err := exec.Command("git", "show", "--pretty=tformat:%b", c.short).CombinedOutput()
152+
if err != nil {
153+
log.Fatal(err)
154+
}
155+
var message string
156+
para := strings.Split(string(out), "\n\n")
157+
if len(para) > 0 && strings.HasPrefix(para[0], "Automatic merge from submit-queue") {
158+
para = para[1:]
159+
}
160+
// this is no longer necessary with the submit queue in place
161+
if len(para) > 0 && strings.HasPrefix(para[0], "Merged by ") {
162+
para = para[1:]
163+
}
164+
// post submit-queue, the merge bot will add the PR title, which is usually pretty good
165+
if len(para) > 0 {
166+
message = strings.Split(para[0], "\n")[0]
167+
}
168+
if len(message) == 0 && len(merged) > 0 {
169+
message = merged[0].message
170+
}
171+
if len(message) > 0 && len(merged) == 1 && message == merged[0].message {
172+
merged = nil
173+
}
174+
175+
// try to calculate a prefix based on the diff
176+
if len(message) > 0 && !prefix.MatchString(message) {
177+
prefix, ok := findPrefixFor(message, merged)
178+
if ok {
179+
message = prefix + ": " + message
180+
}
181+
}
182+
183+
// github merge
184+
185+
// has api changes
186+
display := fmt.Sprintf("%s [\\#%s](https://github.com/openshift/origin/pull/%s)", message, matches[1], matches[1])
187+
if hasFileChanges(c.short, "api/") {
188+
apiChanges = append(apiChanges, display)
189+
}
190+
191+
var filtered []commit
192+
for _, commit := range merged {
193+
if _, ok := hide[commit.short]; ok {
194+
continue
195+
}
196+
filtered = append(filtered, commit)
197+
}
198+
if len(filtered) > 0 {
199+
fmt.Printf("- %s\n", display)
200+
for _, commit := range filtered {
201+
fmt.Printf(" - %s (%s)\n", commit.message, commit.short)
202+
}
203+
}
204+
205+
// stick the merge commit in at the beginning of the next list so we can anchor the previous parent
206+
commits = []commit{c}
207+
}
208+
209+
// chunk the bumps
210+
var lines []string
211+
for _, commit := range bumps {
212+
if m := webconsoleBump.FindStringSubmatch(commit.message); len(m) > 0 {
213+
webconsole = append(webconsole, m[1])
214+
continue
215+
}
216+
lines = append(lines, commit.message)
217+
}
218+
lines = sortAndUniq(lines)
219+
for _, line := range lines {
220+
fmt.Printf("- %s\n", line)
221+
}
222+
223+
// chunk the upstreams
224+
lines = nil
225+
for _, commit := range upstreams {
226+
lines = append(lines, commit.message)
227+
}
228+
lines = sortAndUniq(lines)
229+
for _, line := range lines {
230+
fmt.Printf("- %s\n", upstreamLinkify(line))
231+
}
232+
233+
if len(webconsole) > 0 {
234+
fmt.Printf("- web: from %s^..%s\n", webconsole[0], webconsole[len(webconsole)-1])
235+
}
236+
237+
for _, apiChange := range apiChanges {
238+
fmt.Printf(" - %s\n", apiChange)
239+
}
240+
}
241+
242+
func findPrefixFor(message string, commits []commit) (string, bool) {
243+
message = strings.ToLower(message)
244+
for _, m := range assignments {
245+
if strings.Contains(message, m.term) {
246+
return m.prefix, true
247+
}
248+
}
249+
for _, c := range commits {
250+
if prefix, ok := findPrefixFor(c.message, nil); ok {
251+
return prefix, ok
252+
}
253+
}
254+
return "", false
255+
}
256+
257+
func hasFileChanges(commit string, prefixes ...string) bool {
258+
out, err := exec.Command("git", "diff", "--name-only", fmt.Sprintf("%s^..%s", commit, commit)).CombinedOutput()
259+
if err != nil {
260+
log.Fatal(err)
261+
}
262+
for _, file := range strings.Split(string(out), "\n") {
263+
for _, prefix := range prefixes {
264+
if strings.HasPrefix(file, prefix) {
265+
return true
266+
}
267+
}
268+
}
269+
return false
270+
}
271+
272+
func sortAndUniq(lines []string) []string {
273+
sort.Strings(lines)
274+
out := make([]string, 0, len(lines))
275+
last := ""
276+
for _, s := range lines {
277+
if last == s {
278+
continue
279+
}
280+
last = s
281+
out = append(out, s)
282+
}
283+
return out
284+
}
285+
286+
func upstreamLinkify(line string) string {
287+
if m := upstreamKube.FindStringSubmatch(line); len(m) > 0 {
288+
return fmt.Sprintf("UPSTREAM: [#%s](https://github.com/kubernetes/kubernetes/pull/%s):%s", m[1], m[1], m[2])
289+
}
290+
if m := upstreamRepo.FindStringSubmatch(line); len(m) > 0 {
291+
return fmt.Sprintf("UPSTREAM: [%s#%s](https://github.com/%s/pull/%s):%s", m[1], m[2], m[1], m[2], m[3])
292+
}
293+
return line
294+
}

tools/godepversion/OWNERS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
reviewers:
2+
- stevekuznetsov
3+
approvers:
4+
- stevekuznetsov

tools/godepversion/godepversion.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
)
9+
10+
type Godep struct {
11+
Deps []Dep
12+
}
13+
14+
type Dep struct {
15+
ImportPath string
16+
Comment string
17+
Rev string
18+
}
19+
20+
func main() {
21+
comment := false
22+
args := os.Args[1:]
23+
if len(args) == 3 {
24+
if args[2] == "comment" {
25+
comment = true
26+
} else {
27+
fmt.Fprintf(os.Stderr, "The third argument must be 'comment' or not specified.\n")
28+
os.Exit(1)
29+
}
30+
args = args[:2]
31+
}
32+
if len(args) != 2 {
33+
fmt.Fprintf(os.Stderr, "Expects two arguments, a path to the Godep.json file and a package to get the commit for (and optionally, 'comment' as the third option)\n")
34+
os.Exit(1)
35+
}
36+
37+
path := args[0]
38+
pkg := args[1]
39+
40+
data, err := ioutil.ReadFile(path)
41+
if err != nil {
42+
fmt.Fprintf(os.Stderr, "Unable to read %s: %v\n", path, err)
43+
os.Exit(1)
44+
}
45+
godeps := &Godep{}
46+
if err := json.Unmarshal(data, godeps); err != nil {
47+
fmt.Fprintf(os.Stderr, "Unable to read %s: %v\n", path, err)
48+
os.Exit(1)
49+
}
50+
51+
for _, dep := range godeps.Deps {
52+
if dep.ImportPath != pkg {
53+
continue
54+
}
55+
if len(dep.Rev) > 7 {
56+
dep.Rev = dep.Rev[0:7]
57+
}
58+
if comment && len(dep.Comment) > 0 {
59+
dep.Rev = dep.Comment
60+
}
61+
fmt.Fprintf(os.Stdout, dep.Rev)
62+
return
63+
}
64+
65+
fmt.Fprintf(os.Stderr, "Could not find %s in %s\n", pkg, path)
66+
os.Exit(1)
67+
}

0 commit comments

Comments
 (0)