Skip to content

Commit cf6641c

Browse files
committed
internal/ci: ensure commit messages do not @-mention users
Parse the commit message as GitHub-flavored markdown to only search for @-mentions which would be linkified by GitHub, that is, not within backticks or block quotes. Adding goldmark as a Go dependency is okay given that it has zero dependencies itself, and that Go's lazy module loading means that any Go users of CUE as a library won't download it. Add positive and negative test cases as well. Signed-off-by: Daniel Martí <[email protected]> Change-Id: Ie2c86998bc11384a6d2e6c96c40027a519e233df Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1198294 Reviewed-by: Paul Jolly <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 97eeee4 commit cf6641c

File tree

4 files changed

+82
-1
lines changed

4 files changed

+82
-1
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
github.com/spf13/cobra v1.8.1
2020
github.com/spf13/pflag v1.0.5
2121
github.com/tetratelabs/wazero v1.6.0
22+
github.com/yuin/goldmark v1.4.13
2223
golang.org/x/mod v0.19.0
2324
golang.org/x/net v0.27.0
2425
golang.org/x/oauth2 v0.21.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
5959
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
6060
github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g=
6161
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
62+
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
63+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
6264
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
6365
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
6466
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=

internal/ci/checks/commit.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import (
2323
"regexp"
2424
"slices"
2525
"strings"
26+
27+
"github.com/yuin/goldmark"
28+
mdast "github.com/yuin/goldmark/ast"
29+
mdextension "github.com/yuin/goldmark/extension"
30+
mdtext "github.com/yuin/goldmark/text"
2631
)
2732

2833
func main() {
@@ -81,6 +86,38 @@ func checkCommit(dir string) error {
8186
authors, signers)
8287
}
8388

89+
// Forbid @-mentioning any GitHub usernames in commit messages,
90+
// as that will lead to notifications which are likely unintended.
91+
// If one must include a similar-looking snippet, like @embed(),
92+
// they can use markdown backticks or blockquotes to sidestep the issue.
93+
//
94+
// Note that we parse the body as markdown including git trailers, but that's okay.
95+
// Note that GitHub does not interpret mentions in titles, but we still check them
96+
// for the sake of being conservative and consistent.
97+
md := goldmark.New(
98+
goldmark.WithExtensions(mdextension.GFM),
99+
)
100+
docBody := []byte(body)
101+
doc := md.Parser().Parse(mdtext.NewReader(docBody))
102+
if err := mdast.Walk(doc, func(node mdast.Node, entering bool) (mdast.WalkStatus, error) {
103+
if !entering {
104+
return mdast.WalkContinue, nil
105+
}
106+
// Uncomment for some quick debugging.
107+
// fmt.Printf("%T\n%q\n\n", node, node.Text(docBody))
108+
switch node.(type) {
109+
case *mdast.CodeSpan:
110+
return mdast.WalkSkipChildren, nil
111+
case *mdast.Text:
112+
text := node.Text(docBody)
113+
if m := rxUserMention.FindSubmatch(text); m != nil {
114+
return mdast.WalkStop, fmt.Errorf("commit mentions %q; use backquotes or block quoting for code", m[2])
115+
}
116+
}
117+
return mdast.WalkContinue, nil
118+
}); err != nil {
119+
return err
120+
}
84121
return nil
85122
}
86123

@@ -91,7 +128,10 @@ func runCmd(dir string, exe string, args ...string) (string, error) {
91128
return string(bytes.TrimSpace(out)), err
92129
}
93130

94-
var rxExtractEmail = regexp.MustCompile(`.*<(.*)\>$`)
131+
var (
132+
rxExtractEmail = regexp.MustCompile(`.*<(.*)\>$`)
133+
rxUserMention = regexp.MustCompile(`(^|\s)(@[a-z0-9][a-z0-9-]*)`)
134+
)
95135

96136
func extractEmails(list string) []string {
97137
lines := strings.Split(list, "\n")

internal/ci/checks/testdata/checks.txtar

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,32 @@ Signed-off-by: cueckoo <[email protected]>
3030
Co-authored-by: collaborator <[email protected]>
3131
Signed-off-by: collaborator <[email protected]>
3232
Signed-off-by: collaborator <[email protected]>
33+
-- pass-quoted-embed --
34+
this message quotes an `@embed()` snippet
35+
36+
Signed-off-by: cueckoo <[email protected]>
37+
-- pass-longquoted-embed --
38+
this message quotes a longer `foo: string @embed()` snippet
39+
40+
Signed-off-by: cueckoo <[email protected]>
41+
-- pass-blockquoted-embed --
42+
this message block-quotes a snippet of code
43+
44+
foo: string @embed()
45+
46+
Signed-off-by: cueckoo <[email protected]>
47+
-- pass-version --
48+
versions like cuelang.org/[email protected] are okay
49+
50+
Signed-off-by: cueckoo <[email protected]>
51+
-- pass-lone-at --
52+
lone @ characters are also okay
53+
54+
Signed-off-by: cueckoo <[email protected]>
55+
-- pass-email --
56+
email addresses like [email protected] are okay
57+
58+
Signed-off-by: cueckoo <[email protected]>
3359

3460
-- fail-no-empty --
3561
This message forgot a title
@@ -42,3 +68,15 @@ this message lacks a signed-off-by trailer
4268
this message is signed off by a different person
4369

4470
Signed-off-by: Other Developer <[email protected]>
71+
-- fail-unquoted-embed --
72+
This message does not quote an @embed() snippet.
73+
74+
Signed-off-by: cueckoo <[email protected]>
75+
-- fail-leading-embed --
76+
@embed() may also be at the start.
77+
78+
Signed-off-by: cueckoo <[email protected]>
79+
-- fail-mention --
80+
This is an explicit mention of @someone which we don't do.
81+
82+
Signed-off-by: cueckoo <[email protected]>

0 commit comments

Comments
 (0)