codeclimate-services 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5df730afefd8e53147faaab840a08cc8a7b8a6e2
4
- data.tar.gz: e3228551b4e7acae238ee5da6fbb3f46ea2074e2
3
+ metadata.gz: 82a8384d2bd2085ebf3baeb02d768ab73b2a3cf0
4
+ data.tar.gz: f511465926feb0bc868dd15b8e8f83524112f7ae
5
5
  SHA512:
6
- metadata.gz: d40a0916c6ebf0d981f0731db49d25c1c748dc296efbd2d04e749b4fa848644e423cb3d157afd57dbbeeb825112be3ab525b67ca22549b27c476fb6ff84b545c
7
- data.tar.gz: a8e1a740ba27e3c743b80e4d1245d5bc6b0a72173f799608eb57c64b36a876a8f6579338176fafebcd6ef1ca85cefb0c8c6181ac2769182cc6f4fbebf2493cf6
6
+ metadata.gz: bacfd0ed0c84d297d83bc7b8e294310ff2a36a1f8bb9866d2c263a357bc2db49aeeccf3d9d2b0030689a3b2cc7ec449da103dd39052940fa715f0ed0013943c3
7
+ data.tar.gz: e7847a25fc20c03bb5543d259fdfba706a151eece343396393f88990b9aebe36b9523af64cef0258bb2ea1e2f2e732e86e4522f2ca3a9d078afe92a9e92f40db
@@ -0,0 +1,127 @@
1
+ class CC::PullRequests < CC::Service
2
+ def receive_test
3
+ setup_http
4
+
5
+ receive_test_status
6
+ end
7
+
8
+ def receive_pull_request
9
+ setup_http
10
+ state = @payload["state"]
11
+
12
+ if %w[pending success failure skipped error].include?(state)
13
+ send("update_status_#{state}")
14
+ else
15
+ @response = simple_failure("Unknown state")
16
+ end
17
+
18
+ response
19
+ end
20
+
21
+ def receive_pull_request_coverage
22
+ setup_http
23
+ state = @payload["state"]
24
+
25
+ if state == "success"
26
+ update_coverage_status_success
27
+ else
28
+ @response = simple_failure("Unknown state")
29
+ end
30
+
31
+ response
32
+ end
33
+
34
+ private
35
+
36
+ def simple_failure(message)
37
+ { ok: false, message: message }
38
+ end
39
+
40
+ def response
41
+ @response || simple_failure("Nothing happened")
42
+ end
43
+
44
+ def update_status_skipped
45
+ raise NotImplementedError
46
+ end
47
+
48
+ def update_status_success
49
+ raise NotImplementedError
50
+ end
51
+
52
+ def update_coverage_status_success
53
+ raise NotImplementedError
54
+ end
55
+
56
+ def update_status_failure
57
+ raise NotImplementedError
58
+ end
59
+
60
+ def update_status_error
61
+ raise NotImplementedError
62
+ end
63
+
64
+ def update_status_pending
65
+ raise NotImplementedError
66
+ end
67
+
68
+ def test_status_code
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def receive_test_status
73
+ url = base_status_url("0" * 40)
74
+ params = { state: "success" }
75
+ raw_post(url, params.to_json)
76
+ rescue CC::Service::HTTPError => e
77
+ if e.status == test_status_code
78
+ {
79
+ ok: true,
80
+ params: params.as_json,
81
+ status: e.status,
82
+ endpoint_url: url,
83
+ message: "Access token is valid"
84
+ }
85
+ else
86
+ raise
87
+ end
88
+ end
89
+
90
+ def presenter
91
+ CC::Service::PullRequestsPresenter.new(@payload)
92
+ end
93
+
94
+ def update_status(state, description, context = config.context)
95
+ params = {
96
+ context: context,
97
+ description: description,
98
+ state: state,
99
+ target_url: @payload["details_url"],
100
+ }
101
+ @response = service_post(status_url, params.to_json)
102
+ end
103
+
104
+ def status_url
105
+ base_status_url(commit_sha)
106
+ end
107
+
108
+ def base_status_url(_commit_sha)
109
+ raise NotImplementedError
110
+ end
111
+
112
+ def setup_http
113
+ raise NotImplementedError
114
+ end
115
+
116
+ def commit_sha
117
+ @payload.fetch("commit_sha")
118
+ end
119
+
120
+ def number
121
+ @payload.fetch("number")
122
+ end
123
+
124
+ def git_url
125
+ @git_url ||= URI.parse(@payload.fetch("git_url"))
126
+ end
127
+ end
@@ -42,13 +42,19 @@ module CC
42
42
  vulnerability
