codeclimate-services 1.6.1 → 1.7.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +1 -0
  4. data/Gemfile +1 -2
  5. data/Rakefile +4 -7
  6. data/base_rubocop.yml +152 -0
  7. data/bin/bundler +5 -5
  8. data/bin/coderay +5 -5
  9. data/bin/nokogiri +5 -5
  10. data/bin/pry +5 -5
  11. data/bin/rake +5 -5
  12. data/codeclimate-services.gemspec +15 -15
  13. data/config/load.rb +2 -2
  14. data/lib/cc/formatters/linked_formatter.rb +2 -2
  15. data/lib/cc/formatters/snapshot_formatter.rb +10 -10
  16. data/lib/cc/formatters/ticket_formatter.rb +0 -2
  17. data/lib/cc/helpers/quality_helper.rb +2 -2
  18. data/lib/cc/helpers/vulnerability_helper.rb +0 -2
  19. data/lib/cc/presenters/pull_requests_presenter.rb +1 -5
  20. data/lib/cc/pull_requests.rb +7 -3
  21. data/lib/cc/service.rb +9 -10
  22. data/lib/cc/service/formatter.rb +3 -3
  23. data/lib/cc/service/helper.rb +2 -3
  24. data/lib/cc/service/http.rb +9 -9
  25. data/lib/cc/service/invocation.rb +6 -6
  26. data/lib/cc/service/invocation/with_error_handling.rb +9 -8
  27. data/lib/cc/service/invocation/with_metrics.rb +4 -4
  28. data/lib/cc/service/invocation/with_return_values.rb +0 -1
  29. data/lib/cc/service/response_check.rb +4 -5
  30. data/lib/cc/services.rb +2 -2
  31. data/lib/cc/services/asana.rb +8 -9
  32. data/lib/cc/services/campfire.rb +2 -3
  33. data/lib/cc/services/flowdock.rb +5 -5
  34. data/lib/cc/services/github_issues.rb +6 -7
  35. data/lib/cc/services/github_pull_requests.rb +42 -5
  36. data/lib/cc/services/gitlab_merge_requests.rb +6 -2
  37. data/lib/cc/services/hipchat.rb +3 -4
  38. data/lib/cc/services/jira.rb +8 -9
  39. data/lib/cc/services/lighthouse.rb +4 -5
  40. data/lib/cc/services/pivotal_tracker.rb +6 -7
  41. data/lib/cc/services/slack.rb +8 -8
  42. data/lib/cc/services/stash_pull_requests.rb +2 -2
  43. data/lib/cc/services/version.rb +1 -1
  44. data/pull_request_test.rb +11 -10
  45. data/service_test.rb +5 -5
  46. data/spec/axiom/types/password_spec.rb +14 -0
  47. data/spec/cc/formatters/snapshot_formatter_spec.rb +44 -0
  48. data/spec/cc/presenters/pull_requests_presenter_spec.rb +45 -0
  49. data/{test/asana_test.rb → spec/cc/service/asana_spec.rb} +27 -29
  50. data/{test/campfire_test.rb → spec/cc/service/campfire_spec.rb} +40 -44
  51. data/{test/flowdock_test.rb → spec/cc/service/flowdock_spec.rb} +46 -48
  52. data/{test/github_issues_test.rb → spec/cc/service/github_issues_spec.rb} +33 -35
  53. data/spec/cc/service/github_pull_requests_spec.rb +223 -0
  54. data/{test/gitlab_merge_requests_test.rb → spec/cc/service/gitlab_merge_requests_spec.rb} +30 -35
  55. data/{test/hipchat_test.rb → spec/cc/service/hipchat_spec.rb} +38 -40
  56. data/spec/cc/service/invocation/error_handling_spec.rb +49 -0
  57. data/spec/cc/service/invocation/return_values_spec.rb +19 -0
  58. data/spec/cc/service/invocation/with_metrics_spec.rb +18 -0
  59. data/{test/invocation_test.rb → spec/cc/service/invocation_spec.rb} +31 -34
  60. data/{test/jira_test.rb → spec/cc/service/jira_spec.rb} +25 -27
  61. data/{test/lighthouse_test.rb → spec/cc/service/lighthouse_spec.rb} +23 -26
  62. data/spec/cc/service/pivotal_tracker_spec.rb +70 -0
  63. data/{test/slack_test.rb → spec/cc/service/slack_spec.rb} +66 -77
  64. data/spec/cc/service/stash_pull_requests_spec.rb +132 -0
  65. data/spec/cc/service_spec.rb +78 -0
  66. data/{test → spec}/fixtures.rb +3 -4
  67. data/spec/spec_helper.rb +37 -0
  68. data/{test → spec}/support/fake_logger.rb +0 -0
  69. data/spec/support/service_context.rb +42 -0
  70. metadata +57 -52
  71. data/test/axiom/types/password_test.rb +0 -22
  72. data/test/formatters/snapshot_formatter_test.rb +0 -47
  73. data/test/github_pull_requests_test.rb +0 -217
  74. data/test/helper.rb +0 -58
  75. data/test/invocation_error_handling_test.rb +0 -51
  76. data/test/invocation_return_values_test.rb +0 -21
  77. data/test/pivotal_tracker_test.rb +0 -73
  78. data/test/presenters/pull_requests_presenter_test.rb +0 -70
  79. data/test/service_test.rb +0 -84
  80. data/test/stash_pull_requests_test.rb +0 -146
  81. data/test/with_metrics_test.rb +0 -19
