livebuzz-gitx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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