Skip to content

Commit

Permalink
feat: use coderefs matcher (#35)
Browse files Browse the repository at this point in the history
instead of doing string contains search, we can use the coderefs matcher
to find flag keys and aliases

this ensures that results from the commentor are accurate and consistent
with what is reported by official code refs tool and sets us up to
enable monorepo support

Custom delimiters in `.launchdarkly/coderefs.yaml` will be respected

Related changes:
- test data needed to use `kebabcase` aliases, since we now use
[delimiters](https://github.com/launchdarkly/ld-find-code-refs/blob/ed386199c5f41c224a9e7076a751f031cc38c644/docs/CONFIGURATION.md#delimiters)
like code refs
- test cases added to cover delimiters

Dev notes:
There is certainly some future refactoring that can be done in the code
refs tool itself to make getting a matcher, etc. more uniform.

Tested in gonfalon here:
https://github.com/launchdarkly/gonfalon/pull/27962#issuecomment-1629334562
  • Loading branch information
jazanne authored Jul 10, 2023
1 parent 00ff5c0 commit 49bf7b5
Show file tree
Hide file tree
Showing 57 changed files with 10,030 additions and 58 deletions.
1 change: 1 addition & 0 deletions .launchdarkly/coderefs.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aliases:
- type: camelcase
- type: snakecase
- type: kebabcase
58 changes: 27 additions & 31 deletions diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"os"
"strings"

ldapi "github.com/launchdarkly/api-client-go/v7"
lflags "github.com/launchdarkly/cr-flags/flags"
"github.com/launchdarkly/cr-flags/ignore"
lsearch "github.com/launchdarkly/ld-find-code-refs/v2/search"
"github.com/sourcegraph/go-diff/diff"
)

Expand Down Expand Up @@ -50,44 +50,40 @@ func CheckDiff(parsedDiff *diff.FileDiff, workspace string) *DiffPaths {
return &diffPaths
}

func ProcessDiffs(hunk *diff.Hunk, flagsRef lflags.FlagsRef, flags ldapi.FeatureFlags, aliases map[string][]string, maxFlags int) {
diffRows := strings.Split(string(hunk.Body), "\n")
for _, row := range diffRows {
func ProcessDiffs(matcher lsearch.Matcher, hunk *diff.Hunk, flagsRef lflags.FlagsRef, maxFlags int) {
flagMap := map[Operation]lflags.FlagAliasMap{
Add: flagsRef.FlagsAdded,
Delete: flagsRef.FlagsRemoved,
}
diffLines := strings.Split(string(hunk.Body), "\n")
for _, line := range diffLines {
if flagsRef.Count() >= maxFlags {
break
}
op := operation(row)
for _, flag := range flags.Items {
if strings.Contains(row, flag.Key) {
if op == Add {
if _, ok := flagsRef.FlagsAdded[flag.Key]; !ok {
flagsRef.FlagsAdded[flag.Key] = lflags.AliasSet{}
}
} else if op == Delete {
if _, ok := flagsRef.FlagsRemoved[flag.Key]; !ok {
flagsRef.FlagsRemoved[flag.Key] = lflags.AliasSet{}
}
}

op := operation(line)
if op == Equal {
continue
}

// only one for now
elementMatcher := matcher.Elements[0]
for _, flagKey := range elementMatcher.FindMatches(line) {
if _, ok := flagMap[op][flagKey]; !ok {
flagMap[op][flagKey] = make(lflags.AliasSet)
}
if len(aliases[flag.Key]) > 0 {
for _, alias := range aliases[flag.Key] {
if strings.Contains(row, alias) {
if op == Add {
if _, ok := flagsRef.FlagsAdded[flag.Key]; !ok {
flagsRef.FlagsAdded[flag.Key] = lflags.AliasSet{}
}
flagsRef.FlagsAdded[flag.Key][alias] = true
} else if op == Delete {
if _, ok := flagsRef.FlagsRemoved[flag.Key]; !ok {
flagsRef.FlagsRemoved[flag.Key] = lflags.AliasSet{}
}
flagsRef.FlagsRemoved[flag.Key][alias] = true
}
}
if aliasMatches := matcher.FindAliases(line, flagKey); len(aliasMatches) > 0 {
if _, ok := flagMap[op][flagKey]; !ok {
flagMap[op][flagKey] = make(lflags.AliasSet)
}
for _, alias := range aliasMatches {
flagMap[op][flagKey][alias] = true
}
}
}
}
flagsRef.FlagsAdded = flagMap[Add]
flagsRef.FlagsRemoved = flagMap[Delete]
}

// Operation defines the operation of a diff item.
Expand Down
68 changes: 66 additions & 2 deletions diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
ldapi "github.com/launchdarkly/api-client-go/v7"
"github.com/launchdarkly/cr-flags/config"
lflags "github.com/launchdarkly/cr-flags/flags"
lsearch "github.com/launchdarkly/ld-find-code-refs/v2/search"
"github.com/sourcegraph/go-diff/diff"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -45,10 +46,20 @@ type testProcessor struct {
Config config.Config
}

func (t testProcessor) flagKeys() []string {
keys := make([]string, 0, len(t.Flags.Items))
for _, f := range t.Flags.Items {
keys = append(keys, f.Key)
}
return keys
}

func newProcessFlagAccEnv() *testProcessor {
flag := createFlag("example-flag")
flag2 := createFlag("sample-flag")
flags := ldapi.FeatureFlags{}
flags.Items = append(flags.Items, flag)
flags.Items = append(flags.Items, flag2)
flagsAdded := make(lflags.FlagAliasMap)
flagsRemoved := make(lflags.FlagAliasMap)
flagsRef := lflags.FlagsRef{
Expand Down Expand Up @@ -117,6 +128,7 @@ func TestProcessDiffs(t *testing.T) {
sampleBody string
expected lflags.FlagsRef
aliases map[string][]string
delimiters string
}{
{
name: "add flag",
Expand Down Expand Up @@ -147,6 +159,23 @@ func TestProcessDiffs(t *testing.T) {
-here is a flag
-example-flag
-
this is no changes
in the hunk`,
},
{
name: "add and remove flag",
expected: lflags.FlagsRef{
FlagsAdded: lflags.FlagAliasMap{"sample-flag": lflags.AliasSet{}},
FlagsRemoved: lflags.FlagAliasMap{"example-flag": lflags.AliasSet{}},
},
aliases: map[string][]string{},
sampleBody: `
-Testing data
-this is for testing
-here is a flag
-example-flag
-
+ sample-flag
this is no changes
in the hunk`,
},
Expand Down Expand Up @@ -174,13 +203,43 @@ func TestProcessDiffs(t *testing.T) {
FlagsAdded: lflags.FlagAliasMap{"example-flag": lflags.AliasSet{"exampleFlag": true}},
FlagsRemoved: lflags.FlagAliasMap{},
},
aliases: map[string][]string{"example-flag": []string{"exampleFlag"}},
aliases: map[string][]string{"example-flag": {"exampleFlag"}},
sampleBody: `
+Testing data
+this is for testing
+here is a flag
+exampleFlag
+exampleFlag
+`,
},
{
name: "require delimiters - no matches",
expected: lflags.FlagsRef{
FlagsAdded: lflags.FlagAliasMap{},
FlagsRemoved: lflags.FlagAliasMap{},
},
delimiters: "'\"",
aliases: map[string][]string{},
sampleBody: `
+Testing data
+this is for testing
+here is a flag
+example-flag
+`,
},
{
name: "require delimiters - match",
expected: lflags.FlagsRef{
FlagsAdded: lflags.FlagAliasMap{"example-flag": lflags.AliasSet{}},
FlagsRemoved: lflags.FlagAliasMap{},
},
delimiters: "'\"",
aliases: map[string][]string{},
sampleBody: `
+Testing data
+this is for testing
+here is a flag
+"example-flag"
+`,
},
}
Expand All @@ -196,7 +255,12 @@ func TestProcessDiffs(t *testing.T) {
StartPosition: 1,
Body: []byte(tc.sampleBody),
}
ProcessDiffs(hunk, processor.FlagsRef, processor.Flags, tc.aliases, 5)
elements := []lsearch.ElementMatcher{}
elements = append(elements, lsearch.NewElementMatcher("default", "", tc.delimiters, processor.flagKeys(), tc.aliases))
matcher := lsearch.Matcher{
Elements: elements,
}
ProcessDiffs(matcher, hunk, processor.FlagsRef, 5)
assert.Equal(t, tc.expected, processor.FlagsRef)
})
}
Expand Down
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/jstemmer/go-junit-report/v2 v2.0.0
github.com/kyoh86/richgo v0.3.12
github.com/launchdarkly/api-client-go/v7 v7.1.1
github.com/launchdarkly/ld-find-code-refs/v2 v2.10.1-0.20230627211718-c0eec7327a20
github.com/launchdarkly/ld-find-code-refs/v2 v2.10.1-0.20230628134336-ed386199c5f4
)

require (
Expand All @@ -26,6 +26,7 @@ require (
github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-git/go-git/v5 v5.7.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand All @@ -45,6 +46,8 @@ require (
github.com/morikuni/aec v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
Expand All @@ -57,9 +60,9 @@ require (
golang.org/x/net v0.11.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/tools v0.10.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
14 changes: 10 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE=
github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Expand Down Expand Up @@ -163,7 +165,6 @@ github.com/jstemmer/go-junit-report/v2 v2.0.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuE
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
Expand All @@ -176,8 +177,8 @@ github.com/launchdarkly/api-client-go/v7 v7.1.1 h1:3VBkFt9xHljMw5KDlVFDUogxfH78Y
github.com/launchdarkly/api-client-go/v7 v7.1.1/go.mod h1:GVl1inKsWoKX3yLgdqrjxWw8k4ih0HlSmdnrhi5NNDs=
github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f h1:jfiPiz2hE/7mHv2NOS4cm07sSJCsKlbxmR7pzPhhvpU=
github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f/go.mod h1:CHbYdMs8UjvNnS2fatlQvi4UYnBTRYGxRHc/0kQupSQ=
github.com/launchdarkly/ld-find-code-refs/v2 v2.10.1-0.20230627211718-c0eec7327a20 h1:U5d40xUQQlnD/dTxd7av9k+G1ghC5Ny2Nw7qtShcaMQ=
github.com/launchdarkly/ld-find-code-refs/v2 v2.10.1-0.20230627211718-c0eec7327a20/go.mod h1:nNi9KzXnlIlE2vD9+ZMbWM/pES6VCMciSsK9duta918=
github.com/launchdarkly/ld-find-code-refs/v2 v2.10.1-0.20230628134336-ed386199c5f4 h1:mupbGsSmix7Ct0o+BzGOVetwGY7dRENzJdwDu9YroVM=
github.com/launchdarkly/ld-find-code-refs/v2 v2.10.1-0.20230628134336-ed386199c5f4/go.mod h1:nNi9KzXnlIlE2vD9+ZMbWM/pES6VCMciSsK9duta918=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
Expand All @@ -199,6 +200,10 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8=
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down Expand Up @@ -448,6 +453,8 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down Expand Up @@ -548,7 +555,6 @@ google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
Expand Down
19 changes: 8 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
e "github.com/launchdarkly/cr-flags/errors"
lflags "github.com/launchdarkly/cr-flags/flags"
gha "github.com/launchdarkly/cr-flags/internal/github_actions"
"github.com/launchdarkly/ld-find-code-refs/v2/aliases"
"github.com/launchdarkly/cr-flags/search"
"github.com/launchdarkly/ld-find-code-refs/v2/options"
"github.com/sourcegraph/go-diff/diff"
"github.com/spf13/viper"
Expand All @@ -45,7 +45,10 @@ func main() {
os.Exit(0)
}

aliases, err := getAliases(config, flagKeys)
opts, err := getOptions(config)
failExit(err)

matcher, err := search.GetMatcher(config, opts, flagKeys)
failExit(err)

multiFiles, err := getDiffs(ctx, config, *event.PullRequest.Number)
Expand All @@ -62,7 +65,7 @@ func main() {
continue
}
for _, hunk := range parsedDiff.Hunks {
ldiff.ProcessDiffs(hunk, flagsRef, flags, aliases, config.MaxFlags)
ldiff.ProcessDiffs(matcher, hunk, flagsRef, config.MaxFlags)
}
}

Expand Down Expand Up @@ -188,7 +191,7 @@ func getDiffs(ctx context.Context, config *lcr.Config, prNumber int) ([]*diff.Fi
return diff.ParseMultiFileDiff([]byte(raw))
}

func getAliases(config *lcr.Config, flagKeys []string) (map[string][]string, error) {
func getOptions(config *lcr.Config) (options.Options, error) {
// Needed for ld-find-code-refs to work as a library
viper.Set("dir", config.Workspace)
viper.Set("accessToken", config.ApiToken)
Expand All @@ -197,13 +200,7 @@ func getAliases(config *lcr.Config, flagKeys []string) (map[string][]string, err
if err != nil {
log.Println(err)
}
opts, err := options.GetOptions()
if err != nil {
log.Println(err)
}

return aliases.GenerateAliases(flagKeys, opts.Aliases, config.Workspace)

return options.GetOptions()
}

func setOutputs(flagsRef lflags.FlagsRef) {
Expand Down
Loading

0 comments on commit 49bf7b5

Please sign in to comment.