octopolo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/Guardfile +5 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +55 -0
- data/Rakefile +38 -0
- data/bash_completion.sh +13 -0
- data/bin/octopolo +21 -0
- data/bin/op +21 -0
- data/lib/octopolo.rb +15 -0
- data/lib/octopolo/changelog.rb +27 -0
- data/lib/octopolo/cli.rb +210 -0
- data/lib/octopolo/commands/accept_pull.rb +8 -0
- data/lib/octopolo/commands/compare_release.rb +9 -0
- data/lib/octopolo/commands/deployable.rb +8 -0
- data/lib/octopolo/commands/github_auth.rb +5 -0
- data/lib/octopolo/commands/new_branch.rb +9 -0
- data/lib/octopolo/commands/new_deployable.rb +8 -0
- data/lib/octopolo/commands/new_staging.rb +8 -0
- data/lib/octopolo/commands/octopolo_setup.rb +5 -0
- data/lib/octopolo/commands/pivotal_auth.rb +5 -0
- data/lib/octopolo/commands/pull_request.rb +13 -0
- data/lib/octopolo/commands/signoff.rb +10 -0
- data/lib/octopolo/commands/stage_up.rb +8 -0
- data/lib/octopolo/commands/stale_branches.rb +11 -0
- data/lib/octopolo/commands/sync_branch.rb +11 -0
- data/lib/octopolo/commands/tag_release.rb +13 -0
- data/lib/octopolo/config.rb +146 -0
- data/lib/octopolo/convenience_wrappers.rb +46 -0
- data/lib/octopolo/dated_branch_creator.rb +81 -0
- data/lib/octopolo/git.rb +262 -0
- data/lib/octopolo/github.rb +95 -0
- data/lib/octopolo/github/commit.rb +45 -0
- data/lib/octopolo/github/pull_request.rb +126 -0
- data/lib/octopolo/github/pull_request_creator.rb +127 -0
- data/lib/octopolo/github/user.rb +40 -0
- data/lib/octopolo/jira/story_commenter.rb +26 -0
- data/lib/octopolo/pivotal.rb +44 -0
- data/lib/octopolo/pivotal/story_commenter.rb +19 -0
- data/lib/octopolo/pull_request_merger.rb +99 -0
- data/lib/octopolo/renderer.rb +37 -0
- data/lib/octopolo/reports.rb +18 -0
- data/lib/octopolo/scripts.rb +23 -0
- data/lib/octopolo/scripts/accept_pull.rb +67 -0
- data/lib/octopolo/scripts/compare_release.rb +52 -0
- data/lib/octopolo/scripts/deployable.rb +27 -0
- data/lib/octopolo/scripts/github_auth.rb +87 -0
- data/lib/octopolo/scripts/new_branch.rb +34 -0
- data/lib/octopolo/scripts/new_deployable.rb +14 -0
- data/lib/octopolo/scripts/new_staging.rb +15 -0
- data/lib/octopolo/scripts/octopolo_setup.rb +55 -0
- data/lib/octopolo/scripts/pivotal_auth.rb +44 -0
- data/lib/octopolo/scripts/pull_request.rb +127 -0
- data/lib/octopolo/scripts/signoff.rb +85 -0
- data/lib/octopolo/scripts/stage_up.rb +26 -0
- data/lib/octopolo/scripts/stale_branches.rb +54 -0
- data/lib/octopolo/scripts/sync_branch.rb +37 -0
- data/lib/octopolo/scripts/tag_release.rb +70 -0
- data/lib/octopolo/templates/pull_request_body.erb +24 -0
- data/lib/octopolo/user_config.rb +112 -0
- data/lib/octopolo/version.rb +3 -0
- data/lib/octopolo/week.rb +130 -0
- data/octopolo.gemspec +31 -0
- data/spec/.DS_Store +0 -0
- data/spec/octopolo/cli_spec.rb +310 -0
- data/spec/octopolo/config_spec.rb +344 -0
- data/spec/octopolo/convenience_wrappers_spec.rb +80 -0
- data/spec/octopolo/dated_branch_creator_spec.rb +143 -0
- data/spec/octopolo/git_spec.rb +419 -0
- data/spec/octopolo/github/commit_spec.rb +59 -0
- data/spec/octopolo/github/pull_request_creator_spec.rb +174 -0
- data/spec/octopolo/github/pull_request_spec.rb +291 -0
- data/spec/octopolo/github/user_spec.rb +65 -0
- data/spec/octopolo/github_spec.rb +169 -0
- data/spec/octopolo/jira/stor_commenter_spec.rb +30 -0
- data/spec/octopolo/pivotal/story_commenter_spec.rb +34 -0
- data/spec/octopolo/pivotal_spec.rb +61 -0
- data/spec/octopolo/pull_request_merger_spec.rb +144 -0
- data/spec/octopolo/renderer_spec.rb +35 -0
- data/spec/octopolo/scripts/accept_pull_spec.rb +76 -0
- data/spec/octopolo/scripts/compare_release_spec.rb +115 -0
- data/spec/octopolo/scripts/deployable_spec.rb +52 -0
- data/spec/octopolo/scripts/github_auth_spec.rb +156 -0
- data/spec/octopolo/scripts/new_branch_spec.rb +41 -0
- data/spec/octopolo/scripts/new_deployable_spec.rb +18 -0
- data/spec/octopolo/scripts/new_staging_spec.rb +18 -0
- data/spec/octopolo/scripts/octopolo_setup_spec.rb +120 -0
- data/spec/octopolo/scripts/pivotal_auth_spec.rb +77 -0
- data/spec/octopolo/scripts/pull_request_spec.rb +217 -0
- data/spec/octopolo/scripts/signoff_spec.rb +139 -0
- data/spec/octopolo/scripts/stage_up_spec.rb +52 -0
- data/spec/octopolo/scripts/stale_branches_spec.rb +81 -0
- data/spec/octopolo/scripts/sync_branch_spec.rb +57 -0
- data/spec/octopolo/scripts/tag_release_spec.rb +108 -0
- data/spec/octopolo/user_config_spec.rb +167 -0
- data/spec/octopolo_spec.rb +7 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/engine_yard.cache +0 -0
- data/spec/support/sample_octopolo.yml +2 -0
- data/spec/support/sample_user.yml +2 -0
- data/templates/lib.erb +23 -0
- data/templates/script.erb +7 -0
- data/templates/spec.erb +29 -0
- metadata +344 -0
@@ -0,0 +1,419 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../lib/octopolo/git"
|
3
|
+
|
4
|
+
module Octopolo
|
5
|
+
describe Git do
|
6
|
+
let(:cli) { stub(:CLI) }
|
7
|
+
|
8
|
+
context ".perform(subcommand)" do
|
9
|
+
let(:command) { "status" }
|
10
|
+
|
11
|
+
before { Git.cli = cli }
|
12
|
+
|
13
|
+
it "performs the given subcommand" do
|
14
|
+
cli.should_receive(:perform).with("git #{command}")
|
15
|
+
Git.perform command
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context ".perform_quietly(subcommand)" do
|
20
|
+
let(:command) { "status" }
|
21
|
+
|
22
|
+
before { Git.cli = cli }
|
23
|
+
|
24
|
+
it "performs the given subcommand quietly" do
|
25
|
+
cli.should_receive(:perform_quietly).with("git #{command}")
|
26
|
+
Git.perform_quietly command
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context ".current_branch" do
|
31
|
+
let(:name) { "foo" }
|
32
|
+
let(:output) { "#{name}\n" }
|
33
|
+
let(:nobranch_output) { "#{Git::NO_BRANCH}\n" }
|
34
|
+
before { Git.cli = cli }
|
35
|
+
|
36
|
+
it "performs a command to filter current branch from list of branches" do
|
37
|
+
cli.should_receive(:perform_quietly).with("git branch | grep '^* ' | cut -c 3-") { output }
|
38
|
+
Git.current_branch.should == name
|
39
|
+
end
|
40
|
+
|
41
|
+
it "raises NotOnBranch if not on a branch" do
|
42
|
+
cli.should_receive(:perform_quietly) { nobranch_output }
|
43
|
+
expect { Git.current_branch }.to raise_error(Git::NotOnBranch, "Not currently checked out to a particular branch")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "staging and deploy should be reserved branches" do
|
47
|
+
Git.stub(:current_branch).and_return "staging.05.12"
|
48
|
+
Git.reserved_branch?.should be_true
|
49
|
+
|
50
|
+
Git.stub(:current_branch).and_return "deployable.05.12"
|
51
|
+
Git.reserved_branch?.should be_true
|
52
|
+
|
53
|
+
Git.stub(:current_branch).and_return "qaready.05.12"
|
54
|
+
Git.reserved_branch?.should be_true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "other branches should not be reserved branches" do
|
58
|
+
Git.stub(:current_branch).and_return "not_staging.05.12"
|
59
|
+
Git.reserved_branch?.should_not be_true
|
60
|
+
|
61
|
+
Git.stub(:current_branch).and_return "not_deployable.05.12"
|
62
|
+
Git.reserved_branch?.should_not be_true
|
63
|
+
|
64
|
+
Git.stub(:current_branch).and_return "not_qaready.05.12"
|
65
|
+
Git.reserved_branch?.should_not be_true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
context ".check_out(branch_name)" do
|
72
|
+
let(:name) { "foo" }
|
73
|
+
|
74
|
+
it "checks out the given branch name" do
|
75
|
+
Git.should_receive(:fetch)
|
76
|
+
Git.should_receive(:perform).with("checkout #{name}")
|
77
|
+
Git.should_receive(:pull)
|
78
|
+
Git.should_receive(:current_branch) { name }
|
79
|
+
Git.check_out name
|
80
|
+
end
|
81
|
+
|
82
|
+
it "raises an exception if the current branch is not the requested branch afterward" do
|
83
|
+
Git.should_receive(:fetch)
|
84
|
+
Git.should_receive(:perform)
|
85
|
+
Git.should_receive(:pull)
|
86
|
+
Git.should_receive(:current_branch) { "other" }
|
87
|
+
expect { Git.check_out name }.to raise_error(Git::CheckoutFailed, "Failed to check out '#{name}'")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context ".clean?" do
|
92
|
+
let(:cmd) { "git status --short" }
|
93
|
+
|
94
|
+
before { Git.cli = cli }
|
95
|
+
|
96
|
+
it "returns true if everything is checked in" do
|
97
|
+
cli.should_receive(:perform_quietly).with(cmd) { "" }
|
98
|
+
Git.should be_clean
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns false if the index has untracked files" do
|
102
|
+
cli.should_receive(:perform_quietly).with(cmd) { "?? foo.txt" }
|
103
|
+
Git.should_not be_clean
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns false if the index has missing files" do
|
107
|
+
cli.should_receive(:perform_quietly).with(cmd) { "D foo.txt" }
|
108
|
+
Git.should_not be_clean
|
109
|
+
end
|
110
|
+
|
111
|
+
it "returns false if the index has changed files" do
|
112
|
+
cli.should_receive(:perform_quietly).with(cmd) { "M foo.txt" }
|
113
|
+
Git.should_not be_clean
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context ".if_clean" do
|
118
|
+
let(:custom_message) { "Some other message" }
|
119
|
+
|
120
|
+
it "performs the block if the git index is clean" do
|
121
|
+
Git.should_receive(:clean?) { true }
|
122
|
+
Math.should_receive(:log).with(1)
|
123
|
+
|
124
|
+
Git.if_clean do
|
125
|
+
Math.log 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it "does not perform the block if the git index is not clean" do
|
130
|
+
Git.should_receive(:clean?) { false }
|
131
|
+
Math.should_not_receive(:log)
|
132
|
+
Git.should_receive(:alert_dirty_index).with(Git::DEFAULT_DIRTY_MESSAGE)
|
133
|
+
|
134
|
+
Git.if_clean do
|
135
|
+
Math.log 1
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it "prints a custom message if git index is not clean" do
|
140
|
+
Git.should_receive(:clean?) { false }
|
141
|
+
Math.should_not_receive(:log)
|
142
|
+
Git.should_receive(:alert_dirty_index).with(custom_message)
|
143
|
+
|
144
|
+
Git.if_clean custom_message do
|
145
|
+
Math.log 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context ".alert_dirty_index(message)" do
|
151
|
+
let(:message) { "Some message" }
|
152
|
+
|
153
|
+
before { Git.cli = cli }
|
154
|
+
|
155
|
+
it "prints the given message and shows the git status" do
|
156
|
+
cli.should_receive(:say).with(" ")
|
157
|
+
cli.should_receive(:say).with(message)
|
158
|
+
cli.should_receive(:say).with(" ")
|
159
|
+
Git.should_receive(:perform).with("status")
|
160
|
+
|
161
|
+
Git.alert_dirty_index message
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context ".merge(branch_name)" do
|
166
|
+
let(:branch_name) { "foo" }
|
167
|
+
|
168
|
+
it "fetches the latest code and merges the given branch name" do
|
169
|
+
Git.should_receive(:if_clean).and_yield
|
170
|
+
Git.should_receive(:fetch)
|
171
|
+
Git.should_receive(:perform).with("merge --no-ff origin/#{branch_name}")
|
172
|
+
Git.should_receive(:clean?) { true }
|
173
|
+
Git.should_receive(:push)
|
174
|
+
|
175
|
+
Git.merge branch_name
|
176
|
+
end
|
177
|
+
|
178
|
+
it "does not push and raises MergeFailed if the merge failed" do
|
179
|
+
Git.should_receive(:if_clean).and_yield
|
180
|
+
Git.should_receive(:fetch)
|
181
|
+
Git.should_receive(:perform).with("merge --no-ff origin/#{branch_name}")
|
182
|
+
Git.should_receive(:clean?) { false }
|
183
|
+
Git.should_not_receive(:push)
|
184
|
+
|
185
|
+
expect { Git.merge branch_name }.to raise_error(Git::MergeFailed)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context ".fetch" do
|
190
|
+
it "fetches and prunes remote branches" do
|
191
|
+
Git.should_receive(:perform_quietly).with("fetch --prune")
|
192
|
+
|
193
|
+
Git.fetch
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context ".push" do
|
198
|
+
let(:branch) { "current_branch" }
|
199
|
+
|
200
|
+
it "pushes the current branch" do
|
201
|
+
Git.stub(current_branch: branch)
|
202
|
+
Git.should_receive(:if_clean).and_yield
|
203
|
+
Git.should_receive(:perform).with("push origin #{branch}")
|
204
|
+
|
205
|
+
Git.push
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context ".pull" do
|
210
|
+
it "performs a pull if the index is clean" do
|
211
|
+
Git.should_receive(:if_clean).and_yield
|
212
|
+
Git.should_receive(:perform).with("pull")
|
213
|
+
Git.pull
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context ".remote_branches" do
|
218
|
+
let(:raw_output) { raw_names.join("\n ") }
|
219
|
+
let(:raw_names) { %w(origin/foo origin/bar) }
|
220
|
+
let(:cleaned_names) { %w(foo bar) }
|
221
|
+
|
222
|
+
it "prunes the remote branch list and grabs all the branch names" do
|
223
|
+
Git.should_receive(:fetch)
|
224
|
+
Git.should_receive(:perform_quietly).with("branch --remote") { raw_output }
|
225
|
+
Git.remote_branches.should == cleaned_names.sort
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context ".branches_for branch_type" do
|
230
|
+
let(:remote_branches) { [depl1, rando, stage1, depl2].sort }
|
231
|
+
let(:depl1) { "deployable.12.20" }
|
232
|
+
let(:depl2) { "deployable.11.05" }
|
233
|
+
let(:stage1) { "staging.04.05" }
|
234
|
+
let(:rando) { "something-else" }
|
235
|
+
|
236
|
+
before do
|
237
|
+
Git.should_receive(:remote_branches) { remote_branches }
|
238
|
+
end
|
239
|
+
|
240
|
+
it "can find deployable branches" do
|
241
|
+
deployables = Git.branches_for(Git::DEPLOYABLE_PREFIX)
|
242
|
+
deployables.should include depl1
|
243
|
+
deployables.should include depl2
|
244
|
+
deployables.should == [depl1, depl2].sort
|
245
|
+
deployables.count.should == 2
|
246
|
+
end
|
247
|
+
|
248
|
+
it "can find staging branches" do
|
249
|
+
stagings = Git.branches_for(Git::STAGING_PREFIX)
|
250
|
+
stagings.should include stage1
|
251
|
+
stagings.count.should == 1
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context ".deployable_branch" do
|
256
|
+
let(:depl1) { "deployable.12.05" }
|
257
|
+
let(:depl2) { "deployable.12.25" }
|
258
|
+
|
259
|
+
it "returns the last deployable branch" do
|
260
|
+
Git.should_receive(:branches_for).with(Git::DEPLOYABLE_PREFIX) { [depl1, depl2] }
|
261
|
+
Git.deployable_branch.should == depl2
|
262
|
+
end
|
263
|
+
|
264
|
+
it "raises an exception if none exist" do
|
265
|
+
Git.should_receive(:branches_for).with(Git::DEPLOYABLE_PREFIX) { [] }
|
266
|
+
expect { Git.deployable_branch.should }.to raise_error(Git::NoBranchOfType, "No #{Git::DEPLOYABLE_PREFIX} branch")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context ".staging_branch" do
|
271
|
+
let(:stage1) { "stage1" }
|
272
|
+
let(:stage2) { "stage2" }
|
273
|
+
|
274
|
+
it "returns the last staging branch" do
|
275
|
+
Git.should_receive(:branches_for).with(Git::STAGING_PREFIX) { [stage1, stage2] }
|
276
|
+
Git.staging_branch.should == stage2
|
277
|
+
end
|
278
|
+
|
279
|
+
it "raises an exception if none exist" do
|
280
|
+
Git.should_receive(:branches_for).with(Git::STAGING_PREFIX) { [] }
|
281
|
+
expect { Git.staging_branch}.to raise_error(Git::NoBranchOfType, "No #{Git::STAGING_PREFIX} branch")
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context ".qaready_branch" do
|
286
|
+
let(:qaready1) { "qaready1" }
|
287
|
+
let(:qaready2) { "qaready2" }
|
288
|
+
|
289
|
+
it "returns the last qaready branch" do
|
290
|
+
Git.should_receive(:branches_for).with(Git::QAREADY_PREFIX) { [qaready1, qaready2] }
|
291
|
+
Git.qaready_branch.should == qaready2
|
292
|
+
end
|
293
|
+
|
294
|
+
it "raises an exception if none exist" do
|
295
|
+
Git.should_receive(:branches_for).with(Git::QAREADY_PREFIX) { [] }
|
296
|
+
expect { Git.qaready_branch }.to raise_error(Git::NoBranchOfType, "No #{Git::QAREADY_PREFIX} branch")
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context ".release_tags" do
|
301
|
+
let(:valid1) { "2012.02.28" }
|
302
|
+
let(:valid2) { "2012.11.10" }
|
303
|
+
let(:invalid) { "foothing" }
|
304
|
+
let(:tags) { [valid1, invalid, valid2].join("\n") }
|
305
|
+
|
306
|
+
it "returns all the tags for releases" do
|
307
|
+
Git.should_receive(:perform_quietly).with("tag") { tags }
|
308
|
+
release_tags = Git.release_tags
|
309
|
+
release_tags.should_not include invalid
|
310
|
+
release_tags.should include valid1
|
311
|
+
release_tags.should include valid2
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context ".recent_release_tags" do
|
316
|
+
let(:long_list) { Array.new(100, "sometag#{rand(1000)}") } # big-ass list
|
317
|
+
|
318
|
+
it "returns the last #{Git::RECENT_TAG_LIMIT} tags" do
|
319
|
+
Git.should_receive(:release_tags) { long_list }
|
320
|
+
tags = Git.recent_release_tags
|
321
|
+
tags.count.should == Git::RECENT_TAG_LIMIT
|
322
|
+
tags.should == long_list.last(Git::RECENT_TAG_LIMIT)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context ".new_branch(new_branch_name, source_branch_name)" do
|
327
|
+
let(:new_branch_name) { "foo" }
|
328
|
+
let(:source_branch_name) { "bar" }
|
329
|
+
|
330
|
+
it "creates and pushes a new branch from the source branch" do
|
331
|
+
Git.should_receive(:fetch)
|
332
|
+
Git.should_receive(:perform).with("branch --no-track #{new_branch_name} origin/#{source_branch_name}")
|
333
|
+
Git.should_receive(:check_out).with(new_branch_name)
|
334
|
+
Git.should_receive(:perform).with("push --set-upstream origin #{new_branch_name}")
|
335
|
+
|
336
|
+
Git.new_branch(new_branch_name, source_branch_name)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context ".new_tag(tag_name)" do
|
341
|
+
let(:tag) { "asdf" }
|
342
|
+
|
343
|
+
it "creates a new tag with the given name and pushes it" do
|
344
|
+
Git.should_receive(:perform).with("tag #{tag}")
|
345
|
+
Git.should_receive(:push)
|
346
|
+
Git.should_receive(:perform).with("push --tag")
|
347
|
+
|
348
|
+
Git.new_tag(tag)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context ".stale_branches(destination_branch, branches_to_ignore)" do
|
353
|
+
let(:ignored) { %w(foo bar) }
|
354
|
+
let(:branch_name) { "master" }
|
355
|
+
let(:sha) { "asdf123" }
|
356
|
+
let(:raw_result) do
|
357
|
+
%Q(
|
358
|
+
origin/bing
|
359
|
+
origin/bang
|
360
|
+
)
|
361
|
+
end
|
362
|
+
|
363
|
+
it "checks for stale branches for the given branch, less branches to ignore" do
|
364
|
+
Git.should_receive(:fetch)
|
365
|
+
Git.should_receive(:stale_branches_to_ignore).with(ignored) { ignored }
|
366
|
+
Git.should_receive(:recent_sha).with(branch_name) { sha }
|
367
|
+
Git.should_receive(:perform_quietly).with("branch --remote --merged #{sha} | grep -E -v '(foo|bar)'") { raw_result }
|
368
|
+
|
369
|
+
expect(Git.stale_branches(branch_name, ignored)).to eq(%w(bing bang))
|
370
|
+
end
|
371
|
+
|
372
|
+
it "defaults to master branch and no extra branches to ignore" do
|
373
|
+
Git.should_receive(:fetch)
|
374
|
+
Git.should_receive(:stale_branches_to_ignore).with([]) { ignored }
|
375
|
+
Git.should_receive(:recent_sha).with("master") { sha }
|
376
|
+
Git.should_receive(:perform_quietly).with("branch --remote --merged #{sha} | grep -E -v '(foo|bar)'") { raw_result }
|
377
|
+
|
378
|
+
Git.stale_branches
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
context "#branches_to_ignore(custom_branch_list)" do
|
383
|
+
it "ignores some branches by default" do
|
384
|
+
expect(Git.send(:stale_branches_to_ignore)).to include "HEAD"
|
385
|
+
expect(Git.send(:stale_branches_to_ignore)).to include "master"
|
386
|
+
expect(Git.send(:stale_branches_to_ignore)).to include "staging"
|
387
|
+
expect(Git.send(:stale_branches_to_ignore)).to include "deployable"
|
388
|
+
end
|
389
|
+
|
390
|
+
it "accepts an optional list of additional branches to ignore" do
|
391
|
+
expect(Git.send(:stale_branches_to_ignore, ["foo"])).to include "HEAD"
|
392
|
+
expect(Git.send(:stale_branches_to_ignore, ["foo"])).to include "master"
|
393
|
+
expect(Git.send(:stale_branches_to_ignore, ["foo"])).to include "staging"
|
394
|
+
expect(Git.send(:stale_branches_to_ignore, ["foo"])).to include "deployable"
|
395
|
+
expect(Git.send(:stale_branches_to_ignore, ["foo"])).to include "foo"
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
context "#recent_sha(branch_name)" do
|
400
|
+
let(:branch_name) { "foo" }
|
401
|
+
let(:raw_sha) { "asdf123\n" }
|
402
|
+
|
403
|
+
it "grabs the SHA of the given branch from 1 day ago" do
|
404
|
+
Git.should_receive(:perform_quietly).with("rev-list `git rev-parse remotes/origin/#{branch_name} --before=1.day.ago` --max-count=1") { raw_sha }
|
405
|
+
expect(Git.send(:recent_sha, branch_name)).to eq("asdf123")
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
context ".delete_branch(branch_name)" do
|
410
|
+
let(:branch_name) { "foo" }
|
411
|
+
|
412
|
+
it "leverages git-extra's delete-branch command" do
|
413
|
+
Git.should_receive(:perform).with("push origin :#{branch_name}")
|
414
|
+
Git.should_receive(:perform).with("branch -D #{branch_name}")
|
415
|
+
Git.delete_branch branch_name
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require_relative "../../../lib/octopolo/github/commit"
|
3
|
+
|
4
|
+
module Octopolo
|
5
|
+
module GitHub
|
6
|
+
describe Commit do
|
7
|
+
context ".new" do
|
8
|
+
let(:commit_data) { stub }
|
9
|
+
|
10
|
+
it "remembers the commit data from GitHub API" do
|
11
|
+
commit = Commit.new commit_data
|
12
|
+
commit.commit_data.should == commit_data
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "#author_name" do
|
17
|
+
let(:commit) do
|
18
|
+
Commit.new stub
|
19
|
+
end
|
20
|
+
|
21
|
+
it "fetches the author name from the author" do
|
22
|
+
commit.stub(:author => stub(:author_name => "pbyrne"))
|
23
|
+
commit.author_name.should == "pbyrne"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#author" do
|
28
|
+
let(:commit_data) do
|
29
|
+
stub(:author => stub(:login => "pbyrne"))
|
30
|
+
end
|
31
|
+
|
32
|
+
it "fetches the User from github" do
|
33
|
+
commit = Commit.new commit_data
|
34
|
+
GitHub::User.should_receive(:new).with("pbyrne")
|
35
|
+
commit.author
|
36
|
+
end
|
37
|
+
|
38
|
+
it "gracefully handles a commit without an author" do
|
39
|
+
commit = Commit.new author: nil
|
40
|
+
User.should_receive(:new).with(GitHub::UNKNOWN_USER)
|
41
|
+
commit.author
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context ".for_pull_request pull_request" do
|
46
|
+
let(:pull_request) { stub(repo_name: "foo/bar", number: 123) }
|
47
|
+
let(:raw_commit1) { stub }
|
48
|
+
let(:raw_commits) { [raw_commit1] }
|
49
|
+
let(:wrapper_commit) { stub }
|
50
|
+
|
51
|
+
it "fetches from octokit and returns Commit wrappers" do
|
52
|
+
GitHub.should_receive(:pull_request_commits).with(pull_request.repo_name, pull_request.number) { raw_commits }
|
53
|
+
Commit.should_receive(:new).with(raw_commit1) { wrapper_commit }
|
54
|
+
Commit.for_pull_request(pull_request).should == [wrapper_commit]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|