@@ -7,14 +7,14 @@ class CC::Service::Flowdock < CC::Service
7
7
  validates :api_token, presence: true
8
8
  end
9
9
 
10
- BASE_URL = "https://api.flowdock.com/v1"
10
+ BASE_URL = "https://api.flowdock.com/v1".freeze
11
11
  INVALID_PROJECT_CHARACTERS = /[^0-9a-z\-_ ]+/i
12
12
 
13
13
  self.description = "Send messages to a Flowdock inbox"
14
14
 
15
15
  def receive_test
16
16
  notify("Test", repo_name, formatter.format_test).merge(
17
- message: "Test message sent"
17
+ message: "Test message sent",
18
18
  )
19
19
  end
20
20
 
@@ -37,7 +37,7 @@ class CC::Service::Flowdock < CC::Service
37
37
  self,
38
38
  prefix: "",
39
39
  prefix_with_repo: false,
40
- link_style: :html
40
+ link_style: :html,
41
41
  )
42
42
  end
43
43
 
@@ -48,9 +48,9 @@ class CC::Service::Flowdock < CC::Service
48
48
  from_name: "Code Climate",
49
49
  format: "html",
50
50
  subject: subject,
51
- project: project.gsub(INVALID_PROJECT_CHARACTERS, ''),
51
+ project: project.gsub(INVALID_PROJECT_CHARACTERS, ""),
52
52
  content: content,
53
- link: "https://codeclimate.com"
53
+ link: "https://codeclimate.com",
54
54
  }
55
55
 
56
56
  url = "#{BASE_URL}/messages/team_inbox/#{config.api_token}"
@@ -24,7 +24,7 @@ class CC::Service::GitHubIssues < CC::Service
24
24
  def receive_test
25
25
  result = create_issue("Test ticket from Code Climate", "")
26
26
  result.merge(
27
- message: "Issue <a href='#{result[:url]}'>##{result[:number]}</a> created."
27
+ message: "Issue <a href='#{result[:url]}'>##{result[:number]}</a> created.",
28
28
  )
29
29
  rescue CC::Service::HTTPError => e
30
30
  body = JSON.parse(e.response_body)
@@ -41,19 +41,19 @@ class CC::Service::GitHubIssues < CC::Service
41
41
 
