From 0a5947f45e9329d13ef945550103e1638291889e Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sun, 2 Aug 2026 00:38:20 -0700 Subject: [PATCH] fix: match stage groups exactly --- README.md | 1 + cmd/joj3/conf/conf.go | 11 ++++++++--- cmd/joj3/conf/conf_test.go | 13 +++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ec4e78f..b0eedd1 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ Here are the steps `joj3` will run. 3. Generate stages. - We have an empty list of stages at the beginning. - We check all the stages from the configuration file. Stages with empty `group` field will always be added. Stages with non-empty `group` field requires that value (case insensitive) appears in the commit group. e.g. with commit msg `feat(h5/e3): joj msan [joj]`, stages with the following `group` field will run: `""`, `"joj"`. Currently, it does not support multiple groups within one commit. If the group specified in the commit message is `[all]`, then all groups will run. + - Groups are matched as case-insensitive, comma/space/semicolon/pipe-separated tokens. For example, `[joj, lint]` selects the `joj` and `lint` groups without substring matching. - Every stage needs to have an unique `name`, which means if two stages have the same name, only the first one will be added. 4. Run stages. - By default, all the stages will run sequentially. diff --git a/cmd/joj3/conf/conf.go b/cmd/joj3/conf/conf.go index ac1a90b..7361f37 100644 --- a/cmd/joj3/conf/conf.go +++ b/cmd/joj3/conf/conf.go @@ -201,8 +201,13 @@ func GetConfPath(confRoot, confName, fallbackConfName, msg, tag string) ( func MatchGroups(conf *Conf, conventionalCommit *ConventionalCommit) []string { seen := make(map[string]bool) keywords := []string{} - loweredCommitGroup := strings.ToLower(conventionalCommit.Group) - matchAllGroups := loweredCommitGroup == "all" + requestedGroups := make(map[string]bool) + for _, group := range strings.FieldsFunc(conventionalCommit.Group, func(r rune) bool { + return r == ',' || r == ';' || r == '|' || r == ' ' || r == '\t' + }) { + requestedGroups[strings.ToLower(group)] = true + } + matchAllGroups := requestedGroups["all"] confStages := []ConfStage{} confStages = append(confStages, conf.PreStages...) confStages = append(confStages, conf.Stages...) @@ -221,7 +226,7 @@ func MatchGroups(conf *Conf, conventionalCommit *ConventionalCommit) []string { slog.Info("group keywords from stages", "keywords", keywords) groups := []string{} for _, keyword := range keywords { - if matchAllGroups || strings.Contains(loweredCommitGroup, keyword) { + if matchAllGroups || requestedGroups[keyword] { groups = append(groups, keyword) } } diff --git a/cmd/joj3/conf/conf_test.go b/cmd/joj3/conf/conf_test.go index a52f737..712c7e9 100644 --- a/cmd/joj3/conf/conf_test.go +++ b/cmd/joj3/conf/conf_test.go @@ -130,3 +130,16 @@ func TestParseConventionalCommit(t *testing.T) { }) } } + +func TestMatchGroupsUsesExactTokens(t *testing.T) { + conf := &Conf{Stages: []ConfStage{ + {Name: "short", Groups: []string{"c"}}, + {Name: "cpp", Groups: []string{"cpp"}}, + {Name: "lint", Groups: []string{"lint"}}, + }} + got := MatchGroups(conf, &ConventionalCommit{Group: "cpp, lint"}) + want := []string{"cpp", "lint"} + if !reflect.DeepEqual(got, want) { + t.Fatalf("MatchGroups() = %v, want %v", got, want) + } +}