livebuzz-gitx 0.1.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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +31 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +6 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +8 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +84 -0
  11. data/Rakefile +5 -0
  12. data/bin/git-buildtag +6 -0
  13. data/bin/git-cleanup +7 -0
  14. data/bin/git-integrate +6 -0
  15. data/bin/git-nuke +6 -0
  16. data/bin/git-release +6 -0
  17. data/bin/git-review +6 -0
  18. data/bin/git-reviewrequest +8 -0
  19. data/bin/git-share +6 -0
  20. data/bin/git-start +6 -0
  21. data/bin/git-track +6 -0
  22. data/bin/git-update +6 -0
  23. data/lib/livebuzz/gitx/cli/base_command.rb +58 -0
  24. data/lib/livebuzz/gitx/cli/buildtag_command.rb +41 -0
  25. data/lib/livebuzz/gitx/cli/cleanup_command.rb +47 -0
  26. data/lib/livebuzz/gitx/cli/integrate_command.rb +95 -0
  27. data/lib/livebuzz/gitx/cli/nuke_command.rb +64 -0
  28. data/lib/livebuzz/gitx/cli/release_command.rb +41 -0
  29. data/lib/livebuzz/gitx/cli/review_command.rb +101 -0
  30. data/lib/livebuzz/gitx/cli/share_command.rb +17 -0
  31. data/lib/livebuzz/gitx/cli/start_command.rb +39 -0
  32. data/lib/livebuzz/gitx/cli/track_command.rb +16 -0
  33. data/lib/livebuzz/gitx/cli/update_command.rb +37 -0
  34. data/lib/livebuzz/gitx/configuration.rb +47 -0
  35. data/lib/livebuzz/gitx/extensions/string.rb +12 -0
  36. data/lib/livebuzz/gitx/extensions/thor.rb +39 -0
  37. data/lib/livebuzz/gitx/github.rb +177 -0
  38. data/lib/livebuzz/gitx/version.rb +5 -0
  39. data/lib/livebuzz/gitx.rb +10 -0
  40. data/livebuzz-gitx.gemspec +37 -0
  41. data/spec/fixtures/vcr_cassettes/pull_request_does_exist_with_failure_status.yml +135 -0
  42. data/spec/fixtures/vcr_cassettes/pull_request_does_exist_with_success_status.yml +149 -0
  43. data/spec/fixtures/vcr_cassettes/pull_request_does_not_exist.yml +133 -0
  44. data/spec/livebuzz/gitx/cli/base_command_spec.rb +41 -0
  45. data/spec/livebuzz/gitx/cli/buildtag_command_spec.rb +70 -0
  46. data/spec/livebuzz/gitx/cli/cleanup_command_spec.rb +37 -0
  47. data/spec/livebuzz/gitx/cli/integrate_command_spec.rb +272 -0
  48. data/spec/livebuzz/gitx/cli/nuke_command_spec.rb +165 -0
  49. data/spec/livebuzz/gitx/cli/release_command_spec.rb +148 -0
  50. data/spec/livebuzz/gitx/cli/review_command_spec.rb +307 -0
  51. data/spec/livebuzz/gitx/cli/share_command_spec.rb +32 -0
  52. data/spec/livebuzz/gitx/cli/start_command_spec.rb +96 -0
  53. data/spec/livebuzz/gitx/cli/track_command_spec.rb +31 -0
  54. data/spec/livebuzz/gitx/cli/update_command_spec.rb +79 -0
  55. data/spec/spec_helper.rb +86 -0
  56. data/spec/support/global_config.rb +24 -0
  57. data/spec/support/home_env.rb +11 -0
  58. data/spec/support/matchers/meet_expectations_matcher.rb +7 -0
  59. data/spec/support/pry.rb +1 -0
  60. data/spec/support/stub_execution.rb +14 -0
  61. data/spec/support/timecop.rb +9 -0
  62. data/spec/support/vcr.rb +6 -0
  63. data/spec/support/webmock.rb +1 -0
  64. metadata +350 -0
