diff --git a/server/controllers/events/events_controller_e2e_test.go b/server/controllers/events/events_controller_e2e_test.go index c1cbded81e..1e9ef67c0f 100644 --- a/server/controllers/events/events_controller_e2e_test.go +++ b/server/controllers/events/events_controller_e2e_test.go @@ -824,6 +824,7 @@ func setupE2E(t *testing.T, repoDir string) (events_controllers.VCSEventsControl parallelPoolSize, silenceNoProjects, boltdb, + lockingClient, ) applyCommandRunner := events.NewApplyCommandRunner( diff --git a/server/events/command_runner_test.go b/server/events/command_runner_test.go index 2a23384c6b..9e77e1ec96 100644 --- a/server/events/command_runner_test.go +++ b/server/events/command_runner_test.go @@ -59,6 +59,7 @@ var policyCheckCommandRunner *events.PolicyCheckCommandRunner var approvePoliciesCommandRunner *events.ApprovePoliciesCommandRunner var planCommandRunner *events.PlanCommandRunner var applyLockChecker *lockingmocks.MockApplyLockChecker +var locker *lockingmocks.MockLocker var applyCommandRunner *events.ApplyCommandRunner var unlockCommandRunner *events.UnlockCommandRunner var preWorkflowHooksCommandRunner events.PreWorkflowHooksCommandRunner @@ -85,6 +86,7 @@ func setup(t *testing.T) *vcsmocks.MockClient { drainer = &events.Drainer{} deleteLockCommand = eventmocks.NewMockDeleteLockCommand() applyLockChecker = lockingmocks.NewMockApplyLockChecker() + locker = lockingmocks.NewMockLocker() dbUpdater = &events.DBUpdater{ DB: defaultBoltDB, @@ -128,6 +130,7 @@ func setup(t *testing.T) *vcsmocks.MockClient { parallelPoolSize, SilenceNoProjects, defaultBoltDB, + locker, ) applyCommandRunner = events.NewApplyCommandRunner( @@ -465,6 +468,7 @@ func TestRunAutoplanCommand_DeletePlans(t *testing.T) { fixtures.Pull.BaseRepo = fixtures.GithubRepo ch.RunAutoplanCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.Pull, fixtures.User) pendingPlanFinder.VerifyWasCalledOnce().DeletePlans(tmp) + locker.VerifyWasCalledOnce().UnlockByPull(fixtures.Pull.BaseRepo.FullName, fixtures.Pull.Num) } func TestRunGenericPlanCommand_DeletePlans(t *testing.T) { @@ -480,9 +484,14 @@ func TestRunGenericPlanCommand_DeletePlans(t *testing.T) { When(projectCommandRunner.Plan(matchers.AnyModelsProjectCommandContext())).ThenReturn(models.ProjectResult{PlanSuccess: &models.PlanSuccess{}}) When(workingDir.GetPullDir(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn(tmp, nil) + pull := &github.PullRequest{State: github.String("open")} + modelPull := models.PullRequest{BaseRepo: fixtures.GithubRepo, State: models.OpenPullState, Num: fixtures.Pull.Num} + When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil) + When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, modelPull.BaseRepo, fixtures.GithubRepo, nil) fixtures.Pull.BaseRepo = fixtures.GithubRepo ch.RunCommentCommand(fixtures.GithubRepo, nil, nil, fixtures.User, fixtures.Pull.Num, &events.CommentCommand{Name: models.PlanCommand}) pendingPlanFinder.VerifyWasCalledOnce().DeletePlans(tmp) + locker.VerifyWasCalledOnce().UnlockByPull(fixtures.Pull.BaseRepo.FullName, fixtures.Pull.Num) } func TestRunSpecificPlanCommandDoesnt_DeletePlans(t *testing.T) { diff --git a/server/events/plan_command_runner.go b/server/events/plan_command_runner.go index f3e6f59f37..05a6b65cf8 100644 --- a/server/events/plan_command_runner.go +++ b/server/events/plan_command_runner.go @@ -1,6 +1,7 @@ package events import ( + "github.com/runatlantis/atlantis/server/core/locking" "github.com/runatlantis/atlantis/server/events/models" "github.com/runatlantis/atlantis/server/events/vcs" ) @@ -21,6 +22,7 @@ func NewPlanCommandRunner( parallelPoolSize int, SilenceNoProjects bool, pullStatusFetcher PullStatusFetcher, + locker locking.Locker, ) *PlanCommandRunner { return &PlanCommandRunner{ silenceVCSStatusNoPlans: silenceVCSStatusNoPlans, @@ -38,6 +40,7 @@ func NewPlanCommandRunner( parallelPoolSize: parallelPoolSize, SilenceNoProjects: SilenceNoProjects, pullStatusFetcher: pullStatusFetcher, + locker: locker, } } @@ -63,6 +66,7 @@ type PlanCommandRunner struct { autoMerger *AutoMerger parallelPoolSize int pullStatusFetcher PullStatusFetcher + locker locking.Locker } func (p *PlanCommandRunner) runAutoplan(ctx *CommandContext) { @@ -106,8 +110,12 @@ func (p *PlanCommandRunner) runAutoplan(ctx *CommandContext) { } // discard previous plans that might not be relevant anymore - ctx.Log.Debug("deleting previous plans") + ctx.Log.Debug("deleting previous plans and locks") p.deletePlans(ctx) + _, err = p.locker.UnlockByPull(baseRepo.FullName, pull.Num) + if err != nil { + ctx.Log.Err("deleting locks: %s", err) + } // Only run commands in parallel if enabled var result CommandResult @@ -186,8 +194,12 @@ func (p *PlanCommandRunner) run(ctx *CommandContext, cmd *CommentCommand) { // if the plan is generic, new plans will be generated based on changes // discard previous plans that might not be relevant anymore if !cmd.IsForSpecificProject() { - ctx.Log.Debug("deleting previous plans") + ctx.Log.Debug("deleting previous plans and locks") p.deletePlans(ctx) + _, err = p.locker.UnlockByPull(baseRepo.FullName, pull.Num) + if err != nil { + ctx.Log.Err("deleting locks: %s", err) + } } // Only run commands in parallel if enabled diff --git a/server/server.go b/server/server.go index 93976dc315..2f1918468c 100644 --- a/server/server.go +++ b/server/server.go @@ -523,6 +523,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) { userConfig.ParallelPoolSize, userConfig.SilenceNoProjects, boltdb, + lockingClient, ) applyCommandRunner := events.NewApplyCommandRunner(