diff --git a/server/apply_executor.go b/server/apply_executor.go index 24a8a5fb4..c7ea5404b 100644 --- a/server/apply_executor.go +++ b/server/apply_executor.go @@ -316,3 +316,16 @@ func (a *ApplyExecutor) worstResult(results []PathResult) string { } return worst } + +type ExecutionPath struct { + // Absolute is the full path on the OS where we will execute. + // Will never end with a '/'. + Absolute string + // Relative is the path relative to the repo root. + // Will never end with a '/'. + Relative string +} + +func NewExecutionPath(absolutePath string, relativePath string) ExecutionPath { + return ExecutionPath{filepath.Clean(absolutePath), filepath.Clean(relativePath)} +} diff --git a/server/plan_executor.go b/server/plan_executor.go index ba85c32dd..a4f40f25c 100644 --- a/server/plan_executor.go +++ b/server/plan_executor.go @@ -14,7 +14,7 @@ import ( "strings" ) -// PlanExecutor handles everything related to running the Terraform plan including integration with S3, Terraform, and Github +// PlanExecutor handles everything related to running the Terraform plan including integration with S3, Terraform, and GitHub type PlanExecutor struct { github *GithubClient awsConfig *AWSConfig diff --git a/server/request_parser.go b/server/request_parser.go index 905cc9159..df9d24117 100644 --- a/server/request_parser.go +++ b/server/request_parser.go @@ -24,25 +24,20 @@ type Command struct { commandType CommandType } -func (r *RequestParser) determineCommand(comment *github.IssueCommentEvent) (*Command, error) { +func (r *RequestParser) DetermineCommand(comment *github.IssueCommentEvent) (*Command, error) { // for legacy, also support "run" instead of atlantis atlantisCommentRegex := `^(?:run|atlantis) (plan|apply|help)([[:blank:]])?([a-zA-Z0-9_-]+)?\s*(--verbose)?$` runPlanMatcher := regexp.MustCompile(atlantisCommentRegex) - commentComment := comment.Comment - if commentComment == nil { - return nil, errors.New("key 'comment.comment' is null") - } - - commentBody := commentComment.Body - if commentBody == nil { - return nil, errors.New("key 'comment.comment.body' is null") + commentBody := comment.Comment.GetBody() + if commentBody == "" { + return nil, errors.New("comment.body is null") } // extract the command and environment. ex. for "atlantis plan staging", the command is "plan", and the environment is "staging" - match := runPlanMatcher.FindStringSubmatch(*commentBody) + match := runPlanMatcher.FindStringSubmatch(commentBody) if len(match) < 5 { - var truncated = *commentBody + var truncated = commentBody if len(truncated) > 30 { truncated = truncated[0:30] + "..." } @@ -67,87 +62,86 @@ func (r *RequestParser) determineCommand(comment *github.IssueCommentEvent) (*Co return command, nil } -func (r *RequestParser) extractCommentData(comment *github.IssueCommentEvent, ctx *CommandContext) error { - repoFullName := comment.Repo.FullName - if repoFullName == nil { - return errors.New("key 'comment.repo.full_name' is null") +func (r *RequestParser) ExtractCommentData(comment *github.IssueCommentEvent, ctx *CommandContext) error { + repoFullName := comment.Repo.GetFullName() + if repoFullName == "" { + return errors.New("repository.full_name is null") } - repoOwner := comment.Repo.Owner.Login - if repoOwner == nil { - return errors.New("key 'comment.repo.owner.login' is null") + repoOwner := comment.Repo.Owner.GetLogin() + if repoOwner == "" { + return errors.New("repository.owner.login is null") } - repoName := comment.Repo.Name - if repoName == nil { - return errors.New("key 'comment.repo.name' is null") + repoName := comment.Repo.GetName() + if repoName == "" { + return errors.New("repository.name is null") } - pullNum := comment.Issue.Number - if pullNum == nil { - return errors.New("key 'comment.issue.number' is null") + repoSSHURL := comment.Repo.GetSSHURL() + if repoSSHURL == "" { + return errors.New("comment.repository.ssh_url is null") } - pullCreator := comment.Issue.User.Login - if pullCreator == nil { - return errors.New("key 'comment.issue.user.login' is null") + pullNum := comment.Issue.GetNumber() + if pullNum == 0 { + return errors.New("issue.number' is null") } - commentorUsername := comment.Comment.User.Login - if commentorUsername == nil { - return errors.New("key 'comment.comment.user.login' is null") + pullCreator := comment.Issue.User.GetLogin() + if pullCreator == "" { + return errors.New("issue.user.login' is null") } - repoSSHURL := comment.Repo.SSHURL - if repoSSHURL == nil { - return errors.New("key 'comment.repo.sshurl' is null") + commentorUsername := comment.Comment.User.GetLogin() + if commentorUsername == "" { + return errors.New("comment.user.login is null") } - htmlURL := comment.Issue.HTMLURL - if htmlURL == nil { - return errors.New("key 'comment.issue.htmlUrl' is null") + htmlURL := comment.Issue.GetHTMLURL() + if htmlURL == "" { + return errors.New("comment.issue.html_url is null") } ctx.Repo = models.Repo{ - FullName: *repoFullName, - Owner: *repoOwner, - Name: *repoName, - SSHURL: *repoSSHURL, + FullName: repoFullName, + Owner: repoOwner, + Name: repoName, + SSHURL: repoSSHURL, } ctx.User = models.User{ - Username: *commentorUsername, + Username: commentorUsername, } ctx.Pull = models.PullRequest{ - Num: *pullNum, + Num: pullNum, } - return nil } -func (r *RequestParser) extractPullData(pull *github.PullRequest, params *CommandContext) error { - commit := pull.Head.SHA - if commit == nil { - return errors.New("key 'pull.head.sha' is null") +func (r *RequestParser) ExtractPullData(pull *github.PullRequest, params *CommandContext) error { + commit := pull.Head.GetSHA() + if commit == "" { + return errors.New("head.sha is null") } - base := pull.Base.SHA - if base == nil { - return errors.New("key 'pull.base.sha' is null") + base := pull.Base.GetSHA() + if base == "" { + return errors.New("base.sha is null") } - pullLink := pull.HTMLURL - if pullLink == nil { - return errors.New("key 'pull.html_url' is null") + pullLink := pull.GetHTMLURL() + if pullLink == "" { + return errors.New("html_url is null") } - branch := pull.Head.Ref - if branch == nil { - return errors.New("key 'pull.head.ref' is null") + branch := pull.Head.GetRef() + if branch == "" { + return errors.New("head.ref is null") } - authorUsername := pull.User.Login - if authorUsername == nil { - return errors.New("key 'pull.user.login' is null") + authorUsername := pull.User.GetLogin() + if authorUsername == "" { + return errors.New("user.login is null") } - num := pull.Number - if num == nil { - return errors.New("key 'pull.num' is null") + num := pull.GetNumber() + if num == 0 { + return errors.New("number is null") } params.Pull = models.PullRequest{ - BaseCommit: *base, - Author: *authorUsername, - Branch: *branch, - HeadCommit: *commit, - Link: *pullLink, - Num: *num, + BaseCommit: base, + Author: authorUsername, + Branch: branch, + HeadCommit: commit, + Link: pullLink, + Num: num, } return nil } diff --git a/server/server.go b/server/server.go index 42f0ca8c0..67ac180aa 100644 --- a/server/server.go +++ b/server/server.go @@ -35,7 +35,7 @@ const ( LockingDynamoDBBackend = "dynamodb" ) -// Server listens for Github webhooks and runs the necessary Atlantis command +// Server listens for GitHub events and runs the necessary Atlantis command type Server struct { router *mux.Router port int @@ -73,7 +73,6 @@ type ServerConfig struct { LockingDynamoDBTable string `mapstructure:"locking-dynamodb-table"` } -// todo: rename to Command type CommandContext struct { Repo models.Repo Pull models.PullRequest @@ -95,18 +94,6 @@ type PathResult struct { Result Templater } -type ExecutionPath struct { - // Absolute is the full path on the OS where we will execute. - // Will never end with a '/'. - Absolute string - // Relative is the path relative to the repo root. - // Will never end with a '/'. - Relative string -} - -func NewExecutionPath(absolutePath string, relativePath string) ExecutionPath { - return ExecutionPath{filepath.Clean(absolutePath), filepath.Clean(relativePath)} -} type Templater interface { Template() *CompiledTemplate @@ -320,7 +307,7 @@ func (s *Server) handlePullClosedEvent(w http.ResponseWriter, pullEvent github.P func (s *Server) handleCommentCreatedEvent(w http.ResponseWriter, comment github.IssueCommentEvent, githubReqID string) { // determine if the comment matches a plan or apply command ctx := &CommandContext{} - command, err := s.requestParser.determineCommand(&comment) + command, err := s.requestParser.DetermineCommand(&comment) if err != nil { s.logger.Debug("Ignoring request: %v %s", err, githubReqID) fmt.Fprintln(w, "Ignoring") @@ -328,7 +315,7 @@ func (s *Server) handleCommentCreatedEvent(w http.ResponseWriter, comment github } ctx.Command = command - if err = s.requestParser.extractCommentData(&comment, ctx); err != nil { + if err = s.requestParser.ExtractCommentData(&comment, ctx); err != nil { s.logger.Err("Failed parsing event: %v %s", err, githubReqID) fmt.Fprintln(w, "Ignoring") return @@ -350,7 +337,7 @@ func (s *Server) executeCommand(ctx *CommandContext) { ctx.Log.Err("pull request data api call failed: %v", err) return } - if err := s.requestParser.extractPullData(pull, ctx); err != nil { + if err := s.requestParser.ExtractPullData(pull, ctx); err != nil { ctx.Log.Err("failed to extract required fields from comment data: %v", err) return }