@@ -0,0 +1,272 @@
1
+ require 'spec_helper'
2
+ require 'livebuzz/gitx/cli/integrate_command'
3
+
4
+ describe LiveBuzz::Gitx::Cli::IntegrateCommand do
5
+ let(:args) { [] }
6
+ let(:options) { {} }
7
+ let(:config) do
8
+ {
9
+ pretend: true
10
+ }
11
+ end
12
+ let(:cli) { LiveBuzz::Gitx::Cli::IntegrateCommand.new(args, options, config) }
13
+ let(:current_branch) { double('fake branch', name: 'feature-branch', head?: true) }
14
+ let(:repo) { cli.send(:repo) }
15
+ let(:remote_branch_names) { ['origin/staging', 'origin/prototype'] }
16
+ let(:local_branch_names) { ['feature-branch'] }
17
+
18
+ before do
19
+ allow(cli).to receive(:current_branch).and_return(current_branch)
20
+ branches = double('fake branches')
21
+ allow(branches).to receive(:each_name).with(:local).and_return(local_branch_names)
22
+ allow(branches).to receive(:each_name).with(:remote).and_return(remote_branch_names)
23
+ allow(repo).to receive(:branches).and_return(branches)
24
+ end
25
+
26
+ describe '#integrate' do
27
+ context 'when integration branch is ommitted and remote branch exists' do
28
+ let(:authorization_token) { '123123' }
29
+ let(:remote_branch_names) { ['origin/staging'] }
30
+ before do
31
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
32
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
33
+
34
+ expect(cli).to receive(:run_cmd).with("git fetch origin").ordered
35
+ expect(cli).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
36
+ expect(cli).to receive(:run_cmd).with("git checkout staging").ordered
37
+ expect(cli).to receive(:run_cmd).with("git merge feature-branch").ordered
38
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
39
+ expect(cli).to receive(:run_cmd).with("git checkout feature-branch").ordered
40
+
41
+ stub_request(:post, /.*api.github.com.*/).to_return(:status => 201)
42
+
43
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
44
+ cli.integrate
45
+ end
46
+ end
47
+ it 'defaults to staging branch' do
48
+ should meet_expectations
49
+ end
50
+ it 'posts comment to pull request' do
51
+ expect(WebMock).to have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments").
52
+ with(body: {body: '[gitx] integrated into staging :twisted_rightwards_arrows:'})
53
+ end
54
+ end
55
+ context 'when current_branch == master' do
56
+ let(:current_branch) { double('fake branch', name: 'master', head?: true) }
57
+ let(:local_branch_names) { ['master'] }
58
+ let(:authorization_token) { '123123' }
59
+ let(:remote_branch_names) { ['origin/staging'] }
60
+ before do
61
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
62
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
63
+
64
+ expect(cli).to receive(:run_cmd).with("git fetch origin").ordered
65
+ expect(cli).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
66
+ expect(cli).to receive(:run_cmd).with("git checkout staging").ordered
67
+ expect(cli).to receive(:run_cmd).with("git merge master").ordered
68
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
69
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
70
+
71
+ cli.integrate
72
+ end
73
+ it 'does not create pull request' do
74
+ expect(WebMock).to_not have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/pulls")
75
+ end
76
+ end
77
+ context 'when a pull request doesnt exist for the feature-branch' do
78
+ let(:authorization_token) { '123123' }
79
+ let(:changelog) { '* made some fixes' }
80
+ let(:new_pull_request) do
81
+ {
82
+ html_url: "https://path/to/html/pull/request",
83
+ issue_url: "https://api/path/to/issue/url",
84
+ number: 10,
85
+ head: {
86
+ ref: "branch_name"
87
+ }
88
+ }
89
+ end
90
+ before do
91
+ allow(cli).to receive(:ask_editor).and_return('description')
92
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
93
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update).twice
94
+
95
+ expect(cli).to receive(:run_cmd).with("git fetch origin").ordered
96
+ expect(cli).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
97
+ expect(cli).to receive(:run_cmd).with("git checkout staging").ordered
98
+ expect(cli).to receive(:run_cmd).with("git merge feature-branch").ordered
99
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
100
+ expect(cli).to receive(:run_cmd).with("git checkout feature-branch").ordered
101
+
102
+ expect(cli).to receive(:run_cmd).with("git log master...feature-branch --reverse --no-merges --pretty=format:'* %s%n%b'").and_return("2013-01-01 did some stuff").ordered
103
+
104
+ stub_request(:post, 'https://api.github.com/repos/livebuzzevents/livebuzz-gitx/pulls').to_return(:status => 201, :body => new_pull_request.to_json, :headers => {'Content-Type' => 'application/json'})
105
+ stub_request(:post, 'https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments').to_return(:status => 201)
106
+
107
+ VCR.use_cassette('pull_request_does_not_exist') do
108
+ cli.integrate
109
+ end
110
+ end
111
+ it 'creates github pull request' do
112
+ should meet_expectations
113
+ end
114
+ it 'creates github comment for integration' do
115
+ expect(WebMock).to have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments").
116
+ with(body: {body: '[gitx] integrated into staging :twisted_rightwards_arrows:'})
117
+ end
118
+ it 'runs expected commands' do
119
+ should meet_expectations
120
+ end
121
+ end
122
+ context 'when staging branch does not exist remotely' do
123
+ let(:authorization_token) { '123123' }
124
+ let(:remote_branch_names) { [] }
125
+ before do
126
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
127
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
128
+
129
+ expect(repo).to receive(:create_branch).with('staging', 'master')
130
+
131
+ expect(cli).to receive(:run_cmd).with('git push origin staging:staging').ordered
132
+
133
+ expect(cli).to receive(:run_cmd).with("git fetch origin").ordered
134
+ expect(cli).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
135
+ expect(cli).to receive(:run_cmd).with("git checkout staging").ordered
136
+ expect(cli).to receive(:run_cmd).with("git merge feature-branch").ordered
137
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
138
+ expect(cli).to receive(:run_cmd).with("git checkout feature-branch").ordered
139
+
140
+ stub_request(:post, /.*api.github.com.*/).to_return(:status => 201)
141
+
142
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
143
+ cli.integrate
144
+ end
145
+ end
146
+ it 'creates remote aggregate branch' do
147
+ should meet_expectations
148
+ end
149
+ it 'posts comment to pull request' do
150
+ expect(WebMock).to have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments")
151
+ end
152
+ end
153
+ context 'when integration branch == prototype and remote branch exists' do
154
+ let(:authorization_token) { '123123' }
155
+ let(:remote_branch_names) { ['origin/prototype'] }
156
+ before do
157
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
158
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
159
+
160
+ expect(cli).to receive(:run_cmd).with("git fetch origin").ordered
161
+ expect(cli).to receive(:run_cmd).with("git branch -D prototype", allow_failure: true).ordered
162
+ expect(cli).to receive(:run_cmd).with("git checkout prototype").ordered
163
+ expect(cli).to receive(:run_cmd).with("git merge feature-branch").ordered
164
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
165
+ expect(cli).to receive(:run_cmd).with("git checkout feature-branch").ordered
166
+
167
+ stub_request(:post, /.*api.github.com.*/).to_return(:status => 201)
168
+
169
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
170
+ cli.integrate 'prototype'
171
+ end
172
+ end
173
+ it 'runs expected commands' do
174
+ should meet_expectations
175
+ end
176
+ it 'posts comment to pull request' do
177
+ expect(WebMock).to have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments")
178
+ end
179
+ end
180
+ context 'when integration branch is not an aggregate branch' do
181
+ it 'raises an error' do
182
+ expect { cli.integrate('some-other-branch') }.to raise_error(/Invalid aggregate branch: some-other-branch must be one of supported aggregate branches/)
183
+ end
184
+ end
185
+ context 'when merge conflicts occur during the LiveBuzz::Gitx::Cli::updatecommand execution' do
186
+ let(:remote_branch_names) { ['origin/staging'] }
187
+ before do
188
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update).and_raise(LiveBuzz::Gitx::Cli::BaseCommand::MergeError)
189
+
190
+ expect { cli.integrate }.to raise_error(LiveBuzz::Gitx::Cli::BaseCommand::MergeError, 'Merge Conflict Occurred. Please Merge Conflict Occurred. Please fix merge conflict and rerun the integrate command')
191
+ end
192
+ it 'raises a helpful error' do
193
+ should meet_expectations
194
+ end
195
+ end
196
+ context 'when merge conflicts occur with the integrate command' do
197
+ let(:remote_branch_names) { ['origin/staging'] }
198
+ before do
199
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
200
+
201
+ expect(cli).to receive(:run_cmd).with("git fetch origin").ordered
202
+ expect(cli).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
203
+ expect(cli).to receive(:run_cmd).with("git checkout staging").ordered
204
+ expect(cli).to receive(:run_cmd).with("git merge feature-branch").and_raise('git merge feature-branch failed').ordered
205
+
206
+ expect { cli.integrate }.to raise_error(/Merge Conflict Occurred. Please fix merge conflict and rerun command with --resume feature-branch flag/)
207
+ end
208
+ it 'raises a helpful error' do
209
+ should meet_expectations
210
+ end
211
+ end
212
+ context 'with --resume "feature-branch" flag when feature-branch exists' do
213
+ let(:options) do
214
+ {
215
+ resume: 'feature-branch'
216
+ }
217
+ end
218
+ let(:repo) { cli.send(:repo) }
219
+ let(:authorization_token) { '123123' }
220
+ before do
221
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
222
+
223
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
224
+
225
+ expect(cli).not_to receive(:run_cmd).with("git branch -D staging")
226
+ expect(cli).not_to receive(:run_cmd).with("git push origin HEAD")
227
+ expect(cli).to receive(:run_cmd).with("git checkout feature-branch")
228
+
229
+ stub_request(:post, /.*api.github.com.*/).to_return(:status => 201)
230
+
231
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
232
+ cli.integrate
233
+ end
234
+ end
235
+ it 'does not delete local staging branch' do
236
+ should meet_expectations
237
+ end
238
+ it 'posts comment to pull request' do
239
+ expect(WebMock).to have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments")
240
+ end
241
+ end
242
+ context 'with --resume "feature-branch" flag when feature-branch does not exist' do
243
+ let(:options) do
244
+ {
245
+ resume: 'invalid-feature-branch'
246
+ }
247
+ end
248
+ let(:local_branch_names) { ['feature-branch'] }
249
+ let(:authorization_token) { '123123' }
250
+ before do
251
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
252
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
253
+ expect(cli).to receive(:ask).and_return('feature-branch')
254
+
255
+ expect(cli).not_to receive(:run_cmd).with("git branch -D staging")
256
+ expect(cli).not_to receive(:run_cmd).with("git push origin HEAD")
257
+ expect(cli).to receive(:run_cmd).with("git checkout feature-branch").ordered
258
+
259
+ stub_request(:post, /.*api.github.com.*/).to_return(:status => 201)
260
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
261
+ cli.integrate
262
+ end
263
+ end
264
+ it 'asks user for feature-branch name' do
265
+ should meet_expectations
266
+ end
267
+ it 'posts comment to pull request' do
268
+ expect(WebMock).to have_requested(:post, "https://api.github.com/repos/livebuzzevents/livebuzz-gitx/issues/10/comments")
269
+ end
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+ require 'livebuzz/gitx/cli/nuke_command'
3
+
4
+ describe LiveBuzz::Gitx::Cli::NukeCommand do
5
+ let(:args) { [] }
6
+ let(:options) { {} }
7
+ let(:config) do
8
+ {
9
+ pretend: true
10
+ }
11
+ end
12
+ let(:cli) { LiveBuzz::Gitx::Cli::NukeCommand.new(args, options, config) }
13
+ let(:branch) { double('fake branch', name: 'feature-branch') }
14
+
15
+ before do
16
+ allow(cli).to receive(:current_branch).and_return(branch)
17
+ end
18
+
19
+ describe '#nuke' do
20
+ context 'when target branch == prototype and --destination == master' do
21
+ let(:options) do
22
+ {
23
+ destination: good_branch
24
+ }
25
+ end
26
+ let(:good_branch) { 'master' }
27
+ let(:bad_branch) { 'prototype' }
28
+ let(:buildtag) { 'build-master-2013-10-01-01' }
29
+ before do
30
+ expect(cli).to receive(:yes?).and_return(true)
31
+
32
+ expect(cli).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
33
+
34
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
35
+ expect(cli).to receive(:run_cmd).with("git branch -D prototype", allow_failure: true).ordered
36
+ expect(cli).to receive(:run_cmd).with("git push origin --delete prototype", allow_failure: true).ordered
37
+ expect(cli).to receive(:run_cmd).with("git checkout -b prototype build-master-2013-10-01-01").ordered
38
+ expect(cli).to receive(:run_cmd).with("git push origin prototype").ordered
39
+ expect(cli).to receive(:run_cmd).with("git branch --set-upstream-to origin/prototype").ordered
40
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
41
+
42
+ cli.nuke bad_branch
43
+ end
44
+ it 'runs expected commands' do
45
+ should meet_expectations
46
+ end
47
+ end
48
+ context 'when target branch == prototype and destination prompt == nil' do
49
+ let(:good_branch) { 'master' }
50
+ let(:bad_branch) { 'prototype' }
51
+ let(:buildtag) { 'build-master-2013-10-01-01' }
52
+ before do
53
+ expect(cli).to receive(:ask).and_return(good_branch)
54
+ expect(cli).to receive(:yes?).and_return(true)
55
+
56
+ expect(cli).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
57
+
58
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
59
+ expect(cli).to receive(:run_cmd).with("git branch -D prototype", allow_failure: true).ordered
60
+ expect(cli).to receive(:run_cmd).with("git push origin --delete prototype", allow_failure: true).ordered
61
+ expect(cli).to receive(:run_cmd).with("git checkout -b prototype build-master-2013-10-01-01").ordered
62
+ expect(cli).to receive(:run_cmd).with("git push origin prototype").ordered
63
+ expect(cli).to receive(:run_cmd).with("git branch --set-upstream-to origin/prototype").ordered
64
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
65
+
66
+ cli.nuke 'prototype'
67
+ end
68
+ it 'defaults to prototype and should run expected commands' do
69
+ should meet_expectations
70
+ end
71
+ end
72
+ context 'when user does not confirm nuking the target branch' do
73
+ let(:buildtag) { 'build-master-2013-10-01-01' }
74
+ before do
75
+ expect(cli).to receive(:ask).and_return('master')
76
+ expect(cli).to receive(:yes?).and_return(false)
77
+
78
+ expect(cli).to receive(:current_build_tag).with('master').and_return(buildtag)
79
+
80
+ expect(cli).to_not receive(:run_cmd)
81
+
82
+ cli.nuke 'prototype'
83
+ end
84
+ it 'runs expected commands' do
85
+ should meet_expectations
86
+ end
87
+ end
88
+ context 'when no valid buildtag is found' do
89
+ let(:options) do
90
+ {
91
+ destination: good_branch
92
+ }
93
+ end
94
+ let(:good_branch) { 'master' }
95
+ let(:bad_branch) { 'prototype' }
96
+ let(:buildtags) { '' }
97
+ it 'raises error' do
98
+ expect(cli).to receive(:run_cmd).with("git fetch --tags").ordered
99
+ expect(cli).to receive(:run_cmd).with("git tag -l 'build-master-*'").and_return(buildtags).ordered
100
+
101
+ expect { cli.nuke('prototype') }.to raise_error(/No known good tag found for branch/)
102
+ end
103
+ end
104
+ context 'when database migrations exist and user cancels operation' do
105
+ let(:buildtag) { 'build-master-2013-10-01-01' }
106
+ let(:good_branch) { 'master' }
107
+ let(:bad_branch) { 'prototype' }
108
+ let(:migrations) do
109
+ %w( db/migrate/20140715194946_create_users.rb db/migrate/20140730063034_update_user_account.rb ).join("\n")
110
+ end
111
+ before do
112
+ FileUtils.mkdir_p('db/migrate')
113
+
114
+ expect(cli).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
115
+
116
+ expect(cli).to receive(:ask).and_return(good_branch)
117
+ expect(cli).to receive(:yes?).with('Reset prototype to build-master-2013-10-01-01? (y/n)', :green).and_return(true)
118
+ expect(cli).to receive(:run_cmd).with("git diff build-master-2013-10-01-01...prototype --name-only db/migrate").and_return(migrations)
119
+ expect(cli).to receive(:yes?).with('Are you sure you want to nuke prototype? (y/n) ', :green).and_return(false)
120
+
121
+ cli.nuke 'prototype'
122
+ end
123
+ after do
124
+ FileUtils.rm_rf('db/migrate')
125
+ end
126
+ it 'prompts for nuke confirmation' do
127
+ should meet_expectations
128
+ end
129
+ end
130
+ context 'when database migrations exist and user approves operation' do
131
+ let(:buildtag) { 'build-master-2013-10-01-01' }
132
+ let(:good_branch) { 'master' }
133
+ let(:bad_branch) { 'prototype' }
134
+ let(:migrations) do
135
+ %w( db/migrate/20140715194946_create_users.rb db/migrate/20140730063034_update_user_account.rb ).join("\n")
136
+ end
137
+ before do
138
+ FileUtils.mkdir_p('db/migrate')
139
+
140
+ expect(cli).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
141
+
142
+ expect(cli).to receive(:ask).and_return(good_branch)
143
+ expect(cli).to receive(:yes?).with('Reset prototype to build-master-2013-10-01-01? (y/n)', :green).and_return(true)
144
+ expect(cli).to receive(:run_cmd).with("git diff build-master-2013-10-01-01...prototype --name-only db/migrate").and_return(migrations)
145
+ expect(cli).to receive(:yes?).with('Are you sure you want to nuke prototype? (y/n) ', :green).and_return(true)
146
+
147
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
148
+ expect(cli).to receive(:run_cmd).with("git branch -D prototype", allow_failure: true).ordered
149
+ expect(cli).to receive(:run_cmd).with("git push origin --delete prototype", allow_failure: true).ordered
150
+ expect(cli).to receive(:run_cmd).with("git checkout -b prototype build-master-2013-10-01-01").ordered
151
+ expect(cli).to receive(:run_cmd).with("git push origin prototype").ordered
152
+ expect(cli).to receive(:run_cmd).with("git branch --set-upstream-to origin/prototype").ordered
153
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
154
+
155
+ cli.nuke 'prototype'
156
+ end
157
+ after do
158
+ FileUtils.rm_rf('db/migrate')
159
+ end
160
+ it 'prompts for nuke confirmation' do
161
+ should meet_expectations
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+ require 'livebuzz/gitx/cli/release_command'
3
+
4
+ describe LiveBuzz::Gitx::Cli::ReleaseCommand do
5
+ let(:args) { [] }
6
+ let(:options) { {} }
7
+ let(:config) do
8
+ {
9
+ pretend: true
10
+ }
11
+ end
12
+ let(:cli) { described_class.new(args, options, config) }
13
+ let(:branch) { double('fake branch', name: 'feature-branch') }
14
+ let(:authorization_token) { '123123' }
15
+
16
+ before do
17
+ allow(cli).to receive(:current_branch).and_return(branch)
18
+ end
19
+
20
+ describe '#release' do
21
+ context 'when user rejects release' do
22
+ before do
23
+ expect(cli).to receive(:yes?).and_return(false)
24
+ expect(cli).to_not receive(:run_cmd)
25
+
26
+ cli.release
27
+ end
28
+ it 'only runs update commands' do
29
+ should meet_expectations
30
+ end
31
+ end
32
+ context 'when user confirms release and pull request exists with non-success status' do
33
+ before do
34
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
35
+ expect(cli).to_not receive(:execute_command).with(LiveBuzz::Gitx::Cli::IntegrateCommand, :integrate, 'staging')
36
+ expect(cli).to_not receive(:execute_command).with(LiveBuzz::Gitx::Cli::CleanupCommand, :cleanup)
37
+
38
+ expect(cli).to receive(:yes?).with('Release feature-branch to production? (y/n)', :green).and_return(true)
39
+ expect(cli).to receive(:yes?).with('Branch status is currently: failure. Proceed with release? (y/n)', :red).and_return(false)
40
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
41
+
42
+ expect(cli).to_not receive(:run_cmd).with("git checkout master")
43
+ expect(cli).to_not receive(:run_cmd).with("git pull origin master")
44
+ expect(cli).to_not receive(:run_cmd).with("git merge --no-ff feature-branch")
45
+ expect(cli).to_not receive(:run_cmd).with("git push origin HEAD")
46
+
47
+ VCR.use_cassette('pull_request_does_exist_with_failure_status') do
48
+ cli.release
49
+ end
50
+ end
51
+ it 'runs expected commands' do
52
+ should meet_expectations
53
+ end
54
+ end
55
+ context 'when user confirms release and pull request exists with success status' do
56
+ before do
57
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
58
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::IntegrateCommand, :integrate, 'staging')
59
+ expect(cli).to_not receive(:execute_command).with(LiveBuzz::Gitx::Cli::CleanupCommand, :cleanup)
60
+
61
+ expect(cli).to receive(:yes?).and_return(true)
62
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
63
+
64
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
65
+ expect(cli).to receive(:run_cmd).with("git pull origin master").ordered
66
+ expect(cli).to receive(:run_cmd).with("git merge --no-ff feature-branch").ordered
67
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
68
+
69
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
70
+ cli.release
71
+ end
72
+ end
73
+ it 'runs expected commands' do
74
+ should meet_expectations
75
+ end
76
+ end
77
+ context 'when user confirms release and pull request does not exist' do
78
+ let(:new_pull_request) do
79
+ {
80
+ html_url: "https://path/to/html/pull/request",
81
+ issue_url: "https://api/path/to/issue/url",
82
+ number: 10,
83
+ head: {
84
+ ref: "branch_name"
85
+ }
86
+ }
87
+ end
88
+ before do
89
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
90
+ allow(cli).to receive(:ask_editor).and_return('description')
91
+
92
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update).twice
93
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::IntegrateCommand, :integrate, 'staging')
94
+ expect(cli).to_not receive(:execute_command).with(LiveBuzz::Gitx::Cli::CleanupCommand, :cleanup)
95
+
96
+ expect(cli).to receive(:yes?).with('Release feature-branch to production? (y/n)', :green).and_return(true)
97
+ expect(cli).to receive(:yes?).with('Branch status is currently: pending. Proceed with release? (y/n)', :red).and_return(true)
98
+
99
+ expect(cli).to receive(:run_cmd).with("git log master...feature-branch --reverse --no-merges --pretty=format:'* %s%n%b'").and_return("2013-01-01 did some stuff").ordered
100
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
101
+ expect(cli).to receive(:run_cmd).with("git pull origin master").ordered
102
+ expect(cli).to receive(:run_cmd).with("git merge --no-ff feature-branch").ordered
103
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
104
+
105
+ stub_request(:post, 'https://api.github.com/repos/livebuzzevents/livebuzz-gitx/pulls').to_return(:status => 201, :body => new_pull_request.to_json, :headers => {'Content-Type' => 'application/json'})
106
+ VCR.use_cassette('pull_request_does_not_exist') do
107
+ cli.release
108
+ end
109
+ end
110
+ it 'creates pull request on github' do
111
+ should meet_expectations
112
+ end
113
+ it 'runs expected commands' do
114
+ should meet_expectations
115
+ end
116
+ end
117
+ context 'when --cleanup flag passed' do
118
+ let(:options) do
119
+ {
120
+ cleanup: true
121
+ }
122
+ end
123
+ before do
124
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::UpdateCommand, :update)
125
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::IntegrateCommand, :integrate, 'staging')
126
+ expect(cli).to receive(:execute_command).with(LiveBuzz::Gitx::Cli::CleanupCommand, :cleanup)
127
+
128
+ expect(cli).to receive(:yes?).and_return(true)
129
+ allow(cli).to receive(:authorization_token).and_return(authorization_token)
130
+
131
+ expect(cli).to receive(:run_cmd).with("git checkout master").ordered
132
+ expect(cli).to receive(:run_cmd).with("git pull origin master").ordered
133
+ expect(cli).to receive(:run_cmd).with("git merge --no-ff feature-branch").ordered
134
+ expect(cli).to receive(:run_cmd).with("git push origin HEAD").ordered
135
+
136
+ VCR.use_cassette('pull_request_does_exist_with_success_status') do
137
+ cli.release
138
+ end
139
+ end
140
+ it 'runs expected commands' do
141
+ should meet_expectations
142
+ end
143
+ it 'prunes merged branches (git cleanup)' do
144
+ should meet_expectations
145
+ end
146
+ end
147
+ end
148
+ end