43
43
  ].freeze
44
44
 
45
+ ABSTRACT_SLUGS = %w[
46
+ pullrequests
47
+ ].freeze
48
+
45
49
  # Tracks the defined services.
46
50
  def self.services
47
51
  @services ||= []
48
52
  end
49
53
 
50
54
  def self.inherited(svc)
51
- Service.services << svc
55
+ unless ABSTRACT_SLUGS.include?(svc.slug)
56
+ Service.services << svc
57
+ end
52
58
  super
53
59
  end
54
60
 
@@ -7,3 +7,4 @@ require "active_model"
7
7
  require "active_support/core_ext"
8
8
 
9
9
  require File.expand_path('../service', __FILE__)
10
+ require File.expand_path('../pull_requests', __FILE__)
@@ -1,6 +1,6 @@
1
1
  require "cc/presenters/pull_requests_presenter"
2
2
 
3
- class CC::Service::GitHubPullRequests < CC::Service
3
+ class CC::Service::GitHubPullRequests < CC::PullRequests
4
4
  class Config < CC::Service::Config
5
5
  attribute :oauth_token, Axiom::Types::String,
6
6
  label: "OAuth Token",
@@ -20,50 +20,7 @@ class CC::Service::GitHubPullRequests < CC::Service
20
20
  self.title = "GitHub Pull Requests"
21
21
  self.description = "Update pull requests on GitHub"
22
22
 
23
- # Just make sure we can access GH using the configured token. Without
24
- # additional information (github-slug, PR number, etc) we can't test much
25
- # else.
26
- def receive_test
27
- setup_http
28
-
29
- receive_test_status
30
- end
31
-
32
- def receive_pull_request
33
- setup_http
34
- state = @payload["state"]
35
-
36
- if %w[pending success failure skipped error].include?(state)
37
- send("update_status_#{state}")
38
- else
39
- @response = simple_failure("Unknown state")
40
- end
41
-
42
- response
43
- end
44
-
45
- def receive_pull_request_coverage
46
- setup_http
47
- state = @payload["state"]
48
-
49
- if state == "success"
50
- update_coverage_status_success
51
- else
52
- @response = simple_failure("Unknown state")
53
- end
54
-
55
- response
56
- end
57
-
58
- private
59
-
60
- def simple_failure(message)
61
- { ok: false, message: message }
62
- end
63
-
64
- def response
65
- @response || simple_failure("Nothing happened")
66
- end
23
+ private
67
24
 
68
25
  def update_status_skipped
69
26
  update_status("success", presenter.skipped_message)
@@ -81,10 +38,6 @@ private
81
38
  update_status("failure", presenter.success_message)
82
39
  end
83
40
 
84
- def presenter
85
- CC::Service::PullRequestsPresenter.new(@payload)
86
- end
87
-
88
41
  def update_status_error
89
42
  update_status(
90
43
  "error",
@@ -99,66 +52,25 @@ private
99
52
  )
100
53
  end
101
54
 
102
- def update_status(state, description, context = config.context)
103
- params = {
104
- state: state,
105
- description: description,
106
- target_url: @payload["details_url"],
107
- context: context,
108
- }
109
- @response = service_post(status_url, params.to_json)
110
- end
111
-
112
- def receive_test_status
113
- url = base_status_url("0" * 40)
114
- params = {}
115
- raw_post(url, params.to_json)
116
- rescue CC::Service::HTTPError => e
117
- if e.status == 422
118
- {
119
- ok: true,
120
- params: params.as_json,
121
- status: e.status,
122
- endpoint_url: url,
123
- message: "OAuth token is valid"
124
- }
125
- else
126
- raise
127
- end
128
- end
129
-
130
55
  def setup_http
131
56
  http.headers["Content-Type"] = "application/json"
132
57
  http.headers["Authorization"] = "token #{config.oauth_token}"
133
58
  http.headers["User-Agent"] = "Code Climate"
134
59
  end
135
60
 
136
- def status_url
137
- base_status_url(commit_sha)
138
- end
139
-
140
61
  def base_status_url(commit_sha)
141
62
  "#{config.base_url}/repos/#{github_slug}/statuses/#{commit_sha}"
142
63
  end
143
64
 
