Skip to content

Commit fa43feb

Browse files
authored
Gitlab (#190)
Gitlab initial implementation
1 parent dd39715 commit fa43feb

File tree

121 files changed

+15721
-1021
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+15721
-1021
lines changed

Gopkg.lock

+7-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

+4
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,7 @@
8888
[[constraint]]
8989
branch = "v2"
9090
name = "gopkg.in/yaml.v2"
91+
92+
[[constraint]]
93+
branch = "master"
94+
name = "github.com/lkysow/go-gitlab"

cmd/root.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Package cmd holds all our cli commands.
2-
// These are different from the commands that get run via GitHub comments
2+
// These are different from the commands that get run via pull request comments.
33
package cmd
44

55
import (

cmd/server.go

+53-13
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ const (
2525
GHTokenFlag = "gh-token"
2626
GHUserFlag = "gh-user"
2727
GHWebHookSecret = "gh-webhook-secret"
28+
GitlabHostnameFlag = "gitlab-hostname"
29+
GitlabTokenFlag = "gitlab-token"
30+
GitlabUserFlag = "gitlab-user"
31+
GitlabWebHookSecret = "gitlab-webhook-secret"
2832
LogLevelFlag = "log-level"
2933
PortFlag = "port"
3034
RequireApprovalFlag = "require-approval"
@@ -49,19 +53,42 @@ var stringFlags = []stringFlag{
4953
description: "Hostname of your Github Enterprise installation. If using github.com, no need to set.",
5054
value: "github.com",
5155
},
56+
{
57+
name: GHUserFlag,
58+
description: "GitHub username of API user.",
59+
},
5260
{
5361
name: GHTokenFlag,
54-
description: "[REQUIRED] GitHub token of API user. Can also be specified via the ATLANTIS_GH_TOKEN environment variable.",
62+
description: "GitHub token of API user. Can also be specified via the ATLANTIS_GH_TOKEN environment variable.",
5563
env: "ATLANTIS_GH_TOKEN",
5664
},
5765
{
58-
name: GHUserFlag,
59-
description: "[REQUIRED] GitHub username of API user.",
66+
name: GHWebHookSecret,
67+
description: "Optional secret used to validate GitHub webhooks (see https://developer.github.com/webhooks/securing/)." +
68+
" If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitHub. " +
69+
"Can also be specified via the ATLANTIS_GH_WEBHOOK_SECRET environment variable.",
70+
env: "ATLANTIS_GH_WEBHOOK_SECRET",
71+
},
72+
{
73+
name: GitlabHostnameFlag,
74+
description: "Hostname of your GitLab Enterprise installation. If using gitlab.com, no need to set.",
75+
value: "gitlab.com",
6076
},
6177
{
62-
name: GHWebHookSecret,
63-
description: "Optional secret used for GitHub webhooks (see https://developer.github.com/webhooks/securing/). If not specified, Atlantis won't validate the incoming webhook call.",
64-
env: "ATLANTIS_GH_WEBHOOK_SECRET",
78+
name: GitlabUserFlag,
79+
description: "GitLab username of API user.",
80+
},
81+
{
82+
name: GitlabTokenFlag,
83+
description: "GitLab token of API user. Can also be specified via the ATLANTIS_GITLAB_TOKEN environment variable.",
84+
env: "ATLANTIS_GITLAB_TOKEN",
85+
},
86+
{
87+
name: GitlabWebHookSecret,
88+
description: "Optional secret used to validate GitLab webhooks." +
89+
" If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitLab. " +
90+
"Can also be specified via the ATLANTIS_GITLAB_WEBHOOK_SECRET environment variable.",
91+
env: "ATLANTIS_GITLAB_WEBHOOK_SECRET",
6592
},
6693
{
6794
name: LogLevelFlag,
@@ -206,7 +233,7 @@ func (s *ServerCmd) run() error {
206233
if err := setDataDir(&config); err != nil {
207234
return err
208235
}
209-
sanitizeGithubUser(&config)
236+
trimAtSymbolFromUsers(&config)
210237

211238
// Config looks good. Start the server.
212239
server, err := s.ServerCreator.NewServer(config)
@@ -221,11 +248,23 @@ func validate(config server.Config) error {
221248
if logLevel != "debug" && logLevel != "info" && logLevel != "warn" && logLevel != "error" {
222249
return errors.New("invalid log level: not one of debug, info, warn, error")
223250
}
224-
if config.GithubUser == "" {
225-
return fmt.Errorf("--%s must be set", GHUserFlag)
251+
vcsErr := fmt.Errorf("--%s/--%s or --%s/--%s must be set", GHUserFlag, GHTokenFlag, GitlabUserFlag, GitlabTokenFlag)
252+
253+
// The following combinations are valid.
254+
// 1. github user and token
255+
// 2. gitlab user and token
256+
// 3. all 4 set
257+
// We validate using contradiction (I think).
258+
if config.GithubUser != "" && config.GithubToken == "" || config.GithubToken != "" && config.GithubUser == "" {
259+
return vcsErr
260+
}
261+
if config.GitlabUser != "" && config.GitlabToken == "" || config.GitlabToken != "" && config.GitlabUser == "" {
262+
return vcsErr
226263
}
227-
if config.GithubToken == "" {
228-
return fmt.Errorf("--%s must be set", GHTokenFlag)
264+
// At this point, we know that there can't be a single user/token without
265+
// its pair, but we haven't checked if any user/token is set at all.
266+
if config.GithubUser == "" && config.GitlabUser == "" {
267+
return vcsErr
229268
}
230269
return nil
231270
}
@@ -256,9 +295,10 @@ func setDataDir(config *server.Config) error {
256295
return nil
257296
}
258297

259-
// sanitizeGithubUser trims @ from the front of the github username if it exists.
260-
func sanitizeGithubUser(config *server.Config) {
298+
// trimAtSymbolFromUsers trims @ from the front of the github and gitlab usernames
299+
func trimAtSymbolFromUsers(config *server.Config) {
261300
config.GithubUser = strings.TrimPrefix(config.GithubUser, "@")
301+
config.GitlabUser = strings.TrimPrefix(config.GitlabUser, "@")
262302
}
263303

264304
// withErrPrint prints out any errors to a terminal in red.

cmd/server_test.go

+138-17
Original file line numberDiff line numberDiff line change
@@ -90,57 +90,131 @@ func TestExecute_InvalidConfig(t *testing.T) {
9090
Assert(t, strings.Contains(err.Error(), "unmarshal errors"), "should be an unmarshal error")
9191
}
9292

93-
func TestExecute_Validation(t *testing.T) {
93+
func TestExecute_ValidateLogLevel(t *testing.T) {
94+
t.Log("Should validate log level.")
95+
c := setup(map[string]interface{}{
96+
cmd.LogLevelFlag: "invalid",
97+
cmd.GHUserFlag: "user",
98+
cmd.GHTokenFlag: "token",
99+
})
100+
err := c.Execute()
101+
Assert(t, err != nil, "should be an error")
102+
Equals(t, "invalid log level: not one of debug, info, warn, error", err.Error())
103+
}
104+
105+
func TestExecute_ValidateVCSConfig(t *testing.T) {
106+
expErr := "--gh-user/--gh-token or --gitlab-user/--gitlab-token must be set"
94107
cases := []struct {
95108
description string
96109
flags map[string]interface{}
97-
expErr string
110+
expectError bool
98111
}{
99112
{
100-
"Should validate log level.",
113+
"no config set",
114+
nil,
115+
true,
116+
},
117+
{
118+
"just github token set",
101119
map[string]interface{}{
102-
cmd.LogLevelFlag: "invalid",
103-
cmd.GHUserFlag: "user",
104-
cmd.GHTokenFlag: "token",
120+
cmd.GHTokenFlag: "token",
105121
},
106-
"invalid log level: not one of debug, info, warn, error",
122+
true,
107123
},
108124
{
109-
"Should ensure github user is set.",
125+
"just gitlab token set",
110126
map[string]interface{}{
111-
cmd.GHTokenFlag: "token",
127+
cmd.GitlabTokenFlag: "token",
112128
},
113-
"--gh-user must be set",
129+
true,
114130
},
115131
{
116-
"Should ensure github token is set.",
132+
"just github user set",
117133
map[string]interface{}{
118134
cmd.GHUserFlag: "user",
119135
},
120-
"--gh-token must be set",
136+
true,
137+
},
138+
{
139+
"just gitlab user set",
140+
map[string]interface{}{
141+
cmd.GitlabUserFlag: "user",
142+
},
143+
true,
144+
},
145+
{
146+
"github user and gitlab token set",
147+
map[string]interface{}{
148+
cmd.GHUserFlag: "user",
149+
cmd.GitlabTokenFlag: "token",
150+
},
151+
true,
152+
},
153+
{
154+
"gitlab user and github token set",
155+
map[string]interface{}{
156+
cmd.GitlabUserFlag: "user",
157+
cmd.GHTokenFlag: "token",
158+
},
159+
true,
160+
},
161+
{
162+
"github user and github token set and should be successful",
163+
map[string]interface{}{
164+
cmd.GHUserFlag: "user",
165+
cmd.GHTokenFlag: "token",
166+
},
167+
false,
168+
},
169+
{
170+
"gitlab user and gitlab token set and should be successful",
171+
map[string]interface{}{
172+
cmd.GitlabUserFlag: "user",
173+
cmd.GitlabTokenFlag: "token",
174+
},
175+
false,
176+
},
177+
{
178+
"github and gitlab user and github and gitlab token set and should be successful",
179+
map[string]interface{}{
180+
cmd.GHUserFlag: "user",
181+
cmd.GHTokenFlag: "token",
182+
cmd.GitlabUserFlag: "user",
183+
cmd.GitlabTokenFlag: "token",
184+
},
185+
false,
121186
},
122187
}
123188
for _, testCase := range cases {
124-
t.Log(testCase.description)
189+
t.Log("Should validate vcs config when " + testCase.description)
125190
c := setup(testCase.flags)
126191
err := c.Execute()
127-
Assert(t, err != nil, "should be an error")
128-
Equals(t, testCase.expErr, err.Error())
192+
if testCase.expectError {
193+
Assert(t, err != nil, "should be an error")
194+
Equals(t, expErr, err.Error())
195+
} else {
196+
Ok(t, err)
197+
}
129198
}
130199
}
131200

132201
func TestExecute_Defaults(t *testing.T) {
133202
t.Log("Should set the defaults for all unspecified flags.")
134203
c := setup(map[string]interface{}{
135-
cmd.GHUserFlag: "user",
136-
cmd.GHTokenFlag: "token",
204+
cmd.GHUserFlag: "user",
205+
cmd.GHTokenFlag: "token",
206+
cmd.GitlabUserFlag: "gitlab-user",
207+
cmd.GitlabTokenFlag: "gitlab-token",
137208
})
138209
err := c.Execute()
139210
Ok(t, err)
140211

141212
Equals(t, "user", passedConfig.GithubUser)
142213
Equals(t, "token", passedConfig.GithubToken)
143214
Equals(t, "", passedConfig.GithubWebHookSecret)
215+
Equals(t, "gitlab-user", passedConfig.GitlabUser)
216+
Equals(t, "gitlab-token", passedConfig.GitlabToken)
217+
Equals(t, "", passedConfig.GitlabWebHookSecret)
144218
// Get our hostname since that's what gets defaulted to
145219
hostname, err := os.Hostname()
146220
Ok(t, err)
@@ -151,6 +225,7 @@ func TestExecute_Defaults(t *testing.T) {
151225
Ok(t, err)
152226
Equals(t, dataDir, passedConfig.DataDir)
153227
Equals(t, "github.com", passedConfig.GithubHostname)
228+
Equals(t, "gitlab.com", passedConfig.GitlabHostname)
154229
Equals(t, "info", passedConfig.LogLevel)
155230
Equals(t, false, passedConfig.RequireApproval)
156231
Equals(t, 4141, passedConfig.Port)
@@ -183,6 +258,18 @@ func TestExecute_GithubUser(t *testing.T) {
183258
Equals(t, "user", passedConfig.GithubUser)
184259
}
185260

261+
func TestExecute_GitlabUser(t *testing.T) {
262+
t.Log("Should remove the @ from the gitlab username if it's passed.")
263+
c := setup(map[string]interface{}{
264+
cmd.GitlabUserFlag: "@user",
265+
cmd.GitlabTokenFlag: "token",
266+
})
267+
err := c.Execute()
268+
Ok(t, err)
269+
270+
Equals(t, "user", passedConfig.GitlabUser)
271+
}
272+
186273
func TestExecute_Flags(t *testing.T) {
187274
t.Log("Should use all flags that are set.")
188275
c := setup(map[string]interface{}{
@@ -192,6 +279,10 @@ func TestExecute_Flags(t *testing.T) {
192279
cmd.GHUserFlag: "user",
193280
cmd.GHTokenFlag: "token",
194281
cmd.GHWebHookSecret: "secret",
282+
cmd.GitlabHostnameFlag: "gitlab-hostname",
283+
cmd.GitlabUserFlag: "gitlab-user",
284+
cmd.GitlabTokenFlag: "gitlab-token",
285+
cmd.GitlabWebHookSecret: "gitlab-secret",
195286
cmd.LogLevelFlag: "debug",
196287
cmd.PortFlag: 8181,
197288
cmd.RequireApprovalFlag: true,
@@ -205,6 +296,10 @@ func TestExecute_Flags(t *testing.T) {
205296
Equals(t, "user", passedConfig.GithubUser)
206297
Equals(t, "token", passedConfig.GithubToken)
207298
Equals(t, "secret", passedConfig.GithubWebHookSecret)
299+
Equals(t, "gitlab-hostname", passedConfig.GitlabHostname)
300+
Equals(t, "gitlab-user", passedConfig.GitlabUser)
301+
Equals(t, "gitlab-token", passedConfig.GitlabToken)
302+
Equals(t, "gitlab-secret", passedConfig.GitlabWebHookSecret)
208303
Equals(t, "debug", passedConfig.LogLevel)
209304
Equals(t, 8181, passedConfig.Port)
210305
Equals(t, true, passedConfig.RequireApproval)
@@ -219,6 +314,10 @@ gh-hostname: "ghhostname"
219314
gh-user: "user"
220315
gh-token: "token"
221316
gh-webhook-secret: "secret"
317+
gitlab-hostname: "gitlab-hostname"
318+
gitlab-user: "gitlab-user"
319+
gitlab-token: "gitlab-token"
320+
gitlab-webhook-secret: "gitlab-secret"
222321
log-level: "debug"
223322
port: 8181
224323
require-approval: true`)
@@ -235,6 +334,10 @@ require-approval: true`)
235334
Equals(t, "user", passedConfig.GithubUser)
236335
Equals(t, "token", passedConfig.GithubToken)
237336
Equals(t, "secret", passedConfig.GithubWebHookSecret)
337+
Equals(t, "gitlab-hostname", passedConfig.GitlabHostname)
338+
Equals(t, "gitlab-user", passedConfig.GitlabUser)
339+
Equals(t, "gitlab-token", passedConfig.GitlabToken)
340+
Equals(t, "gitlab-secret", passedConfig.GitlabWebHookSecret)
238341
Equals(t, "debug", passedConfig.LogLevel)
239342
Equals(t, 8181, passedConfig.Port)
240343
Equals(t, true, passedConfig.RequireApproval)
@@ -279,6 +382,24 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
279382
Equals(t, "override", passedConfig.GithubToken)
280383
}
281384

385+
func TestExecute_EnvVars(t *testing.T) {
386+
t.Log("Setting flags by env var should work.")
387+
os.Setenv("ATLANTIS_GH_TOKEN", "gh-token") // nolint: errcheck
388+
os.Setenv("ATLANTIS_GH_WEBHOOK_SECRET", "gh-webhook") // nolint: errcheck
389+
os.Setenv("ATLANTIS_GITLAB_TOKEN", "gitlab-token") // nolint: errcheck
390+
os.Setenv("ATLANTIS_GITLAB_WEBHOOK_SECRET", "gitlab-webhook") // nolint: errcheck
391+
c := setup(map[string]interface{}{
392+
cmd.GHUserFlag: "user",
393+
cmd.GitlabUserFlag: "user",
394+
})
395+
err := c.Execute()
396+
Ok(t, err)
397+
Equals(t, "gh-token", passedConfig.GithubToken)
398+
Equals(t, "gh-webhook", passedConfig.GithubWebHookSecret)
399+
Equals(t, "gitlab-token", passedConfig.GitlabToken)
400+
Equals(t, "gitlab-webhook", passedConfig.GitlabWebHookSecret)
401+
}
402+
282403
func setup(flags map[string]interface{}) *cobra.Command {
283404
viper := viper.New()
284405
for k, v := range flags {

0 commit comments

Comments
 (0)