42
42
  create_issue(
43
43
  formatter.format_vulnerability_title,
44
- formatter.format_vulnerability_body
44
+ formatter.format_vulnerability_body,
45
45
  )
46
46
  end
47
47
 
48
48
  def receive_issue
49
- title = %{Fix "#{issue["check_name"]}" issue in #{constant_name}}
49
+ title = %(Fix "#{issue["check_name"]}" issue in #{constant_name})
50
50
 
51
51
  body = [issue["description"], details_url].join("\n\n")
52
52
 
53
53
  create_issue(title, body)
54
54
  end
55
55
 
56
- private
56
+ private
57
57
 
58
58
  def create_issue(title, issue_body)
59
59
  params = { title: title, body: issue_body }
@@ -67,14 +67,13 @@ private
67
67
  http.headers["User-Agent"] = "Code Climate"
68
68
 
69
69
  url = "#{config.base_url}/repos/#{config.project}/issues"
70
- service_post(url, params.to_json) do |response|
70
+ service_post_with_redirects(url, params.to_json) do |response|
71
71
  body = JSON.parse(response.body)
72
72
  {
73
73
  id: body["id"],
74
74
  number: body["number"],
75
- url: body["html_url"]
75
+ url: body["html_url"],
76
76
  }
77
77
  end
78
78
  end
79
-
80
79
  end
@@ -13,6 +13,12 @@ class CC::Service::GitHubPullRequests < CC::PullRequests
13
13
  label: "Github Context",
14
14
  description: "The integration name next to the pull request status",
15
15
  default: "codeclimate"
16
+ attribute :rollout_usernames, Axiom::Types::String,
17
+ label: "Allowed Author's Usernames",
18
+ description: "The GitHub usernames of authors to report status for, comma separated"
19
+ attribute :rollout_percentage, Axiom::Types::Integer,
20
+ label: "Author Rollout Percentage",
21
+ description: "The percentage of users to report status for"
16
22
 
17
23
  validates :oauth_token, presence: true
18
24
  end
@@ -22,6 +28,37 @@ class CC::Service::GitHubPullRequests < CC::PullRequests
22
28
 
23
29
  private
24
30
 
31
+ def report_status?
32
+ if should_apply_rollout?
33
+ rollout_allowed_by_username? || rollout_allowed_by_percentage?
34
+ else
35
+ true
36
+ end
37
+ end
38
+
39
+ def should_apply_rollout?
40
+ (github_login.present? && config.rollout_usernames.present?) ||
41
+ (github_user_id.present? && config.rollout_percentage.present?)
42
+ end
43
+
44
+ def rollout_allowed_by_username?
45
+ github_login.present? && config.rollout_usernames.present? &&
46
+ config.rollout_usernames.split(",").map(&:strip).include?(github_login)
47
+ end
48
+
49
+ def rollout_allowed_by_percentage?
50
+ github_user_id.present? && config.rollout_percentage.present? &&
51
+ github_user_id % 100 < config.rollout_percentage
52
+ end
53
+
54
+ def github_login
55
+ @payload["github_login"]
56
+ end
57
+
58
+ def github_user_id
59
+ @payload["github_user_id"]
60
+ end
61
+
25
62
  def update_status_skipped
26
63
  update_status("success", presenter.skipped_message)
27
64
  end
@@ -41,21 +78,21 @@ class CC::Service::GitHubPullRequests < CC::PullRequests
41
78
  def update_status_error
42
79
  update_status(
43
80
  "error",
44
- @payload["message"] || presenter.error_message
81
+ @payload["message"] || presenter.error_message,
45
82
  )
46
83
  end
47
84
 
48
85
  def update_status_pending
49
86
  update_status(
50
87
  "pending",
51
- @payload["message"] || presenter.pending_message
88
+ @payload["message"] || presenter.pending_message,
52
89
  )
53
90
  end
54
91
 
55
92
  def setup_http
56
- http.headers["Content-Type"] = "application/json"
93
+ http.headers["Content-Type"] = "application/json"
57
94
  http.headers["Authorization"] = "token #{config.oauth_token}"
58
- http.headers["User-Agent"] = "Code Climate"
95
+ http.headers["User-Agent"] = "Code Climate"
59
96
  end
60
97
 
61
98
  def base_status_url(commit_sha)
@@ -67,7 +104,7 @@ class CC::Service::GitHubPullRequests < CC::PullRequests
67
104
  end
68
105
 
69
106
  def response_includes_repo_scope?(response)
70
- response.headers['x-oauth-scopes'] && response.headers['x-oauth-scopes'].split(/\s*,\s*/).include?("repo")
107
+ response.headers["x-oauth-scopes"] && response.headers["x-oauth-scopes"].split(/\s*,\s*/).include?("repo")
71
108
  end
72
109
 
73
110
  def test_status_code
@@ -22,6 +22,10 @@ class CC::Service::GitlabMergeRequests < CC::PullRequests
22
22
 
23
23
  private
24
24
 
25
+ def report_status?
26
+ true
27
+ end
28
+
25
29
  def update_status_skipped
26
30
  update_status("success", presenter.skipped_message)
27
31
  end
@@ -41,14 +45,14 @@ class CC::Service::GitlabMergeRequests < CC::PullRequests
41
45
  def update_status_error
42
46
  update_status(
43
47
  "failed",
44
- @payload["message"] || presenter.error_message
48
+ @payload["message"] || presenter.error_message,
45
49
  )
46
50
  end
47
51
 
48
52
  def update_status_pending
49
53
  update_status(
50
54
  "running",
51
- @payload["message"] || presenter.pending_message
55
+ @payload["message"] || presenter.pending_message,
52
56
  )
53
57
  end
54
58
 
@@ -13,13 +13,13 @@ class CC::Service::HipChat < CC::Service
13
13
  validates :room_id, presence: true
14
14
  end
15
15
 
16
- BASE_URL = "https://api.hipchat.com/v1"
16
+ BASE_URL = "https://api.hipchat.com/v1".freeze
17
17
 
18
18
  self.description = "Send messages to a HipChat chat room"
19
19
 
20
20
  def receive_test
21
21
  speak(formatter.format_test, "green").merge(
22
- message: "Test message sent"
22
+ message: "Test message sent",
23
23
  )
24
24
  end
25
25
 
@@ -49,9 +49,8 @@ class CC::Service::HipChat < CC::Service
49
49
  auth_token: config.auth_token,
50
50
  room_id: config.room_id,
51
51
  notify: !!config.notify,
52
- color: color
52
+ color: color,
53
53
  }
54
54
  service_post(url, params)
55
55
  end
56
-
57
56
  end
@@ -1,4 +1,4 @@
1
- require 'base64'
1
+ require "base64"
2
2
 
3
3
  class CC::Service::Jira < CC::Service
4
4
  class Config < CC::Service::Config
@@ -35,7 +35,7 @@ class CC::Service::Jira < CC::Service
35
35
  def receive_test
36
36
  result = create_ticket("Test ticket from Code Climate", "Test ticket from Code Climate")
37
37
  result.merge(
38
- message: "Ticket <a href='#{result[:url]}'>#{result[:id]}</a> created."
38
+ message: "Ticket <a href='#{result[:url]}'>#{result[:id]}</a> created.",
39
39
  )
40
40
  end
41
41
 
@@ -44,7 +44,7 @@ class CC::Service::Jira < CC::Service
44
44
  end
45
45
 
46
46
  def receive_issue
47
- title = %{Fix "#{issue["check_name"]}" issue in #{constant_name}}
47
+ title = %(Fix "#{issue["check_name"]}" issue in #{constant_name})
48
48
 
49
49
  body = [issue["description"], details_url].join("\n\n")
50
50
 
@@ -56,11 +56,11 @@ class CC::Service::Jira < CC::Service
56
56
 
57
57
  create_ticket(
58
58
  formatter.format_vulnerability_title,
59
- formatter.format_vulnerability_body
59
+ formatter.format_vulnerability_body,
60
60
  )
61
61
  end
62
62
 
63
- private
63
+ private
64
64
 
65
65
  def create_ticket(title, ticket_body)
66
66
  params = {
@@ -69,8 +69,8 @@ private
69
69
  project: { id: config.project_id },
70
70
  summary: title,
71
71
  description: ticket_body,
72
- issuetype: { name: config.issue_type }
73
- }
72
+ issuetype: { name: config.issue_type },
73
+ },
74
74
  }
75
75
 
76
76
  if config.labels.present?
@@ -87,9 +87,8 @@ private
87
87
  {
88
88
  id: body["id"],
89
89
  key: body["key"],
90
- url: "https://#{config.domain}/browse/#{body["key"]}"
90
+ url: "https://#{config.domain}/browse/#{body["key"]}",
91
91
  }
92
92
  end
93
93
  end
94
-
95
94
  end
@@ -25,7 +25,7 @@ class CC::Service::Lighthouse < CC::Service
25
25
  def receive_test
26
26
  result = create_ticket("Test ticket from Code Climate", "")
27
27
  result.merge(
28
- message: "Ticket <a href='#{result[:url]}'>#{result[:id]}</a> created."
28
+ message: "Ticket <a href='#{result[:url]}'>#{result[:id]}</a> created.",
29
29
  )
30
30
  end
31
31
 
@@ -34,7 +34,7 @@ class CC::Service::Lighthouse < CC::Service
34
34
  end
35
35
 
36
36
  def receive_issue
37
- title = %{Fix "#{issue["check_name"]}" issue in #{constant_name}}
37
+ title = %(Fix "#{issue["check_name"]}" issue in #{constant_name})
38
38
 
39
39
  body = [issue["description"], details_url].join("\n\n")
40
40
 
@@ -46,11 +46,11 @@ class CC::Service::Lighthouse < CC::Service
46
46
 
47
47
  create_ticket(
48
48
  formatter.format_vulnerability_title,
49
- formatter.format_vulnerability_body
49
+ formatter.format_vulnerability_body,
50
50
  )
51
51
  end
52
52
 
53
- private
53
+ private
54
54
 
55
55
  def create_ticket(title, ticket_body)
56
56
  params = { ticket: { title: title, body: ticket_body } }
@@ -73,5 +73,4 @@ private
73
73
  }
74
74
  end
75
75
  end
76
-
77
76
  end
@@ -18,12 +18,12 @@ class CC::Service::PivotalTracker < CC::Service
18
18
  self.description = "Create stories on Pivotal Tracker"
19
19
  self.issue_tracker = true
20
20
 
21
- BASE_URL = "https://www.pivotaltracker.com/services/v3"
21
+ BASE_URL = "https://www.pivotaltracker.com/services/v3".freeze
22
22
 
23
23
  def receive_test
24
24
  result = create_story("Test ticket from Code Climate", "")
25
25
  result.merge(
26
- message: "Ticket <a href='#{result[:url]}'>#{result[:id]}</a> created."
26
+ message: "Ticket <a href='#{result[:url]}'>#{result[:id]}</a> created.",
27
27
  )
28
28
  end
29
29
 
@@ -32,7 +32,7 @@ class CC::Service::PivotalTracker < CC::Service
32
32
  end
33
33
 
34
34
  def receive_issue
35
- title = %{Fix "#{issue["check_name"]}" issue in #{constant_name}}
35
+ title = %(Fix "#{issue["check_name"]}" issue in #{constant_name})
36
36
 
37
37
  body = [issue["description"], details_url].join("\n\n")
38
38
 
@@ -44,11 +44,11 @@ class CC::Service::PivotalTracker < CC::Service
44
44
 
45
45
  create_story(
46
46
  formatter.format_vulnerability_title,
47
- formatter.format_vulnerability_body
47
+ formatter.format_vulnerability_body,
48
48
  )
49
49
  end
50
50
 
51
- private
51
+ private
52
52
 
53
53
  def create_story(name, description)
54
54
  params = {
@@ -68,9 +68,8 @@ private
68
68
  body = Nokogiri::XML(response.body)
69
69
  {
70
70
  id: (body / "story/id").text,
71
- url: (body / "story/url").text
71
+ url: (body / "story/url").text,
72
72
  }
73
73
  end
74
74
  end
75
-
76
75
  end
@@ -1,4 +1,4 @@
1
- # encoding: UTF-8
1
+ # encoding: UTF-8
2
2
 
3
3
  class CC::Service::Slack < CC::Service
4
4
  include CC::Service::QualityHelper
@@ -18,7 +18,7 @@ class CC::Service::Slack < CC::Service
18
18
  # payloads for test receivers include the weekly quality report.
19
19
  send_snapshot_to_slack(CC::Formatters::SnapshotFormatter::Sample.new(payload))
20
20
  speak(formatter.format_test).merge(
21
- message: "Test message sent"
21
+ message: "Test message sent",
22
22
  )
23
23
  end
24
24
 
@@ -45,20 +45,20 @@ class CC::Service::Slack < CC::Service
45
45
  color: color,
46
46
  fallback: message,
47
47
  fields: [{ value: message }],
48
- mrkdwn_in: ["fields", "fallback"]
49
- }]}
48
+ mrkdwn_in: %w[fields fallback],
49
+ }] }
50
50
 