144
- def user_url
145
- "#{config.base_url}/user"
146
- end
147
-
148
65
  def github_slug
149
66
  @payload.fetch("github_slug")
150
67
  end
151
68
 
152
- def commit_sha
153
- @payload.fetch("commit_sha")
154
- end
155
-
156
- def number
157
- @payload.fetch("number")
158
- end
159
-
160
69
  def response_includes_repo_scope?(response)
161
70
  response.headers['x-oauth-scopes'] && response.headers['x-oauth-scopes'].split(/\s*,\s*/).include?("repo")
162
71
  end
163
72
 
73
+ def test_status_code
74
+ 422
75
+ end
164
76
  end
@@ -0,0 +1,70 @@
1
+ require "cc/presenters/pull_requests_presenter"
2
+
3
+ class CC::Service::GitlabMergeRequests < CC::PullRequests
4
+ class Config < CC::Service::Config
5
+ attribute :access_token, Axiom::Types::String,
6
+ label: "Access Token",
7
+ description: "A personal access token with permissions for the repo."
8
+ attribute :context, Axiom::Types::String,
9
+ label: "Context",
10
+ description: "The integration name for the merge request status",
11
+ default: "codeclimate"
12
+ attribute :base_url, Axiom::Types::String,
13
+ label: "GitLab API Base URL",
14
+ description: "Base URL for the GitLab API",
15
+ default: "https://gitlab.com"
16
+ end
17
+
18
+ self.title = "GitLab Merge Requests"
19
+ self.description = "Update merge requests on GitLab"
20
+
21
+ private
22
+
23
+ def update_status_skipped
24
+ update_status("success", presenter.skipped_message)
25
+ end
26
+
27
+ def update_status_success
28
+ update_status("success", presenter.success_message)
29
+ end
30
+
31
+ def update_coverage_status_success
32
+ update_status("success", presenter.coverage_message, "#{config.context}/coverage")
33
+ end
34
+
35
+ def update_status_failure
36
+ update_status("failed", presenter.success_message)
37
+ end
38
+
39
+ def update_status_error
40
+ update_status(
41
+ "failed",
42
+ @payload["message"] || presenter.error_message
43
+ )
44
+ end
45
+
46
+ def update_status_pending
47
+ update_status(
48
+ "running",
49
+ @payload["message"] || presenter.pending_message
50
+ )
51
+ end
52
+
53
+ def setup_http
54
+ http.headers["Content-Type"] = "application/json"
55
+ http.headers["PRIVATE-TOKEN"] = config.access_token
56
+ http.headers["User-Agent"] = "Code Climate"
57
+ end
58
+
59
+ def base_status_url(commit_sha)
60
+ "#{config.base_url}/api/v3/projects/#{CGI.escape(slug)}/statuses/#{commit_sha}"
61
+ end
62
+
63
+ def slug
64
+ git_url.path.gsub(/(^\/|.git$)/, "")
65
+ end
66
+
67
+ def test_status_code
68
+ 404
69
+ end
70
+ end
@@ -1,5 +1,5 @@
1
1
  module CC
2
2
  module Services
3
- VERSION = "1.4.0"
3
+ VERSION = "1.5.0"
4
4
  end
5
5
  end
@@ -37,7 +37,7 @@ class TestGitHubPullRequests < CC::Service::TestCase
37
37
  })
38
38
 
