caperoma 0.1.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -0
  3. data/Capefile +48 -0
  4. data/Capefile.template +48 -0
  5. data/Capefile.test +20 -0
  6. data/Gemfile +25 -10
  7. data/Gemfile.lock +196 -77
  8. data/HELP +321 -0
  9. data/README.md +528 -0
  10. data/Rakefile +73 -18
  11. data/VERSION +1 -1
  12. data/bin/caperoma +47 -11
  13. data/caperoma.gemspec +144 -45
  14. data/config/crontab +10 -0
  15. data/config/schedule.rb +21 -0
  16. data/lib/caperoma.rb +409 -9
  17. data/lib/caperoma/models/account.rb +47 -0
  18. data/lib/caperoma/models/application_record.rb +5 -0
  19. data/lib/caperoma/models/branch.rb +6 -0
  20. data/lib/caperoma/models/project.rb +14 -0
  21. data/lib/caperoma/models/property.rb +5 -0
  22. data/lib/caperoma/models/report.rb +177 -0
  23. data/lib/caperoma/models/report_recipient.rb +6 -0
  24. data/lib/caperoma/models/reports/daily_report.rb +23 -0
  25. data/lib/caperoma/models/reports/retrospective_report.rb +19 -0
  26. data/lib/caperoma/models/reports/three_day_report.rb +19 -0
  27. data/lib/caperoma/models/task.rb +368 -0
  28. data/lib/caperoma/models/tasks/bug.rb +36 -0
  29. data/lib/caperoma/models/tasks/chore.rb +40 -0
  30. data/lib/caperoma/models/tasks/feature.rb +27 -0
  31. data/lib/caperoma/models/tasks/fix.rb +56 -0
  32. data/lib/caperoma/models/tasks/meeting.rb +40 -0
  33. data/lib/caperoma/models/tasks/modules/git.rb +65 -0
  34. data/lib/caperoma/models/tasks/task_with_commit.rb +40 -0
  35. data/lib/caperoma/models/tasks/task_with_separate_branch.rb +42 -0
  36. data/lib/caperoma/services/airbrake_email_processor.rb +47 -0
  37. data/lib/caperoma/services/pivotal_fetcher.rb +108 -0
  38. data/lib/caperoma/version.rb +9 -0
  39. data/spec/caperoma_spec.rb +3 -21
  40. data/spec/factories/accounts.rb +10 -0
  41. data/spec/factories/branches.rb +9 -0
  42. data/spec/factories/projects.rb +8 -0
  43. data/spec/factories/report_recipients.rb +7 -0
  44. data/spec/factories/reports.rb +16 -0
  45. data/spec/factories/tasks.rb +37 -0
  46. data/spec/features/bug_spec.rb +60 -0
  47. data/spec/features/chore_spec.rb +60 -0
  48. data/spec/features/command_unknown_spec.rb +14 -0
  49. data/spec/features/config_spec.rb +161 -0
  50. data/spec/features/feature_spec.rb +60 -0
  51. data/spec/features/finish_spec.rb +18 -0
  52. data/spec/features/fix_spec.rb +60 -0
  53. data/spec/features/meeting_spec.rb +22 -0
  54. data/spec/features/projects_spec.rb +17 -0
  55. data/spec/features/report_recipientss_spec.rb +117 -0
  56. data/spec/features/reports_spec.rb +65 -0
  57. data/spec/features/status_spec.rb +33 -0
  58. data/spec/features/version_spec.rb +11 -0
  59. data/spec/models/account_spec.rb +51 -0
  60. data/spec/models/branch_spec.rb +8 -0
  61. data/spec/models/bug_spec.rb +33 -0
  62. data/spec/models/chore_spec.rb +33 -0
  63. data/spec/models/daily_report_spec.rb +38 -0
  64. data/spec/models/feature_spec.rb +33 -0
  65. data/spec/models/fix_spec.rb +55 -0
  66. data/spec/models/meeting_spec.rb +33 -0
  67. data/spec/models/project_spec.rb +11 -0
  68. data/spec/models/report_recipient_spec.rb +22 -0
  69. data/spec/models/report_spec.rb +16 -0
  70. data/spec/models/retrospective_report_spec.rb +38 -0
  71. data/spec/models/task_spec.rb +613 -0
  72. data/spec/models/task_with_commit_spec.rb +105 -0
  73. data/spec/models/task_with_separate_branch_spec.rb +97 -0
  74. data/spec/models/three_day_report_spec.rb +49 -0
  75. data/spec/spec_helper.rb +26 -16
  76. data/spec/support/capefile_generator.rb +36 -0
  77. data/spec/support/database_cleaner.rb +21 -0
  78. data/spec/support/stubs.rb +178 -9
  79. metadata +283 -42
  80. data/.document +0 -5
  81. data/README.rdoc +0 -26
  82. data/lib/caperoma/credentials.rb +0 -13
  83. data/lib/caperoma/jira_client.rb +0 -57
  84. data/spec/caperoma/credentials_spec.rb +0 -25
  85. data/spec/caperoma/jira_spec.rb +0 -35
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Branch < ActiveRecord::Base
4
+ belongs_to :project
5
+ has_many :tasks
6
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Project < ApplicationRecord
4
+ has_many :branches
5
+ has_many :chores
6
+ has_many :bugs
7
+ has_many :features
8
+ has_many :meetings
9
+ has_many :fixes
10
+
11
+ def folder_path
12
+ %(#{self[:folder_path]})
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Property < ApplicationRecord
4
+ validates :name, :value, presence: true
5
+ end
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Report < ApplicationRecord
4
+ include ActionView::Helpers::TextHelper
5
+ has_many :tasks
6
+
7
+ after_initialize :set_variables
8
+
9
+ after_create :assign_unreported_tasks
10
+ after_create :send_email, if: :not_test?
11
+ after_create :update_content
12
+
13
+ def self.schedule
14
+ # may screw up existing cron tasks
15
+ puts 'Turning on auto reports'
16
+ root = File.dirname __dir__
17
+ crontab_file = File.join root, 'config', 'crontab'
18
+ `crontab #{crontab_file}`
19
+ # > whenever --update-crontab caperoma
20
+ puts 'Auto reports turned on'
21
+ end
22
+
23
+ def self.unschedule
24
+ puts 'Turning off auto reports'
25
+ puts 'pending'
26
+ puts 'Auto reports turned off'
27
+ end
28
+
29
+ private
30
+
31
+ def set_variables
32
+ @smtp = Net::SMTP.new 'smtp.gmail.com', 587
33
+ @smtp.enable_starttls
34
+ @account = Account.gmail
35
+ end
36
+
37
+ # most of it is related to email formatting
38
+
39
+ def assign_unreported_tasks
40
+ unreported_tasks.update_all(report_sti_key => id)
41
+ end
42
+
43
+ def send_email
44
+ @smtp.start('gmail.com', @account.email, @account.password, :login, &send_email_method)
45
+ end
46
+
47
+ def send_email_method
48
+ proc { @smtp.send_message(report_msg, @account.email, to_addresses) }
49
+ end
50
+
51
+ def unreported_tasks
52
+ Task.finished.where(report_sti_key => nil)
53
+ end
54
+
55
+ def report_sti_key
56
+ self.class.to_s.foreign_key
57
+ end
58
+
59
+ def update_content
60
+ update content: report_msg
61
+ end
62
+
63
+ def reported_tasks
64
+ tasks.finished.order(finished_at: :desc)
65
+ end
66
+
67
+ def total_time_spent
68
+ "#{hours_spent}h #{remaining_minutes_spent}m"
69
+ end
70
+
71
+ def hours_spent
72
+ (total_time_spent_in_minutes / 60).to_i
73
+ end
74
+
75
+ def remaining_minutes_spent
76
+ (total_time_spent_in_minutes - hours_spent * 60).to_i
77
+ end
78
+
79
+ def total_time_spent_in_minutes
80
+ reported_tasks.all.collect(&:time_spent_in_minutes).sum
81
+ end
82
+
83
+ def not_test?
84
+ ENV['CAPEROMA_INTEGRATION_TEST'].blank? && ENV['CAPEROMA_TEST'].blank?
85
+ end
86
+
87
+ def to_addresses
88
+ ReportRecipient.all.collect(&:email)
89
+ end
90
+
91
+ def report_msg
92
+ report_msg_content.join("\n")
93
+ end
94
+
95
+ def report_msg_content
96
+ ["subject: #{report_subject}", 'Content-Type: text/html; charset=UTF-8', report_body]
97
+ end
98
+
99
+ def formatted_day(day)
100
+ day.strftime('%b %-d')
101
+ end
102
+
103
+ def formatted_start_day
104
+ formatted_day(start_day)
105
+ end
106
+
107
+ def formatted_end_day
108
+ formatted_day(end_day)
109
+ end
110
+
111
+ def timeframe
112
+ [formatted_start_day, formatted_end_day].join(' - ')
113
+ end
114
+
115
+ def report_subject
116
+ [subject_name, subject_timeframe].join(' ')
117
+ end
118
+
119
+ def subject_timeframe
120
+ "(#{timeframe})"
121
+ end
122
+
123
+ def report_body
124
+ [
125
+ "\n",
126
+ "<h2>Done during #{timeframe}:</h2>",
127
+ "<br />",
128
+ "<table style=\"width: 100%;text-align: left;\">",
129
+ "<thead>",
130
+ "<tr><th>Jira</th><th>Pivotal</th><th>Title</th><th>Time spent</th></tr>",
131
+ "</thead>",
132
+ "<tbody>",
133
+ reported_tasks_rows,
134
+ "</tbody>",
135
+ "</table>",
136
+ "<br />",
137
+ "<strong>Total time spent during #{timeframe}:</strong> #{total_time_spent}."
138
+ ].flatten.join("\n")
139
+ end
140
+
141
+ def reported_tasks_rows
142
+ reported_tasks.collect { |task| table_row(task) }.join("\n")
143
+ end
144
+
145
+ def table_row(task)
146
+ '<tr>' + task_row_data(task).collect{|task| '<td>' + task + '</td>' }.join("\n") + '</tr>'
147
+ end
148
+
149
+ def task_row_data(task)
150
+ [
151
+ jira_url_or_blank(task),
152
+ pivotal_url_or_blank(task),
153
+ formatted_title(task),
154
+ task.time_spent
155
+ ]
156
+ end
157
+
158
+ def formatted_title(task)
159
+ truncate(task.title, length: 90)
160
+ end
161
+
162
+ def jira_url_or_blank(task)
163
+ task.jira_key.present? ? jira_formatted_url(task) : ''
164
+ end
165
+
166
+ def jira_formatted_url(task)
167
+ "<a href=\"#{task.jira_live_url}\">#{task.jira_key}</a>"
168
+ end
169
+
170
+ def pivotal_url_or_blank(task)
171
+ task.pivotal_id.present? ? pivotal_formatted_url(task) : ''
172
+ end
173
+
174
+ def pivotal_formatted_url(task)
175
+ "<a href=\"#{task.pivotal_url}\">#{task.pivotal_id}</a>"
176
+ end
177
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ReportRecipient < ApplicationRecord
4
+ validates :email, presence: true, uniqueness: true
5
+ validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, on: :create # TODO: just email validator dude
6
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DailyReport < Report
4
+ has_many :tasks
5
+
6
+ private
7
+
8
+ def subject_name
9
+ 'Daily Report'
10
+ end
11
+
12
+ def body_heading
13
+ 'Today'
14
+ end
15
+
16
+ def timeframe
17
+ formatted_day(start_day)
18
+ end
19
+
20
+ def start_day
21
+ Date.today
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RetrospectiveReport < Report
4
+ has_many :tasks
5
+
6
+ private
7
+
8
+ def subject_name
9
+ 'Weekly Report'
10
+ end
11
+
12
+ def start_day
13
+ Date.today.beginning_of_week
14
+ end
15
+
16
+ def end_day
17
+ Date.today
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThreeDayReport < Report
4
+ has_many :tasks
5
+
6
+ private
7
+
8
+ def subject_name
9
+ 'Three Day Report'
10
+ end
11
+
12
+ def start_day
13
+ Date.today - 2.days
14
+ end
15
+
16
+ def end_day
17
+ Date.today
18
+ end
19
+ end
@@ -0,0 +1,368 @@
1
+ # frozen_string_literal: true
2
+ class Task < ActiveRecord::Base
3
+ include Git
4
+
5
+ belongs_to :project
6
+ belongs_to :daily_report
7
+ belongs_to :three_day_report
8
+ belongs_to :retrospective_report
9
+
10
+ validates :title, presence: true
11
+ validates :pivotal_id, length: { minimum: 6 }, allow_blank: true, numericality: { only_integer: true }
12
+
13
+ before_create :generate_uuid
14
+ before_create :set_start_time
15
+
16
+ after_create :create_issue_on_jira, if: :create_on_jira?
17
+ after_create :start_issue_on_jira, if: :start_on_jira?
18
+ after_create :create_issue_on_pivotal, if: :create_on_pivotal?
19
+ after_create :start_issue_on_pivotal, if: :start_on_pivotal?
20
+ after_save :output_jira_key, if: :output_jira_key?
21
+
22
+ scope :unfinished, -> { where(finished_at: nil) }
23
+ scope :finished, -> { where.not(finished_at: nil) }
24
+
25
+ def self.finish_started(comment)
26
+ puts 'Finishing current task'
27
+ unfinished.each { |task| task.finish(comment) }
28
+ puts 'Current task finished'
29
+ end
30
+
31
+ def self.pause_started(comment)
32
+ puts 'Pausing current task'
33
+ unfinished.each { |task| task.pause(comment) }
34
+ puts 'Current task paused'
35
+ end
36
+
37
+ def self.abort_started(comment)
38
+ puts 'Aborting current task'
39
+ unfinished.each { |task| task.abort(comment) }
40
+ puts 'Current task aborted'
41
+ end
42
+
43
+ def self.abort_started_without_time(comment)
44
+ puts 'Aborting current task without putting time into Jira'
45
+ unfinished.each { |task| task.abort_without_time(comment) }
46
+ puts 'Current task aborted without putting time into Jira'
47
+ end
48
+
49
+ def self.status
50
+ if unfinished.length == 0
51
+ puts "You are not working on anything now."
52
+ else
53
+ unfinished.each do |task|
54
+ puts "You are working on: "
55
+ puts "Title: #{task.title}"
56
+ puts "Type: #{task.type}"
57
+ puts "Jira ID: #{task.jira_key}." if task.jira_key.present?
58
+ puts "Pivotal ID: #{task.pivotal_id} (#{task.pivotal_url})" if task.pivotal_id.present?
59
+ puts "Time spent at the moment: #{task.time_spent_so_far}"
60
+ puts "Pull request will be sent to this branch: #{task.parent_branch}" if task.parent_branch.present?
61
+ puts "Project location: #{task.project.folder_path}"
62
+ end
63
+ end
64
+ end
65
+
66
+ attr_writer :additional_time
67
+
68
+ def finish(comment)
69
+ # full pull request
70
+ update_attribute(:finished_at, Time.now)
71
+ close_issue_on_jira
72
+ log_work_to_jira(comment)
73
+ finish_on_pivotal if pivotal_id.present?
74
+ puts time_spent
75
+ end
76
+
77
+ def pause(comment = 'Done')
78
+ # finish with commit & push but without pull request
79
+ update_attribute(:finished_at, Time.now)
80
+ close_issue_on_jira
81
+ log_work_to_jira(comment)
82
+ finish_on_pivotal if pivotal_id.present?
83
+ puts time_spent
84
+ end
85
+
86
+ def abort(comment)
87
+ # finish without commit or push
88
+ update_attribute(:finished_at, Time.now)
89
+ close_issue_on_jira
90
+ log_work_to_jira(comment)
91
+ finish_on_pivotal if pivotal_id.present?
92
+ puts time_spent
93
+ end
94
+
95
+ def abort_without_time(comment)
96
+ # finish without commit or push
97
+ update_attribute(:finished_at, Time.now)
98
+ close_issue_on_jira
99
+ # the task closes on Jira, but is still running in Pivotal
100
+ puts time_spent
101
+ end
102
+
103
+ def time_spent_so_far
104
+ result = TimeDifference.between(started_at, Time.now).in_minutes
105
+
106
+ hours = (result / 60).to_i
107
+ minutes = (result - hours * 60).to_i
108
+
109
+ "#{hours}h #{minutes}m"
110
+ end
111
+
112
+ def time_spent
113
+ result = TimeDifference.between(started_at, finished_at).in_minutes
114
+
115
+ hours = (result / 60).to_i
116
+ minutes = (result - hours * 60).to_i
117
+
118
+ "#{hours}h #{minutes}m"
119
+ end
120
+
121
+ def pivotal_url
122
+ "https://www.pivotaltracker.com/story/show/#{pivotal_id}" if pivotal_id.present?
123
+ end
124
+
125
+ def jira_live_url
126
+ "#{project.jira_url}browse/#{jira_key}" if jira_key.present?
127
+ end
128
+
129
+ def time_spent_in_minutes
130
+ TimeDifference.between(started_at, finished_at).in_minutes # TODO: test
131
+ end
132
+
133
+ private
134
+
135
+ def story_type
136
+ 'chore' # default is chore, it's never used directly
137
+ end
138
+
139
+ def create_on_jira?
140
+ Account.jira.present? && ENV['CAPEROMA_INTEGRATION_TEST'].blank?
141
+ end
142
+
143
+ def start_on_jira?
144
+ jira_key.present? && Account.jira.present? && ENV['CAPEROMA_INTEGRATION_TEST'].blank?
145
+ end
146
+
147
+ def create_on_pivotal?
148
+ pivotal_id.blank? && this_is_a_type_a_user_wants_to_create? && Account.pivotal.present? && ENV['CAPEROMA_INTEGRATION_TEST'].blank?
149
+ end
150
+
151
+ def start_on_pivotal?
152
+ pivotal_id.present? && Account.pivotal.present? && ENV['CAPEROMA_INTEGRATION_TEST'].blank?
153
+ end
154
+
155
+ def this_is_a_type_a_user_wants_to_create?
156
+ false
157
+ end
158
+
159
+ def generate_uuid
160
+ self.uuid = SecureRandom.uuid
161
+ end
162
+
163
+ def set_start_time
164
+ time = Time.now
165
+ time -= @additional_time.to_i.minutes if @additional_time.present?
166
+ self.started_at = time
167
+ end
168
+
169
+ def output_jira_key
170
+ puts jira_key
171
+ end
172
+
173
+ def output_jira_key?
174
+ jira_key.present? && ENV['CAPEROMA_INTEGRATION_TEST'].blank?
175
+ end
176
+
177
+ def start_issue_on_pivotal_data
178
+ Jbuilder.encode do |j|
179
+ j.current_state 'started'
180
+ end
181
+ end
182
+
183
+ def start_issue_on_pivotal
184
+ if not_test?
185
+ conn = Faraday.new(url: 'https://www.pivotaltracker.com/') do |c|
186
+ c.adapter Faraday.default_adapter
187
+ end
188
+
189
+ response = conn.put do |request|
190
+ request.url "services/v5/stories/#{pivotal_id}"
191
+ request.body = start_issue_on_pivotal_data
192
+ request.headers['User-Agent'] = 'Caperoma'
193
+ request.headers['Content-Type'] = 'application/json'
194
+ request.headers['X-TrackerToken'] = Account.pivotal.password
195
+ end
196
+ end
197
+ end
198
+
199
+ def finish_on_pivotal_data
200
+ Jbuilder.encode do |j|
201
+ j.current_state 'finished'
202
+ end
203
+ end
204
+
205
+ def finish_on_pivotal
206
+ if not_test?
207
+ conn = Faraday.new(url: 'https://www.pivotaltracker.com/') do |c|
208
+ c.adapter Faraday.default_adapter
209
+ end
210
+
211
+ response = conn.put do |request|
212
+ request.url "services/v5/stories/#{pivotal_id}"
213
+ request.body = finish_on_pivotal_data
214
+ request.headers['User-Agent'] = 'Caperoma'
215
+ request.headers['Content-Type'] = 'application/json'
216
+ request.headers['X-TrackerToken'] = Account.pivotal.password
217
+ end
218
+ end
219
+ end
220
+
221
+ def start_issue_on_jira_data
222
+ Jbuilder.encode do |j|
223
+ j.transition { j.id project.jira_transition_id_in_progress }
224
+ end
225
+ end
226
+
227
+ def start_issue_on_jira
228
+ if not_test?
229
+ conn = Faraday.new(url: project.jira_url) do |c|
230
+ c.basic_auth(Account.jira.email, Account.jira.password)
231
+ c.adapter Faraday.default_adapter
232
+ end
233
+
234
+ conn.post do |request|
235
+ request.url "rest/api/3/issue/#{jira_key}/transitions"
236
+ request.body = start_issue_on_jira_data
237
+ request.headers['User-Agent'] = 'Caperoma'
238
+ request.headers['Content-Type'] = 'application/json'
239
+ end
240
+ end
241
+ end
242
+
243
+ def close_issue_on_jira_data
244
+ Jbuilder.encode do |j|
245
+ j.transition { j.id project.jira_transition_id_done }
246
+ end
247
+ end
248
+
249
+ def close_issue_on_jira
250
+ if not_test?
251
+ conn = Faraday.new(url: project.jira_url) do |c|
252
+ c.basic_auth(Account.jira.email, Account.jira.password)
253
+ c.adapter Faraday.default_adapter
254
+ end
255
+
256
+ response = conn.post do |request|
257
+ request.url "rest/api/3/issue/#{jira_key}/transitions"
258
+ request.body = close_issue_on_jira_data
259
+ request.headers['User-Agent'] = 'Caperoma'
260
+ request.headers['Content-Type'] = 'application/json'
261
+ end
262
+ end
263
+ end
264
+
265
+ def log_work_to_jira_data(comment = 'Done')
266
+ Jbuilder.encode do |j|
267
+ j.comment comment
268
+ j.started current_time
269
+ j.timeSpent time_spent
270
+ end
271
+ end
272
+
273
+ def log_work_to_jira(comment = 'Done')
274
+ if not_test?
275
+ conn = Faraday.new(url: project.jira_url) do |c|
276
+ c.basic_auth(Account.jira.email, Account.jira.password)
277
+ c.adapter Faraday.default_adapter
278
+ end
279
+
280
+ result = conn.post do |request|
281
+ request.url "rest/api/3/issue/#{jira_key}/worklog"
282
+ request.body = log_work_to_jira_data(comment)
283
+ request.headers['User-Agent'] = 'Caperoma'
284
+ request.headers['Content-Type'] = 'application/json'
285
+ end
286
+ end
287
+ end
288
+
289
+ def current_time
290
+ Time.now.in_time_zone('UTC').strftime('%Y-%m-%dT%H:%M:00.000+0000')
291
+ end
292
+
293
+ def issue_type
294
+ project.feature_jira_task_id
295
+ end
296
+
297
+ def create_issue_on_pivotal_data
298
+ Jbuilder.encode do |j|
299
+ j.current_state 'unstarted'
300
+ j.estimate 1
301
+ j.name title.to_s
302
+ j.story_type story_type
303
+ end
304
+ end
305
+
306
+ def create_issue_on_pivotal
307
+ if not_test?
308
+ conn = Faraday.new(url: 'https://www.pivotaltracker.com/') do |c|
309
+ c.adapter Faraday.default_adapter
310
+ end
311
+
312
+ response = conn.post do |request|
313
+ request.url "services/v5/projects/#{project.pivotal_tracker_project_id}/stories"
314
+ request.body = create_issue_on_pivotal_data
315
+ request.headers['User-Agent'] = 'Caperoma'
316
+ request.headers['Content-Type'] = 'application/json'
317
+ request.headers['X-TrackerToken'] = Account.pivotal.password
318
+ end
319
+
320
+ result = JSON.parse response.body
321
+
322
+ update_attributes(
323
+ pivotal_id: result['id']
324
+ )
325
+ end
326
+ end
327
+
328
+ def create_issue_on_jira_data
329
+ Jbuilder.encode do |j|
330
+ j.fields do
331
+ j.project { j.id project.jira_project_id.to_s }
332
+ j.issuetype { j.id issue_type }
333
+ j.summary title.to_s
334
+ j.assignee do
335
+ j.name Account.jira.username
336
+ end
337
+ end
338
+ end
339
+ end
340
+
341
+ def create_issue_on_jira
342
+ if not_test?
343
+ conn = Faraday.new(url: project.jira_url) do |c|
344
+ c.basic_auth(Account.jira.email, Account.jira.password)
345
+ c.adapter Faraday.default_adapter
346
+ end
347
+
348
+ response = conn.post do |request|
349
+ request.url 'rest/api/3/issue.json'
350
+ request.body = create_issue_on_jira_data
351
+ request.headers['User-Agent'] = 'Caperoma'
352
+ request.headers['Content-Type'] = 'application/json'
353
+ end
354
+
355
+ result = JSON.parse response.body
356
+
357
+ update_attributes(
358
+ jira_id: result['id'],
359
+ jira_key: result['key'],
360
+ jira_url: result['self']
361
+ )
362
+ end
363
+ end
364
+
365
+ def not_test?
366
+ ENV['CAPEROMA_INTEGRATION_TEST'].blank?
367
+ end
368
+ end