From 60ac5a1d374cbb2aaacfc04e6c123d07b66fae5a Mon Sep 17 00:00:00 2001 From: Andriy Knysh Date: Wed, 17 Oct 2018 00:07:23 -0400 Subject: [PATCH] Add `wake-word` command line argument (#13) --- cmd/server.go | 14 +++++++++++++- server/events/comment_parser.go | 20 +++++++++++--------- server/events/comment_parser_test.go | 5 +++-- server/server.go | 2 ++ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cmd/server.go b/cmd/server.go index bc5238c118..4952337331 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -59,6 +59,7 @@ const ( RequireApprovalFlag = "require-approval" SSLCertFileFlag = "ssl-cert-file" SSLKeyFileFlag = "ssl-key-file" + WakeWordFlag = "wake-word" // Flag defaults. DefaultBitbucketBaseURL = bitbucketcloud.BaseURL @@ -69,6 +70,7 @@ const ( DefaultLogLevel = "info" DefaultPort = 4141 DefaultRepoConfig = "atlantis.yaml" + DefaultWakeWord = "atlantis" ) const redTermStart = "\033[31m" @@ -169,7 +171,8 @@ var stringFlags = []stringFlag{ description: "Optional path to the Atlantis YAML config file contained in each repo that this server should use. " + "This allows different Atlantis servers to point at different configs in the same repo.", defaultValue: DefaultRepoConfig, - }, { + }, + { name: RepoWhitelistFlag, description: "Comma separated list of repositories that Atlantis will operate on. " + "The format is {hostname}/{owner}/{repo}, ex. github.com/runatlantis/atlantis. '*' matches any characters until the next comma and can be used for example to whitelist " + @@ -184,6 +187,12 @@ var stringFlags = []stringFlag{ name: SSLKeyFileFlag, description: fmt.Sprintf("File containing x509 private key matching --%s.", SSLCertFileFlag), }, + { + name: WakeWordFlag, + description: "Wake word for this server to listen to. Default is 'atlantis'. " + + "This allows different wake commands (e.g. 'staging' or 'prod') to be used for different stages if more than one server operates on the same repo.", + defaultValue: DefaultWakeWord, + }, } var boolFlags = []boolFlag{ { @@ -389,6 +398,9 @@ func (s *ServerCmd) setDefaults(c *server.UserConfig) { if c.RepoConfig == "" { c.RepoConfig = DefaultRepoConfig } + if c.WakeWord == "" { + c.WakeWord = DefaultWakeWord + } } func (s *ServerCmd) validate(userConfig server.UserConfig) error { diff --git a/server/events/comment_parser.go b/server/events/comment_parser.go index 9b151ba632..0d26213064 100644 --- a/server/events/comment_parser.go +++ b/server/events/comment_parser.go @@ -34,7 +34,6 @@ const ( projectFlagShort = "p" verboseFlagLong = "verbose" verboseFlagShort = "" - atlantisExecutable = "atlantis" ) // multiLineRegex is used to ignore multi-line comments since those aren't valid @@ -67,6 +66,7 @@ type CommentParser struct { GithubToken string GitlabUser string GitlabToken string + WakeWord string } // CommentParseResult describes the result of parsing a comment as a command. @@ -84,7 +84,7 @@ type CommentParseResult struct { // Parse parses the comment as an Atlantis command. // // Valid commands contain: -// - The initial "executable" name, 'run' or 'atlantis' or '@GithubUser' +// - The initial "executable" name or '@GithubUser' // where GithubUser is the API user Atlantis is running as. // - Then a command, either 'plan', 'apply', or 'help'. // - Then optional flags, then an optional separator '--' followed by optional @@ -111,7 +111,7 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen // Helpfully warn the user if they're using "terraform" instead of "atlantis" if args[0] == "terraform" { - return CommentParseResult{CommentResponse: DidYouMeanAtlantisComment} + return CommentParseResult{CommentResponse: e.GetDidYouMeanWakeWordComment()} } // Atlantis can be invoked using the name of the VCS host user we're @@ -120,7 +120,7 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen if vcsHost == models.Gitlab { vcsUser = e.GitlabUser } - executableNames := []string{"run", atlantisExecutable, "@" + vcsUser} + executableNames := []string{e.WakeWord, "@" + vcsUser} // If the comment doesn't start with the name of our 'executable' then // ignore it. @@ -245,13 +245,13 @@ func (e *CommentParser) BuildPlanComment(repoRelDir string, workspace string, pr } commentFlags = fmt.Sprintf(" -- %s", strings.Join(flagsWithoutQuotes, " ")) } - return fmt.Sprintf("%s %s%s%s", atlantisExecutable, PlanCommand.String(), flags, commentFlags) + return fmt.Sprintf("%s %s%s%s", e.WakeWord, PlanCommand.String(), flags, commentFlags) } // BuildApplyComment builds an apply comment for the specified args. func (e *CommentParser) BuildApplyComment(repoRelDir string, workspace string, project string) string { flags := e.buildFlags(repoRelDir, workspace, project) - return fmt.Sprintf("%s %s%s", atlantisExecutable, ApplyCommand.String(), flags) + return fmt.Sprintf("%s %s%s", e.WakeWord, ApplyCommand.String(), flags) } func (e *CommentParser) buildFlags(repoRelDir string, workspace string, project string) string { @@ -338,6 +338,8 @@ Flags: Use "atlantis [command] --help" for more information about a command. ` -// 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 `atlantis` instead of `terraform`?" +// GetDidYouMeanWakeWordComment is the comment we add to the pull request when +// someone runs a command with terraform instead of the specified wake word. +func (e *CommentParser) GetDidYouMeanWakeWordComment() string { + return fmt.Sprintf("Did you mean to use `%s` instead of `terraform`?", e.WakeWord) +} diff --git a/server/events/comment_parser_test.go b/server/events/comment_parser_test.go index 0bb166dc2d..2ce9bdb538 100644 --- a/server/events/comment_parser_test.go +++ b/server/events/comment_parser_test.go @@ -28,6 +28,7 @@ var commentParser = events.CommentParser{ GithubToken: "github-token", GitlabUser: "gitlab-user", GitlabToken: "gitlab-token", + WakeWord: "atlantis", } func TestParse_Ignored(t *testing.T) { @@ -141,8 +142,8 @@ func TestParse_DidYouMeanAtlantis(t *testing.T) { } for _, c := range comments { r := commentParser.Parse(c, models.Github) - Assert(t, r.CommentResponse == events.DidYouMeanAtlantisComment, - "For comment %q expected CommentResponse==%q but got %q", c, events.DidYouMeanAtlantisComment, r.CommentResponse) + Assert(t, r.CommentResponse == commentParser.GetDidYouMeanWakeWordComment(), + "For comment %q expected CommentResponse==%q but got %q", c, commentParser.GetDidYouMeanWakeWordComment(), r.CommentResponse) } } diff --git a/server/server.go b/server/server.go index 86ff5cac12..0f540d970e 100644 --- a/server/server.go +++ b/server/server.go @@ -108,6 +108,7 @@ type UserConfig struct { SlackToken string `mapstructure:"slack-token"` SSLCertFile string `mapstructure:"ssl-cert-file"` SSLKeyFile string `mapstructure:"ssl-key-file"` + WakeWord string `mapstructure:"wake-word"` Webhooks []WebhookConfig `mapstructure:"webhooks"` } @@ -257,6 +258,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) { GithubToken: userConfig.GithubToken, GitlabUser: userConfig.GitlabUser, GitlabToken: userConfig.GitlabToken, + WakeWord: userConfig.WakeWord, } defaultTfVersion := terraformClient.Version() commandRunner := &events.DefaultCommandRunner{