diff --git a/scripts/e2e-deps.sh b/scripts/e2e-deps.sh index b01559bad9..4ac9b9272b 100755 --- a/scripts/e2e-deps.sh +++ b/scripts/e2e-deps.sh @@ -18,7 +18,7 @@ unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip chmod +x terraform cp terraform /home/circleci/go/bin # Download ngrok to create a tunnel to expose atlantis server -wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v2-stable-linux-amd64.zip -O ngrok-stable-linux-amd64.zip +wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v2-stable-linux-amd64.zip -O ngrok-stable-linux-amd64.zip unzip ngrok-stable-linux-amd64.zip chmod +x ngrok # Download jq diff --git a/server/events/vcs/gitlab_client.go b/server/events/vcs/gitlab_client.go index cd1a05645c..f96d964fda 100644 --- a/server/events/vcs/gitlab_client.go +++ b/server/events/vcs/gitlab_client.go @@ -280,6 +280,15 @@ func (g *GitlabClient) PullIsMergeable(repo models.Repo, pull models.PullRequest return false, err } + // Prevent nil pointer error when mr.HeadPipeline is empty + // See: https://github.com/runatlantis/atlantis/issues/1852 + commit := pull.HeadCommit + isPipelineSkipped := true + if mr.HeadPipeline != nil { + commit = mr.HeadPipeline.SHA + isPipelineSkipped = mr.HeadPipeline.Status == "skipped" + } + // Get project configuration project, _, err := g.Client.Projects.GetProject(mr.ProjectID, nil) if err != nil { @@ -287,7 +296,7 @@ func (g *GitlabClient) PullIsMergeable(repo models.Repo, pull models.PullRequest } // Get Commit Statuses - statuses, _, err := g.Client.Commits.GetCommitStatuses(mr.ProjectID, mr.HeadPipeline.SHA, nil) + statuses, _, err := g.Client.Commits.GetCommitStatuses(mr.ProjectID, commit, nil) if err != nil { return false, err } @@ -302,7 +311,6 @@ func (g *GitlabClient) PullIsMergeable(repo models.Repo, pull models.PullRequest } } - isPipelineSkipped := mr.HeadPipeline.Status == "skipped" allowSkippedPipeline := project.AllowMergeOnSkippedPipeline && isPipelineSkipped ok, err := g.SupportsDetailedMergeStatus() diff --git a/server/events/vcs/gitlab_client_test.go b/server/events/vcs/gitlab_client_test.go index 674015c978..8a883f5d0f 100644 --- a/server/events/vcs/gitlab_client_test.go +++ b/server/events/vcs/gitlab_client_test.go @@ -323,40 +323,62 @@ func TestGitlabClient_PullIsMergeable(t *testing.T) { gitlabVersionUnder15_6 := "15.3.2-ce" gitlabServerVersions := []string{gitlabVersionOver15_6, gitlabVersion15_6, gitlabVersionUnder15_6} vcsStatusName := "atlantis-test" + defaultMR = 1 + noHeadPipelineMR = 2 cases := []struct { statusName string status models.CommitStatus gitlabVersion []string + mrId int expState bool }{ { fmt.Sprintf("%s/apply: resource/default", vcsStatusName), models.FailedCommitStatus, gitlabServerVersions, + defaultMr, true, }, { fmt.Sprintf("%s/apply", vcsStatusName), models.FailedCommitStatus, gitlabServerVersions, + defaultMr, true, }, { fmt.Sprintf("%s/plan: resource/default", vcsStatusName), models.FailedCommitStatus, gitlabServerVersions, + defaultMr, false, }, { fmt.Sprintf("%s/plan", vcsStatusName), models.PendingCommitStatus, gitlabServerVersions, + defaultMr, + false, + }, + { + fmt.Sprintf("%s/plan", vcsStatusName), + models.PendingCommitStatus, + gitlabServerVersions, + noHeadPipelineMR, + false, + }, + { + fmt.Sprintf("%s/plan", vcsStatusName), + models.FailedCommitStatus, + gitlabServerVersions, + noHeadPipelineMR, false, }, { fmt.Sprintf("%s/plan", vcsStatusName), models.SuccessCommitStatus, gitlabServerVersions, + noHeadPipelineMR, true, }, } @@ -372,6 +394,9 @@ func TestGitlabClient_PullIsMergeable(t *testing.T) { case "/api/v4/projects/runatlantis%2Fatlantis/merge_requests/1": w.WriteHeader(http.StatusOK) w.Write([]byte(pipelineSuccess)) // nolint: errcheck + case "/api/v4/projects/runatlantis%2Fatlantis/merge_requests/2": + w.WriteHeader(http.StatusOK) + w.Write([]byte(pipelineNotAvailable)) // nolint: errcheck case "/api/v4/projects/4580910": w.WriteHeader(http.StatusOK) w.Write([]byte(projectSuccess)) // nolint: errcheck @@ -409,11 +434,13 @@ func TestGitlabClient_PullIsMergeable(t *testing.T) { Hostname: "gitlab.com", }, } + mergeable, err := client.PullIsMergeable(repo, models.PullRequest{ - Num: 1, + Num: c.mrId, BaseRepo: repo, HeadCommit: "sha", }, vcsStatusName) + Ok(t, err) Equals(t, c.expState, mergeable) })