Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context object to update status structs. #224

Merged
merged 2 commits into from
Mar 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions server/controllers/events/events_controller_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package events_test

import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -34,6 +35,7 @@ import (
"github.com/runatlantis/atlantis/server/events/models"
"github.com/runatlantis/atlantis/server/events/vcs"
lyft_vcs "github.com/runatlantis/atlantis/server/events/vcs/lyft"
"github.com/runatlantis/atlantis/server/events/vcs/types"
"github.com/runatlantis/atlantis/server/events/webhooks"
"github.com/runatlantis/atlantis/server/logging"
"github.com/runatlantis/atlantis/server/lyft/feature"
Expand Down Expand Up @@ -552,7 +554,7 @@ func setupE2E(t *testing.T, repoFixtureDir string, userConfig *server.UserConfig
// TODO: aggregate some of this with that of server.go to minimize duplication
allowForkPRs := false
vcsClient := vcs.NewClientProxy(ghClient, nil, nil, nil, nil)
e2eStatusUpdater := &events.DefaultCommitStatusUpdater{Client: vcsClient, TitleBuilder: vcs.StatusTitleBuilder{TitlePrefix: "atlantis"}}
e2eStatusUpdater := &command.VCSStatusUpdater{Client: vcsClient, TitleBuilder: vcs.StatusTitleBuilder{TitlePrefix: "atlantis"}}

eventParser := &events.EventParser{
GithubUser: "github-user",
Expand Down Expand Up @@ -1153,7 +1155,7 @@ func (t *testGithubClient) PullIsApproved(repo models.Repo, pull models.PullRequ
func (t *testGithubClient) PullIsMergeable(repo models.Repo, pull models.PullRequest) (bool, error) {
return false, nil
}
func (t *testGithubClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, src string, description string, url string) error {
func (t *testGithubClient) UpdateStatus(ctx context.Context, request types.UpdateStatusRequest) error {
return nil
}
func (t *testGithubClient) MergePull(pull models.PullRequest, pullOptions models.PullRequestOptions) error {
Expand Down
3 changes: 2 additions & 1 deletion server/core/runtime/apply_step_runner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package runtime

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -126,7 +127,7 @@ func (a *ApplyStepRunner) runRemoteApply(

// updateStatusF will update the commit status and log any error.
updateStatusF := func(status models.CommitStatus, url string) {
if err := a.CommitStatusUpdater.UpdateProject(ctx, command.Apply, status, url); err != nil {
if err := a.CommitStatusUpdater.UpdateProject(context.TODO(), ctx, command.Apply, status, url); err != nil {
ctx.Log.Err("unable to update status: %s", err)
}
}
Expand Down
5 changes: 3 additions & 2 deletions server/core/runtime/apply_step_runner_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package runtime_test

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -280,8 +281,8 @@ Apply complete! Resources: 0 added, 0 changed, 1 destroyed.

// Check that the status was updated with the run url.
runURL := "https://app.terraform.io/app/lkysow-enterprises/atlantis-tfe-test-dir2/runs/run-PiDsRYKGcerTttV2"
updater.VerifyWasCalledOnce().UpdateProject(ctx, command.Apply, models.PendingCommitStatus, runURL)
updater.VerifyWasCalledOnce().UpdateProject(ctx, command.Apply, models.SuccessCommitStatus, runURL)
updater.VerifyWasCalledOnce().UpdateProject(context.TODO(), ctx, command.Apply, models.PendingCommitStatus, runURL)
updater.VerifyWasCalledOnce().UpdateProject(context.TODO(), ctx, command.Apply, models.SuccessCommitStatus, runURL)
}

// Test that if the plan is different, we error out.
Expand Down
3 changes: 2 additions & 1 deletion server/core/runtime/plan_step_runner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package runtime

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -247,7 +248,7 @@ func (p *PlanStepRunner) runRemotePlan(

// updateStatusF will update the commit status and log any error.
updateStatusF := func(status models.CommitStatus, url string) {
if err := p.CommitStatusUpdater.UpdateProject(ctx, command.Plan, status, url); err != nil {
if err := p.CommitStatusUpdater.UpdateProject(context.TODO(), ctx, command.Plan, status, url); err != nil {
ctx.Log.Err("unable to update status: %s", err)
}
}
Expand Down
5 changes: 3 additions & 2 deletions server/core/runtime/plan_step_runner_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package runtime_test

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -808,8 +809,8 @@ Plan: 0 to add, 0 to change, 1 to destroy.`, string(bytes))

// Ensure that the status was updated with the runURL.
runURL := "https://app.terraform.io/app/lkysow-enterprises/atlantis-tfe-test/runs/run-is4oVvJfrkud1KvE"
updater.VerifyWasCalledOnce().UpdateProject(ctx, command.Plan, models.PendingCommitStatus, runURL)
updater.VerifyWasCalledOnce().UpdateProject(ctx, command.Plan, models.SuccessCommitStatus, runURL)
updater.VerifyWasCalledOnce().UpdateProject(context.TODO(), ctx, command.Plan, models.PendingCommitStatus, runURL)
updater.VerifyWasCalledOnce().UpdateProject(context.TODO(), ctx, command.Plan, models.SuccessCommitStatus, runURL)
})
}
}
Expand Down
3 changes: 2 additions & 1 deletion server/core/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package runtime

import (
"bytes"
"context"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -48,7 +49,7 @@ type AsyncTFExec interface {
// StatusUpdater brings the interface from CommitStatusUpdater into this package
// without causing circular imports.
type StatusUpdater interface {
UpdateProject(ctx command.ProjectContext, cmdName command.Name, status models.CommitStatus, url string) error
UpdateProject(ctx context.Context, projectCtx command.ProjectContext, cmdName fmt.Stringer, status models.CommitStatus, url string) error
}

//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_runner.go Runner
Expand Down
9 changes: 6 additions & 3 deletions server/events/apply_command_runner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package events

import (
"context"

"github.com/runatlantis/atlantis/server/core/locking"
"github.com/runatlantis/atlantis/server/events/command"
"github.com/runatlantis/atlantis/server/events/models"
Expand Down Expand Up @@ -90,7 +92,7 @@ func (a *ApplyCommandRunner) Run(ctx *command.Context, cmd *command.Comment) {
return
}

if err = a.commitStatusUpdater.UpdateCombined(baseRepo, pull, models.PendingCommitStatus, cmd.CommandName()); err != nil {
if err = a.commitStatusUpdater.UpdateCombined(context.TODO(), baseRepo, pull, models.PendingCommitStatus, cmd.CommandName()); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}

Expand All @@ -112,7 +114,7 @@ func (a *ApplyCommandRunner) Run(ctx *command.Context, cmd *command.Comment) {
projectCmds, err = a.prjCmdBuilder.BuildApplyCommands(ctx, cmd)

if err != nil {
if statusErr := a.commitStatusUpdater.UpdateCombined(ctx.Pull.BaseRepo, ctx.Pull, models.FailedCommitStatus, cmd.CommandName()); statusErr != nil {
if statusErr := a.commitStatusUpdater.UpdateCombined(context.TODO(), ctx.Pull.BaseRepo, ctx.Pull, models.FailedCommitStatus, cmd.CommandName()); statusErr != nil {
ctx.Log.Warn("unable to update commit status: %s", statusErr)
}
a.pullUpdater.UpdatePull(ctx, cmd, command.Result{Error: err})
Expand All @@ -127,7 +129,7 @@ func (a *ApplyCommandRunner) Run(ctx *command.Context, cmd *command.Comment) {
// with 0/0 projects applied successfully because some users require
// the Atlantis status to be passing for all pull requests.
ctx.Log.Debug("setting VCS status to success with no projects found")
if err := a.commitStatusUpdater.UpdateCombinedCount(baseRepo, pull, models.SuccessCommitStatus, command.Apply, 0, 0); err != nil {
if err := a.commitStatusUpdater.UpdateCombinedCount(context.TODO(), baseRepo, pull, models.SuccessCommitStatus, command.Apply, 0, 0); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}
}
Expand Down Expand Up @@ -188,6 +190,7 @@ func (a *ApplyCommandRunner) updateCommitStatus(ctx *command.Context, pullStatus
}

if err := a.commitStatusUpdater.UpdateCombinedCount(
context.TODO(),
ctx.Pull.BaseRepo,
ctx.Pull,
status,
Expand Down
9 changes: 5 additions & 4 deletions server/events/approve_policies_command_runner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package events

import (
"context"
"fmt"

"github.com/runatlantis/atlantis/server/events/command"
Expand Down Expand Up @@ -43,13 +44,13 @@ func (a *ApprovePoliciesCommandRunner) Run(ctx *command.Context, cmd *command.Co
baseRepo := ctx.Pull.BaseRepo
pull := ctx.Pull

if err := a.commitStatusUpdater.UpdateCombined(baseRepo, pull, models.PendingCommitStatus, command.PolicyCheck); err != nil {
if err := a.commitStatusUpdater.UpdateCombined(context.TODO(), baseRepo, pull, models.PendingCommitStatus, command.PolicyCheck); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}

projectCmds, err := a.prjCmdBuilder.BuildApprovePoliciesCommands(ctx, cmd)
if err != nil {
if statusErr := a.commitStatusUpdater.UpdateCombined(ctx.Pull.BaseRepo, ctx.Pull, models.FailedCommitStatus, command.PolicyCheck); statusErr != nil {
if statusErr := a.commitStatusUpdater.UpdateCombined(context.TODO(), ctx.Pull.BaseRepo, ctx.Pull, models.FailedCommitStatus, command.PolicyCheck); statusErr != nil {
ctx.Log.Warn("unable to update commit status: %s", statusErr)
}
a.pullUpdater.UpdatePull(ctx, cmd, command.Result{Error: err})
Expand All @@ -63,7 +64,7 @@ func (a *ApprovePoliciesCommandRunner) Run(ctx *command.Context, cmd *command.Co
// with 0/0 projects approve_policies successfully because some users require
// the Atlantis status to be passing for all pull requests.
ctx.Log.Debug("setting VCS status to success with no projects found")
if err := a.commitStatusUpdater.UpdateCombinedCount(ctx.Pull.BaseRepo, ctx.Pull, models.SuccessCommitStatus, command.PolicyCheck, 0, 0); err != nil {
if err := a.commitStatusUpdater.UpdateCombinedCount(context.TODO(), ctx.Pull.BaseRepo, ctx.Pull, models.SuccessCommitStatus, command.PolicyCheck, 0, 0); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}
}
Expand Down Expand Up @@ -118,7 +119,7 @@ func (a *ApprovePoliciesCommandRunner) updateCommitStatus(ctx *command.Context,
status = models.FailedCommitStatus
}

if err := a.commitStatusUpdater.UpdateCombinedCount(ctx.Pull.BaseRepo, ctx.Pull, status, command.PolicyCheck, numSuccess, len(pullStatus.Projects)); err != nil {
if err := a.commitStatusUpdater.UpdateCombinedCount(context.TODO(), ctx.Pull.BaseRepo, ctx.Pull, status, command.PolicyCheck, numSuccess, len(pullStatus.Projects)); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}
}
97 changes: 97 additions & 0 deletions server/events/command/vcs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package command

import (
"context"
"fmt"
"strings"

"github.com/runatlantis/atlantis/server/events/models"
"github.com/runatlantis/atlantis/server/events/vcs"
"github.com/runatlantis/atlantis/server/events/vcs/types"
)

// VCSStatusUpdater updates the status of a commit with the VCS host. We set
// the status to signify whether the plan/apply succeeds.
type VCSStatusUpdater struct {
Client vcs.Client
TitleBuilder vcs.StatusTitleBuilder
}

func (d *VCSStatusUpdater) UpdateCombined(ctx context.Context, repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmdName fmt.Stringer) error {
src := d.TitleBuilder.Build(cmdName.String())
descrip := fmt.Sprintf("%s %s", strings.Title(cmdName.String()), d.statusDescription(status))

request := types.UpdateStatusRequest{
Repo: repo,
PullNum: pull.Num,
Ref: pull.HeadCommit,
StatusName: src,
State: status,
Description: descrip,
DetailsURL: "",
}
return d.Client.UpdateStatus(ctx, request)
}

func (d *VCSStatusUpdater) UpdateCombinedCount(ctx context.Context, repo models.Repo, pull models.PullRequest, status models.CommitStatus, cmdName fmt.Stringer, numSuccess int, numTotal int) error {
src := d.TitleBuilder.Build(cmdName.String())
cmdVerb := "unknown"

switch cmdName {
case Plan:
cmdVerb = "planned"
case PolicyCheck:
cmdVerb = "policies checked"
case Apply:
cmdVerb = "applied"
}

request := types.UpdateStatusRequest{
Repo: repo,
PullNum: pull.Num,
Ref: pull.HeadCommit,
StatusName: src,
State: status,
Description: fmt.Sprintf("%d/%d projects %s successfully.", numSuccess, numTotal, cmdVerb),
DetailsURL: "",
}

return d.Client.UpdateStatus(ctx, request)
}

func (d *VCSStatusUpdater) UpdateProject(ctx context.Context, projectCtx ProjectContext, cmdName fmt.Stringer, status models.CommitStatus, url string) error {
projectID := projectCtx.ProjectName
if projectID == "" {
projectID = fmt.Sprintf("%s/%s", projectCtx.RepoRelDir, projectCtx.Workspace)
}
statusName := d.TitleBuilder.Build(cmdName.String(), vcs.StatusTitleOptions{
ProjectName: projectID,
})

description := fmt.Sprintf("%s %s", strings.Title(cmdName.String()), d.statusDescription(status))
request := types.UpdateStatusRequest{
Repo: projectCtx.BaseRepo,
PullNum: projectCtx.Pull.Num,
Ref: projectCtx.Pull.HeadCommit,
StatusName: statusName,
State: status,
Description: description,
DetailsURL: url,
}

return d.Client.UpdateStatus(ctx, request)
}

func (d *VCSStatusUpdater) statusDescription(status models.CommitStatus) string {
var description string
switch status {
case models.PendingCommitStatus:
description = "in progress..."
case models.FailedCommitStatus:
description = "failed."
case models.SuccessCommitStatus:
description = "succeeded."
}

return description
}
Loading