39
39
  receive_pull_request(
40
- { },
40
+ {},
41
41
  {
42
42
  github_slug: "pbrisbin/foo",
43
43
  commit_sha: "abc123",
@@ -0,0 +1,219 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class TestGitlabMergeRequests < CC::Service::TestCase
4
+ def test_merge_request_status_pending
5
+ expect_status_update(
6
+ "hal/hal9000",
7
+ "abc123",
8
+ "state" => "running",
9
+ "description" => /is analyzing/,
10
+ )
11
+
12
+ receive_merge_request(
13
+ {},
14
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
15
+ commit_sha: "abc123",
16
+ state: "pending",
17
+ )
18
+ end
19
+
20
+ def test_merge_request_status_success_detailed
21
+ expect_status_update(
22
+ "hal/hal9000",
23
+ "abc123",
24
+ "state" => "success",
25
+ "description" => "Code Climate found 2 new issues and 1 fixed issue.",
26
+ )
27
+
28
+ receive_merge_request(
29
+ {},
30
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
31
+ commit_sha: "abc123",
32
+ state: "success",
33
+ )
34
+ end
35
+
36
+ def test_merge_request_status_failure
37
+ expect_status_update(
38
+ "hal/hal9000",
39
+ "abc123",
40
+ "state" => "failed",
41
+ "description" => "Code Climate found 2 new issues and 1 fixed issue.",
42
+ )
43
+
44
+ receive_merge_request(
45
+ {},
46
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
47
+ commit_sha: "abc123",
48
+ state: "failure",
49
+ )
50
+ end
51
+
52
+ def test_merge_request_status_error
53
+ expect_status_update(
54
+ "hal/hal9000",
55
+ "abc123",
56
+ "state" => "failed",
57
+ "description" => "Code Climate encountered an error attempting to analyze this pull request.",
58
+ )
59
+
60
+ receive_merge_request(
61
+ {},
62
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
63
+ commit_sha: "abc123",
64
+ state: "error",
65
+ message: nil,
66
+ )
67
+ end
68
+
69
+ def test_merge_request_status_error_message_provided
70
+ expect_status_update(
71
+ "hal/hal9000",
72
+ "abc123",
73
+ "state" => "failed",
74
+ "description" => "I'm sorry Dave, I'm afraid I can't do that",
75
+ )
76
+
77
+ receive_merge_request(
78
+ {},
79
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
80
+ commit_sha: "abc123",
81
+ state: "error",
82
+ message: "I'm sorry Dave, I'm afraid I can't do that",
83
+ )
84
+ end
85
+
86
+ def test_merge_request_status_skipped
87
+ expect_status_update(
88
+ "hal/hal9000",
89
+ "abc123",
90
+ "state" => "success",
91
+ "description" => /skipped analysis/,
92
+ )
93
+
94
+ receive_merge_request(
95
+ {},
96
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
97
+ commit_sha: "abc123",
98
+ state: "skipped",
99
+ )
100
+ end
101
+
102
+ def test_merge_request_coverage_status_success
103
+ expect_status_update(
104
+ "hal/hal9000",
105
+ "abc123",
106
+ "state" => "success",
107
+ "description" => "87% test coverage (+2%)",
108
+ )
109
+
110
+ receive_merge_request_coverage(
111
+ {},
112
+ git_url: "ssh://git@gitlab.com/hal/hal9000.git",
113
+ commit_sha: "abc123",
114
+ state: "success",
115
+ covered_percent: 87,
116
+ covered_percent_delta: 2.0,
117
+ )
118
+ end
119
+
120
+ def test_merge_request_status_test_success
121
+ @stubs.post("api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}") { |env| [404, {}, ""] }
122
+
123
+ assert receive_test({}, { git_url: "ssh://git@gitlab.com/hal/hal9000.git" })[:ok], "Expected test of pull request to be true"
124
+ end
125
+
126
+ def test_merge_request_status_test_failure
127
+ @stubs.post("api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}") { |env| [401, {}, ""] }
128
+
129
+ assert_raises(CC::Service::HTTPError) do
130
+ receive_test({}, { git_url: "ssh://git@gitlab.com/hal/hal9000.git" })
131
+ end
132
+ end
133
+
134
+ def test_merge_request_unknown_state
135
+ response = receive_merge_request({}, { state: "unknown" })
136
+
137
+ assert_equal({ ok: false, message: "Unknown state" }, response)
138
+ end
139
+
140
+ def test_different_base_url
141
+ @stubs.post("api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}") do |env|
142
+ assert env[:url].to_s == "https://gitlab.hal.org/api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}"
143
+ [404, {}, ""]
144
+ end
145
+
146
+ assert receive_test({ base_url: "https://gitlab.hal.org" }, { git_url: "ssh://git@gitlab.com/hal/hal9000.git" })[:ok], "Expected test of pull request to be true"
147
+ end
148
+
149
+ def test_different_context
150
+ expect_status_update(
151
+ "gordondiggs/ellis",
152
+ "abc123",
153
+ "context" => "sup",
154
+ "state" => "running",
155
+ )
156
+
157
+ response = receive_merge_request(
158
+ { context: "sup" },
159
+ git_url: "https://gitlab.com/gordondiggs/ellis.git",
160
+ commit_sha: "abc123",
161
+ state: "pending",
162
+ )
163
+ end
164
+
165
+ def test_default_context
166
+ expect_status_update(
167
+ "gordondiggs/ellis",
168
+ "abc123",
169
+ "context" => "codeclimate",
170
+ "state" => "running",
171
+ )
172
+
173
+ response = receive_merge_request(
174
+ {},
175
+ git_url: "https://gitlab.com/gordondiggs/ellis.git",
176
+ commit_sha: "abc123",
177
+ state: "pending",
178
+ )
179
+ end
180
+
181
+ private
182
+
183
+ def expect_status_update(repo, commit_sha, params)
184
+ @stubs.post "api/v3/projects/#{CGI.escape(repo)}/statuses/#{commit_sha}" do |env|
185
+ assert_equal "123", env[:request_headers]["PRIVATE-TOKEN"]
186
+
187
+ body = JSON.parse(env[:body])
188
+
189
+ params.each do |k, v|
190
+ assert v === body[k],
191
+ "Unexpected value for #{k}. #{v.inspect} !== #{body[k].inspect}"
192
+ end
193
+ end
194
+ end
195
+
196
+ def receive_merge_request(config, event_data)
197
+ receive(
198
+ CC::Service::GitlabMergeRequests,
199
+ { access_token: "123" }.merge(config),
200
+ { name: "pull_request", issue_comparison_counts: {'fixed' => 1, 'new' => 2} }.merge(event_data)
201
+ )
202
+ end
203
+
204
+ def receive_merge_request_coverage(config, event_data)
205
+ receive(
206
+ CC::Service::GitlabMergeRequests,
207
+ { access_token: "123" }.merge(config),
208
+ { name: "pull_request_coverage", issue_comparison_counts: {'fixed' => 1, 'new' => 2} }.merge(event_data)
209
+ )
210
+ end
211
+
212
+ def receive_test(config, event_data = {})
213
+ receive(
214
+ CC::Service::GitlabMergeRequests,
215
+ { oauth_token: "123" }.merge(config),
216
+ { name: "test", issue_comparison_counts: {'fixed' => 1, 'new' => 2} }.merge(event_data)
217
+ )
218
+ end
219
+ end
@@ -75,4 +75,10 @@ class TestService < CC::Service::TestCase
75
75
  service_post("/my/wrong/url", {token: "1234"}.to_json, {})
76
76
  end
77
77
  end
78
+
79
+ def test_services
80
+ services = CC::Service.services
81
+
82
+ assert !services.include?(CC::PullRequests)
83
+ end
78
84
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeclimate-services
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Helmkamp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-11 00:00:00.000000000 Z
11
+ date: 2016-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -168,6 +168,7 @@ files:
168
168
  - lib/cc/helpers/quality_helper.rb
169
169
  - lib/cc/helpers/vulnerability_helper.rb
170
170
  - lib/cc/presenters/pull_requests_presenter.rb
171
+ - lib/cc/pull_requests.rb
171
172
  - lib/cc/service.rb
172
173
  - lib/cc/service/config.rb
173
174
  - lib/cc/service/formatter.rb
@@ -186,6 +187,7 @@ files:
186
187
  - lib/cc/services/flowdock.rb
187
188
  - lib/cc/services/github_issues.rb
188
189
  - lib/cc/services/github_pull_requests.rb
190
+ - lib/cc/services/gitlab_merge_requests.rb
189
191
  - lib/cc/services/hipchat.rb
190
192
  - lib/cc/services/jira.rb
191
193
  - lib/cc/services/lighthouse.rb
@@ -203,6 +205,7 @@ files:
203
205
  - test/formatters/snapshot_formatter_test.rb
204
206
  - test/github_issues_test.rb
205
207
  - test/github_pull_requests_test.rb
208
+ - test/gitlab_merge_requests_test.rb
206
209
  - test/helper.rb
207
210
  - test/hipchat_test.rb
208
211
  - test/invocation_error_handling_test.rb
@@ -237,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
240
  version: '0'
238
241
  requirements: []
239
242
  rubyforge_project:
240
- rubygems_version: 2.5.1
243
+ rubygems_version: 2.4.5
241
244
  signing_key:
242
245
  specification_version: 4
243
246
  summary: Service classes for Code Climate
@@ -250,6 +253,7 @@ test_files:
250
253
  - test/formatters/snapshot_formatter_test.rb
251
254
  - test/github_issues_test.rb
252
255
  - test/github_pull_requests_test.rb
256
+ - test/gitlab_merge_requests_test.rb
253
257
  - test/helper.rb
254
258
  - test/hipchat_test.rb
255
259
  - test/invocation_error_handling_test.rb