mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-28 21:48:25 +00:00
WIP bitbucket
This commit is contained in:
@@ -32,32 +32,36 @@ import (
|
||||
// 3. Add your flag's description etc. to the stringFlags, intFlags, or boolFlags slices.
|
||||
const (
|
||||
// Flag names.
|
||||
AllowForkPRsFlag = "allow-fork-prs"
|
||||
AllowRepoConfigFlag = "allow-repo-config"
|
||||
AtlantisURLFlag = "atlantis-url"
|
||||
ConfigFlag = "config"
|
||||
DataDirFlag = "data-dir"
|
||||
GHHostnameFlag = "gh-hostname"
|
||||
GHTokenFlag = "gh-token"
|
||||
GHUserFlag = "gh-user"
|
||||
GHWebHookSecret = "gh-webhook-secret" // nolint: gas
|
||||
GitlabHostnameFlag = "gitlab-hostname"
|
||||
GitlabTokenFlag = "gitlab-token"
|
||||
GitlabUserFlag = "gitlab-user"
|
||||
GitlabWebHookSecret = "gitlab-webhook-secret"
|
||||
LogLevelFlag = "log-level"
|
||||
PortFlag = "port"
|
||||
RepoWhitelistFlag = "repo-whitelist"
|
||||
RequireApprovalFlag = "require-approval"
|
||||
SSLCertFileFlag = "ssl-cert-file"
|
||||
SSLKeyFileFlag = "ssl-key-file"
|
||||
AllowForkPRsFlag = "allow-fork-prs"
|
||||
AllowRepoConfigFlag = "allow-repo-config"
|
||||
AtlantisURLFlag = "atlantis-url"
|
||||
BitbucketHostnameFlag = "bitbucket-hostname"
|
||||
BitbucketTokenFlag = "bitbucket-token"
|
||||
BitbucketUserFlag = "bitbucket-user"
|
||||
ConfigFlag = "config"
|
||||
DataDirFlag = "data-dir"
|
||||
GHHostnameFlag = "gh-hostname"
|
||||
GHTokenFlag = "gh-token"
|
||||
GHUserFlag = "gh-user"
|
||||
GHWebHookSecret = "gh-webhook-secret" // nolint: gas
|
||||
GitlabHostnameFlag = "gitlab-hostname"
|
||||
GitlabTokenFlag = "gitlab-token"
|
||||
GitlabUserFlag = "gitlab-user"
|
||||
GitlabWebHookSecret = "gitlab-webhook-secret"
|
||||
LogLevelFlag = "log-level"
|
||||
PortFlag = "port"
|
||||
RepoWhitelistFlag = "repo-whitelist"
|
||||
RequireApprovalFlag = "require-approval"
|
||||
SSLCertFileFlag = "ssl-cert-file"
|
||||
SSLKeyFileFlag = "ssl-key-file"
|
||||
|
||||
// Flag defaults.
|
||||
DefaultDataDir = "~/.atlantis"
|
||||
DefaultGHHostname = "github.com"
|
||||
DefaultGitlabHostname = "gitlab.com"
|
||||
DefaultLogLevel = "info"
|
||||
DefaultPort = 4141
|
||||
DefaultBitbucketHostname = "bitbucket.org"
|
||||
DefaultDataDir = "~/.atlantis"
|
||||
DefaultGHHostname = "github.com"
|
||||
DefaultGitlabHostname = "gitlab.com"
|
||||
DefaultLogLevel = "info"
|
||||
DefaultPort = 4141
|
||||
)
|
||||
|
||||
const RedTermStart = "\033[31m"
|
||||
@@ -68,6 +72,19 @@ var stringFlags = []stringFlag{
|
||||
name: AtlantisURLFlag,
|
||||
description: "URL that Atlantis can be reached at. Defaults to http://$(hostname):$port where $port is from --" + PortFlag + ".",
|
||||
},
|
||||
{
|
||||
name: BitbucketUserFlag,
|
||||
description: "Bitbucket username of API user.",
|
||||
},
|
||||
{
|
||||
name: BitbucketTokenFlag,
|
||||
description: "Bitbucket app password of API user. Can also be specified via the ATLANTIS_BITBUCKET_TOKEN environment variable.",
|
||||
},
|
||||
{
|
||||
name: BitbucketHostnameFlag,
|
||||
description: "Currently not supported! We only support bitbucket cloud (aka bitbucket.org) at this time.",
|
||||
defaultValue: DefaultBitbucketHostname,
|
||||
},
|
||||
{
|
||||
name: ConfigFlag,
|
||||
description: "Path to config file. All flags can be set in a YAML config file instead.",
|
||||
@@ -326,6 +343,9 @@ func (s *ServerCmd) setDefaults(c *server.UserConfig) {
|
||||
if c.GitlabHostname == "" {
|
||||
c.GitlabHostname = DefaultGitlabHostname
|
||||
}
|
||||
if c.BitbucketHostname == "" {
|
||||
c.BitbucketHostname = DefaultBitbucketHostname
|
||||
}
|
||||
if c.LogLevel == "" {
|
||||
c.LogLevel = DefaultLogLevel
|
||||
}
|
||||
@@ -344,23 +364,31 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
|
||||
return fmt.Errorf("--%s and --%s are both required for ssl", SSLKeyFileFlag, SSLCertFileFlag)
|
||||
}
|
||||
|
||||
if userConfig.BitbucketHostname != DefaultBitbucketHostname {
|
||||
return fmt.Errorf("--%s is currently not allowed because we only support bitbucket cloud", BitbucketHostnameFlag)
|
||||
}
|
||||
|
||||
// The following combinations are valid.
|
||||
// 1. github user and token set
|
||||
// 2. gitlab user and token set
|
||||
// 3. all 4 set
|
||||
vcsErr := fmt.Errorf("--%s and --%s or --%s and --%s must be set", GHUserFlag, GHTokenFlag, GitlabUserFlag, GitlabTokenFlag)
|
||||
if ((userConfig.GithubUser == "") != (userConfig.GithubToken == "")) || ((userConfig.GitlabUser == "") != (userConfig.GitlabToken == "")) {
|
||||
// 3. bitbucket user and token set
|
||||
// 4. any combination of the above
|
||||
vcsErr := fmt.Errorf("--%s/--%s or --%s/--%s or --%s/--%s must be set", GHUserFlag, GHTokenFlag, GitlabUserFlag, GitlabTokenFlag, BitbucketUserFlag, BitbucketTokenFlag)
|
||||
if ((userConfig.GithubUser == "") != (userConfig.GithubToken == "")) || ((userConfig.GitlabUser == "") != (userConfig.GitlabToken == "")) || ((userConfig.BitbucketUser == "") != (userConfig.BitbucketToken == "")) {
|
||||
return vcsErr
|
||||
}
|
||||
// At this point, we know that there can't be a single user/token without
|
||||
// its partner, but we haven't checked if any user/token is set at all.
|
||||
if userConfig.GithubUser == "" && userConfig.GitlabUser == "" {
|
||||
if userConfig.GithubUser == "" && userConfig.GitlabUser == "" && userConfig.BitbucketUser == "" {
|
||||
return vcsErr
|
||||
}
|
||||
|
||||
if userConfig.RepoWhitelist == "" {
|
||||
return fmt.Errorf("--%s must be set for security purposes", RepoWhitelistFlag)
|
||||
}
|
||||
if strings.Contains(userConfig.RepoWhitelist, "://") {
|
||||
return fmt.Errorf("--%s cannot contain ://, should be hostnames only", RepoWhitelistFlag)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -405,6 +433,7 @@ func (s *ServerCmd) setDataDir(userConfig *server.UserConfig) error {
|
||||
func (s *ServerCmd) trimAtSymbolFromUsers(userConfig *server.UserConfig) {
|
||||
userConfig.GithubUser = strings.TrimPrefix(userConfig.GithubUser, "@")
|
||||
userConfig.GitlabUser = strings.TrimPrefix(userConfig.GitlabUser, "@")
|
||||
userConfig.BitbucketUser = strings.TrimPrefix(userConfig.BitbucketUser, "@")
|
||||
}
|
||||
|
||||
func (s *ServerCmd) securityWarnings(userConfig *server.UserConfig) {
|
||||
|
||||
@@ -105,6 +105,18 @@ func TestExecute_RequireRepoWhitelist(t *testing.T) {
|
||||
Equals(t, "--repo-whitelist must be set for security purposes", err.Error())
|
||||
}
|
||||
|
||||
// Should error if the repo whitelist contained a scheme.
|
||||
func TestExecute_RepoWhitelistScheme(t *testing.T) {
|
||||
c := setup(map[string]interface{}{
|
||||
cmd.GHUserFlag: "user",
|
||||
cmd.GHTokenFlag: "token",
|
||||
cmd.RepoWhitelistFlag: "http://github.com/*",
|
||||
})
|
||||
err := c.Execute()
|
||||
Assert(t, err != nil, "should be an error")
|
||||
Equals(t, "--repo-whitelist cannot contain ://, should be hostnames only", err.Error())
|
||||
}
|
||||
|
||||
func TestExecute_ValidateLogLevel(t *testing.T) {
|
||||
t.Log("Should validate log level.")
|
||||
c := setupWithDefaults(map[string]interface{}{
|
||||
@@ -164,7 +176,7 @@ func TestExecute_ValidateSSLConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestExecute_ValidateVCSConfig(t *testing.T) {
|
||||
expErr := "--gh-user and --gh-token or --gitlab-user and --gitlab-token must be set"
|
||||
expErr := "--gh-user/--gh-token or --gitlab-user/--gitlab-token or --bitbucket-user/--bitbucket-token must be set"
|
||||
cases := []struct {
|
||||
description string
|
||||
flags map[string]interface{}
|
||||
@@ -189,6 +201,13 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"just bitbucket token set",
|
||||
map[string]interface{}{
|
||||
cmd.BitbucketTokenFlag: "token",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"just github user set",
|
||||
map[string]interface{}{
|
||||
@@ -203,6 +222,13 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"just bitbucket user set",
|
||||
map[string]interface{}{
|
||||
cmd.BitbucketUserFlag: "user",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"github user and gitlab token set",
|
||||
map[string]interface{}{
|
||||
@@ -219,6 +245,14 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"github user and bitbucket token set",
|
||||
map[string]interface{}{
|
||||
cmd.GHUserFlag: "user",
|
||||
cmd.BitbucketTokenFlag: "token",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"github user and github token set and should be successful",
|
||||
map[string]interface{}{
|
||||
@@ -236,12 +270,22 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
|
||||
false,
|
||||
},
|
||||
{
|
||||
"github and gitlab user and github and gitlab token set and should be successful",
|
||||
"bitbucket user and bitbucket token set and should be successful",
|
||||
map[string]interface{}{
|
||||
cmd.GHUserFlag: "user",
|
||||
cmd.GHTokenFlag: "token",
|
||||
cmd.GitlabUserFlag: "user",
|
||||
cmd.GitlabTokenFlag: "token",
|
||||
cmd.BitbucketUserFlag: "user",
|
||||
cmd.BitbucketTokenFlag: "token",
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"all set should be successful",
|
||||
map[string]interface{}{
|
||||
cmd.GHUserFlag: "user",
|
||||
cmd.GHTokenFlag: "token",
|
||||
cmd.GitlabUserFlag: "user",
|
||||
cmd.GitlabTokenFlag: "token",
|
||||
cmd.BitbucketUserFlag: "user",
|
||||
cmd.BitbucketTokenFlag: "token",
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -261,14 +305,29 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Currently we only support bitbucket cloud so we shouldn't allow setting of
|
||||
// the bitbucket hostname flag.
|
||||
func TestExecute_BitbucketHostname(t *testing.T) {
|
||||
c := setup(map[string]interface{}{
|
||||
cmd.BitbucketTokenFlag: "bitbucket-token",
|
||||
cmd.BitbucketUserFlag: "bitbucket-token",
|
||||
cmd.BitbucketHostnameFlag: "hostname",
|
||||
cmd.RepoWhitelistFlag: "*",
|
||||
})
|
||||
err := c.Execute()
|
||||
ErrEquals(t, "--bitbucket-hostname is currently not allowed because we only support bitbucket cloud", err)
|
||||
}
|
||||
|
||||
func TestExecute_Defaults(t *testing.T) {
|
||||
t.Log("Should set the defaults for all unspecified flags.")
|
||||
c := setup(map[string]interface{}{
|
||||
cmd.GHUserFlag: "user",
|
||||
cmd.GHTokenFlag: "token",
|
||||
cmd.GitlabUserFlag: "gitlab-user",
|
||||
cmd.GitlabTokenFlag: "gitlab-token",
|
||||
cmd.RepoWhitelistFlag: "*",
|
||||
cmd.GHUserFlag: "user",
|
||||
cmd.GHTokenFlag: "token",
|
||||
cmd.GitlabUserFlag: "gitlab-user",
|
||||
cmd.GitlabTokenFlag: "gitlab-token",
|
||||
cmd.BitbucketUserFlag: "bitbucket-user",
|
||||
cmd.BitbucketTokenFlag: "bitbucket-token",
|
||||
cmd.RepoWhitelistFlag: "*",
|
||||
})
|
||||
err := c.Execute()
|
||||
Ok(t, err)
|
||||
@@ -293,6 +352,9 @@ func TestExecute_Defaults(t *testing.T) {
|
||||
Equals(t, "gitlab-token", passedConfig.GitlabToken)
|
||||
Equals(t, "gitlab-user", passedConfig.GitlabUser)
|
||||
Equals(t, "", passedConfig.GitlabWebHookSecret)
|
||||
Equals(t, "bitbucket.org", passedConfig.BitbucketHostname)
|
||||
Equals(t, "bitbucket-token", passedConfig.BitbucketToken)
|
||||
Equals(t, "bitbucket-user", passedConfig.BitbucketUser)
|
||||
Equals(t, "info", passedConfig.LogLevel)
|
||||
Equals(t, 4141, passedConfig.Port)
|
||||
Equals(t, false, passedConfig.RequireApproval)
|
||||
@@ -357,12 +419,28 @@ func TestExecute_GitlabUser(t *testing.T) {
|
||||
Equals(t, "user", passedConfig.GitlabUser)
|
||||
}
|
||||
|
||||
func TestExecute_BitbucketUser(t *testing.T) {
|
||||
t.Log("Should remove the @ from the bitbucket username if it's passed.")
|
||||
c := setup(map[string]interface{}{
|
||||
cmd.BitbucketUserFlag: "@user",
|
||||
cmd.BitbucketTokenFlag: "token",
|
||||
cmd.RepoWhitelistFlag: "*",
|
||||
})
|
||||
err := c.Execute()
|
||||
Ok(t, err)
|
||||
|
||||
Equals(t, "user", passedConfig.BitbucketUser)
|
||||
}
|
||||
|
||||
func TestExecute_Flags(t *testing.T) {
|
||||
t.Log("Should use all flags that are set.")
|
||||
c := setup(map[string]interface{}{
|
||||
cmd.AtlantisURLFlag: "url",
|
||||
cmd.AllowForkPRsFlag: true,
|
||||
cmd.AllowRepoConfigFlag: true,
|
||||
//cmd.BitbucketHostnameFlag: "ghhostname",
|
||||
cmd.BitbucketTokenFlag: "bitbucket-token",
|
||||
cmd.BitbucketUserFlag: "bitbucket-user",
|
||||
cmd.DataDirFlag: "/path",
|
||||
cmd.GHHostnameFlag: "ghhostname",
|
||||
cmd.GHTokenFlag: "token",
|
||||
@@ -385,6 +463,8 @@ func TestExecute_Flags(t *testing.T) {
|
||||
Equals(t, "url", passedConfig.AtlantisURL)
|
||||
Equals(t, true, passedConfig.AllowForkPRs)
|
||||
Equals(t, true, passedConfig.AllowRepoConfig)
|
||||
Equals(t, "bitbucket-token", passedConfig.BitbucketToken)
|
||||
Equals(t, "bitbucket-user", passedConfig.BitbucketUser)
|
||||
Equals(t, "/path", passedConfig.DataDir)
|
||||
Equals(t, "ghhostname", passedConfig.GithubHostname)
|
||||
Equals(t, "token", passedConfig.GithubToken)
|
||||
@@ -408,6 +488,8 @@ func TestExecute_ConfigFile(t *testing.T) {
|
||||
atlantis-url: "url"
|
||||
allow-fork-prs: true
|
||||
allow-repo-config: true
|
||||
bitbucket-token: "bitbucket-token"
|
||||
bitbucket-user: "bitbucket-user"
|
||||
data-dir: "/path"
|
||||
gh-hostname: "ghhostname"
|
||||
gh-token: "token"
|
||||
@@ -434,6 +516,8 @@ ssl-key-file: key-file
|
||||
Equals(t, "url", passedConfig.AtlantisURL)
|
||||
Equals(t, true, passedConfig.AllowForkPRs)
|
||||
Equals(t, true, passedConfig.AllowRepoConfig)
|
||||
Equals(t, "bitbucket-token", passedConfig.BitbucketToken)
|
||||
Equals(t, "bitbucket-user", passedConfig.BitbucketUser)
|
||||
Equals(t, "/path", passedConfig.DataDir)
|
||||
Equals(t, "ghhostname", passedConfig.GithubHostname)
|
||||
Equals(t, "token", passedConfig.GithubToken)
|
||||
@@ -457,6 +541,8 @@ func TestExecute_EnvironmentOverride(t *testing.T) {
|
||||
atlantis-url: "url"
|
||||
allow-fork-prs: true
|
||||
allow-repo-config: true
|
||||
bitbucket-token: "bitbucket-token"
|
||||
bitbucket-user: "bitbucket-user"
|
||||
data-dir: "/path"
|
||||
gh-hostname: "ghhostname"
|
||||
gh-token: "token"
|
||||
@@ -480,6 +566,8 @@ ssl-key-file: key-file
|
||||
"ATLANTIS_URL": "override-url",
|
||||
"ALLOW_FORK_PRS": "false",
|
||||
"ALLOW_REPO_CONFIG": "false",
|
||||
"BITBUCKET_TOKEN": "override-bitbucket-token",
|
||||
"BITBUCKET_USER": "override-bitbucket-user",
|
||||
"DATA_DIR": "/override-path",
|
||||
"GH_HOSTNAME": "override-gh-hostname",
|
||||
"GH_TOKEN": "override-gh-token",
|
||||
@@ -506,6 +594,8 @@ ssl-key-file: key-file
|
||||
Equals(t, "override-url", passedConfig.AtlantisURL)
|
||||
Equals(t, false, passedConfig.AllowForkPRs)
|
||||
Equals(t, false, passedConfig.AllowRepoConfig)
|
||||
Equals(t, "override-bitbucket-token", passedConfig.BitbucketToken)
|
||||
Equals(t, "override-bitbucket-user", passedConfig.BitbucketUser)
|
||||
Equals(t, "/override-path", passedConfig.DataDir)
|
||||
Equals(t, "override-gh-hostname", passedConfig.GithubHostname)
|
||||
Equals(t, "override-gh-token", passedConfig.GithubToken)
|
||||
@@ -529,6 +619,8 @@ func TestExecute_FlagConfigOverride(t *testing.T) {
|
||||
atlantis-url: "url"
|
||||
allow-fork-prs: true
|
||||
allow-repo-config: true
|
||||
bitbucket-token: "bitbucket-token"
|
||||
bitbucket-user: "bitbucket-user"
|
||||
data-dir: "/path"
|
||||
gh-hostname: "ghhostname"
|
||||
gh-token: "token"
|
||||
@@ -551,6 +643,8 @@ ssl-key-file: key-file
|
||||
cmd.AtlantisURLFlag: "override-url",
|
||||
cmd.AllowForkPRsFlag: false,
|
||||
cmd.AllowRepoConfigFlag: false,
|
||||
cmd.BitbucketTokenFlag: "override-bitbucket-token",
|
||||
cmd.BitbucketUserFlag: "override-bitbucket-user",
|
||||
cmd.DataDirFlag: "/override-path",
|
||||
cmd.GHHostnameFlag: "override-gh-hostname",
|
||||
cmd.GHTokenFlag: "override-gh-token",
|
||||
@@ -571,6 +665,8 @@ ssl-key-file: key-file
|
||||
Ok(t, err)
|
||||
Equals(t, "override-url", passedConfig.AtlantisURL)
|
||||
Equals(t, false, passedConfig.AllowForkPRs)
|
||||
Equals(t, "override-bitbucket-token", passedConfig.BitbucketToken)
|
||||
Equals(t, "override-bitbucket-user", passedConfig.BitbucketUser)
|
||||
Equals(t, "/override-path", passedConfig.DataDir)
|
||||
Equals(t, "override-gh-hostname", passedConfig.GithubHostname)
|
||||
Equals(t, "override-gh-token", passedConfig.GithubToken)
|
||||
@@ -595,6 +691,8 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
|
||||
"ATLANTIS_URL": "url",
|
||||
"ALLOW_FORK_PRS": "true",
|
||||
"ALLOW_REPO_CONFIG": "true",
|
||||
"BITBUCKET_TOKEN": "bitbucket-token",
|
||||
"BITBUCKET_USER": "bitbucket-user",
|
||||
"DATA_DIR": "/path",
|
||||
"GH_HOSTNAME": "gh-hostname",
|
||||
"GH_TOKEN": "gh-token",
|
||||
@@ -618,6 +716,8 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
|
||||
cmd.AtlantisURLFlag: "override-url",
|
||||
cmd.AllowForkPRsFlag: false,
|
||||
cmd.AllowRepoConfigFlag: false,
|
||||
cmd.BitbucketTokenFlag: "override-bitbucket-token",
|
||||
cmd.BitbucketUserFlag: "override-bitbucket-user",
|
||||
cmd.DataDirFlag: "/override-path",
|
||||
cmd.GHHostnameFlag: "override-gh-hostname",
|
||||
cmd.GHTokenFlag: "override-gh-token",
|
||||
@@ -640,6 +740,8 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
|
||||
Equals(t, "override-url", passedConfig.AtlantisURL)
|
||||
Equals(t, false, passedConfig.AllowForkPRs)
|
||||
Equals(t, false, passedConfig.AllowRepoConfig)
|
||||
Equals(t, "override-bitbucket-token", passedConfig.BitbucketToken)
|
||||
Equals(t, "override-bitbucket-user", passedConfig.BitbucketUser)
|
||||
Equals(t, "/override-path", passedConfig.DataDir)
|
||||
Equals(t, "override-gh-hostname", passedConfig.GithubHostname)
|
||||
Equals(t, "override-gh-token", passedConfig.GithubToken)
|
||||
|
||||
@@ -32,7 +32,7 @@ type CommandRunner interface {
|
||||
// RunCommentCommand is the first step after a command request has been parsed.
|
||||
// It handles gathering additional information needed to execute the command
|
||||
// and then calling the appropriate services to finish executing the command.
|
||||
RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, user models.User, pullNum int, cmd *CommentCommand)
|
||||
RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, maybePull *models.PullRequest, user models.User, pullNum int, cmd *CommentCommand)
|
||||
RunAutoplanCommand(baseRepo models.Repo, headRepo models.Repo, pull models.PullRequest, user models.User)
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo
|
||||
if !c.validateCtxAndComment(ctx) {
|
||||
return
|
||||
}
|
||||
if err := c.CommitStatusUpdater.Update(ctx.BaseRepo, ctx.Pull, vcs.Pending, Plan); err != nil {
|
||||
if err := c.CommitStatusUpdater.Update(ctx.BaseRepo, ctx.Pull, models.Pending, Plan); err != nil {
|
||||
ctx.Log.Warn("unable to update commit status: %s", err)
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo
|
||||
// enough data to construct the Repo model and callers might want to wait until
|
||||
// the event is further validated before making an additional (potentially
|
||||
// wasteful) call to get the necessary data.
|
||||
func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, user models.User, pullNum int, cmd *CommentCommand) {
|
||||
func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, maybePull *models.PullRequest, user models.User, pullNum int, cmd *CommentCommand) {
|
||||
log := c.buildLogger(baseRepo.FullName, pullNum)
|
||||
var headRepo models.Repo
|
||||
if maybeHeadRepo != nil {
|
||||
@@ -125,6 +125,11 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead
|
||||
pull, headRepo, err = c.getGithubData(baseRepo, pullNum)
|
||||
case models.Gitlab:
|
||||
pull, err = c.getGitlabData(baseRepo, pullNum)
|
||||
case models.Bitbucket:
|
||||
if maybePull == nil {
|
||||
err = errors.New("pull request should not be nil, this is a bug!")
|
||||
}
|
||||
pull = *maybePull
|
||||
default:
|
||||
err = errors.New("Unknown VCS type, this is a bug!")
|
||||
}
|
||||
@@ -145,7 +150,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.CommitStatusUpdater.Update(ctx.BaseRepo, ctx.Pull, vcs.Pending, cmd.CommandName()); err != nil {
|
||||
if err := c.CommitStatusUpdater.Update(ctx.BaseRepo, ctx.Pull, models.Pending, cmd.CommandName()); err != nil {
|
||||
ctx.Log.Warn("unable to update commit status: %s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
"github.com/runatlantis/atlantis/server/events/models/fixtures"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs"
|
||||
vcsmocks "github.com/runatlantis/atlantis/server/events/vcs/mocks"
|
||||
logmocks "github.com/runatlantis/atlantis/server/logging/mocks"
|
||||
. "github.com/runatlantis/atlantis/testing"
|
||||
@@ -74,8 +73,8 @@ func TestRunCommentCommand_LogPanics(t *testing.T) {
|
||||
setup(t)
|
||||
ch.AllowForkPRs = true // Lets us get to the panic code.
|
||||
defer func() { ch.AllowForkPRs = false }()
|
||||
When(ghStatus.Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, events.Plan)).ThenPanic("panic")
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, fixtures.User, 1, nil)
|
||||
When(ghStatus.Update(fixtures.GithubRepo, fixtures.Pull, models.Pending, events.Plan)).ThenPanic("panic")
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, 1, nil)
|
||||
_, _, comment := vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString()).GetCapturedArguments()
|
||||
Assert(t, strings.Contains(comment, "Error: goroutine panic"), "comment should be about a goroutine panic")
|
||||
}
|
||||
@@ -84,7 +83,7 @@ func TestRunCommentCommand_NoGithubPullGetter(t *testing.T) {
|
||||
t.Log("if DefaultCommandRunner was constructed with a nil GithubPullGetter an error should be logged")
|
||||
setup(t)
|
||||
ch.GithubPullGetter = nil
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, fixtures.User, 1, nil)
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, 1, nil)
|
||||
Equals(t, "[ERROR] runatlantis/atlantis#1: Atlantis not configured to support GitHub\n", logBytes.String())
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ func TestRunCommentCommand_NoGitlabMergeGetter(t *testing.T) {
|
||||
t.Log("if DefaultCommandRunner was constructed with a nil GitlabMergeRequestGetter an error should be logged")
|
||||
setup(t)
|
||||
ch.GitlabMergeRequestGetter = nil
|
||||
ch.RunCommentCommand(fixtures.GitlabRepo, &fixtures.GitlabRepo, fixtures.User, 1, nil)
|
||||
ch.RunCommentCommand(fixtures.GitlabRepo, &fixtures.GitlabRepo, nil, fixtures.User, 1, nil)
|
||||
Equals(t, "[ERROR] runatlantis/atlantis#1: Atlantis not configured to support GitLab\n", logBytes.String())
|
||||
}
|
||||
|
||||
@@ -100,7 +99,7 @@ func TestRunCommentCommand_GithubPullErr(t *testing.T) {
|
||||
t.Log("if getting the github pull request fails an error should be logged")
|
||||
setup(t)
|
||||
When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err"))
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, nil)
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil)
|
||||
Equals(t, "[ERROR] runatlantis/atlantis#1: Making pull request API call to GitHub: err\n", logBytes.String())
|
||||
}
|
||||
|
||||
@@ -108,7 +107,7 @@ func TestRunCommentCommand_GitlabMergeRequestErr(t *testing.T) {
|
||||
t.Log("if getting the gitlab merge request fails an error should be logged")
|
||||
setup(t)
|
||||
When(gitlabGetter.GetMergeRequest(fixtures.GithubRepo.FullName, fixtures.Pull.Num)).ThenReturn(nil, errors.New("err"))
|
||||
ch.RunCommentCommand(fixtures.GitlabRepo, &fixtures.GitlabRepo, fixtures.User, fixtures.Pull.Num, nil)
|
||||
ch.RunCommentCommand(fixtures.GitlabRepo, &fixtures.GitlabRepo, nil, fixtures.User, fixtures.Pull.Num, nil)
|
||||
Equals(t, "[ERROR] runatlantis/atlantis#1: Making merge request API call to GitLab: err\n", logBytes.String())
|
||||
}
|
||||
|
||||
@@ -119,7 +118,7 @@ func TestRunCommentCommand_GithubPullParseErr(t *testing.T) {
|
||||
When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(&pull, nil)
|
||||
When(eventParsing.ParseGithubPull(&pull)).ThenReturn(fixtures.Pull, fixtures.GithubRepo, fixtures.GitlabRepo, errors.New("err"))
|
||||
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, nil)
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil)
|
||||
Equals(t, "[ERROR] runatlantis/atlantis#1: Extracting required fields from comment data: err\n", logBytes.String())
|
||||
}
|
||||
|
||||
@@ -137,7 +136,7 @@ func TestRunCommentCommand_ForkPRDisabled(t *testing.T) {
|
||||
headRepo.Owner = "forkrepo"
|
||||
When(eventParsing.ParseGithubPull(&pull)).ThenReturn(modelPull, modelPull.BaseRepo, headRepo, nil)
|
||||
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil)
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, nil, nil, fixtures.User, fixtures.Pull.Num, nil)
|
||||
vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "Atlantis commands can't be run on fork pull requests. To enable, set --"+ch.AllowForkPRsFlag)
|
||||
}
|
||||
|
||||
@@ -152,7 +151,7 @@ func TestRunCommentCommand_ClosedPull(t *testing.T) {
|
||||
When(githubGetter.GetPullRequest(fixtures.GithubRepo, fixtures.Pull.Num)).ThenReturn(pull, nil)
|
||||
When(eventParsing.ParseGithubPull(pull)).ThenReturn(modelPull, modelPull.BaseRepo, fixtures.GithubRepo, nil)
|
||||
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, fixtures.User, fixtures.Pull.Num, nil)
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, &fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, nil)
|
||||
vcsClient.VerifyWasCalledOnce().CreateComment(fixtures.GithubRepo, modelPull.Num, "Atlantis commands can't be run on closed pull requests")
|
||||
}
|
||||
|
||||
@@ -182,9 +181,9 @@ func TestRunCommentCommand_FullRun(t *testing.T) {
|
||||
When(projectCommandBuilder.BuildApplyCommand(matchers.AnyPtrToEventsCommandContext(), matchers.AnyPtrToEventsCommentCommand())).ThenReturn(cmdCtx, nil)
|
||||
}
|
||||
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, nil, fixtures.User, fixtures.Pull.Num, cmd)
|
||||
ch.RunCommentCommand(fixtures.GithubRepo, nil, nil, fixtures.User, fixtures.Pull.Num, cmd)
|
||||
|
||||
ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, c)
|
||||
ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, models.Pending, c)
|
||||
_, _, response := ghStatus.VerifyWasCalledOnce().UpdateProjectResult(matchers.AnyPtrToEventsCommandContext(), matchers.AnyEventsCommandName(), matchers.AnyEventsCommandResult()).GetCapturedArguments()
|
||||
Equals(t, expCmdResult, response)
|
||||
vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString())
|
||||
@@ -204,7 +203,7 @@ func TestRunAutoplanCommands(t *testing.T) {
|
||||
When(projectCommandBuilder.BuildAutoplanCommands(matchers.AnyPtrToEventsCommandContext())).ThenReturn([]models.ProjectCommandContext{{RepoRelDir: ".", Workspace: "default"}}, nil)
|
||||
ch.RunAutoplanCommand(fixtures.GithubRepo, fixtures.GithubRepo, fixtures.Pull, fixtures.User)
|
||||
|
||||
ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, vcs.Pending, events.Plan)
|
||||
ghStatus.VerifyWasCalledOnce().Update(fixtures.GithubRepo, fixtures.Pull, models.Pending, events.Plan)
|
||||
_, _, response := ghStatus.VerifyWasCalledOnce().UpdateProjectResult(matchers.AnyPtrToEventsCommandContext(), matchers.AnyEventsCommandName(), matchers.AnyEventsCommandResult()).GetCapturedArguments()
|
||||
Equals(t, expCmdResult, response)
|
||||
vcsClient.VerifyWasCalledOnce().CreateComment(matchers.AnyModelsRepo(), AnyInt(), AnyString())
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
// the status to signify whether the plan/apply succeeds.
|
||||
type CommitStatusUpdater interface {
|
||||
// Update updates the status of the head commit of pull.
|
||||
Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, command CommandName) error
|
||||
Update(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command CommandName) error
|
||||
// UpdateProjectResult updates the status of the head commit given the
|
||||
// state of response.
|
||||
UpdateProjectResult(ctx *CommandContext, commandName CommandName, res CommandResult) error
|
||||
@@ -39,18 +39,18 @@ type DefaultCommitStatusUpdater struct {
|
||||
}
|
||||
|
||||
// Update updates the commit status.
|
||||
func (d *DefaultCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, command CommandName) error {
|
||||
func (d *DefaultCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command CommandName) error {
|
||||
description := fmt.Sprintf("%s %s", strings.Title(command.String()), strings.Title(status.String()))
|
||||
return d.Client.UpdateStatus(repo, pull, status, description)
|
||||
}
|
||||
|
||||
// UpdateProjectResult updates the commit status based on the status of res.
|
||||
func (d *DefaultCommitStatusUpdater) UpdateProjectResult(ctx *CommandContext, commandName CommandName, res CommandResult) error {
|
||||
var status vcs.CommitStatus
|
||||
var status models.CommitStatus
|
||||
if res.Error != nil || res.Failure != "" {
|
||||
status = vcs.Failed
|
||||
status = models.Failed
|
||||
} else {
|
||||
var statuses []vcs.CommitStatus
|
||||
var statuses []models.CommitStatus
|
||||
for _, p := range res.ProjectResults {
|
||||
statuses = append(statuses, p.Status())
|
||||
}
|
||||
@@ -59,11 +59,11 @@ func (d *DefaultCommitStatusUpdater) UpdateProjectResult(ctx *CommandContext, co
|
||||
return d.Update(ctx.BaseRepo, ctx.Pull, status, commandName)
|
||||
}
|
||||
|
||||
func (d *DefaultCommitStatusUpdater) worstStatus(ss []vcs.CommitStatus) vcs.CommitStatus {
|
||||
func (d *DefaultCommitStatusUpdater) worstStatus(ss []models.CommitStatus) models.CommitStatus {
|
||||
for _, s := range ss {
|
||||
if s == vcs.Failed {
|
||||
return vcs.Failed
|
||||
if s == models.Failed {
|
||||
return models.Failed
|
||||
}
|
||||
}
|
||||
return vcs.Success
|
||||
return models.Success
|
||||
}
|
||||
|
||||
@@ -21,14 +21,13 @@ import (
|
||||
. "github.com/petergtz/pegomock"
|
||||
"github.com/runatlantis/atlantis/server/events"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs/mocks"
|
||||
. "github.com/runatlantis/atlantis/testing"
|
||||
)
|
||||
|
||||
var repoModel = models.Repo{}
|
||||
var pullModel = models.PullRequest{}
|
||||
var status = vcs.Success
|
||||
var status = models.Success
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
RegisterMockTestingT(t)
|
||||
@@ -49,7 +48,7 @@ func TestUpdateProjectResult_Error(t *testing.T) {
|
||||
s := events.DefaultCommitStatusUpdater{Client: client}
|
||||
err := s.UpdateProjectResult(ctx, events.Plan, events.CommandResult{Error: errors.New("err")})
|
||||
Ok(t, err)
|
||||
client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, vcs.Failed, "Plan Failed")
|
||||
client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, models.Failed, "Plan Failed")
|
||||
}
|
||||
|
||||
func TestUpdateProjectResult_Failure(t *testing.T) {
|
||||
@@ -62,7 +61,7 @@ func TestUpdateProjectResult_Failure(t *testing.T) {
|
||||
s := events.DefaultCommitStatusUpdater{Client: client}
|
||||
err := s.UpdateProjectResult(ctx, events.Plan, events.CommandResult{Failure: "failure"})
|
||||
Ok(t, err)
|
||||
client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, vcs.Failed, "Plan Failed")
|
||||
client.VerifyWasCalledOnce().UpdateStatus(repoModel, pullModel, models.Failed, "Plan Failed")
|
||||
}
|
||||
|
||||
func TestUpdateProjectResult(t *testing.T) {
|
||||
@@ -75,35 +74,35 @@ func TestUpdateProjectResult(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
Statuses []string
|
||||
Expected vcs.CommitStatus
|
||||
Expected models.CommitStatus
|
||||
}{
|
||||
{
|
||||
[]string{"success", "failure", "error"},
|
||||
vcs.Failed,
|
||||
models.Failed,
|
||||
},
|
||||
{
|
||||
[]string{"failure", "error", "success"},
|
||||
vcs.Failed,
|
||||
models.Failed,
|
||||
},
|
||||
{
|
||||
[]string{"success", "failure"},
|
||||
vcs.Failed,
|
||||
models.Failed,
|
||||
},
|
||||
{
|
||||
[]string{"success", "error"},
|
||||
vcs.Failed,
|
||||
models.Failed,
|
||||
},
|
||||
{
|
||||
[]string{"failure", "error"},
|
||||
vcs.Failed,
|
||||
models.Failed,
|
||||
},
|
||||
{
|
||||
[]string{"success"},
|
||||
vcs.Success,
|
||||
models.Success,
|
||||
},
|
||||
{
|
||||
[]string{"success", "success"},
|
||||
vcs.Success,
|
||||
models.Success,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
@@ -23,6 +24,8 @@ import (
|
||||
"github.com/lkysow/go-gitlab"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs/bitbucket"
|
||||
"gopkg.in/go-playground/validator.v9"
|
||||
)
|
||||
|
||||
const gitlabPullOpened = "opened"
|
||||
@@ -32,8 +35,6 @@ const usagesCols = 90
|
||||
// Atlantis commands.
|
||||
var multiLineRegex = regexp.MustCompile(`.*\r?\n.+`)
|
||||
|
||||
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_event_parsing.go EventParsing
|
||||
|
||||
type CommandInterface interface {
|
||||
CommandName() CommandName
|
||||
IsVerbose() bool
|
||||
@@ -105,26 +106,124 @@ func NewCommentCommand(repoRelDir string, flags []string, name CommandName, verb
|
||||
}
|
||||
}
|
||||
|
||||
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_event_parsing.go EventParsing
|
||||
|
||||
type EventParsing interface {
|
||||
ParseGithubIssueCommentEvent(comment *github.IssueCommentEvent) (baseRepo models.Repo, user models.User, pullNum int, err error)
|
||||
// ParseGithubPull returns the pull request, base repo and head repo.
|
||||
ParseGithubPull(pull *github.PullRequest) (models.PullRequest, models.Repo, models.Repo, error)
|
||||
// ParseGithubPullEvent returns the pull request, head repo and user that
|
||||
// caused the event. Base repo is available as a field on PullRequest.
|
||||
ParseGithubPullEvent(pullEvent *github.PullRequestEvent) (pull models.PullRequest, baseRepo models.Repo, headRepo models.Repo, user models.User, err error)
|
||||
ParseGithubPullEvent(pullEvent *github.PullRequestEvent) (pull models.PullRequest, pullEventType models.PullRequestEventType, baseRepo models.Repo, headRepo models.Repo, user models.User, err error)
|
||||
ParseGithubRepo(ghRepo *github.Repository) (models.Repo, error)
|
||||
// ParseGitlabMergeEvent returns the pull request, base repo, head repo and
|
||||
// user that caused the event.
|
||||
ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo, models.Repo, models.User, error)
|
||||
ParseGitlabMergeEvent(event gitlab.MergeEvent) (pull models.PullRequest, pullEventType models.PullRequestEventType, baseRepo models.Repo, headRepo models.Repo, user models.User, err error)
|
||||
ParseGitlabMergeCommentEvent(event gitlab.MergeCommentEvent) (baseRepo models.Repo, headRepo models.Repo, user models.User, err error)
|
||||
ParseGitlabMergeRequest(mr *gitlab.MergeRequest, baseRepo models.Repo) models.PullRequest
|
||||
ParseBitbucketCloudPullEvent(body []byte) (pull models.PullRequest, baseRepo models.Repo, headRepo models.Repo, user models.User, err error)
|
||||
ParseBitbucketCloudCommentEvent(body []byte) (pull models.PullRequest, baseRepo models.Repo, headRepo models.Repo, user models.User, comment string, err error)
|
||||
GetBitbucketEventType(eventTypeHeader string) models.PullRequestEventType
|
||||
}
|
||||
|
||||
type EventParser struct {
|
||||
GithubUser string
|
||||
GithubToken string
|
||||
GitlabUser string
|
||||
GitlabToken string
|
||||
GithubUser string
|
||||
GithubToken string
|
||||
GitlabUser string
|
||||
GitlabToken string
|
||||
BitbucketCloudUser string
|
||||
BitbucketCloudToken string
|
||||
}
|
||||
|
||||
// GetBitbucketEventType translates the bitbucket header name into a pull
|
||||
// request event type.
|
||||
func (e *EventParser) GetBitbucketEventType(eventTypeHeader string) models.PullRequestEventType {
|
||||
switch eventTypeHeader {
|
||||
case "pullrequest:created":
|
||||
return models.OpenedPullEvent
|
||||
case "pullrequest:updated":
|
||||
return models.UpdatedPullEvent
|
||||
case "pullrequest:fulfilled", "pullrequest:rejected":
|
||||
return models.ClosedPullEvent
|
||||
}
|
||||
return models.OtherPullEvent
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseBitbucketCloudCommentEvent(body []byte) (pull models.PullRequest, baseRepo models.Repo, headRepo models.Repo, user models.User, comment string, err error) {
|
||||
var event bitbucket.CommentEvent
|
||||
if err = json.Unmarshal(body, &event); err != nil {
|
||||
err = errors.Wrap(err, "parsing json")
|
||||
return
|
||||
}
|
||||
if err = validator.New().Struct(event); err != nil {
|
||||
return
|
||||
}
|
||||
pull, baseRepo, headRepo, user, err = e.parseCommonBitbucketEventData(event.CommonEventData)
|
||||
comment = *event.Comment.Content.Raw
|
||||
return
|
||||
}
|
||||
|
||||
func (e *EventParser) parseCommonBitbucketEventData(event bitbucket.CommonEventData) (pull models.PullRequest, baseRepo models.Repo, headRepo models.Repo, user models.User, err error) {
|
||||
var prState models.PullRequestState
|
||||
switch *event.PullRequest.State {
|
||||
case "OPEN":
|
||||
prState = models.Open
|
||||
case "MERGED":
|
||||
prState = models.Closed
|
||||
case "SUPERSEDED":
|
||||
prState = models.Closed
|
||||
case "DECLINE":
|
||||
prState = models.Closed
|
||||
default:
|
||||
err = fmt.Errorf("unable to determine pull request state from %q, this is a bug!", *event.PullRequest.State)
|
||||
return
|
||||
}
|
||||
|
||||
headRepo, err = models.NewRepo(
|
||||
models.Bitbucket,
|
||||
*event.PullRequest.Source.Repository.FullName,
|
||||
*event.PullRequest.Source.Repository.Links.HTML.HREF,
|
||||
e.BitbucketCloudUser,
|
||||
e.BitbucketCloudToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
baseRepo, err = models.NewRepo(
|
||||
models.Bitbucket,
|
||||
*event.Repository.FullName,
|
||||
*event.Repository.Links.HTML.HREF,
|
||||
e.BitbucketCloudUser,
|
||||
e.BitbucketCloudToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pull = models.PullRequest{
|
||||
Num: *event.PullRequest.ID,
|
||||
HeadCommit: *event.PullRequest.Source.Commit.Hash,
|
||||
URL: *event.PullRequest.Links.HTML.HREF,
|
||||
Branch: *event.PullRequest.Source.Branch.Name,
|
||||
Author: *event.Actor.Username,
|
||||
State: prState,
|
||||
BaseRepo: baseRepo,
|
||||
}
|
||||
user = models.User{
|
||||
Username: *event.Actor.Username,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseBitbucketCloudPullEvent(body []byte) (pull models.PullRequest, baseRepo models.Repo, headRepo models.Repo, user models.User, err error) {
|
||||
var event bitbucket.PullRequestEvent
|
||||
if err = json.Unmarshal(body, &event); err != nil {
|
||||
err = errors.Wrap(err, "parsing json")
|
||||
return
|
||||
}
|
||||
if err = validator.New().Struct(event); err != nil {
|
||||
return
|
||||
}
|
||||
pull, baseRepo, headRepo, user, err = e.parseCommonBitbucketEventData(event.CommonEventData)
|
||||
return
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseGithubIssueCommentEvent(comment *github.IssueCommentEvent) (baseRepo models.Repo, user models.User, pullNum int, err error) {
|
||||
@@ -148,22 +247,36 @@ func (e *EventParser) ParseGithubIssueCommentEvent(comment *github.IssueCommentE
|
||||
return
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseGithubPullEvent(pullEvent *github.PullRequestEvent) (models.PullRequest, models.Repo, models.Repo, models.User, error) {
|
||||
func (e *EventParser) ParseGithubPullEvent(pullEvent *github.PullRequestEvent) (pull models.PullRequest, pullEventType models.PullRequestEventType, baseRepo models.Repo, headRepo models.Repo, user models.User, err error) {
|
||||
if pullEvent.PullRequest == nil {
|
||||
return models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, errors.New("pull_request is null")
|
||||
err = errors.New("pull_request is null")
|
||||
return
|
||||
}
|
||||
pull, baseRepo, headRepo, err := e.ParseGithubPull(pullEvent.PullRequest)
|
||||
pull, baseRepo, headRepo, err = e.ParseGithubPull(pullEvent.PullRequest)
|
||||
if err != nil {
|
||||
return models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, err
|
||||
return
|
||||
}
|
||||
if pullEvent.Sender == nil {
|
||||
return models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, errors.New("sender is null")
|
||||
err = errors.New("sender is null")
|
||||
return
|
||||
}
|
||||
senderUsername := pullEvent.Sender.GetLogin()
|
||||
if senderUsername == "" {
|
||||
return models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, errors.New("sender.login is null")
|
||||
err = errors.New("sender.login is null")
|
||||
return
|
||||
}
|
||||
return pull, baseRepo, headRepo, models.User{Username: senderUsername}, nil
|
||||
switch pullEvent.GetAction() {
|
||||
case "opened":
|
||||
pullEventType = models.OpenedPullEvent
|
||||
case "synchronize":
|
||||
pullEventType = models.UpdatedPullEvent
|
||||
case "closed":
|
||||
pullEventType = models.ClosedPullEvent
|
||||
default:
|
||||
pullEventType = models.OtherPullEvent
|
||||
}
|
||||
user = models.User{Username: senderUsername}
|
||||
return
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseGithubPull(pull *github.PullRequest) (pullModel models.PullRequest, baseRepo models.Repo, headRepo models.Repo, err error) {
|
||||
@@ -223,7 +336,7 @@ func (e *EventParser) ParseGithubRepo(ghRepo *github.Repository) (models.Repo, e
|
||||
return models.NewRepo(models.Github, ghRepo.GetFullName(), ghRepo.GetCloneURL(), e.GithubUser, e.GithubToken)
|
||||
}
|
||||
|
||||
func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.PullRequest, models.Repo, models.Repo, models.User, error) {
|
||||
func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (pull models.PullRequest, eventType models.PullRequestEventType, baseRepo models.Repo, headRepo models.Repo, user models.User, err error) {
|
||||
modelState := models.Closed
|
||||
if event.ObjectAttributes.State == gitlabPullOpened {
|
||||
modelState = models.Open
|
||||
@@ -231,16 +344,16 @@ func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.Pul
|
||||
// GitLab also has a "merged" state, but we map that to Closed so we don't
|
||||
// need to check for it.
|
||||
|
||||
baseRepo, err := models.NewRepo(models.Gitlab, event.Project.PathWithNamespace, event.Project.GitHTTPURL, e.GitlabUser, e.GitlabToken)
|
||||
baseRepo, err = models.NewRepo(models.Gitlab, event.Project.PathWithNamespace, event.Project.GitHTTPURL, e.GitlabUser, e.GitlabToken)
|
||||
if err != nil {
|
||||
return models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, err
|
||||
return
|
||||
}
|
||||
headRepo, err := models.NewRepo(models.Gitlab, event.ObjectAttributes.Source.PathWithNamespace, event.ObjectAttributes.Source.GitHTTPURL, e.GitlabUser, e.GitlabToken)
|
||||
headRepo, err = models.NewRepo(models.Gitlab, event.ObjectAttributes.Source.PathWithNamespace, event.ObjectAttributes.Source.GitHTTPURL, e.GitlabUser, e.GitlabToken)
|
||||
if err != nil {
|
||||
return models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, err
|
||||
return
|
||||
}
|
||||
|
||||
pull := models.PullRequest{
|
||||
pull = models.PullRequest{
|
||||
URL: event.ObjectAttributes.URL,
|
||||
Author: event.User.Username,
|
||||
Num: event.ObjectAttributes.IID,
|
||||
@@ -250,11 +363,22 @@ func (e *EventParser) ParseGitlabMergeEvent(event gitlab.MergeEvent) (models.Pul
|
||||
BaseRepo: baseRepo,
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
switch event.ObjectAttributes.Action {
|
||||
case "open":
|
||||
eventType = models.OpenedPullEvent
|
||||
case "update":
|
||||
eventType = models.UpdatedPullEvent
|
||||
case "merge", "close":
|
||||
eventType = models.ClosedPullEvent
|
||||
default:
|
||||
eventType = models.OtherPullEvent
|
||||
}
|
||||
|
||||
user = models.User{
|
||||
Username: event.User.Username,
|
||||
}
|
||||
|
||||
return pull, baseRepo, headRepo, user, err
|
||||
return
|
||||
}
|
||||
|
||||
// ParseGitlabMergeCommentEvent creates Atlantis models out of a GitLab event.
|
||||
|
||||
@@ -15,6 +15,8 @@ package events_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
@@ -103,25 +105,25 @@ func TestParseGithubIssueCommentEvent(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseGithubPullEvent(t *testing.T) {
|
||||
_, _, _, _, err := parser.ParseGithubPullEvent(&github.PullRequestEvent{})
|
||||
_, _, _, _, _, err := parser.ParseGithubPullEvent(&github.PullRequestEvent{})
|
||||
ErrEquals(t, "pull_request is null", err)
|
||||
|
||||
testEvent := deepcopy.Copy(PullEvent).(github.PullRequestEvent)
|
||||
testEvent.PullRequest.HTMLURL = nil
|
||||
_, _, _, _, err = parser.ParseGithubPullEvent(&testEvent)
|
||||
_, _, _, _, _, err = parser.ParseGithubPullEvent(&testEvent)
|
||||
ErrEquals(t, "html_url is null", err)
|
||||
|
||||
testEvent = deepcopy.Copy(PullEvent).(github.PullRequestEvent)
|
||||
testEvent.Sender = nil
|
||||
_, _, _, _, err = parser.ParseGithubPullEvent(&testEvent)
|
||||
_, _, _, _, _, err = parser.ParseGithubPullEvent(&testEvent)
|
||||
ErrEquals(t, "sender is null", err)
|
||||
|
||||
testEvent = deepcopy.Copy(PullEvent).(github.PullRequestEvent)
|
||||
testEvent.Sender.Login = nil
|
||||
_, _, _, _, err = parser.ParseGithubPullEvent(&testEvent)
|
||||
_, _, _, _, _, err = parser.ParseGithubPullEvent(&testEvent)
|
||||
ErrEquals(t, "sender.login is null", err)
|
||||
|
||||
actPull, actBaseRepo, actHeadRepo, actUser, err := parser.ParseGithubPullEvent(&PullEvent)
|
||||
actPull, evType, actBaseRepo, actHeadRepo, actUser, err := parser.ParseGithubPullEvent(&PullEvent)
|
||||
Ok(t, err)
|
||||
expBaseRepo := models.Repo{
|
||||
Owner: "owner",
|
||||
@@ -145,9 +147,68 @@ func TestParseGithubPullEvent(t *testing.T) {
|
||||
State: models.Open,
|
||||
BaseRepo: expBaseRepo,
|
||||
}, actPull)
|
||||
Equals(t, models.OpenedPullEvent, evType)
|
||||
Equals(t, models.User{Username: "user"}, actUser)
|
||||
}
|
||||
|
||||
func TestParseGithubPullEvent_EventType(t *testing.T) {
|
||||
cases := []struct {
|
||||
action string
|
||||
exp models.PullRequestEventType
|
||||
}{
|
||||
{
|
||||
action: "assigned",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "unassigned",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "review_requested",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "review_request_removed",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "labeled",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "unlabeled",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "opened",
|
||||
exp: models.OpenedPullEvent,
|
||||
},
|
||||
{
|
||||
action: "edited",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
{
|
||||
action: "closed",
|
||||
exp: models.ClosedPullEvent,
|
||||
},
|
||||
{
|
||||
action: "reopened",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.action, func(t *testing.T) {
|
||||
event := deepcopy.Copy(PullEvent).(github.PullRequestEvent)
|
||||
event.Action = &c.action
|
||||
_, actType, _, _, _, err := parser.ParseGithubPullEvent(&event)
|
||||
Ok(t, err)
|
||||
Equals(t, c.exp, actType)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseGithubPull(t *testing.T) {
|
||||
testPull := deepcopy.Copy(Pull).(github.PullRequest)
|
||||
testPull.Head.SHA = nil
|
||||
@@ -205,7 +266,7 @@ func TestParseGitlabMergeEvent(t *testing.T) {
|
||||
var event *gitlab.MergeEvent
|
||||
err := json.Unmarshal([]byte(mergeEventJSON), &event)
|
||||
Ok(t, err)
|
||||
pull, actBaseRepo, actHeadRepo, actUser, err := parser.ParseGitlabMergeEvent(*event)
|
||||
pull, evType, actBaseRepo, actHeadRepo, actUser, err := parser.ParseGitlabMergeEvent(*event)
|
||||
Ok(t, err)
|
||||
|
||||
expBaseRepo := models.Repo{
|
||||
@@ -229,6 +290,7 @@ func TestParseGitlabMergeEvent(t *testing.T) {
|
||||
State: models.Open,
|
||||
BaseRepo: expBaseRepo,
|
||||
}, pull)
|
||||
Equals(t, models.OpenedPullEvent, evType)
|
||||
|
||||
Equals(t, expBaseRepo, actBaseRepo)
|
||||
Equals(t, models.Repo{
|
||||
@@ -246,11 +308,51 @@ func TestParseGitlabMergeEvent(t *testing.T) {
|
||||
|
||||
t.Log("If the state is closed, should set field correctly.")
|
||||
event.ObjectAttributes.State = "closed"
|
||||
pull, _, _, _, err = parser.ParseGitlabMergeEvent(*event)
|
||||
pull, _, _, _, _, err = parser.ParseGitlabMergeEvent(*event)
|
||||
Ok(t, err)
|
||||
Equals(t, models.Closed, pull.State)
|
||||
}
|
||||
|
||||
func TestParseGitlabMergeEvent_ActionType(t *testing.T) {
|
||||
cases := []struct {
|
||||
action string
|
||||
exp models.PullRequestEventType
|
||||
}{
|
||||
{
|
||||
action: "open",
|
||||
exp: models.OpenedPullEvent,
|
||||
},
|
||||
{
|
||||
action: "update",
|
||||
exp: models.UpdatedPullEvent,
|
||||
},
|
||||
{
|
||||
action: "merge",
|
||||
exp: models.ClosedPullEvent,
|
||||
},
|
||||
{
|
||||
action: "close",
|
||||
exp: models.ClosedPullEvent,
|
||||
},
|
||||
{
|
||||
action: "other",
|
||||
exp: models.OtherPullEvent,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.action, func(t *testing.T) {
|
||||
var event *gitlab.MergeEvent
|
||||
eventJSON := strings.Replace(mergeEventJSON, `"action": "open"`, fmt.Sprintf(`"action": %q`, c.action), 1)
|
||||
err := json.Unmarshal([]byte(eventJSON), &event)
|
||||
Ok(t, err)
|
||||
_, evType, _, _, _, err := parser.ParseGitlabMergeEvent(*event)
|
||||
Ok(t, err)
|
||||
Equals(t, c.exp, evType)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseGitlabMergeRequest(t *testing.T) {
|
||||
t.Log("should properly parse a gitlab merge request")
|
||||
var event *gitlab.MergeRequest
|
||||
|
||||
@@ -124,7 +124,7 @@ func (m *MarkdownRenderer) renderTemplate(tmpl *template.Template, data interfac
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
var singleProjectTmpl = template.Must(template.New("").Parse("{{$result := index .Results 0}}Ran {{.Command}} in dir: `{{$result.RepoRelDir}}` workspace: `{{$result.Workspace}}`\n{{$result.Rendered}}\n" + logTmpl))
|
||||
var singleProjectTmpl = template.Must(template.New("").Parse("{{$result := index .Results 0}}Ran {{.Command}} in dir: `{{$result.RepoRelDir}}` workspace: `{{$result.Workspace}}`\n\n{{$result.Rendered}}\n" + logTmpl))
|
||||
var multiProjectTmpl = template.Must(template.New("").Funcs(sprig.TxtFuncMap()).Parse(
|
||||
"Ran {{.Command}} for {{ len .Results }} projects:\n" +
|
||||
"{{ range $result := .Results }}" +
|
||||
|
||||
@@ -144,7 +144,7 @@ func TestRenderProjectResults(t *testing.T) {
|
||||
RepoRelDir: "path",
|
||||
},
|
||||
},
|
||||
"Ran Plan in dir: `path` workspace: `workspace`\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n\n",
|
||||
"Ran Plan in dir: `path` workspace: `workspace`\n\n```diff\nterraform-output\n```\n\n* To **discard** this plan click [here](lock-url).\n\n",
|
||||
},
|
||||
{
|
||||
"single successful apply",
|
||||
@@ -158,7 +158,7 @@ func TestRenderProjectResults(t *testing.T) {
|
||||
RepoRelDir: "path",
|
||||
},
|
||||
},
|
||||
"Ran Apply in dir: `path` workspace: `workspace`\n```diff\nsuccess\n```\n\n",
|
||||
"Ran Apply in dir: `path` workspace: `workspace`\n\n```diff\nsuccess\n```\n\n",
|
||||
},
|
||||
{
|
||||
"multiple successful plans",
|
||||
@@ -220,7 +220,7 @@ func TestRenderProjectResults(t *testing.T) {
|
||||
Workspace: "workspace",
|
||||
},
|
||||
},
|
||||
"Ran Plan in dir: `path` workspace: `workspace`\n**Plan Error**\n```\nerror\n```\n\n\n",
|
||||
"Ran Plan in dir: `path` workspace: `workspace`\n\n**Plan Error**\n```\nerror\n```\n\n\n",
|
||||
},
|
||||
{
|
||||
"single failed plan",
|
||||
@@ -234,7 +234,7 @@ func TestRenderProjectResults(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"Ran Plan in dir: `path` workspace: `workspace`\n**Plan Failed**: failure\n\n\n",
|
||||
"Ran Plan in dir: `path` workspace: `workspace`\n\n**Plan Failed**: failure\n\n\n",
|
||||
},
|
||||
{
|
||||
"successful, failed, and errored plan",
|
||||
|
||||
20
server/events/mocks/matchers/models_pullrequesteventtype.go
Normal file
20
server/events/mocks/matchers/models_pullrequesteventtype.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyModelsPullRequestEventType() models.PullRequestEventType {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.PullRequestEventType))(nil)).Elem()))
|
||||
var nullValue models.PullRequestEventType
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqModelsPullRequestEventType(value models.PullRequestEventType) models.PullRequestEventType {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue models.PullRequestEventType
|
||||
return nullValue
|
||||
}
|
||||
20
server/events/mocks/matchers/ptr_to_models_pullrequest.go
Normal file
20
server/events/mocks/matchers/ptr_to_models_pullrequest.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyPtrToModelsPullRequest() *models.PullRequest {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(*models.PullRequest))(nil)).Elem()))
|
||||
var nullValue *models.PullRequest
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqPtrToModelsPullRequest(value *models.PullRequest) *models.PullRequest {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue *models.PullRequest
|
||||
return nullValue
|
||||
}
|
||||
19
server/events/mocks/matchers/slice_of_byte.go
Normal file
19
server/events/mocks/matchers/slice_of_byte.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/petergtz/pegomock"
|
||||
)
|
||||
|
||||
func AnySliceOfByte() []byte {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*([]byte))(nil)).Elem()))
|
||||
var nullValue []byte
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqSliceOfByte(value []byte) []byte {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue []byte
|
||||
return nullValue
|
||||
}
|
||||
@@ -4,17 +4,17 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/petergtz/pegomock"
|
||||
vcs "github.com/runatlantis/atlantis/server/events/vcs"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyVcsCommitStatus() vcs.CommitStatus {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(vcs.CommitStatus))(nil)).Elem()))
|
||||
var nullValue vcs.CommitStatus
|
||||
func AnyVcsCommitStatus() models.CommitStatus {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.CommitStatus))(nil)).Elem()))
|
||||
var nullValue models.CommitStatus
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqVcsCommitStatus(value vcs.CommitStatus) vcs.CommitStatus {
|
||||
func EqVcsCommitStatus(value models.CommitStatus) models.CommitStatus {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue vcs.CommitStatus
|
||||
var nullValue models.CommitStatus
|
||||
return nullValue
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ func NewMockCommandRunner() *MockCommandRunner {
|
||||
return &MockCommandRunner{fail: pegomock.GlobalFailHandler}
|
||||
}
|
||||
|
||||
func (mock *MockCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, user models.User, pullNum int, cmd *events.CommentCommand) {
|
||||
params := []pegomock.Param{baseRepo, maybeHeadRepo, user, pullNum, cmd}
|
||||
func (mock *MockCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, maybePull *models.PullRequest, user models.User, pullNum int, cmd *events.CommentCommand) {
|
||||
params := []pegomock.Param{baseRepo, maybeHeadRepo, maybePull, user, pullNum, cmd}
|
||||
pegomock.GetGenericMockFrom(mock).Invoke("RunCommentCommand", params, []reflect.Type{})
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ type VerifierCommandRunner struct {
|
||||
inOrderContext *pegomock.InOrderContext
|
||||
}
|
||||
|
||||
func (verifier *VerifierCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, user models.User, pullNum int, cmd *events.CommentCommand) *CommandRunner_RunCommentCommand_OngoingVerification {
|
||||
params := []pegomock.Param{baseRepo, maybeHeadRepo, user, pullNum, cmd}
|
||||
func (verifier *VerifierCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHeadRepo *models.Repo, maybePull *models.PullRequest, user models.User, pullNum int, cmd *events.CommentCommand) *CommandRunner_RunCommentCommand_OngoingVerification {
|
||||
params := []pegomock.Param{baseRepo, maybeHeadRepo, maybePull, user, pullNum, cmd}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "RunCommentCommand", params)
|
||||
return &CommandRunner_RunCommentCommand_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
@@ -58,12 +58,12 @@ type CommandRunner_RunCommentCommand_OngoingVerification struct {
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *CommandRunner_RunCommentCommand_OngoingVerification) GetCapturedArguments() (models.Repo, *models.Repo, models.User, int, *events.CommentCommand) {
|
||||
baseRepo, maybeHeadRepo, user, pullNum, cmd := c.GetAllCapturedArguments()
|
||||
return baseRepo[len(baseRepo)-1], maybeHeadRepo[len(maybeHeadRepo)-1], user[len(user)-1], pullNum[len(pullNum)-1], cmd[len(cmd)-1]
|
||||
func (c *CommandRunner_RunCommentCommand_OngoingVerification) GetCapturedArguments() (models.Repo, *models.Repo, *models.PullRequest, models.User, int, *events.CommentCommand) {
|
||||
baseRepo, maybeHeadRepo, maybePull, user, pullNum, cmd := c.GetAllCapturedArguments()
|
||||
return baseRepo[len(baseRepo)-1], maybeHeadRepo[len(maybeHeadRepo)-1], maybePull[len(maybePull)-1], user[len(user)-1], pullNum[len(pullNum)-1], cmd[len(cmd)-1]
|
||||
}
|
||||
|
||||
func (c *CommandRunner_RunCommentCommand_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []*models.Repo, _param2 []models.User, _param3 []int, _param4 []*events.CommentCommand) {
|
||||
func (c *CommandRunner_RunCommentCommand_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []*models.Repo, _param2 []*models.PullRequest, _param3 []models.User, _param4 []int, _param5 []*events.CommentCommand) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.Repo, len(params[0]))
|
||||
@@ -74,17 +74,21 @@ func (c *CommandRunner_RunCommentCommand_OngoingVerification) GetAllCapturedArgu
|
||||
for u, param := range params[1] {
|
||||
_param1[u] = param.(*models.Repo)
|
||||
}
|
||||
_param2 = make([]models.User, len(params[2]))
|
||||
_param2 = make([]*models.PullRequest, len(params[2]))
|
||||
for u, param := range params[2] {
|
||||
_param2[u] = param.(models.User)
|
||||
_param2[u] = param.(*models.PullRequest)
|
||||
}
|
||||
_param3 = make([]int, len(params[3]))
|
||||
_param3 = make([]models.User, len(params[3]))
|
||||
for u, param := range params[3] {
|
||||
_param3[u] = param.(int)
|
||||
_param3[u] = param.(models.User)
|
||||
}
|
||||
_param4 = make([]*events.CommentCommand, len(params[4]))
|
||||
_param4 = make([]int, len(params[4]))
|
||||
for u, param := range params[4] {
|
||||
_param4[u] = param.(*events.CommentCommand)
|
||||
_param4[u] = param.(int)
|
||||
}
|
||||
_param5 = make([]*events.CommentCommand, len(params[5]))
|
||||
for u, param := range params[5] {
|
||||
_param5[u] = param.(*events.CommentCommand)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
pegomock "github.com/petergtz/pegomock"
|
||||
events "github.com/runatlantis/atlantis/server/events"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
vcs "github.com/runatlantis/atlantis/server/events/vcs"
|
||||
)
|
||||
|
||||
type MockCommitStatusUpdater struct {
|
||||
@@ -20,7 +19,7 @@ func NewMockCommitStatusUpdater() *MockCommitStatusUpdater {
|
||||
return &MockCommitStatusUpdater{fail: pegomock.GlobalFailHandler}
|
||||
}
|
||||
|
||||
func (mock *MockCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, command events.CommandName) error {
|
||||
func (mock *MockCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command events.CommandName) error {
|
||||
params := []pegomock.Param{repo, pull, status, command}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("Update", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 error
|
||||
@@ -62,7 +61,7 @@ type VerifierCommitStatusUpdater struct {
|
||||
inOrderContext *pegomock.InOrderContext
|
||||
}
|
||||
|
||||
func (verifier *VerifierCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status vcs.CommitStatus, command events.CommandName) *CommitStatusUpdater_Update_OngoingVerification {
|
||||
func (verifier *VerifierCommitStatusUpdater) Update(repo models.Repo, pull models.PullRequest, status models.CommitStatus, command events.CommandName) *CommitStatusUpdater_Update_OngoingVerification {
|
||||
params := []pegomock.Param{repo, pull, status, command}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Update", params)
|
||||
return &CommitStatusUpdater_Update_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
@@ -73,12 +72,12 @@ type CommitStatusUpdater_Update_OngoingVerification struct {
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *CommitStatusUpdater_Update_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, events.CommandName) {
|
||||
func (c *CommitStatusUpdater_Update_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, models.CommitStatus, events.CommandName) {
|
||||
repo, pull, status, command := c.GetAllCapturedArguments()
|
||||
return repo[len(repo)-1], pull[len(pull)-1], status[len(status)-1], command[len(command)-1]
|
||||
}
|
||||
|
||||
func (c *CommitStatusUpdater_Update_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []events.CommandName) {
|
||||
func (c *CommitStatusUpdater_Update_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []models.CommitStatus, _param3 []events.CommandName) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.Repo, len(params[0]))
|
||||
@@ -89,9 +88,9 @@ func (c *CommitStatusUpdater_Update_OngoingVerification) GetAllCapturedArguments
|
||||
for u, param := range params[1] {
|
||||
_param1[u] = param.(models.PullRequest)
|
||||
}
|
||||
_param2 = make([]vcs.CommitStatus, len(params[2]))
|
||||
_param2 = make([]models.CommitStatus, len(params[2]))
|
||||
for u, param := range params[2] {
|
||||
_param2[u] = param.(vcs.CommitStatus)
|
||||
_param2[u] = param.(models.CommitStatus)
|
||||
}
|
||||
_param3 = make([]events.CommandName, len(params[3]))
|
||||
for u, param := range params[3] {
|
||||
|
||||
@@ -68,32 +68,36 @@ func (mock *MockEventParsing) ParseGithubPull(pull *github.PullRequest) (models.
|
||||
return ret0, ret1, ret2, ret3
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGithubPullEvent(pullEvent *github.PullRequestEvent) (models.PullRequest, models.Repo, models.Repo, models.User, error) {
|
||||
func (mock *MockEventParsing) ParseGithubPullEvent(pullEvent *github.PullRequestEvent) (models.PullRequest, models.PullRequestEventType, models.Repo, models.Repo, models.User, error) {
|
||||
params := []pegomock.Param{pullEvent}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGithubPullEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGithubPullEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.PullRequestEventType)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.PullRequest
|
||||
var ret1 models.Repo
|
||||
var ret1 models.PullRequestEventType
|
||||
var ret2 models.Repo
|
||||
var ret3 models.User
|
||||
var ret4 error
|
||||
var ret3 models.Repo
|
||||
var ret4 models.User
|
||||
var ret5 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullRequest)
|
||||
}
|
||||
if result[1] != nil {
|
||||
ret1 = result[1].(models.Repo)
|
||||
ret1 = result[1].(models.PullRequestEventType)
|
||||
}
|
||||
if result[2] != nil {
|
||||
ret2 = result[2].(models.Repo)
|
||||
}
|
||||
if result[3] != nil {
|
||||
ret3 = result[3].(models.User)
|
||||
ret3 = result[3].(models.Repo)
|
||||
}
|
||||
if result[4] != nil {
|
||||
ret4 = result[4].(error)
|
||||
ret4 = result[4].(models.User)
|
||||
}
|
||||
if result[5] != nil {
|
||||
ret5 = result[5].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1, ret2, ret3, ret4
|
||||
return ret0, ret1, ret2, ret3, ret4, ret5
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGithubRepo(ghRepo *github.Repository) (models.Repo, error) {
|
||||
@@ -112,32 +116,36 @@ func (mock *MockEventParsing) ParseGithubRepo(ghRepo *github.Repository) (models
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGitlabMergeEvent(event go_gitlab.MergeEvent) (models.PullRequest, models.Repo, models.Repo, models.User, error) {
|
||||
func (mock *MockEventParsing) ParseGitlabMergeEvent(event go_gitlab.MergeEvent) (models.PullRequest, models.PullRequestEventType, models.Repo, models.Repo, models.User, error) {
|
||||
params := []pegomock.Param{event}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGitlabMergeEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseGitlabMergeEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.PullRequestEventType)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.PullRequest
|
||||
var ret1 models.Repo
|
||||
var ret1 models.PullRequestEventType
|
||||
var ret2 models.Repo
|
||||
var ret3 models.User
|
||||
var ret4 error
|
||||
var ret3 models.Repo
|
||||
var ret4 models.User
|
||||
var ret5 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullRequest)
|
||||
}
|
||||
if result[1] != nil {
|
||||
ret1 = result[1].(models.Repo)
|
||||
ret1 = result[1].(models.PullRequestEventType)
|
||||
}
|
||||
if result[2] != nil {
|
||||
ret2 = result[2].(models.Repo)
|
||||
}
|
||||
if result[3] != nil {
|
||||
ret3 = result[3].(models.User)
|
||||
ret3 = result[3].(models.Repo)
|
||||
}
|
||||
if result[4] != nil {
|
||||
ret4 = result[4].(error)
|
||||
ret4 = result[4].(models.User)
|
||||
}
|
||||
if result[5] != nil {
|
||||
ret5 = result[5].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1, ret2, ret3, ret4
|
||||
return ret0, ret1, ret2, ret3, ret4, ret5
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseGitlabMergeCommentEvent(event go_gitlab.MergeCommentEvent) (models.Repo, models.Repo, models.User, error) {
|
||||
@@ -176,6 +184,78 @@ func (mock *MockEventParsing) ParseGitlabMergeRequest(mr *go_gitlab.MergeRequest
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseBitbucketCloudPullEvent(body []byte) (models.PullRequest, models.Repo, models.Repo, models.User, error) {
|
||||
params := []pegomock.Param{body}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseBitbucketCloudPullEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.PullRequest
|
||||
var ret1 models.Repo
|
||||
var ret2 models.Repo
|
||||
var ret3 models.User
|
||||
var ret4 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullRequest)
|
||||
}
|
||||
if result[1] != nil {
|
||||
ret1 = result[1].(models.Repo)
|
||||
}
|
||||
if result[2] != nil {
|
||||
ret2 = result[2].(models.Repo)
|
||||
}
|
||||
if result[3] != nil {
|
||||
ret3 = result[3].(models.User)
|
||||
}
|
||||
if result[4] != nil {
|
||||
ret4 = result[4].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1, ret2, ret3, ret4
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) ParseBitbucketCloudCommentEvent(body []byte) (models.PullRequest, models.Repo, models.Repo, models.User, string, error) {
|
||||
params := []pegomock.Param{body}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("ParseBitbucketCloudCommentEvent", params, []reflect.Type{reflect.TypeOf((*models.PullRequest)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.Repo)(nil)).Elem(), reflect.TypeOf((*models.User)(nil)).Elem(), reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 models.PullRequest
|
||||
var ret1 models.Repo
|
||||
var ret2 models.Repo
|
||||
var ret3 models.User
|
||||
var ret4 string
|
||||
var ret5 error
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullRequest)
|
||||
}
|
||||
if result[1] != nil {
|
||||
ret1 = result[1].(models.Repo)
|
||||
}
|
||||
if result[2] != nil {
|
||||
ret2 = result[2].(models.Repo)
|
||||
}
|
||||
if result[3] != nil {
|
||||
ret3 = result[3].(models.User)
|
||||
}
|
||||
if result[4] != nil {
|
||||
ret4 = result[4].(string)
|
||||
}
|
||||
if result[5] != nil {
|
||||
ret5 = result[5].(error)
|
||||
}
|
||||
}
|
||||
return ret0, ret1, ret2, ret3, ret4, ret5
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) GetBitbucketEventType(eventTypeHeader string) models.PullRequestEventType {
|
||||
params := []pegomock.Param{eventTypeHeader}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("GetBitbucketEventType", params, []reflect.Type{reflect.TypeOf((*models.PullRequestEventType)(nil)).Elem()})
|
||||
var ret0 models.PullRequestEventType
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(models.PullRequestEventType)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockEventParsing) VerifyWasCalledOnce() *VerifierEventParsing {
|
||||
return &VerifierEventParsing{mock, pegomock.Times(1), nil}
|
||||
}
|
||||
@@ -386,3 +466,84 @@ func (c *EventParsing_ParseGitlabMergeRequest_OngoingVerification) GetAllCapture
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierEventParsing) ParseBitbucketCloudPullEvent(body []byte) *EventParsing_ParseBitbucketCloudPullEvent_OngoingVerification {
|
||||
params := []pegomock.Param{body}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ParseBitbucketCloudPullEvent", params)
|
||||
return &EventParsing_ParseBitbucketCloudPullEvent_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type EventParsing_ParseBitbucketCloudPullEvent_OngoingVerification struct {
|
||||
mock *MockEventParsing
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *EventParsing_ParseBitbucketCloudPullEvent_OngoingVerification) GetCapturedArguments() []byte {
|
||||
body := c.GetAllCapturedArguments()
|
||||
return body[len(body)-1]
|
||||
}
|
||||
|
||||
func (c *EventParsing_ParseBitbucketCloudPullEvent_OngoingVerification) GetAllCapturedArguments() (_param0 [][]byte) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([][]byte, len(params[0]))
|
||||
for u, param := range params[0] {
|
||||
_param0[u] = param.([]byte)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierEventParsing) ParseBitbucketCloudCommentEvent(body []byte) *EventParsing_ParseBitbucketCloudCommentEvent_OngoingVerification {
|
||||
params := []pegomock.Param{body}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "ParseBitbucketCloudCommentEvent", params)
|
||||
return &EventParsing_ParseBitbucketCloudCommentEvent_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type EventParsing_ParseBitbucketCloudCommentEvent_OngoingVerification struct {
|
||||
mock *MockEventParsing
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *EventParsing_ParseBitbucketCloudCommentEvent_OngoingVerification) GetCapturedArguments() []byte {
|
||||
body := c.GetAllCapturedArguments()
|
||||
return body[len(body)-1]
|
||||
}
|
||||
|
||||
func (c *EventParsing_ParseBitbucketCloudCommentEvent_OngoingVerification) GetAllCapturedArguments() (_param0 [][]byte) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([][]byte, len(params[0]))
|
||||
for u, param := range params[0] {
|
||||
_param0[u] = param.([]byte)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierEventParsing) GetBitbucketEventType(eventTypeHeader string) *EventParsing_GetBitbucketEventType_OngoingVerification {
|
||||
params := []pegomock.Param{eventTypeHeader}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GetBitbucketEventType", params)
|
||||
return &EventParsing_GetBitbucketEventType_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type EventParsing_GetBitbucketEventType_OngoingVerification struct {
|
||||
mock *MockEventParsing
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *EventParsing_GetBitbucketEventType_OngoingVerification) GetCapturedArguments() string {
|
||||
eventTypeHeader := c.GetAllCapturedArguments()
|
||||
return eventTypeHeader[len(eventTypeHeader)-1]
|
||||
}
|
||||
|
||||
func (c *EventParsing_GetBitbucketEventType_OngoingVerification) GetAllCapturedArguments() (_param0 []string) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]string, len(params[0]))
|
||||
for u, param := range params[0] {
|
||||
_param0[u] = param.(string)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// limitations under the License.
|
||||
// Modified hereafter by contributors to runatlantis/atlantis.
|
||||
//
|
||||
package vcs
|
||||
package models
|
||||
|
||||
// CommitStatus is the result of executing an Atlantis command for the commit.
|
||||
// In Github the options are: error, failure, pending, success.
|
||||
19
server/events/models/commit_status_test.go
Normal file
19
server/events/models/commit_status_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
. "github.com/runatlantis/atlantis/testing"
|
||||
)
|
||||
|
||||
func TestStatus_String(t *testing.T) {
|
||||
cases := map[models.CommitStatus]string{
|
||||
models.Pending: "pending",
|
||||
models.Success: "success",
|
||||
models.Failed: "failed",
|
||||
}
|
||||
for k, v := range cases {
|
||||
Equals(t, v, k.String())
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,10 @@ type Repo struct {
|
||||
VCSHost VCSHost
|
||||
}
|
||||
|
||||
// NewRepo constructs a Repo object. repoFullName is the owner/repo form,
|
||||
// cloneURL can be with or without .git at the end
|
||||
// ex. https://github.com/runatlantis/atlantis.git OR
|
||||
// https://github.com/runatlantis/atlantis
|
||||
func NewRepo(vcsHostType VCSHostType, repoFullName string, cloneURL string, vcsUser string, vcsToken string) (Repo, error) {
|
||||
if repoFullName == "" {
|
||||
return Repo{}, errors.New("repoFullName can't be empty")
|
||||
@@ -59,6 +63,10 @@ func NewRepo(vcsHostType VCSHostType, repoFullName string, cloneURL string, vcsU
|
||||
return Repo{}, errors.New("cloneURL can't be empty")
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(cloneURL, ".git") {
|
||||
cloneURL += ".git"
|
||||
}
|
||||
|
||||
// Ensure the Clone URL is for the same repo to avoid something malicious.
|
||||
cloneURLParsed, err := url.Parse(cloneURL)
|
||||
if err != nil {
|
||||
@@ -103,8 +111,10 @@ func NewRepo(vcsHostType VCSHostType, repoFullName string, cloneURL string, vcsU
|
||||
type PullRequest struct {
|
||||
// Num is the pull request number or ID.
|
||||
Num int
|
||||
// HeadCommit points to the head of the branch that is being
|
||||
// pull requested into the base.
|
||||
// HeadCommit is a sha256 that points to the head of the branch that is being
|
||||
// pull requested into the base. If the pull request is from BitBucket,
|
||||
// the string will only be 12 characters long because BitBucket truncates
|
||||
// its commit IDs.
|
||||
HeadCommit string
|
||||
// URL is the url of the pull request.
|
||||
// ex. "https://github.com/runatlantis/atlantis/pull/1"
|
||||
@@ -128,6 +138,29 @@ const (
|
||||
Closed
|
||||
)
|
||||
|
||||
type PullRequestEventType int
|
||||
|
||||
const (
|
||||
OpenedPullEvent PullRequestEventType = iota
|
||||
UpdatedPullEvent
|
||||
ClosedPullEvent
|
||||
OtherPullEvent
|
||||
)
|
||||
|
||||
func (p PullRequestEventType) String() string {
|
||||
switch p {
|
||||
case OpenedPullEvent:
|
||||
return "opened"
|
||||
case UpdatedPullEvent:
|
||||
return "updated"
|
||||
case ClosedPullEvent:
|
||||
return "closed"
|
||||
case OtherPullEvent:
|
||||
return "other"
|
||||
}
|
||||
return "<missing String() implementation>"
|
||||
}
|
||||
|
||||
// User is a VCS user.
|
||||
// During an autoplan, the user will be the Atlantis API user.
|
||||
type User struct {
|
||||
@@ -208,6 +241,7 @@ type VCSHostType int
|
||||
const (
|
||||
Github VCSHostType = iota
|
||||
Gitlab
|
||||
Bitbucket
|
||||
)
|
||||
|
||||
func (h VCSHostType) String() string {
|
||||
@@ -216,6 +250,8 @@ func (h VCSHostType) String() string {
|
||||
return "Github"
|
||||
case Gitlab:
|
||||
return "Gitlab"
|
||||
case Bitbucket:
|
||||
return "Bitbucket"
|
||||
}
|
||||
return "<missing String() implementation>"
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestNewRepo_EmptyCloneURL(t *testing.T) {
|
||||
|
||||
func TestNewRepo_InvalidCloneURL(t *testing.T) {
|
||||
_, err := models.NewRepo(models.Github, "owner/repo", ":", "u", "p")
|
||||
ErrEquals(t, "invalid clone url: parse :: missing protocol scheme", err)
|
||||
ErrEquals(t, "invalid clone url: parse :.git: missing protocol scheme", err)
|
||||
}
|
||||
|
||||
func TestNewRepo_CloneURLWrongRepo(t *testing.T) {
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
//
|
||||
package events
|
||||
|
||||
import "github.com/runatlantis/atlantis/server/events/vcs"
|
||||
import (
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
// ProjectResult is the result of executing a plan/apply for a project.
|
||||
type ProjectResult struct {
|
||||
@@ -30,12 +32,12 @@ type ProjectCommandResult struct {
|
||||
}
|
||||
|
||||
// Status returns the vcs commit status of this project result.
|
||||
func (p ProjectResult) Status() vcs.CommitStatus {
|
||||
func (p ProjectResult) Status() models.CommitStatus {
|
||||
if p.Error != nil {
|
||||
return vcs.Failed
|
||||
return models.Failed
|
||||
}
|
||||
if p.Failure != "" {
|
||||
return vcs.Failed
|
||||
return models.Failed
|
||||
}
|
||||
return vcs.Success
|
||||
return models.Success
|
||||
}
|
||||
|
||||
@@ -24,16 +24,28 @@ const Wildcard = "*"
|
||||
// RepoWhitelistChecker implements checking if repos are whitelisted to be used with
|
||||
// this Atlantis.
|
||||
type RepoWhitelistChecker struct {
|
||||
// Whitelist is a comma separated list of rules with wildcards '*' allowed.
|
||||
Whitelist string
|
||||
rules []string
|
||||
}
|
||||
|
||||
// NewRepoWhitelistChecker constructs a new checker and validates that the
|
||||
// whitelist isn't malformed.
|
||||
func NewRepoWhitelistChecker(whitelist string) (*RepoWhitelistChecker, error) {
|
||||
rules := strings.Split(whitelist, ",")
|
||||
for _, rule := range rules {
|
||||
if strings.Contains(rule, "://") {
|
||||
return nil, fmt.Errorf("whitelist %q contained ://", rule)
|
||||
}
|
||||
}
|
||||
return &RepoWhitelistChecker{
|
||||
rules: rules,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IsWhitelisted returns true if this repo is in our whitelist and false
|
||||
// otherwise.
|
||||
func (r *RepoWhitelistChecker) IsWhitelisted(repoFullName string, vcsHostname string) bool {
|
||||
candidate := fmt.Sprintf("%s/%s", vcsHostname, repoFullName)
|
||||
rules := strings.Split(r.Whitelist, ",")
|
||||
for _, rule := range rules {
|
||||
for _, rule := range r.rules {
|
||||
if r.matchesRule(rule, candidate) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -151,7 +151,8 @@ func TestRepoWhitelistChecker_IsWhitelisted(t *testing.T) {
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.Description, func(t *testing.T) {
|
||||
w := events.RepoWhitelistChecker{Whitelist: c.Whitelist}
|
||||
w, err := events.NewRepoWhitelistChecker(c.Whitelist)
|
||||
Ok(t, err)
|
||||
Equals(t, c.Exp, w.IsWhitelisted(c.RepoFullName, c.Hostname))
|
||||
})
|
||||
}
|
||||
|
||||
197
server/events/vcs/bitbucket/client.go
Normal file
197
server/events/vcs/bitbucket/client.go
Normal file
@@ -0,0 +1,197 @@
|
||||
package bitbucket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
HttpClient *http.Client
|
||||
Username string
|
||||
Password string
|
||||
BaseURL string
|
||||
AtlantisBaseURL string
|
||||
}
|
||||
|
||||
func NewClient(httpClient *http.Client, username string, password string, baseURL string, atlantisBaseUrl string) (*Client, error) {
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
}
|
||||
// Remove the trailing '/' from the URL.
|
||||
parsedURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "parsing %s", baseURL)
|
||||
}
|
||||
urlWithoutPath := fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host)
|
||||
return &Client{
|
||||
HttpClient: httpClient,
|
||||
Username: username,
|
||||
Password: password,
|
||||
BaseURL: urlWithoutPath,
|
||||
AtlantisBaseURL: atlantisBaseUrl,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Client) prepRequest(method string, path string, body io.Reader) (*http.Request, error) {
|
||||
req, err := http.NewRequest(method, path, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.SetBasicAuth(b.Username, b.Password)
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// GetModifiedFiles returns the names of files that were modified in the merge request.
|
||||
// The names include the path to the file from the repo root, ex. parent/child/file.txt.
|
||||
func (b *Client) GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error) {
|
||||
path := fmt.Sprintf("%s/2.0/repositories/%s/pullrequests/%d/diffstat", b.BaseURL, repo.FullName, pull.Num)
|
||||
// todo: remove duplication
|
||||
req, err := b.prepRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := b.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("unexpected status code: %d, body: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
// todo: pagination
|
||||
var diffStat DiffStat
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "reading body")
|
||||
}
|
||||
if err := json.Unmarshal(body, &diffStat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hash := make(map[string]bool)
|
||||
var unique []string
|
||||
for _, v := range diffStat.Values {
|
||||
var paths []string
|
||||
if v.Old != nil {
|
||||
paths = append(paths, *v.Old.Path)
|
||||
}
|
||||
if v.New != nil {
|
||||
paths = append(paths, *v.New.Path)
|
||||
}
|
||||
for _, path := range paths {
|
||||
if !hash[path] {
|
||||
unique = append(unique, path)
|
||||
hash[path] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return unique, nil
|
||||
}
|
||||
|
||||
// CreateComment creates a comment on the merge request.
|
||||
func (b *Client) CreateComment(repo models.Repo, pullNum int, comment string) error {
|
||||
bodyBytes, err := json.Marshal(map[string]string{"content": comment})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "json encoding")
|
||||
}
|
||||
path := fmt.Sprintf("%s/1.0/repositories/%s/pullrequests/%d/comments", b.BaseURL, repo.FullName, pullNum)
|
||||
req, err := b.prepRequest("POST", path, bytes.NewBuffer(bodyBytes))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "constructing request")
|
||||
}
|
||||
resp, err := b.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("unexpected status code: %d for url: %s, body: %s", resp.StatusCode, path, string(body))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PullIsApproved returns true if the merge request was approved.
|
||||
func (b *Client) PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error) {
|
||||
path := fmt.Sprintf("%s/2.0/repositories/%s/pullrequests/%d", b.BaseURL, repo.FullName, pull.Num)
|
||||
req, err := b.prepRequest("GET", path, nil)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "constructing request")
|
||||
}
|
||||
resp, err := b.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return false, fmt.Errorf("unexpected status code: %d, body: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "reading response body")
|
||||
}
|
||||
|
||||
parsedPull, err := ParseBitBucketPullRequest(body)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "parsing response")
|
||||
}
|
||||
for _, participant := range parsedPull.Participants {
|
||||
if *participant.Approved == true {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// UpdateStatus updates the ~ status of a commit.
|
||||
func (b *Client) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
bbState := "FAILED"
|
||||
switch state {
|
||||
case models.Pending:
|
||||
bbState = "INPROGRESS"
|
||||
case models.Success:
|
||||
bbState = "SUCCESSFUL"
|
||||
case models.Failed:
|
||||
bbState = "FAILED"
|
||||
}
|
||||
|
||||
bodyBytes, err := json.Marshal(map[string]string{
|
||||
"key": "atlantis",
|
||||
"url": b.AtlantisBaseURL,
|
||||
"state": bbState,
|
||||
"description": description,
|
||||
})
|
||||
|
||||
path := fmt.Sprintf("%s/2.0/repositories/%s/commit/%s/statuses/build", b.BaseURL, repo.FullName, pull.HeadCommit)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "json encoding")
|
||||
}
|
||||
req, err := b.prepRequest("POST", path, bytes.NewBuffer(bodyBytes))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "constructing request")
|
||||
}
|
||||
resp, err := b.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// Check for both 201 and 200 because on a new status we'll get a 201 but
|
||||
// on a status update we'll get a 200.
|
||||
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("unexpected status code: %d, body: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1
server/events/vcs/bitbucket/client_test.go
Normal file
1
server/events/vcs/bitbucket/client_test.go
Normal file
@@ -0,0 +1 @@
|
||||
package bitbucket
|
||||
82
server/events/vcs/bitbucket/models.go
Normal file
82
server/events/vcs/bitbucket/models.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package bitbucket
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type CommentEvent struct {
|
||||
CommonEventData
|
||||
Comment *Comment `json:"comment,omitempty" validate:"required"`
|
||||
}
|
||||
|
||||
type PullRequestEvent struct {
|
||||
CommonEventData
|
||||
}
|
||||
|
||||
type CommonEventData struct {
|
||||
Actor *Actor `json:"actor,omitempty" validate:"required"`
|
||||
Repository *Repository `json:"repository,omitempty" validate:"required"`
|
||||
PullRequest *PullRequest `json:"pullrequest,omitempty" validate:"required"`
|
||||
}
|
||||
|
||||
type DiffStat struct {
|
||||
Values []DiffStatValue `json:"values,omitempty" validate:"required"`
|
||||
}
|
||||
type DiffStatValue struct {
|
||||
// Old is the old file, this can be null.
|
||||
Old *DiffStatFile `json:"old,omitempty"`
|
||||
// New is the new file, this can be null.
|
||||
New *DiffStatFile `json:"new,omitempty"`
|
||||
}
|
||||
type DiffStatFile struct {
|
||||
Path *string `json:"path,omitempty" validate:"required"`
|
||||
}
|
||||
|
||||
type Actor struct {
|
||||
Username *string `json:"username,omitempty" validate:"required"`
|
||||
}
|
||||
type Repository struct {
|
||||
FullName *string `json:"full_name,omitempty" validate:"required"`
|
||||
Links Links `json:"links,omitempty" validate:"required"`
|
||||
}
|
||||
type PullRequest struct {
|
||||
ID *int `json:"id,omitempty" validate:"required"`
|
||||
Source *Source `json:"source,omitempty" validate:"required"`
|
||||
Participants []Participant `json:"participants,omitempty" validate:"required"`
|
||||
Links *Links `json:"links,omitempty" validate:"required"`
|
||||
State *string `json:"state,omitempty" validate:"required"`
|
||||
}
|
||||
type Links struct {
|
||||
HTML *Link `json:"html,omitempty" validate:"required"`
|
||||
}
|
||||
type Link struct {
|
||||
HREF *string `json:"href,omitempty" validate:"required"`
|
||||
}
|
||||
type Participant struct {
|
||||
Approved *bool `json:"approved,omitempty" validate:"required"`
|
||||
}
|
||||
type Source struct {
|
||||
Repository *Repository `json:"repository,omitempty" validate:"required"`
|
||||
Commit *Commit `json:"commit,omitempty" validate:"required"`
|
||||
Branch *Branch `json:"branch,omitempty" validate:"required"`
|
||||
}
|
||||
type Branch struct {
|
||||
Name *string `json:"name,omitempty" validate:"required"`
|
||||
}
|
||||
type Commit struct {
|
||||
Hash *string `json:"hash,omitempty" validate:"required"`
|
||||
}
|
||||
type Comment struct {
|
||||
Content *CommentContent `json:"content,omitempty" validate:"required"`
|
||||
}
|
||||
type CommentContent struct {
|
||||
Raw *string `json:"raw,omitempty" validate:"required"`
|
||||
}
|
||||
|
||||
func ParseBitBucketPullRequest(body []byte) (PullRequest, error) {
|
||||
var pull PullRequest
|
||||
if err := json.Unmarshal(body, &pull); err != nil {
|
||||
return PullRequest{}, err
|
||||
}
|
||||
return pull, nil
|
||||
}
|
||||
@@ -24,5 +24,5 @@ type Client interface {
|
||||
GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error)
|
||||
CreateComment(repo models.Repo, pullNum int, comment string) error
|
||||
PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error)
|
||||
UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error
|
||||
UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ var PullEvent = github.PullRequestEvent{
|
||||
},
|
||||
Repo: &Repo,
|
||||
PullRequest: &Pull,
|
||||
Action: github.String("opened"),
|
||||
}
|
||||
|
||||
var Pull = github.PullRequest{
|
||||
|
||||
@@ -123,15 +123,15 @@ func (g *GithubClient) GetPullRequest(repo models.Repo, num int) (*github.PullRe
|
||||
|
||||
// UpdateStatus updates the status badge on the pull request.
|
||||
// See https://github.com/blog/1227-commit-status-api.
|
||||
func (g *GithubClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error {
|
||||
func (g *GithubClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
const statusContext = "Atlantis"
|
||||
ghState := "error"
|
||||
switch state {
|
||||
case Pending:
|
||||
case models.Pending:
|
||||
ghState = "pending"
|
||||
case Success:
|
||||
case models.Success:
|
||||
ghState = "success"
|
||||
case Failed:
|
||||
case models.Failed:
|
||||
ghState = "failure"
|
||||
}
|
||||
status := &github.RepoStatus{
|
||||
|
||||
@@ -78,19 +78,19 @@ func TestGithubClient_GetModifiedFiles(t *testing.T) {
|
||||
|
||||
func TestGithubClient_UpdateStatus(t *testing.T) {
|
||||
cases := []struct {
|
||||
status vcs.CommitStatus
|
||||
status models.CommitStatus
|
||||
expState string
|
||||
}{
|
||||
{
|
||||
vcs.Pending,
|
||||
models.Pending,
|
||||
"pending",
|
||||
},
|
||||
{
|
||||
vcs.Success,
|
||||
models.Success,
|
||||
"success",
|
||||
},
|
||||
{
|
||||
vcs.Failed,
|
||||
models.Failed,
|
||||
"failure",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -79,16 +79,16 @@ func (g *GitlabClient) PullIsApproved(repo models.Repo, pull models.PullRequest)
|
||||
}
|
||||
|
||||
// UpdateStatus updates the build status of a commit.
|
||||
func (g *GitlabClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error {
|
||||
func (g *GitlabClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
const statusContext = "Atlantis"
|
||||
|
||||
gitlabState := gitlab.Failed
|
||||
switch state {
|
||||
case Pending:
|
||||
case models.Pending:
|
||||
gitlabState = gitlab.Pending
|
||||
case Failed:
|
||||
case models.Failed:
|
||||
gitlabState = gitlab.Failed
|
||||
case Success:
|
||||
case models.Success:
|
||||
gitlabState = gitlab.Success
|
||||
}
|
||||
_, _, err := g.Client.Commits.SetCommitStatus(repo.FullName, pull.HeadCommit, &gitlab.SetCommitStatusOptions{
|
||||
|
||||
@@ -4,17 +4,17 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/petergtz/pegomock"
|
||||
vcs "github.com/runatlantis/atlantis/server/events/vcs"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
)
|
||||
|
||||
func AnyVcsCommitStatus() vcs.CommitStatus {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(vcs.CommitStatus))(nil)).Elem()))
|
||||
var nullValue vcs.CommitStatus
|
||||
func AnyVcsCommitStatus() models.CommitStatus {
|
||||
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.CommitStatus))(nil)).Elem()))
|
||||
var nullValue models.CommitStatus
|
||||
return nullValue
|
||||
}
|
||||
|
||||
func EqVcsCommitStatus(value vcs.CommitStatus) vcs.CommitStatus {
|
||||
func EqVcsCommitStatus(value models.CommitStatus) models.CommitStatus {
|
||||
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
|
||||
var nullValue vcs.CommitStatus
|
||||
var nullValue models.CommitStatus
|
||||
return nullValue
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
pegomock "github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
vcs "github.com/runatlantis/atlantis/server/events/vcs"
|
||||
)
|
||||
|
||||
type MockClient struct {
|
||||
@@ -63,7 +62,7 @@ func (mock *MockClient) PullIsApproved(repo models.Repo, pull models.PullRequest
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string) error {
|
||||
func (mock *MockClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
params := []pegomock.Param{repo, pull, state, description}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdateStatus", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 error
|
||||
@@ -190,7 +189,7 @@ func (c *Client_PullIsApproved_OngoingVerification) GetAllCapturedArguments() (_
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string) *Client_UpdateStatus_OngoingVerification {
|
||||
func (verifier *VerifierClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) *Client_UpdateStatus_OngoingVerification {
|
||||
params := []pegomock.Param{repo, pull, state, description}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdateStatus", params)
|
||||
return &Client_UpdateStatus_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
@@ -201,12 +200,12 @@ type Client_UpdateStatus_OngoingVerification struct {
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *Client_UpdateStatus_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, string) {
|
||||
func (c *Client_UpdateStatus_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, models.CommitStatus, string) {
|
||||
repo, pull, state, description := c.GetAllCapturedArguments()
|
||||
return repo[len(repo)-1], pull[len(pull)-1], state[len(state)-1], description[len(description)-1]
|
||||
}
|
||||
|
||||
func (c *Client_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []string) {
|
||||
func (c *Client_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []models.CommitStatus, _param3 []string) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.Repo, len(params[0]))
|
||||
@@ -217,9 +216,9 @@ func (c *Client_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_pa
|
||||
for u, param := range params[1] {
|
||||
_param1[u] = param.(models.PullRequest)
|
||||
}
|
||||
_param2 = make([]vcs.CommitStatus, len(params[2]))
|
||||
_param2 = make([]models.CommitStatus, len(params[2]))
|
||||
for u, param := range params[2] {
|
||||
_param2[u] = param.(vcs.CommitStatus)
|
||||
_param2[u] = param.(models.CommitStatus)
|
||||
}
|
||||
_param3 = make([]string, len(params[3]))
|
||||
for u, param := range params[3] {
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
pegomock "github.com/petergtz/pegomock"
|
||||
models "github.com/runatlantis/atlantis/server/events/models"
|
||||
vcs "github.com/runatlantis/atlantis/server/events/vcs"
|
||||
)
|
||||
|
||||
type MockClientProxy struct {
|
||||
@@ -63,7 +62,7 @@ func (mock *MockClientProxy) PullIsApproved(repo models.Repo, pull models.PullRe
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string) error {
|
||||
func (mock *MockClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
params := []pegomock.Param{repo, pull, state, description}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("UpdateStatus", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
|
||||
var ret0 error
|
||||
@@ -190,7 +189,7 @@ func (c *ClientProxy_PullIsApproved_OngoingVerification) GetAllCapturedArguments
|
||||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state vcs.CommitStatus, description string) *ClientProxy_UpdateStatus_OngoingVerification {
|
||||
func (verifier *VerifierClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) *ClientProxy_UpdateStatus_OngoingVerification {
|
||||
params := []pegomock.Param{repo, pull, state, description}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "UpdateStatus", params)
|
||||
return &ClientProxy_UpdateStatus_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
@@ -201,12 +200,12 @@ type ClientProxy_UpdateStatus_OngoingVerification struct {
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *ClientProxy_UpdateStatus_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, vcs.CommitStatus, string) {
|
||||
func (c *ClientProxy_UpdateStatus_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest, models.CommitStatus, string) {
|
||||
repo, pull, state, description := c.GetAllCapturedArguments()
|
||||
return repo[len(repo)-1], pull[len(pull)-1], state[len(state)-1], description[len(description)-1]
|
||||
}
|
||||
|
||||
func (c *ClientProxy_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []vcs.CommitStatus, _param3 []string) {
|
||||
func (c *ClientProxy_UpdateStatus_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest, _param2 []models.CommitStatus, _param3 []string) {
|
||||
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
|
||||
if len(params) > 0 {
|
||||
_param0 = make([]models.Repo, len(params[0]))
|
||||
@@ -217,9 +216,9 @@ func (c *ClientProxy_UpdateStatus_OngoingVerification) GetAllCapturedArguments()
|
||||
for u, param := range params[1] {
|
||||
_param1[u] = param.(models.PullRequest)
|
||||
}
|
||||
_param2 = make([]vcs.CommitStatus, len(params[2]))
|
||||
_param2 = make([]models.CommitStatus, len(params[2]))
|
||||
for u, param := range params[2] {
|
||||
_param2[u] = param.(vcs.CommitStatus)
|
||||
_param2[u] = param.(models.CommitStatus)
|
||||
}
|
||||
_param3 = make([]string, len(params[3]))
|
||||
for u, param := range params[3] {
|
||||
|
||||
@@ -35,7 +35,7 @@ func (a *NotConfiguredVCSClient) CreateComment(repo models.Repo, pullNum int, co
|
||||
func (a *NotConfiguredVCSClient) PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error) {
|
||||
return false, a.err()
|
||||
}
|
||||
func (a *NotConfiguredVCSClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error {
|
||||
func (a *NotConfiguredVCSClient) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
return a.err()
|
||||
}
|
||||
func (a *NotConfiguredVCSClient) err() error {
|
||||
|
||||
@@ -26,26 +26,31 @@ type ClientProxy interface {
|
||||
GetModifiedFiles(repo models.Repo, pull models.PullRequest) ([]string, error)
|
||||
CreateComment(repo models.Repo, pullNum int, comment string) error
|
||||
PullIsApproved(repo models.Repo, pull models.PullRequest) (bool, error)
|
||||
UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error
|
||||
UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error
|
||||
}
|
||||
|
||||
// DefaultClientProxy proxies calls to the correct VCS client depending on which
|
||||
// VCS host is required.
|
||||
type DefaultClientProxy struct {
|
||||
GithubClient Client
|
||||
GitlabClient Client
|
||||
GithubClient Client
|
||||
GitlabClient Client
|
||||
BitbucketClient Client
|
||||
}
|
||||
|
||||
func NewDefaultClientProxy(githubClient Client, gitlabClient Client) *DefaultClientProxy {
|
||||
func NewDefaultClientProxy(githubClient Client, gitlabClient Client, bitbucketClient Client) *DefaultClientProxy {
|
||||
if githubClient == nil {
|
||||
githubClient = &NotConfiguredVCSClient{}
|
||||
}
|
||||
if gitlabClient == nil {
|
||||
gitlabClient = &NotConfiguredVCSClient{}
|
||||
}
|
||||
if bitbucketClient == nil {
|
||||
bitbucketClient = &NotConfiguredVCSClient{}
|
||||
}
|
||||
return &DefaultClientProxy{
|
||||
GitlabClient: gitlabClient,
|
||||
GithubClient: githubClient,
|
||||
GitlabClient: gitlabClient,
|
||||
GithubClient: githubClient,
|
||||
BitbucketClient: bitbucketClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +62,8 @@ func (d *DefaultClientProxy) GetModifiedFiles(repo models.Repo, pull models.Pull
|
||||
return d.GithubClient.GetModifiedFiles(repo, pull)
|
||||
case models.Gitlab:
|
||||
return d.GitlabClient.GetModifiedFiles(repo, pull)
|
||||
case models.Bitbucket:
|
||||
return d.BitbucketClient.GetModifiedFiles(repo, pull)
|
||||
}
|
||||
return nil, invalidVCSErr
|
||||
}
|
||||
@@ -67,6 +74,8 @@ func (d *DefaultClientProxy) CreateComment(repo models.Repo, pullNum int, commen
|
||||
return d.GithubClient.CreateComment(repo, pullNum, comment)
|
||||
case models.Gitlab:
|
||||
return d.GitlabClient.CreateComment(repo, pullNum, comment)
|
||||
case models.Bitbucket:
|
||||
return d.BitbucketClient.CreateComment(repo, pullNum, comment)
|
||||
}
|
||||
return invalidVCSErr
|
||||
}
|
||||
@@ -77,16 +86,20 @@ func (d *DefaultClientProxy) PullIsApproved(repo models.Repo, pull models.PullRe
|
||||
return d.GithubClient.PullIsApproved(repo, pull)
|
||||
case models.Gitlab:
|
||||
return d.GitlabClient.PullIsApproved(repo, pull)
|
||||
case models.Bitbucket:
|
||||
return d.BitbucketClient.PullIsApproved(repo, pull)
|
||||
}
|
||||
return false, invalidVCSErr
|
||||
}
|
||||
|
||||
func (d *DefaultClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state CommitStatus, description string) error {
|
||||
func (d *DefaultClientProxy) UpdateStatus(repo models.Repo, pull models.PullRequest, state models.CommitStatus, description string) error {
|
||||
switch repo.VCSHost.Type {
|
||||
case models.Github:
|
||||
return d.GithubClient.UpdateStatus(repo, pull, state, description)
|
||||
case models.Gitlab:
|
||||
return d.GitlabClient.UpdateStatus(repo, pull, state, description)
|
||||
case models.Bitbucket:
|
||||
return d.BitbucketClient.UpdateStatus(repo, pull, state, description)
|
||||
}
|
||||
return invalidVCSErr
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package vcs_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/runatlantis/atlantis/server/events/vcs"
|
||||
. "github.com/runatlantis/atlantis/testing"
|
||||
)
|
||||
|
||||
func TestStatus_String(t *testing.T) {
|
||||
cases := map[vcs.CommitStatus]string{
|
||||
vcs.Pending: "pending",
|
||||
vcs.Success: "success",
|
||||
vcs.Failed: "failed",
|
||||
}
|
||||
for k, v := range cases {
|
||||
Equals(t, v, k.String())
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (w *FileWorkspace) Clone(
|
||||
return w.forceClone(log, cloneDir, headRepo, p)
|
||||
}
|
||||
currCommit := strings.Trim(string(output), "\n")
|
||||
if currCommit == p.HeadCommit {
|
||||
if strings.HasPrefix(currCommit, p.HeadCommit) {
|
||||
log.Debug("repo is at correct commit %q so will not re-clone", p.HeadCommit)
|
||||
return cloneDir, nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
@@ -27,6 +28,8 @@ import (
|
||||
|
||||
const githubHeader = "X-Github-Event"
|
||||
const gitlabHeader = "X-Gitlab-Event"
|
||||
const bitbucketEventTypeHeader = "X-Event-Key"
|
||||
const bitbucketRequestIDHeader = "X-Request-UUID"
|
||||
|
||||
// EventsController handles all webhook requests which signify 'events' in the
|
||||
// VCS host, ex. GitHub.
|
||||
@@ -72,6 +75,14 @@ func (e *EventsController) Post(w http.ResponseWriter, r *http.Request) {
|
||||
e.Logger.Debug("handling GitLab post")
|
||||
e.handleGitlabPost(w, r)
|
||||
return
|
||||
} else if r.Header.Get(bitbucketEventTypeHeader) != "" {
|
||||
if !e.supportsHost(models.Bitbucket) {
|
||||
e.respond(w, logging.Debug, http.StatusBadRequest, "Ignoring request since not configured to support Bitbucket")
|
||||
return
|
||||
}
|
||||
e.Logger.Debug("handling Bitbucket post")
|
||||
e.handleBitbucketPost(w, r)
|
||||
return
|
||||
}
|
||||
e.respond(w, logging.Debug, http.StatusBadRequest, "Ignoring request")
|
||||
}
|
||||
@@ -99,6 +110,29 @@ func (e *EventsController) handleGithubPost(w http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EventsController) handleBitbucketPost(w http.ResponseWriter, r *http.Request) {
|
||||
eventType := r.Header.Get(bitbucketEventTypeHeader)
|
||||
reqID := r.Header.Get(bitbucketRequestIDHeader)
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
e.respond(w, logging.Error, http.StatusBadRequest, "Unable to read body: %s %s=%s", err, bitbucketRequestIDHeader, reqID)
|
||||
return
|
||||
}
|
||||
switch eventType {
|
||||
case "pullrequest:created", "pullrequest:updated", "pullrequest:fulfilled", "pullrequest:rejected":
|
||||
e.Logger.Debug("handling as pull request state changed event")
|
||||
e.HandleBitbucketPullRequestEvent(w, eventType, body, reqID)
|
||||
return
|
||||
case "pullrequest:comment_created":
|
||||
e.Logger.Debug("handling as comment created event")
|
||||
e.HandleBitbucketCommentEvent(w, body, reqID)
|
||||
return
|
||||
default:
|
||||
e.respond(w, logging.Debug, http.StatusOK, "Ignoring unsupported event type %s %s=%s", eventType, bitbucketRequestIDHeader, reqID)
|
||||
}
|
||||
}
|
||||
|
||||
// HandleGithubCommentEvent handles comment events from GitHub where Atlantis
|
||||
// commands can come from. It's exported to make testing easier.
|
||||
func (e *EventsController) HandleGithubCommentEvent(w http.ResponseWriter, event *github.IssueCommentEvent, githubReqID string) {
|
||||
@@ -115,45 +149,50 @@ func (e *EventsController) HandleGithubCommentEvent(w http.ResponseWriter, event
|
||||
|
||||
// We pass in nil for maybeHeadRepo because the head repo data isn't
|
||||
// available in the GithubIssueComment event.
|
||||
e.handleCommentEvent(w, baseRepo, nil, user, pullNum, event.Comment.GetBody(), models.Github)
|
||||
e.handleCommentEvent(w, baseRepo, nil, nil, user, pullNum, event.Comment.GetBody(), models.Github)
|
||||
}
|
||||
|
||||
// HandleBitbucketCommentEvent handles comment events from Bitbucket.
|
||||
func (e *EventsController) HandleBitbucketCommentEvent(w http.ResponseWriter, body []byte, reqID string) {
|
||||
pull, baseRepo, headRepo, user, comment, err := e.Parser.ParseBitbucketCloudCommentEvent(body)
|
||||
if err != nil {
|
||||
e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing pull data: %s %s=%s", err, bitbucketRequestIDHeader, reqID)
|
||||
return
|
||||
}
|
||||
e.handleCommentEvent(w, baseRepo, &headRepo, &pull, user, pull.Num, comment, models.Bitbucket)
|
||||
}
|
||||
|
||||
func (e *EventsController) HandleBitbucketPullRequestEvent(w http.ResponseWriter, eventType string, body []byte, reqID string) {
|
||||
pull, baseRepo, headRepo, user, err := e.Parser.ParseBitbucketCloudPullEvent(body)
|
||||
if err != nil {
|
||||
e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing pull data: %s %s=%s", err, bitbucketRequestIDHeader, reqID)
|
||||
return
|
||||
}
|
||||
pullEventType := e.Parser.GetBitbucketEventType(eventType)
|
||||
e.Logger.Info("identified event as type %q", pullEventType.String())
|
||||
e.handlePullRequestEvent(w, baseRepo, headRepo, pull, user, pullEventType)
|
||||
}
|
||||
|
||||
// HandleGithubPullRequestEvent will delete any locks associated with the pull
|
||||
// request if the event is a pull request closed event. It's exported to make
|
||||
// testing easier.
|
||||
func (e *EventsController) HandleGithubPullRequestEvent(w http.ResponseWriter, pullEvent *github.PullRequestEvent, githubReqID string) {
|
||||
pull, baseRepo, headRepo, user, err := e.Parser.ParseGithubPullEvent(pullEvent)
|
||||
pull, pullEventType, baseRepo, headRepo, user, err := e.Parser.ParseGithubPullEvent(pullEvent)
|
||||
if err != nil {
|
||||
e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing pull data: %s %s", err, githubReqID)
|
||||
return
|
||||
}
|
||||
var eventType string
|
||||
switch pullEvent.GetAction() {
|
||||
case "opened":
|
||||
eventType = OpenPullEvent
|
||||
case "synchronize":
|
||||
eventType = UpdatedPullEvent
|
||||
case "closed":
|
||||
eventType = ClosedPullEvent
|
||||
default:
|
||||
eventType = OtherPullEvent
|
||||
}
|
||||
e.Logger.Info("identified event as type %q", eventType)
|
||||
e.handlePullRequestEvent(w, baseRepo, headRepo, pull, user, eventType)
|
||||
e.Logger.Info("identified event as type %q", pullEventType.String())
|
||||
e.handlePullRequestEvent(w, baseRepo, headRepo, pull, user, pullEventType)
|
||||
}
|
||||
|
||||
const OpenPullEvent = "opened"
|
||||
const UpdatedPullEvent = "updated"
|
||||
const ClosedPullEvent = "closed"
|
||||
const OtherPullEvent = "other"
|
||||
|
||||
func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, baseRepo models.Repo, headRepo models.Repo, pull models.PullRequest, user models.User, eventType string) {
|
||||
func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, baseRepo models.Repo, headRepo models.Repo, pull models.PullRequest, user models.User, eventType models.PullRequestEventType) {
|
||||
if !e.RepoWhitelistChecker.IsWhitelisted(baseRepo.FullName, baseRepo.VCSHost.Hostname) {
|
||||
// If the repo isn't whitelisted and we receive an opened pull request
|
||||
// event we comment back on the pull request that the repo isn't
|
||||
// whitelisted. This is because the user might be expecting Atlantis to
|
||||
// autoplan. For other events, we just ignore them.
|
||||
if eventType == OpenPullEvent {
|
||||
if eventType == models.OpenedPullEvent {
|
||||
e.commentNotWhitelisted(baseRepo, pull.Num)
|
||||
}
|
||||
e.respond(w, logging.Debug, http.StatusForbidden, "Ignoring pull request event from non-whitelisted repo")
|
||||
@@ -161,7 +200,7 @@ func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, baseRep
|
||||
}
|
||||
|
||||
switch eventType {
|
||||
case OpenPullEvent, UpdatedPullEvent:
|
||||
case models.OpenedPullEvent, models.UpdatedPullEvent:
|
||||
// If the pull request was opened or updated, we will try to autoplan.
|
||||
|
||||
// Respond with success and then actually execute the command asynchronously.
|
||||
@@ -177,7 +216,7 @@ func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, baseRep
|
||||
e.CommandRunner.RunAutoplanCommand(baseRepo, headRepo, pull, user)
|
||||
}
|
||||
return
|
||||
case ClosedPullEvent:
|
||||
case models.ClosedPullEvent:
|
||||
// If the pull request was closed, we delete locks.
|
||||
if err := e.PullCleaner.CleanUpPull(baseRepo, pull); err != nil {
|
||||
e.respond(w, logging.Error, http.StatusInternalServerError, "Error cleaning pull request: %s", err)
|
||||
@@ -186,7 +225,7 @@ func (e *EventsController) handlePullRequestEvent(w http.ResponseWriter, baseRep
|
||||
e.Logger.Info("deleted locks and workspace for repo %s, pull %d", baseRepo.FullName, pull.Num)
|
||||
fmt.Fprintln(w, "Pull request cleaned successfully")
|
||||
return
|
||||
case OtherPullEvent:
|
||||
case models.OtherPullEvent:
|
||||
// Else we ignore the event.
|
||||
e.respond(w, logging.Debug, http.StatusOK, "Ignoring non-actionable pull request event")
|
||||
return
|
||||
@@ -217,15 +256,16 @@ func (e *EventsController) handleGitlabPost(w http.ResponseWriter, r *http.Reque
|
||||
// HandleGitlabCommentEvent handles comment events from GitLab where Atlantis
|
||||
// commands can come from. It's exported to make testing easier.
|
||||
func (e *EventsController) HandleGitlabCommentEvent(w http.ResponseWriter, event gitlab.MergeCommentEvent) {
|
||||
// todo: can gitlab return the pull request here too?
|
||||
baseRepo, headRepo, user, err := e.Parser.ParseGitlabMergeCommentEvent(event)
|
||||
if err != nil {
|
||||
e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing webhook: %s", err)
|
||||
return
|
||||
}
|
||||
e.handleCommentEvent(w, baseRepo, &headRepo, user, event.MergeRequest.IID, event.ObjectAttributes.Note, models.Gitlab)
|
||||
e.handleCommentEvent(w, baseRepo, &headRepo, nil, user, event.MergeRequest.IID, event.ObjectAttributes.Note, models.Gitlab)
|
||||
}
|
||||
|
||||
func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo models.Repo, maybeHeadRepo *models.Repo, user models.User, pullNum int, comment string, vcsHost models.VCSHostType) {
|
||||
func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo models.Repo, maybeHeadRepo *models.Repo, maybePull *models.PullRequest, user models.User, pullNum int, comment string, vcsHost models.VCSHostType) {
|
||||
parseResult := e.CommentParser.Parse(comment, vcsHost)
|
||||
if parseResult.Ignore {
|
||||
truncated := comment
|
||||
@@ -264,10 +304,10 @@ func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo mo
|
||||
// Respond with success and then actually execute the command asynchronously.
|
||||
// We use a goroutine so that this function returns and the connection is
|
||||
// closed.
|
||||
go e.CommandRunner.RunCommentCommand(baseRepo, maybeHeadRepo, user, pullNum, parseResult.Command)
|
||||
go e.CommandRunner.RunCommentCommand(baseRepo, maybeHeadRepo, maybePull, user, pullNum, parseResult.Command)
|
||||
} else {
|
||||
// When testing we want to wait for everything to complete.
|
||||
e.CommandRunner.RunCommentCommand(baseRepo, maybeHeadRepo, user, pullNum, parseResult.Command)
|
||||
e.CommandRunner.RunCommentCommand(baseRepo, maybeHeadRepo, maybePull, user, pullNum, parseResult.Command)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,24 +315,13 @@ func (e *EventsController) handleCommentEvent(w http.ResponseWriter, baseRepo mo
|
||||
// request if the event is a merge request closed event. It's exported to make
|
||||
// testing easier.
|
||||
func (e *EventsController) HandleGitlabMergeRequestEvent(w http.ResponseWriter, event gitlab.MergeEvent) {
|
||||
pull, baseRepo, headRepo, user, err := e.Parser.ParseGitlabMergeEvent(event)
|
||||
pull, pullEventType, baseRepo, headRepo, user, err := e.Parser.ParseGitlabMergeEvent(event)
|
||||
if err != nil {
|
||||
e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing webhook: %s", err)
|
||||
return
|
||||
}
|
||||
var eventType string
|
||||
switch event.ObjectAttributes.Action {
|
||||
case "open":
|
||||
eventType = OpenPullEvent
|
||||
case "update":
|
||||
eventType = UpdatedPullEvent
|
||||
case "merge", "close":
|
||||
eventType = ClosedPullEvent
|
||||
default:
|
||||
eventType = OtherPullEvent
|
||||
}
|
||||
e.Logger.Info("identified event as type %q", eventType)
|
||||
e.handlePullRequestEvent(w, baseRepo, headRepo, pull, user, eventType)
|
||||
e.Logger.Info("identified event as type %q", pullEventType.String())
|
||||
e.handlePullRequestEvent(w, baseRepo, headRepo, pull, user, pullEventType)
|
||||
}
|
||||
|
||||
// supportsHost returns true if h is in e.SupportedVCSHosts and false otherwise.
|
||||
|
||||
@@ -280,6 +280,9 @@ func setupE2E(t *testing.T) (server.EventsController, *vcsmocks.MockClientProxy,
|
||||
},
|
||||
}
|
||||
|
||||
repoWhitelistChecker, err := events.NewRepoWhitelistChecker("*")
|
||||
Ok(t, err)
|
||||
|
||||
ctrl := server.EventsController{
|
||||
TestingMode: true,
|
||||
CommandRunner: commandRunner,
|
||||
@@ -295,11 +298,9 @@ func setupE2E(t *testing.T) (server.EventsController, *vcsmocks.MockClientProxy,
|
||||
GithubRequestValidator: &server.DefaultGithubRequestValidator{},
|
||||
GitlabRequestParserValidator: &server.DefaultGitlabRequestParserValidator{},
|
||||
GitlabWebHookSecret: nil,
|
||||
RepoWhitelistChecker: &events.RepoWhitelistChecker{
|
||||
Whitelist: "*",
|
||||
},
|
||||
SupportedVCSHosts: []models.VCSHostType{models.Gitlab, models.Github},
|
||||
VCSClient: e2eVCSClient,
|
||||
RepoWhitelistChecker: repoWhitelistChecker,
|
||||
SupportedVCSHosts: []models.VCSHostType{models.Gitlab, models.Github, models.Bitbucket},
|
||||
VCSClient: e2eVCSClient,
|
||||
}
|
||||
return ctrl, e2eVCSClient, e2eGithubGetter, workingDir
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ func TestPost_GitlabCommentSuccess(t *testing.T) {
|
||||
e.Post(w, req)
|
||||
responseContains(t, w, http.StatusOK, "Processing...")
|
||||
|
||||
cr.VerifyWasCalledOnce().RunCommentCommand(models.Repo{}, &models.Repo{}, models.User{}, 0, nil)
|
||||
cr.VerifyWasCalledOnce().RunCommentCommand(models.Repo{}, &models.Repo{}, nil, models.User{}, 0, nil)
|
||||
}
|
||||
|
||||
func TestPost_GithubCommentSuccess(t *testing.T) {
|
||||
@@ -287,7 +287,7 @@ func TestPost_GithubCommentSuccess(t *testing.T) {
|
||||
e.Post(w, req)
|
||||
responseContains(t, w, http.StatusOK, "Processing...")
|
||||
|
||||
cr.VerifyWasCalledOnce().RunCommentCommand(baseRepo, nil, user, 1, &cmd)
|
||||
cr.VerifyWasCalledOnce().RunCommentCommand(baseRepo, nil, nil, user, 1, &cmd)
|
||||
}
|
||||
|
||||
func TestPost_GithubPullRequestInvalid(t *testing.T) {
|
||||
@@ -298,7 +298,7 @@ func TestPost_GithubPullRequestInvalid(t *testing.T) {
|
||||
|
||||
event := `{"action": "closed"}`
|
||||
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(models.PullRequest{}, models.Repo{}, models.Repo{}, models.User{}, errors.New("err"))
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(models.PullRequest{}, models.OpenedPullEvent, models.Repo{}, models.Repo{}, models.User{}, errors.New("err"))
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
responseContains(t, w, http.StatusBadRequest, "Error parsing pull data: err")
|
||||
@@ -312,7 +312,7 @@ func TestPost_GitlabMergeRequestInvalid(t *testing.T) {
|
||||
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
|
||||
repo := models.Repo{}
|
||||
pullRequest := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, models.User{}, errors.New("err"))
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, errors.New("err"))
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
responseContains(t, w, http.StatusBadRequest, "Error parsing webhook: err")
|
||||
@@ -321,7 +321,9 @@ func TestPost_GitlabMergeRequestInvalid(t *testing.T) {
|
||||
func TestPost_GithubPullRequestNotWhitelisted(t *testing.T) {
|
||||
t.Log("when the event is a github pull request to a non-whitelisted repo we return a 400")
|
||||
e, v, _, _, _, _, _, _ := setup(t)
|
||||
e.RepoWhitelistChecker = &events.RepoWhitelistChecker{Whitelist: "github.com/nevermatch"}
|
||||
var err error
|
||||
e.RepoWhitelistChecker, err = events.NewRepoWhitelistChecker("github.com/nevermatch")
|
||||
Ok(t, err)
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
req.Header.Set(githubHeader, "pull_request")
|
||||
|
||||
@@ -338,11 +340,13 @@ func TestPost_GitlabMergeRequestNotWhitelisted(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
req.Header.Set(gitlabHeader, "value")
|
||||
|
||||
e.RepoWhitelistChecker = &events.RepoWhitelistChecker{Whitelist: "github.com/nevermatch"}
|
||||
var err error
|
||||
e.RepoWhitelistChecker, err = events.NewRepoWhitelistChecker("github.com/nevermatch")
|
||||
Ok(t, err)
|
||||
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
|
||||
repo := models.Repo{}
|
||||
pullRequest := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
@@ -350,6 +354,7 @@ func TestPost_GitlabMergeRequestNotWhitelisted(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPost_GithubPullRequestUnsupportedAction(t *testing.T) {
|
||||
t.Skip("relies too much on mocks, should use real event parser")
|
||||
e, v, _, _, _, _, _, _ := setup(t)
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
req.Header.Set(githubHeader, "pull_request")
|
||||
@@ -357,11 +362,13 @@ func TestPost_GithubPullRequestUnsupportedAction(t *testing.T) {
|
||||
event := `{"action": "unsupported"}`
|
||||
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
||||
w := httptest.NewRecorder()
|
||||
e.Parser = &events.EventParser{}
|
||||
e.Post(w, req)
|
||||
responseContains(t, w, http.StatusOK, "Ignoring non-actionable pull request event")
|
||||
}
|
||||
|
||||
func TestPost_GitlabMergeRequestUnsupportedAction(t *testing.T) {
|
||||
t.Skip("relies too much on mocks, should use real event parser")
|
||||
t.Log("when the event is a gitlab merge request to a non-whitelisted repo we return a 400")
|
||||
e, _, gl, p, _, _, _, _ := setup(t)
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
@@ -378,6 +385,7 @@ func TestPost_GitlabMergeRequestUnsupportedAction(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPost_GithubPullRequestClosedErrCleaningPull(t *testing.T) {
|
||||
t.Skip("relies too much on mocks, should use real event parser")
|
||||
t.Log("when the event is a closed pull request and we have an error calling CleanUpPull we return a 503")
|
||||
RegisterMockTestingT(t)
|
||||
e, v, _, p, _, c, _, _ := setup(t)
|
||||
@@ -388,7 +396,7 @@ func TestPost_GithubPullRequestClosedErrCleaningPull(t *testing.T) {
|
||||
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
||||
repo := models.Repo{}
|
||||
pull := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(pull, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(pull, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
When(c.CleanUpPull(repo, pull)).ThenReturn(errors.New("cleanup err"))
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
@@ -396,6 +404,7 @@ func TestPost_GithubPullRequestClosedErrCleaningPull(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPost_GitlabMergeRequestClosedErrCleaningPull(t *testing.T) {
|
||||
t.Skip("relies too much on mocks, should use real event parser")
|
||||
t.Log("when the event is a closed gitlab merge request and an error occurs calling CleanUpPull we return a 500")
|
||||
e, _, gl, p, _, c, _, _ := setup(t)
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
@@ -404,7 +413,7 @@ func TestPost_GitlabMergeRequestClosedErrCleaningPull(t *testing.T) {
|
||||
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
|
||||
repo := models.Repo{}
|
||||
pullRequest := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
When(c.CleanUpPull(repo, pullRequest)).ThenReturn(errors.New("err"))
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
@@ -412,6 +421,7 @@ func TestPost_GitlabMergeRequestClosedErrCleaningPull(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPost_GithubClosedPullRequestSuccess(t *testing.T) {
|
||||
t.Skip("relies too much on mocks, should use real event parser")
|
||||
t.Log("when the event is a pull request and everything works we return a 200")
|
||||
e, v, _, p, _, c, _, _ := setup(t)
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
@@ -421,7 +431,7 @@ func TestPost_GithubClosedPullRequestSuccess(t *testing.T) {
|
||||
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
||||
repo := models.Repo{}
|
||||
pull := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(pull, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(pull, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
When(c.CleanUpPull(repo, pull)).ThenReturn(nil)
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
@@ -429,6 +439,7 @@ func TestPost_GithubClosedPullRequestSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPost_GitlabMergeRequestSuccess(t *testing.T) {
|
||||
t.Skip("relies too much on mocks, should use real event parser")
|
||||
t.Log("when the event is a gitlab merge request and the cleanup works we return a 200")
|
||||
e, _, gl, p, _, _, _, _ := setup(t)
|
||||
req, _ := http.NewRequest("GET", "", bytes.NewBuffer(nil))
|
||||
@@ -436,7 +447,7 @@ func TestPost_GitlabMergeRequestSuccess(t *testing.T) {
|
||||
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
|
||||
repo := models.Repo{}
|
||||
pullRequest := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
responseContains(t, w, http.StatusOK, "Pull request cleaned successfully")
|
||||
@@ -481,14 +492,14 @@ func TestPost_PullOpenedOrUpdated(t *testing.T) {
|
||||
When(gl.ParseAndValidate(req, secret)).ThenReturn(gitlabMergeEvent, nil)
|
||||
repo := models.Repo{}
|
||||
pullRequest := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGitlabMergeEvent(gitlabMergeEvent)).ThenReturn(pullRequest, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
case models.Github:
|
||||
req.Header.Set(githubHeader, "pull_request")
|
||||
event := fmt.Sprintf(`{"action": "%s"}`, c.Action)
|
||||
When(v.Validate(req, secret)).ThenReturn([]byte(event), nil)
|
||||
repo := models.Repo{}
|
||||
pull := models.PullRequest{State: models.Closed}
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(pull, repo, repo, models.User{}, nil)
|
||||
When(p.ParseGithubPullEvent(matchers.AnyPtrToGithubPullRequestEvent())).ThenReturn(pull, models.OpenedPullEvent, repo, repo, models.User{}, nil)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
e.Post(w, req)
|
||||
@@ -507,6 +518,8 @@ func setup(t *testing.T) (server.EventsController, *mocks.MockGithubRequestValid
|
||||
cr := emocks.NewMockCommandRunner()
|
||||
c := emocks.NewMockPullCleaner()
|
||||
vcsmock := vcsmocks.NewMockClientProxy()
|
||||
repoWhitelistChecker, err := events.NewRepoWhitelistChecker("*")
|
||||
Ok(t, err)
|
||||
e := server.EventsController{
|
||||
TestingMode: true,
|
||||
Logger: logging.NewNoopLogger(),
|
||||
@@ -519,10 +532,8 @@ func setup(t *testing.T) (server.EventsController, *mocks.MockGithubRequestValid
|
||||
SupportedVCSHosts: []models.VCSHostType{models.Github, models.Gitlab},
|
||||
GitlabWebHookSecret: secret,
|
||||
GitlabRequestParserValidator: gl,
|
||||
RepoWhitelistChecker: &events.RepoWhitelistChecker{
|
||||
Whitelist: "*",
|
||||
},
|
||||
VCSClient: vcsmock,
|
||||
RepoWhitelistChecker: repoWhitelistChecker,
|
||||
VCSClient: vcsmock,
|
||||
}
|
||||
return e, v, gl, p, cr, c, vcsmock, cp
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
"github.com/runatlantis/atlantis/server/events/runtime"
|
||||
"github.com/runatlantis/atlantis/server/events/terraform"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs/bitbucket"
|
||||
"github.com/runatlantis/atlantis/server/events/webhooks"
|
||||
"github.com/runatlantis/atlantis/server/events/yaml"
|
||||
"github.com/runatlantis/atlantis/server/logging"
|
||||
@@ -83,6 +84,9 @@ type UserConfig struct {
|
||||
AllowForkPRs bool `mapstructure:"allow-fork-prs"`
|
||||
AllowRepoConfig bool `mapstructure:"allow-repo-config"`
|
||||
AtlantisURL string `mapstructure:"atlantis-url"`
|
||||
BitbucketHostname string `mapstructure:"bitbucket-hostname"`
|
||||
BitbucketToken string `mapstructure:"bitbucket-token"`
|
||||
BitbucketUser string `mapstructure:"bitbucket-user"`
|
||||
DataDir string `mapstructure:"data-dir"`
|
||||
GithubHostname string `mapstructure:"gh-hostname"`
|
||||
GithubToken string `mapstructure:"gh-token"`
|
||||
@@ -133,6 +137,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
|
||||
var supportedVCSHosts []models.VCSHostType
|
||||
var githubClient *vcs.GithubClient
|
||||
var gitlabClient *vcs.GitlabClient
|
||||
var bitbucketClient *bitbucket.Client
|
||||
if userConfig.GithubUser != "" {
|
||||
supportedVCSHosts = append(supportedVCSHosts, models.Github)
|
||||
var err error
|
||||
@@ -162,6 +167,21 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if userConfig.BitbucketUser != "" {
|
||||
supportedVCSHosts = append(supportedVCSHosts, models.Bitbucket)
|
||||
var err error
|
||||
bitbucketClient, err = bitbucket.NewClient(
|
||||
http.DefaultClient,
|
||||
userConfig.BitbucketUser,
|
||||
userConfig.BitbucketToken,
|
||||
// todo: don't hardcode when we allow for bitbucket server
|
||||
"https://api.bitbucket.org/",
|
||||
userConfig.AtlantisURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "setting up Bitbucket client")
|
||||
}
|
||||
}
|
||||
|
||||
var webhooksConfig []webhooks.Config
|
||||
for _, c := range userConfig.Webhooks {
|
||||
config := webhooks.Config{
|
||||
@@ -176,7 +196,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "initializing webhooks")
|
||||
}
|
||||
vcsClient := vcs.NewDefaultClientProxy(githubClient, gitlabClient)
|
||||
vcsClient := vcs.NewDefaultClientProxy(githubClient, gitlabClient, bitbucketClient)
|
||||
commitStatusUpdater := &events.DefaultCommitStatusUpdater{Client: vcsClient}
|
||||
terraformClient, err := terraform.NewClient(userConfig.DataDir)
|
||||
// The flag.Lookup call is to detect if we're running in a unit test. If we
|
||||
@@ -216,6 +236,9 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
|
||||
GithubToken: userConfig.GithubToken,
|
||||
GitlabUser: userConfig.GitlabUser,
|
||||
GitlabToken: userConfig.GitlabToken,
|
||||
// todo: fill in properly
|
||||
BitbucketCloudUser: "lkysow",
|
||||
BitbucketCloudToken: os.Getenv("BITBUCKET_TOKEN"),
|
||||
}
|
||||
commentParser := &events.CommentParser{
|
||||
GithubUser: userConfig.GithubUser,
|
||||
@@ -267,8 +290,9 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
|
||||
RequireApprovalOverride: userConfig.RequireApproval,
|
||||
},
|
||||
}
|
||||
repoWhitelist := &events.RepoWhitelistChecker{
|
||||
Whitelist: userConfig.RepoWhitelist,
|
||||
repoWhitelist, err := events.NewRepoWhitelistChecker(userConfig.RepoWhitelist)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
locksController := &LocksController{
|
||||
AtlantisVersion: config.AtlantisVersion,
|
||||
|
||||
@@ -118,7 +118,8 @@ func TestHealthz(t *testing.T) {
|
||||
|
||||
func responseContains(t *testing.T, r *httptest.ResponseRecorder, status int, bodySubstr string) {
|
||||
t.Helper()
|
||||
Equals(t, status, r.Result().StatusCode)
|
||||
body, _ := ioutil.ReadAll(r.Result().Body)
|
||||
body, err := ioutil.ReadAll(r.Result().Body)
|
||||
Ok(t, err)
|
||||
Assert(t, status == r.Result().StatusCode, "exp %d got %d, body: %s", status, r.Result().StatusCode, string(body))
|
||||
Assert(t, strings.Contains(string(body), bodySubstr), "exp %q to be contained in %q", bodySubstr, string(body))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user