Skip to content

Commit d1e3d46

Browse files
authored
feat(internal/gapicgen): change commit formatting to match standard (#3500)
Changing the commit formatting so that it can be parsed as a footer with a conventional commits parser. Here is an example of what a commit looked like previously: - docs(dialogflow): update comments on parameters and validation result. PiperOrigin-RevId: 348673154 Source-Link: googleapis/googleapis@0795e3f And what it will look like now: docs(dialogflow): update comments on parameters and validation result. PiperOrigin-RevId: 348673154 Source-Link: googleapis/googleapis@0795e3f
1 parent ac85c2e commit d1e3d46

File tree

4 files changed

+125
-68
lines changed

4 files changed

+125
-68
lines changed

internal/gapicgen/cmd/genbot/github.go

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func (gc *GithubClient) CreateGenprotoPR(ctx context.Context, genprotoDir string
187187
sb.WriteString(genprotoCommitBody)
188188
if !hasCorrespondingPR {
189189
sb.WriteString("\n\nThere is no corresponding google-cloud-go PR.\n")
190-
sb.WriteString(formatChanges(changes, false))
190+
sb.WriteString(generator.FormatChanges(changes, false))
191191
}
192192
body := sb.String()
193193

@@ -264,7 +264,7 @@ func (gc *GithubClient) CreateGocloudPR(ctx context.Context, gocloudDir string,
264264
} else {
265265
sb.WriteString("\n\nThere is no corresponding genproto PR.\n")
266266
}
267-
sb.WriteString(formatChanges(changes, true))
267+
sb.WriteString(generator.FormatChanges(changes, true))
268268
body := sb.String()
269269

270270
c := exec.Command("/bin/bash", "-c", `
@@ -318,7 +318,7 @@ func (gc *GithubClient) AmendGenprotoPR(ctx context.Context, genprotoPRNum int,
318318
var body strings.Builder
319319
body.WriteString(genprotoCommitBody)
320320
body.WriteString(fmt.Sprintf("\n\nCorresponding google-cloud-go PR: googleapis/google-cloud-go#%d\n", gocloudPRNum))
321-
body.WriteString(formatChanges(changes, false))
321+
body.WriteString(generator.FormatChanges(changes, false))
322322
sBody := body.String()
323323
c := exec.Command("/bin/bash", "-c", `
324324
set -ex
@@ -367,31 +367,3 @@ func (gc *GithubClient) MarkPRReadyForReview(ctx context.Context, repo string, n
367367
}
368368
return nil
369369
}
370-
371-
func formatChanges(changes []*generator.ChangeInfo, onlyGapicChanges bool) string {
372-
if len(changes) == 0 {
373-
return ""
374-
}
375-
var sb strings.Builder
376-
sb.WriteString("\nChanges:\n")
377-
for _, c := range changes {
378-
if onlyGapicChanges && !c.HasGapicChanges {
379-
continue
380-
}
381-
sb.WriteString("- ")
382-
ss := strings.Split(c.Body, "\n")
383-
for i, s := range ss {
384-
if i == 0 {
385-
sb.WriteString(fmt.Sprintf("%s\n", s))
386-
continue
387-
}
388-
if s == "" {
389-
sb.WriteString("\n")
390-
continue
391-
}
392-
sb.WriteString(fmt.Sprintf(" %s\n", s))
393-
}
394-
sb.WriteString("\n")
395-
}
396-
return sb.String()
397-
}

internal/gapicgen/cmd/genlocal/main.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ package main
2222
import (
2323
"context"
2424
"flag"
25-
"fmt"
2625
"io/ioutil"
2726
"log"
2827
"os"
@@ -93,12 +92,7 @@ func main() {
9392
log.Println(gocloudDir)
9493

9594
if *verbose {
96-
log.Println("Changes:")
97-
fmt.Println()
98-
for _, v := range changes {
99-
fmt.Println("********************************************")
100-
fmt.Println(v.Body)
101-
}
95+
log.Println(generator.FormatChanges(changes, false))
10296
}
10397
}
10498

internal/gapicgen/generator/git.go

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,55 @@ import (
2222

2323
// ChangeInfo represents a change and its associated metadata.
2424
type ChangeInfo struct {
25-
Body string
26-
GoogleapisHash string
27-
HasGapicChanges bool
25+
Body string
26+
Title string
27+
Package string
28+
GoogleapisHash string
29+
}
30+
31+
// FormatChanges turns a slice of changes into formatted string that will match
32+
// the conventional commit footer pattern. This will allow these changes to be
33+
// parsed into the changelog.
34+
func FormatChanges(changes []*ChangeInfo, onlyGapicChanges bool) string {
35+
if len(changes) == 0 {
36+
return ""
37+
}
38+
var sb strings.Builder
39+
sb.WriteString("\nChanges:\n\n")
40+
for _, c := range changes {
41+
if onlyGapicChanges && c.Package == "" {
42+
continue
43+
}
44+
45+
title := c.Title
46+
if c.Package != "" {
47+
// Try to add in pkg affected into conventional commit scope.
48+
titleParts := strings.SplitN(c.Title, ":", 2)
49+
if len(titleParts) == 2 {
50+
// If a scope is already provided, remove it.
51+
if i := strings.Index(titleParts[0], "("); i > 0 {
52+
titleParts[0] = titleParts[0][:i]
53+
}
54+
titleParts[0] = fmt.Sprintf("%s(%s)", titleParts[0], c.Package)
55+
}
56+
title = strings.Join(titleParts, ":")
57+
}
58+
sb.WriteString(fmt.Sprintf("%s\n", title))
59+
60+
// Format the commit body to conventional commit footer standards.
61+
splitBody := strings.Split(c.Body, "\n")
62+
for i := range splitBody {
63+
splitBody[i] = fmt.Sprintf(" %s", splitBody[i])
64+
}
65+
body := strings.Join(splitBody, "\n")
66+
sb.WriteString(fmt.Sprintf("%s\n\n", body))
67+
}
68+
// If the buffer is empty except for the "Changes:" text return an empty
69+
// string.
70+
if sb.Len() == 11 {
71+
return ""
72+
}
73+
return sb.String()
2874
}
2975

3076
// ParseChangeInfo gets the ChangeInfo for a given googleapis hash.
@@ -40,15 +86,21 @@ func ParseChangeInfo(googleapisDir string, hashes []string) ([]*ChangeInfo, erro
4086
for _, hash := range hashes {
4187
// Get commit title and body
4288
rawBody := bytes.NewBuffer(nil)
43-
c := command("git", "show", "--pretty=format:%B", "-s", hash)
89+
c := command("git", "show", "--pretty=format:%s~~%b", "-s", hash)
4490
c.Stdout = rawBody
4591
c.Dir = googleapisDir
4692
if err := c.Run(); err != nil {
4793
return nil, err
4894
}
4995

96+
ss := strings.Split(rawBody.String(), "~~")
97+
if len(ss) != 2 {
98+
return nil, fmt.Errorf("expected two segments for commit, got %d: %q", len(ss), rawBody.String())
99+
}
100+
title, body := strings.TrimSpace(ss[0]), strings.TrimSpace(ss[1])
101+
50102
// Add link so corresponding googleapis commit.
51-
body := fmt.Sprintf("%s\nSource-Link: https://github.com/googleapis/googleapis/commit/%s", strings.TrimSpace(rawBody.String()), hash)
103+
body = fmt.Sprintf("%s\nSource-Link: https://github.com/googleapis/googleapis/commit/%s", body, hash)
52104

53105
// Try to map files updated to a package in google-cloud-go. Assumes only
54106
// one servies protos are updated per commit. Multile versions are okay.
@@ -70,33 +122,12 @@ func ParseChangeInfo(googleapisDir string, hashes []string) ([]*ChangeInfo, erro
70122
break
71123
}
72124
}
73-
if pkg == "" {
74-
changes = append(changes, &ChangeInfo{
75-
Body: body,
76-
GoogleapisHash: hash,
77-
})
78-
continue
79-
}
80-
81-
// Try to add in pkg affected into conventional commit scope.
82-
bodyParts := strings.SplitN(body, "\n", 2)
83-
if len(bodyParts) > 0 {
84-
titleParts := strings.SplitN(bodyParts[0], ":", 2)
85-
if len(titleParts) == 2 {
86-
// If a scope is already provided, remove it.
87-
if i := strings.Index(titleParts[0], "("); i > 0 {
88-
titleParts[0] = titleParts[0][:i]
89-
}
90-
titleParts[0] = fmt.Sprintf("%s(%s)", titleParts[0], pkg)
91-
bodyParts[0] = strings.Join(titleParts, ":")
92-
}
93-
body = strings.Join(bodyParts, "\n")
94-
}
95125

96126
changes = append(changes, &ChangeInfo{
97-
Body: body,
98-
GoogleapisHash: hash,
99-
HasGapicChanges: true,
127+
Title: title,
128+
Body: body,
129+
Package: pkg,
130+
GoogleapisHash: hash,
100131
})
101132
}
102133
return changes, nil

internal/gapicgen/generator/git_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,63 @@ func TestParseConventionalCommitPkg(t *testing.T) {
3434
})
3535
}
3636
}
37+
38+
func TestFormatChanges(t *testing.T) {
39+
tests := []struct {
40+
name string
41+
changes []*ChangeInfo
42+
onlyGapics bool
43+
want string
44+
}{
45+
{
46+
name: "basic",
47+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar"}},
48+
want: "\nChanges:\n\nfix: foo\n bar\n\n",
49+
},
50+
{
51+
name: "breaking change",
52+
changes: []*ChangeInfo{{Title: "feat!: breaking change", Body: "BREAKING CHANGE: The world is breaking."}},
53+
want: "\nChanges:\n\nfeat!: breaking change\n BREAKING CHANGE: The world is breaking.\n\n",
54+
},
55+
{
56+
name: "multi-lined body indented",
57+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar\nbaz"}},
58+
want: "\nChanges:\n\nfix: foo\n bar\n baz\n\n",
59+
},
60+
{
61+
name: "multi-lined body indented, multiple changes",
62+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar\nbaz"}, {Title: "fix: baz", Body: "foo\nbar"}},
63+
want: "\nChanges:\n\nfix: foo\n bar\n baz\n\nfix: baz\n foo\n bar\n\n",
64+
},
65+
{
66+
name: "no package, filtered",
67+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar"}},
68+
onlyGapics: true,
69+
want: "",
70+
},
71+
{
72+
name: "with package",
73+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar", Package: "baz"}},
74+
want: "\nChanges:\n\nfix(baz): foo\n bar\n\n",
75+
},
76+
{
77+
name: "multiple changes",
78+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar", Package: "foo"}, {Title: "fix: baz", Body: "bar"}},
79+
want: "\nChanges:\n\nfix(foo): foo\n bar\n\nfix: baz\n bar\n\n",
80+
},
81+
{
82+
name: "multiple changes, some filtered",
83+
changes: []*ChangeInfo{{Title: "fix: foo", Body: "bar", Package: "foo"}, {Title: "fix: baz", Body: "bar"}},
84+
onlyGapics: true,
85+
want: "\nChanges:\n\nfix(foo): foo\n bar\n\n",
86+
},
87+
}
88+
89+
for _, tc := range tests {
90+
t.Run(tc.name, func(t *testing.T) {
91+
if got := FormatChanges(tc.changes, tc.onlyGapics); got != tc.want {
92+
t.Errorf("FormatChanges() = %q, want %q", got, tc.want)
93+
}
94+
})
95+
}
96+
}

0 commit comments

Comments
 (0)