Skip to content

Commit

Permalink
feat: Add check for misspelled executable name command
Browse files Browse the repository at this point in the history
  • Loading branch information
edbighead committed Feb 21, 2023
1 parent 40f4e8c commit c264a83
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 4 deletions.
11 changes: 8 additions & 3 deletions server/events/comment_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ func (e *CommentParser) Parse(rawComment string, vcsHost models.VCSHostType) Com

// Helpfully warn the user if they're using "terraform" instead of "atlantis"
if args[0] == "terraform" && e.ExecutableName != "terraform" {
return CommentParseResult{CommentResponse: fmt.Sprintf(DidYouMeanAtlantisComment, e.ExecutableName)}
return CommentParseResult{CommentResponse: fmt.Sprintf(DidYouMeanAtlantisComment, e.ExecutableName, "terraform")}
}

// Helpfully warn the user that the command might be misspelled
if utils.IsSimilarWord(args[0], e.ExecutableName) {
return CommentParseResult{CommentResponse: fmt.Sprintf(DidYouMeanAtlantisComment, e.ExecutableName, args[0])}
}

// Atlantis can be invoked using the name of the VCS host user we're
Expand Down Expand Up @@ -541,8 +546,8 @@ Use "{{ .ExecutableName }} [command] --help" for more information about a comman
"\n```"

// DidYouMeanAtlantisComment is the comment we add to the pull request when
// someone runs a command with terraform instead of atlantis.
var DidYouMeanAtlantisComment = "Did you mean to use `%s` instead of `terraform`?"
// someone runs a misspelled command or terraform instead of atlantis.
var DidYouMeanAtlantisComment = "Did you mean to use `%s` instead of `%s`?"

// UnlockUsage is the comment we add to the pull request when someone runs
// `atlantis unlock` with flags.
Expand Down
2 changes: 1 addition & 1 deletion server/events/comment_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func TestParse_DidYouMeanAtlantis(t *testing.T) {
}
for _, c := range comments {
r := commentParser.Parse(c, models.Github)
Assert(t, r.CommentResponse == fmt.Sprintf(events.DidYouMeanAtlantisComment, "atlantis"),
Assert(t, r.CommentResponse == fmt.Sprintf(events.DidYouMeanAtlantisComment, "atlantis", "terraform"),
"For comment %q expected CommentResponse==%q but got %q", c, events.DidYouMeanAtlantisComment, r.CommentResponse)
}
}
Expand Down
17 changes: 17 additions & 0 deletions server/utils/spellcheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package utils

import (
"github.com/agext/levenshtein"
)

// IsSimilarWord calculates "The Levenshtein Distance" between two strings which
// represents the minimum total cost of edits that would convert the first string
// into the second. If the distance is less than 3, the word is considered misspelled.
func IsSimilarWord(given string, suggestion string) bool {
dist := levenshtein.Distance(given, suggestion, nil)
if dist > 0 && dist < 3 {
return true
}

return false
}
65 changes: 65 additions & 0 deletions server/utils/spellcheck_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package utils_test

import (
"fmt"
"testing"

"github.com/runatlantis/atlantis/server/utils"
. "github.com/runatlantis/atlantis/testing"
)

func Test_Spellcheck(t *testing.T) {
t.Log("check if given executable name is misspelled or just an unrelated word")

spellings := []struct {
Misspelled bool
Given string
Want string
}{
{
false,
"atlantis",
"atlantis",
},
{
false,
"maybe",
"atlantis",
},
{
false,
"atlantis-qa",
"atlantis-prod",
},
{
true,
"altantis",
"atlantis",
},
{
true,
"atlants",
"atlantis",
},
{
true,
"teraform",
"terraform",
},
}

for _, s := range spellings {
t.Run(fmt.Sprintf("given %s want %s", s.Given, s.Want), func(t *testing.T) {
isMisspelled := utils.IsSimilarWord(s.Given, s.Want)

if s.Misspelled {
Equals(t, isMisspelled, true)
}

if !s.Misspelled {
Equals(t, isMisspelled, false)
}
})
}

}

0 comments on commit c264a83

Please sign in to comment.