diff --git a/server/events/comment_parser.go b/server/events/comment_parser.go index 58b018878f..102ef14a1d 100644 --- a/server/events/comment_parser.go +++ b/server/events/comment_parser.go @@ -16,15 +16,14 @@ package events import ( "fmt" "github.com/flynn-archive/go-shlex" + "github.com/runatlantis/atlantis/server/events/models" + "github.com/runatlantis/atlantis/server/events/yaml" + "github.com/spf13/pflag" "io/ioutil" "net/url" "path/filepath" "regexp" "strings" - - "github.com/runatlantis/atlantis/server/events/models" - "github.com/runatlantis/atlantis/server/events/yaml" - "github.com/spf13/pflag" ) const ( @@ -104,32 +103,37 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen return CommentParseResult{Ignore: true} } - args, err := shlex.Split(comment) - if err != nil { - return CommentParseResult{CommentResponse: fmt.Sprintf("```\nError parsing command: %s\n```", err)} - } + // We first use strings.Fields to parse and do an initial evaluation. + // Later we use a proper shell parser and re-parse. + args := strings.Fields(comment) if len(args) < 1 { return CommentParseResult{Ignore: true} } - // Helpfully warn the user if they're using "terraform" instead of "atlantis" - if args[0] == "terraform" { - return CommentParseResult{CommentResponse: DidYouMeanAtlantisComment} - } - // Atlantis can be invoked using the name of the VCS host user we're // running under. Need to be able to match against that user. vcsUser := e.GithubUser if vcsHost == models.Gitlab { vcsUser = e.GitlabUser } - executableNames := []string{"run", atlantisExecutable, "@" + vcsUser} - - // If the comment doesn't start with the name of our 'executable' then - // ignore it. + executableNames := []string{"run", "terraform", atlantisExecutable, "@" + vcsUser} if !e.stringInSlice(args[0], executableNames) { return CommentParseResult{Ignore: true} } + // Helpfully warn the user if they're using "terraform" instead of "atlantis" + if args[0] == "terraform" { + return CommentParseResult{CommentResponse: DidYouMeanAtlantisComment} + } + + // Now that we know Atlantis is being invoked, re-parse using a shell-style + // parser. + args, err := shlex.Split(comment) + if err != nil { + return CommentParseResult{CommentResponse: fmt.Sprintf("```\nError parsing command: %s\n```", err)} + } + if len(args) < 1 { + return CommentParseResult{Ignore: true} + } // If they've just typed the name of the executable then give them the help // output. diff --git a/server/events/comment_parser_test.go b/server/events/comment_parser_test.go index 4913a7fbc5..93a7ae8028 100644 --- a/server/events/comment_parser_test.go +++ b/server/events/comment_parser_test.go @@ -37,6 +37,7 @@ func TestParse_Ignored(t *testing.T) { "abc", "atlantis plan\nbut with newlines", "terraform plan\nbut with newlines", + "This shouldn't error, but it does.", } for _, c := range ignoreComments { r := commentParser.Parse(c, models.Github)