51
51
  if config.channel
52
52
  params[:channel] = config.channel
53
53
  end
54
54
 
55
- http.headers['Content-Type'] = 'application/json'
55
+ http.headers["Content-Type"] = "application/json"
56
56
  url = config.webhook_url
57
57
 
58
58
  service_post(url, params.to_json) do |response|
59
59
  {
60
60
  ok: response.body == "ok",
61
- message: response.body
61
+ message: response.body,
62
62
  }
63
63
  end
64
64
  end
@@ -88,7 +88,7 @@ class CC::Service::Slack < CC::Service
88
88
 
89
89
  if constant["from"]
90
90
  from_rating = constant["from"]["rating"]
91
- to_rating = constant["to"]["rating"]
91
+ to_rating = constant["to"]["rating"]
92
92
 
93
93
  message << "• _#{object_identifier}_ just declined from #{with_article(from_rating, :bold)} to #{with_article(to_rating, :bold)}"
94
94
  else
@@ -113,7 +113,7 @@ class CC::Service::Slack < CC::Service
113
113
  constants[0..2].each do |constant|
114
114
  object_identifier = constant_basename(constant["name"])
115
115
  from_rating = constant["from"]["rating"]
116
- to_rating = constant["to"]["rating"]
116
+ to_rating = constant["to"]["rating"]
117
117
 
118
118
  message << "• _#{object_identifier}_ just improved from #{with_article(from_rating, :bold)} to #{with_article(to_rating, :bold)}"
119
119
  end
@@ -81,9 +81,9 @@ class CC::Service::StashPullRequests < CC::Service
81
81
  end
82
82
 
83
83
  def setup_http
84
- http.headers["Content-Type"] = "application/json"
84
+ http.headers["Content-Type"] = "application/json"
85
85
  http.headers["Authorization"] = "Basic #{auth_token}"
86
- http.headers["User-Agent"] = "Code Climate"
86
+ http.headers["User-Agent"] = "Code Climate"
87
87
  end
88
88
 
89
89
  # Following Basic Auth headers here:
@@ -1,5 +1,5 @@
1
1
  module CC
2
2
  module Services
3
- VERSION = "1.6.1"
3
+ VERSION = "1.7.0".freeze
4
4
  end
5
5
  end