caperoma 4.0.1 → 5.0.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 +4 -4
- data/Capefile +6 -6
- data/Capefile.template +4 -1
- data/Gemfile +1 -5
- data/Gemfile.lock +3 -45
- data/HELP +84 -13
- data/README.md +165 -29
- data/Rakefile +25 -22
- data/VERSION +1 -1
- data/bin/caperoma +6 -9
- data/caperoma.gemspec +15 -13
- data/config/crontab +0 -2
- data/config/schedule.rb +17 -19
- data/config/unschedule.rb +3 -0
- data/images/circle.png +0 -0
- data/images/report.png +0 -0
- data/lib/caperoma.rb +308 -98
- data/lib/caperoma/models/account.rb +1 -1
- data/lib/caperoma/models/project.rb +1 -2
- data/lib/caperoma/models/report.rb +15 -15
- data/lib/caperoma/models/task.rb +203 -46
- data/lib/caperoma/models/tasks/chore.rb +2 -0
- data/lib/caperoma/models/tasks/feature.rb +1 -0
- data/lib/caperoma/models/tasks/fix.rb +2 -0
- data/lib/caperoma/models/tasks/meeting.rb +2 -0
- data/lib/caperoma/models/tasks/modules/git.rb +94 -15
- data/lib/caperoma/models/tasks/task_with_commit.rb +8 -5
- data/lib/caperoma/models/tasks/task_with_separate_branch.rb +6 -4
- data/spec/caperoma_spec.rb +558 -2
- data/spec/factories/accounts.rb +1 -1
- data/spec/factories/projects.rb +1 -1
- data/spec/factories/report_recipients.rb +1 -1
- data/spec/factories/reports.rb +1 -1
- data/spec/factories/tasks.rb +1 -2
- data/spec/features/command_unknown_spec.rb +0 -1
- data/spec/features/feature_spec.rb +64 -44
- data/spec/features/init_spec.rb +20 -0
- data/spec/features/status_spec.rb +12 -11
- data/spec/models/project_spec.rb +0 -1
- data/spec/models/task_spec.rb +811 -27
- data/spec/models/task_with_commit_spec.rb +0 -4
- data/spec/models/task_with_separate_branch_spec.rb +4 -4
- data/spec/models/three_day_report_spec.rb +2 -3
- data/spec/spec_helper.rb +2 -0
- data/spec/support/capefile_generator.rb +35 -27
- data/spec/support/stubs.rb +7 -74
- metadata +47 -24
- data/lib/caperoma/models/branch.rb +0 -6
- data/lib/caperoma/services/airbrake_email_processor.rb +0 -47
- data/lib/caperoma/services/pivotal_fetcher.rb +0 -108
- data/spec/factories/branches.rb +0 -9
- data/spec/models/branch_spec.rb +0 -8
@@ -7,10 +7,6 @@ RSpec.describe TaskWithCommit, type: :model do
|
|
7
7
|
it { expect(subject).to be_a_kind_of Task }
|
8
8
|
end
|
9
9
|
|
10
|
-
describe 'relations' do
|
11
|
-
it { expect(subject).to belong_to :branch }
|
12
|
-
end
|
13
|
-
|
14
10
|
describe 'methods' do
|
15
11
|
describe '#finish' do
|
16
12
|
let!(:task) { create :task_with_commit }
|
@@ -11,7 +11,7 @@ RSpec.describe TaskWithSeparateBranch, type: :model do
|
|
11
11
|
allow_any_instance_of(TaskWithSeparateBranch).to receive(:description_for_pull_request).and_return 'pivotal-url'
|
12
12
|
allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_current_branch).and_return 'parent-branch'
|
13
13
|
|
14
|
-
expect(task).to receive(:git_pull_request)
|
14
|
+
expect(task).to receive(:git_pull_request)
|
15
15
|
expect(task).to receive(:git_checkout).with('parent-branch')
|
16
16
|
|
17
17
|
task.finish(nil)
|
@@ -23,7 +23,7 @@ RSpec.describe TaskWithSeparateBranch, type: :model do
|
|
23
23
|
|
24
24
|
it 'should commit with generated message' do
|
25
25
|
allow_any_instance_of(TaskWithSeparateBranch).to receive(:description_for_pull_request).and_return 'pivotal-url'
|
26
|
-
expect(task).not_to receive(:git_pull_request)
|
26
|
+
expect(task).not_to receive(:git_pull_request)
|
27
27
|
expect(task).not_to receive(:git_checkout).with('parent-branch')
|
28
28
|
|
29
29
|
task.pause(nil)
|
@@ -65,10 +65,10 @@ RSpec.describe TaskWithSeparateBranch, type: :model do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
describe '::
|
68
|
+
describe '::git_branch' do
|
69
69
|
it 'should make a new branch' do
|
70
70
|
expect_any_instance_of(TaskWithSeparateBranch).to receive(:branch_name).and_return 'branch-name'
|
71
|
-
expect_any_instance_of(TaskWithSeparateBranch).to receive(:git_branch)
|
71
|
+
expect_any_instance_of(TaskWithSeparateBranch).to receive(:git_branch)
|
72
72
|
|
73
73
|
create :task_with_separate_branch
|
74
74
|
end
|
@@ -37,13 +37,12 @@ RSpec.describe ThreeDayReport, type: :model do
|
|
37
37
|
|
38
38
|
describe 'message body', :unstub_puts do
|
39
39
|
let(:report) { create :three_day_report }
|
40
|
-
let!(:task1) { create :task, jira_key: 'DOV-2', pivotal_id:
|
41
|
-
let!(:task2) { create :task, jira_key: 'MOB-8', pivotal_id:
|
40
|
+
let!(:task1) { create :task, jira_key: 'DOV-2', pivotal_id: 2_345_678, three_day_report: nil, finished_at: 2.days.ago }
|
41
|
+
let!(:task2) { create :task, jira_key: 'MOB-8', pivotal_id: 2_345_674, three_day_report: nil, finished_at: 1.day.ago }
|
42
42
|
|
43
43
|
specify do
|
44
44
|
expect(report.send(:report_body)).to match /table/
|
45
45
|
end
|
46
|
-
|
47
46
|
end
|
48
47
|
end
|
49
48
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,6 +4,8 @@ ENV['CAPEROMA_TEST'] = 'true'
|
|
4
4
|
|
5
5
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
6
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'models'))
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'models', 'tasks'))
|
8
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'models', 'tasks', 'modules'))
|
7
9
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
10
|
|
9
11
|
require 'caperoma'
|
@@ -1,36 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'yaml'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
'
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
'
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
5
|
+
def create_capefile(jira_project_id = 12_345)
|
6
|
+
capefile_sample_data = {
|
7
|
+
'github_repo' => 'owner/repo',
|
8
|
+
'jira_url' => 'https://owner.atlassian.net/',
|
9
|
+
'jira_project_id' => 10_001,
|
10
|
+
'jira_issue_type_ids' => {
|
11
|
+
'feature' => 10_101,
|
12
|
+
'bug' => 10_103,
|
13
|
+
'chore' => 10_100,
|
14
|
+
'fix' => 10_101,
|
15
|
+
'meeting' => 10_100
|
16
|
+
},
|
17
|
+
'jira_transition_ids' => {
|
18
|
+
'todo' => 11,
|
19
|
+
'in_progress' => 21,
|
20
|
+
'done' => 31
|
21
|
+
},
|
22
|
+
'pivotal_tracker_project_id' => 2_374_972,
|
23
|
+
'create_features_in_pivotal' => true,
|
24
|
+
'create_bugs_in_pivotal' => true,
|
25
|
+
'create_chores_in_pivotal' => true,
|
26
|
+
'create_fixes_in_pivotal_as_chores' => false,
|
27
|
+
'create_meetings_in_pivotal_as_chores' => false
|
28
|
+
}
|
29
|
+
capefile_sample_data['jira_project_id'] = jira_project_id
|
30
|
+
yaml = capefile_sample_data.to_yaml
|
31
|
+
File.write 'Capefile.test', yaml
|
32
|
+
end
|
27
33
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
34
|
+
def create_incomplete_capefile
|
35
|
+
capefile_sample_data = {
|
36
|
+
'github_repo' => 'owner/repo'
|
37
|
+
}
|
38
|
+
yaml = capefile_sample_data.to_yaml
|
31
39
|
File.write 'Capefile.test', yaml
|
32
40
|
end
|
33
41
|
|
34
42
|
def remove_capefile
|
35
|
-
File.delete 'Capefile.test'
|
43
|
+
File.delete 'Capefile.test' if File.exist? 'Capefile.test'
|
36
44
|
end
|
data/spec/support/stubs.rb
CHANGED
@@ -66,87 +66,20 @@ end
|
|
66
66
|
|
67
67
|
RSpec.configure do |config|
|
68
68
|
config.before do |example|
|
69
|
-
# if example.metadata[:unstab_capefile].blank?
|
70
|
-
# Caperoma::Capefile::JIRA_URL = '123'
|
71
|
-
# end
|
72
|
-
|
73
|
-
# if example.metadata[:unstub_git].blank?
|
74
|
-
# allow_any_instance_of(Feature).to receive(:git_branch)
|
75
|
-
# allow_any_instance_of(Feature).to receive(:git_commit)
|
76
|
-
# allow_any_instance_of(Feature).to receive(:git_push)
|
77
|
-
# allow_any_instance_of(Feature).to receive(:git_last_commit_name).and_return 'some commit'
|
78
|
-
# allow_any_instance_of(Feature).to receive(:git_current_branch).and_return 'parent-branch'
|
79
|
-
# allow_any_instance_of(Feature).to receive(:git_pull_request)
|
80
|
-
# allow_any_instance_of(Feature).to receive(:git_checkout)
|
81
|
-
|
82
|
-
# allow_any_instance_of(Bug).to receive(:git_branch)
|
83
|
-
# allow_any_instance_of(Bug).to receive(:git_commit)
|
84
|
-
# allow_any_instance_of(Bug).to receive(:git_push)
|
85
|
-
# allow_any_instance_of(Bug).to receive(:git_last_commit_name).and_return 'some commit'
|
86
|
-
# allow_any_instance_of(Bug).to receive(:git_current_branch).and_return 'parent-branch'
|
87
|
-
# allow_any_instance_of(Bug).to receive(:git_pull_request)
|
88
|
-
# allow_any_instance_of(Bug).to receive(:git_checkout)
|
89
|
-
|
90
|
-
# allow_any_instance_of(Chore).to receive(:git_branch)
|
91
|
-
# allow_any_instance_of(Chore).to receive(:git_commit)
|
92
|
-
# allow_any_instance_of(Chore).to receive(:git_push)
|
93
|
-
# allow_any_instance_of(Chore).to receive(:git_last_commit_name).and_return 'some commit'
|
94
|
-
# allow_any_instance_of(Chore).to receive(:git_current_branch).and_return 'parent-branch'
|
95
|
-
# allow_any_instance_of(Chore).to receive(:git_pull_request)
|
96
|
-
# allow_any_instance_of(Chore).to receive(:git_checkout)
|
97
|
-
|
98
|
-
# allow_any_instance_of(Fix).to receive(:git_branch)
|
99
|
-
# allow_any_instance_of(Fix).to receive(:git_commit)
|
100
|
-
# allow_any_instance_of(Fix).to receive(:git_push)
|
101
|
-
# allow_any_instance_of(Fix).to receive(:git_last_commit_name).and_return 'some commit'
|
102
|
-
# allow_any_instance_of(Fix).to receive(:git_current_branch).and_return 'parent-branch'
|
103
|
-
# allow_any_instance_of(Fix).to receive(:git_pull_request)
|
104
|
-
# allow_any_instance_of(Fix).to receive(:git_checkout)
|
105
|
-
|
106
|
-
# allow_any_instance_of(Meeting).to receive(:git_branch)
|
107
|
-
# allow_any_instance_of(Meeting).to receive(:git_commit)
|
108
|
-
# allow_any_instance_of(Meeting).to receive(:git_push)
|
109
|
-
# allow_any_instance_of(Meeting).to receive(:git_last_commit_name).and_return 'some commit'
|
110
|
-
# allow_any_instance_of(Meeting).to receive(:git_current_branch).and_return 'parent-branch'
|
111
|
-
# allow_any_instance_of(Meeting).to receive(:git_pull_request)
|
112
|
-
# allow_any_instance_of(Meeting).to receive(:git_checkout)
|
113
|
-
|
114
|
-
# allow_any_instance_of(Task).to receive(:git_branch)
|
115
|
-
# allow_any_instance_of(Task).to receive(:git_commit)
|
116
|
-
# allow_any_instance_of(Task).to receive(:git_push)
|
117
|
-
# allow_any_instance_of(Task).to receive(:git_last_commit_name).and_return 'some commit'
|
118
|
-
# allow_any_instance_of(Task).to receive(:git_current_branch).and_return 'parent-branch'
|
119
|
-
# allow_any_instance_of(Task).to receive(:git_pull_request)
|
120
|
-
# allow_any_instance_of(Task).to receive(:git_checkout)
|
121
|
-
|
122
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_branch)
|
123
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_commit)
|
124
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_push)
|
125
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_last_commit_name).and_return 'some commit'
|
126
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_current_branch).and_return 'parent-branch'
|
127
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_pull_request)
|
128
|
-
# allow_any_instance_of(TaskWithSeparateBranch).to receive(:git_checkout)
|
129
|
-
|
130
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_branch)
|
131
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_commit)
|
132
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_push)
|
133
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_last_commit_name).and_return 'some commit'
|
134
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_current_branch).and_return 'parent-branch'
|
135
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_pull_request)
|
136
|
-
# allow_any_instance_of(TaskWithCommit).to receive(:git_checkout)
|
137
|
-
# end
|
138
|
-
|
139
69
|
if example.metadata[:unstub_reports].blank?
|
140
70
|
allow_any_instance_of(Report).to receive(:send_email)
|
141
71
|
end
|
142
72
|
|
143
73
|
if example.metadata[:unstab_api_calls].blank?
|
144
|
-
|
74
|
+
response = double('Faraday', body: JIRA_ISSUE_CREATION_RESPONSE, status: 200)
|
75
|
+
faraday = double('Faraday', post: response)
|
76
|
+
|
145
77
|
allow(Faraday).to receive(:new).and_return faraday
|
146
78
|
allow(Faraday).to receive(:default_adapter)
|
147
|
-
|
148
|
-
allow(faraday).to receive(:post)
|
149
|
-
allow(faraday).to receive(:
|
79
|
+
|
80
|
+
allow(faraday).to receive(:post).and_return response
|
81
|
+
allow(faraday).to receive(:get).and_return response
|
82
|
+
allow(faraday).to receive(:put).and_return response
|
150
83
|
end
|
151
84
|
|
152
85
|
allow(STDOUT).to receive(:puts) if example.metadata[:unstub_puts].blank?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caperoma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Serge Vinogradoff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: 0.7.0
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: whenever
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 1.0.0
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 1.0.0
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
name: bundler
|
169
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,19 +207,19 @@ dependencies:
|
|
193
207
|
- !ruby/object:Gem::Version
|
194
208
|
version: 1.7.0
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
210
|
+
name: factory_girl
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
198
212
|
requirements:
|
199
213
|
- - "~>"
|
200
214
|
- !ruby/object:Gem::Version
|
201
|
-
version:
|
215
|
+
version: 4.9.0
|
202
216
|
type: :development
|
203
217
|
prerelease: false
|
204
218
|
version_requirements: !ruby/object:Gem::Requirement
|
205
219
|
requirements:
|
206
220
|
- - "~>"
|
207
221
|
- !ruby/object:Gem::Version
|
208
|
-
version:
|
222
|
+
version: 4.9.0
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
224
|
name: rdoc
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,18 +290,26 @@ dependencies:
|
|
276
290
|
- - "~>"
|
277
291
|
- !ruby/object:Gem::Version
|
278
292
|
version: 0.9.1
|
279
|
-
description:
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
293
|
+
description: |2
|
294
|
+
Caperoma automates many decisions related to the programming that you often don't realize, and which you can forget hundreds of times during the time of working on the project:
|
295
|
+
pulling the latest code from upstream before you start working,
|
296
|
+
remembering from which branch you started the feature to later make a pull request into it,
|
297
|
+
creating & starting tasks in Jira,
|
298
|
+
creating & starting tasks in Pivotal,
|
299
|
+
naming branches,
|
300
|
+
adding Jira ID into the branch name,
|
301
|
+
style guide checks,
|
302
|
+
commits,
|
303
|
+
naming commits,
|
304
|
+
adding Jira ID into commit name,
|
305
|
+
adding Pivotal ID into commit name,
|
306
|
+
git pushes,
|
307
|
+
pull requests into correct branches,
|
308
|
+
stopping tasks in Jira,
|
309
|
+
stopping tasks in Pivotal,
|
310
|
+
tracking time,
|
311
|
+
logging time to Jira,
|
312
|
+
switching back into the original branch and much more.
|
291
313
|
email: sergevinogradoff.caperoma@gmail.com
|
292
314
|
executables:
|
293
315
|
- caperoma
|
@@ -311,10 +333,12 @@ files:
|
|
311
333
|
- caperoma.gemspec
|
312
334
|
- config/crontab
|
313
335
|
- config/schedule.rb
|
336
|
+
- config/unschedule.rb
|
337
|
+
- images/circle.png
|
338
|
+
- images/report.png
|
314
339
|
- lib/caperoma.rb
|
315
340
|
- lib/caperoma/models/account.rb
|
316
341
|
- lib/caperoma/models/application_record.rb
|
317
|
-
- lib/caperoma/models/branch.rb
|
318
342
|
- lib/caperoma/models/project.rb
|
319
343
|
- lib/caperoma/models/property.rb
|
320
344
|
- lib/caperoma/models/report.rb
|
@@ -331,12 +355,9 @@ files:
|
|
331
355
|
- lib/caperoma/models/tasks/modules/git.rb
|
332
356
|
- lib/caperoma/models/tasks/task_with_commit.rb
|
333
357
|
- lib/caperoma/models/tasks/task_with_separate_branch.rb
|
334
|
-
- lib/caperoma/services/airbrake_email_processor.rb
|
335
|
-
- lib/caperoma/services/pivotal_fetcher.rb
|
336
358
|
- lib/caperoma/version.rb
|
337
359
|
- spec/caperoma_spec.rb
|
338
360
|
- spec/factories/accounts.rb
|
339
|
-
- spec/factories/branches.rb
|
340
361
|
- spec/factories/projects.rb
|
341
362
|
- spec/factories/report_recipients.rb
|
342
363
|
- spec/factories/reports.rb
|
@@ -348,6 +369,7 @@ files:
|
|
348
369
|
- spec/features/feature_spec.rb
|
349
370
|
- spec/features/finish_spec.rb
|
350
371
|
- spec/features/fix_spec.rb
|
372
|
+
- spec/features/init_spec.rb
|
351
373
|
- spec/features/meeting_spec.rb
|
352
374
|
- spec/features/projects_spec.rb
|
353
375
|
- spec/features/report_recipientss_spec.rb
|
@@ -355,7 +377,6 @@ files:
|
|
355
377
|
- spec/features/status_spec.rb
|
356
378
|
- spec/features/version_spec.rb
|
357
379
|
- spec/models/account_spec.rb
|
358
|
-
- spec/models/branch_spec.rb
|
359
380
|
- spec/models/bug_spec.rb
|
360
381
|
- spec/models/chore_spec.rb
|
361
382
|
- spec/models/daily_report_spec.rb
|
@@ -394,8 +415,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
394
415
|
- !ruby/object:Gem::Version
|
395
416
|
version: '0'
|
396
417
|
requirements:
|
397
|
-
-
|
398
|
-
-
|
418
|
+
- Ruby 2.4 or higher
|
419
|
+
- SQLite
|
420
|
+
- Git
|
421
|
+
- Crontab
|
399
422
|
rubygems_version: 3.0.4
|
400
423
|
signing_key:
|
401
424
|
specification_version: 4
|
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class AirbrakeEmailProcessor
|
4
|
-
# stub for test env
|
5
|
-
def process
|
6
|
-
account = Account.gmail
|
7
|
-
Gmail.new(account.email, account.password) do |gmail|
|
8
|
-
gmail.inbox.emails(:unread, from: 'donotreply@alerts.airbrake.io').select { |email| email.subject.include? '[Ruck.us]' }.each do |email|
|
9
|
-
# get reply address
|
10
|
-
reply_to = "#{email.to.first.mailbox}@#{email.to.first.host}"
|
11
|
-
|
12
|
-
# generate reply body
|
13
|
-
body = ''
|
14
|
-
|
15
|
-
story = PivotalFetcher.get_story_by_title(email.subject)
|
16
|
-
if story.present? && story.respond_to?(:url)
|
17
|
-
body = "Duplicate of: #{story.url}"
|
18
|
-
else
|
19
|
-
story = PivotalFetcher.create_story(email.subject, email.body.raw_source[0..1000])
|
20
|
-
body = "Created new story: #{story.url}"
|
21
|
-
end
|
22
|
-
|
23
|
-
# compose reply email (to get identifiers)
|
24
|
-
reply = email.reply do
|
25
|
-
subject "Re: #{email.subject}"
|
26
|
-
body body
|
27
|
-
end
|
28
|
-
|
29
|
-
# bugfix to make reply work
|
30
|
-
new_email = gmail.compose do
|
31
|
-
to reply_to # note it's generated email, not airbrake one
|
32
|
-
subject reply.subject
|
33
|
-
in_reply_to reply.in_reply_to
|
34
|
-
references reply.references
|
35
|
-
body reply.body.raw_source
|
36
|
-
end
|
37
|
-
|
38
|
-
# deliver reply
|
39
|
-
new_email.deliver!
|
40
|
-
|
41
|
-
# archive email
|
42
|
-
email.mark(:read)
|
43
|
-
email.archive!
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,108 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class PivotalFetcher
|
4
|
-
def self.process(story_id)
|
5
|
-
story = get_story(story_id)
|
6
|
-
|
7
|
-
if story.present?
|
8
|
-
title = story.name
|
9
|
-
description = story.description
|
10
|
-
type = story.story_type
|
11
|
-
# labels = story.labels # in case I do Critical thing
|
12
|
-
# something liek if lables.include?("hot") pass "critical" status to Jira.
|
13
|
-
|
14
|
-
story.update(current_state: 'started', owned_by: 'Serge Vinogradoff')
|
15
|
-
|
16
|
-
args = [type, title, description, story_id] # or args = [type, title, description, "1", story_id] ? I use that 1 in older versions
|
17
|
-
case type
|
18
|
-
when 'feature'
|
19
|
-
Caperoma.feature(args)
|
20
|
-
when 'bug'
|
21
|
-
Caperoma.bug(args)
|
22
|
-
else
|
23
|
-
puts 'Unknown story type in Pivotal'
|
24
|
-
end
|
25
|
-
|
26
|
-
# copy Jira ID to Pivotal story
|
27
|
-
task = Task.where(pivotal_id: story_id).first
|
28
|
-
if task.present?
|
29
|
-
task.jira_key
|
30
|
-
story.notes.create(text: task.jira_key)
|
31
|
-
else
|
32
|
-
puts 'task does not exist'
|
33
|
-
end
|
34
|
-
else
|
35
|
-
puts 'Did not find a story'
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.finish(story_id)
|
40
|
-
story = nil
|
41
|
-
|
42
|
-
PivotalTracker::Project.all.each do |project|
|
43
|
-
story = project.stories.find(story_id)
|
44
|
-
break if story.present?
|
45
|
-
end
|
46
|
-
|
47
|
-
story
|
48
|
-
|
49
|
-
if story.present? && story.tasks.all.empty?
|
50
|
-
story.update current_state: 'finished'
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.create_story(title, description)
|
55
|
-
connect
|
56
|
-
|
57
|
-
project_id = 993_892
|
58
|
-
|
59
|
-
# this isn't needed anymore... these are PT ID's of Ruck.us.
|
60
|
-
if title.include? '[Ruck.us] Production '
|
61
|
-
project_id = 993_892
|
62
|
-
elsif title.include? '[Ruck.us] Staging '
|
63
|
-
project_id = 1_110_744
|
64
|
-
elsif title.include? '[Ruck.us] Staging2 '
|
65
|
-
project_id = 1_266_704
|
66
|
-
end
|
67
|
-
|
68
|
-
# TODO: icebox, need probably to move to backlog
|
69
|
-
project = PivotalTracker::Project.find(project_id)
|
70
|
-
story = project.stories.create name: title,
|
71
|
-
description: description,
|
72
|
-
requested_by: 'Serge Vinogradoff',
|
73
|
-
owned_by: 'Serge Vinogradoff',
|
74
|
-
story_type: 'bug'
|
75
|
-
|
76
|
-
story
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.get_story_by_title(title)
|
80
|
-
connect
|
81
|
-
|
82
|
-
story = nil
|
83
|
-
|
84
|
-
PivotalTracker::Project.all.each do |project|
|
85
|
-
story = project.stories.all.select { |x| x.name == title }.first
|
86
|
-
break if story.present?
|
87
|
-
end
|
88
|
-
|
89
|
-
story
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.get_story(story_id)
|
93
|
-
connect
|
94
|
-
|
95
|
-
story = nil
|
96
|
-
|
97
|
-
PivotalTracker::Project.all.each do |project|
|
98
|
-
story = project.stories.find(story_id)
|
99
|
-
break if story.present?
|
100
|
-
end
|
101
|
-
|
102
|
-
story
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.connect
|
106
|
-
PivotalTracker::Client.token(Account.pivotal.email, Account.pivotal.password)
|
107
|
-
end
|
108
|
-
end
|