gitcycle 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -99,11 +99,8 @@ This will add a "pass" label to the issue and will complete the pull request by
99
99
  Todo
100
100
  ----
101
101
 
102
- * Make ticket active when starting branch
103
- * Label issues with ticket milestone?
104
102
  * Check for conflict whenever merge happens
103
+ * Add conflict check when calling "qa pass [ticket]"
105
104
  * Instead of detecting CONFLICT, use error status $? != 0
106
105
  * Add comment on lighthouse with issue URL
107
- * Need to make sure when a branch is created, it is always from the pristine remote version, not local
108
- * Add conflict check when calling "qa pass [ticket]"
109
- * Need to change Github.parseLabels so we can have a "Fail" label along side a "Pending" tag, but for all other cases there should only be one of these tags present: "Pending QA", "Pending Review", "Pass"
106
+ * Label issues with ticket milestone?
@@ -29,13 +29,11 @@ Scenario: Feature branch w/ custom branch name
29
29
  """
30
30
  Retrieving branch information from gitcycle.
31
31
  Your work will eventually merge into 'master'. Is this correct? (y/n)
32
- Adding remote repo 'br/gitcycle_test'.
33
- Fetching remote repo 'br'.
34
- Checking out remote branch 'master' from 'br/gitcycle_test'.
35
32
  Would you like to name your branch 'ticket.id'? (y/n)
36
33
  What would you like to name your branch?
37
- Creating 'ticket.id-rename' from 'master'.
38
- Checking out branch 'ticket.id-rename'.
34
+ Adding remote repo 'config.owner/config.repo'.
35
+ Fetching remote repo 'config.owner/config.repo'.
36
+ Checking out remote branch 'ticket.id-rename' from 'config.owner/config.repo/master'.
39
37
  Pushing 'ticket.id-rename'.
40
38
  Sending branch information to gitcycle.
41
39
  """
@@ -53,12 +51,10 @@ Scenario: Feature branch
53
51
  """
54
52
  Retrieving branch information from gitcycle.
55
53
  Your work will eventually merge into 'master'. Is this correct? (y/n)
56
- Adding remote repo 'br/gitcycle_test'.
57
- Fetching remote repo 'br'.
58
- Checking out remote branch 'master' from 'br/gitcycle_test'.
59
54
  Would you like to name your branch 'ticket.id'? (y/n)
60
- Creating 'ticket.id' from 'master'.
61
- Checking out branch 'ticket.id'.
55
+ Adding remote repo 'config.owner/config.repo'.
56
+ Fetching remote repo 'config.owner/config.repo'.
57
+ Checking out remote branch 'ticket.id' from 'config.owner/config.repo/master'.
62
58
  Pushing 'ticket.id'.
63
59
  Sending branch information to gitcycle.
64
60
  """
@@ -99,7 +95,7 @@ Scenario: Pull changes from upstream
99
95
  """
100
96
  Retrieving branch information from gitcycle.
101
97
  Adding remote repo 'config.owner/config.repo'.
102
- Fetching remote repo 'config.owner'.
98
+ Fetching remote repo 'config.owner/config.repo'.
103
99
  Merging remote branch 'master' from 'config.owner/config.repo'.
104
100
  """
105
101
  And git log should contain the last commit
@@ -179,11 +175,25 @@ Scenario: QA issue
179
175
  """
180
176
  Retrieving branch information from gitcycle.
181
177
  Deleting old QA branch 'qa_master'.
182
- Creating QA branch 'qa_master'.
183
- Adding remote repo 'config.user/gitcycle_test'.
184
- Fetching remote repo 'config.user'.
185
- Merging remote branch 'ticket.id' from 'config.user/gitcycle_test'.
186
- Pushing QA branch 'qa_master'.
178
+ Adding remote repo 'config.owner/config.repo'.
179
+ Fetching remote repo 'config.owner/config.repo'.
180
+ Checking out remote branch 'qa_master' from 'config.owner/config.repo/master'.
181
+ Pushing 'qa_master'.
182
+ Adding remote repo 'config.user/config.repo'.
183
+ Fetching remote repo 'config.user/config.repo'.
184
+ Merging remote branch 'ticket.id' from 'config.user/config.repo'.
185
+ Pushing branch 'qa_master'.
187
186
  Type 'gitc qa pass' to approve all issues in this branch.
188
187
  Type 'gitc qa fail' to reject all issues in this branch.
188
+ """
189
+
190
+ Scenario: QA issue list
191
+ When I cd to the owner repo
192
+ And I checkout master
193
+ And I execute gitcycle with "qa"
194
+ Then gitcycle runs
195
+ And output includes
196
+ """
197
+ qa_master
198
+ issue #issue.id config.user/ticket.id
189
199
  """
data/gitcycle.gemspec CHANGED
@@ -6,7 +6,7 @@ $:.unshift lib unless $:.include?(lib)
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "gitcycle"
9
- s.version = '0.1.10'
9
+ s.version = '0.1.11'
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = [ 'Winton Welsh' ]
12
12
  s.email = [ 'mail@wintoni.us' ]
data/lib/gitcycle.rb CHANGED
@@ -63,39 +63,32 @@ class Gitcycle
63
63
  branch['home'] = @git_login
64
64
  branch['source'] = branches(:current => true)
65
65
 
66
- unless yes?("Your work will eventually merge into '#{branch['source']}'. Is this correct?")
66
+ unless yes?("\nYour work will eventually merge into '#{branch['source']}'. Is this correct?")
67
67
  branch['source'] = q("What branch would you like to eventually merge into?")
68
68
  end
69
69
 
70
- checkout_remote_branch(
71
- :owner => owner,
72
- :repo => repo,
73
- :branch => branch['source']
74
- )
75
-
76
70
  unless yes?("Would you like to name your branch '#{name}'?")
77
71
  name = q("\nWhat would you like to name your branch?")
78
72
  name = name.gsub(/[\s\W]/, '-')
79
73
  end
80
74
 
81
- unless branches(:match => name)
82
- puts "\nCreating '#{name}' from '#{branch['source']}'.\n".green
83
- run("git branch #{name}")
84
- end
75
+ checkout_remote_branch(
76
+ :owner => owner,
77
+ :repo => repo,
78
+ :branch => branch['source'],
79
+ :target => name
80
+ )
85
81
  end
86
82
 
87
- if branches(:match => name)
88
- puts "Checking out branch '#{name}'.\n".green
89
- run("git checkout #{name}")
83
+ if branch['exists']
84
+ if branches(:match => name)
85
+ puts "Checking out branch '#{name}'.\n".green
86
+ run("git checkout #{name}")
87
+ else
88
+ puts "Tracking branch '#{name}'.\n".green
89
+ run("git fetch && git checkout -b #{name} origin/#{name}")
90
+ end
90
91
  else
91
- puts "Tracking branch '#{name}'.\n".green
92
- run("git fetch && git checkout -b #{name} origin/#{name}")
93
- end
94
-
95
- unless branch['exists']
96
- puts "Pushing '#{name}'.\n".green
97
- run("git push origin #{name}")
98
-
99
92
  puts "Sending branch information to gitcycle.".green
100
93
  get('branch',
101
94
  'branch[home]' => branch['home'],
@@ -175,52 +168,56 @@ class Gitcycle
175
168
  puts "\nRetrieving branch information from gitcycle.\n".green
176
169
  qa_branch = get('qa_branch', :source => branch.gsub(/^qa_/, ''))
177
170
 
178
- puts "Checking out #{qa_branch['source']}.".green
179
- run("git checkout #{qa_branch['source']}")
180
- run("git pull origin #{qa_branch['source']}")
171
+ pass_fail = issues.first
172
+ issues = issues[1..-1]
181
173
 
182
- if issues[1..-1].empty?
183
- if issues.first == 'pass'
184
- puts "Merging '#{branch}' into '#{qa_branch['source']}'.\n".green
185
- run("git merge #{branch}")
186
- run("git pull origin #{qa_branch['source']}")
187
- run("git push origin #{qa_branch['source']}")
188
- end
189
-
190
- puts "\nLabeling all issues as '#{label}'.\n".green
191
- get('label',
192
- 'qa_branch[source]' => branch.gsub(/^qa_/, ''),
193
- 'labels' => [ label ]
194
- )
174
+ if pass_fail == 'pass'
175
+ puts "Checking out #{qa_branch['source']}.".green
176
+ run("git checkout #{qa_branch['source']}")
177
+ run("git pull origin #{qa_branch['source']}")
178
+ # TODO: track if source branch doesn't exist
179
+ end
195
180
 
181
+ if issues.empty?
196
182
  branches = qa_branch['branches']
197
183
  else
198
- issues = [1..-1]
199
-
200
184
  branches = qa_branch['branches'].select do |b|
201
185
  issues.include?(b['issue'])
202
186
  end
187
+ end
203
188
 
204
- branches.each do |branch|
205
- if issues.first == 'pass'
206
- merge_remote_branch(
207
- :user => branch['user'],
208
- :repo => branch['repo'].split(':'),
209
- :branch => branch['branch']
210
- )
211
- end
189
+ branches.each do |branch|
190
+ if pass_fail == 'pass'
191
+ merge_remote_branch(
192
+ :owner => branch['home'],
193
+ :repo => branch['repo'].split(':')[1],
194
+ :branch => branch['branch'],
195
+ :issue => branch['issue'],
196
+ :issues => qa_branch['branches'].collect { |b| b['issue'] },
197
+ :type => :from_qa
198
+ )
199
+ end
212
200
 
201
+ if !issues.empty? || pass_fail == 'pass'
213
202
  puts "\nLabeling issue #{branch['issue']} as '#{label}'.\n".green
214
203
  get('label',
215
- 'qa_branch[source]' => branch.gsub(/^qa_/, ''),
204
+ 'qa_branch[source]' => qa_branch['source'],
216
205
  'issue' => branch['issue'],
217
206
  'labels' => [ label ]
218
207
  )
219
208
  end
220
209
  end
221
210
 
222
- if issues.first == 'pass'
223
- puts "\nMarking Lighthouse tickets as 'pending-approval'.\n".green
211
+ if issues.empty? && pass_fail == 'fail'
212
+ puts "\nLabeling all issues as '#{label}'.\n".green
213
+ get('label',
214
+ 'qa_branch[source]' => qa_branch['source'],
215
+ 'labels' => [ label ]
216
+ )
217
+ end
218
+
219
+ if pass_fail == 'pass'
220
+ puts "Marking Lighthouse tickets as 'pending-approval'.\n".green
224
221
  branches = branches.collect do |b|
225
222
  { :name => b['branch'], :repo => b['repo'], :user => b['user'] }
226
223
  end
@@ -235,26 +232,27 @@ class Gitcycle
235
232
  if branch =~ /^qa_/
236
233
  puts "\nRetrieving branch information from gitcycle.\n".green
237
234
  qa_branch = get('qa_branch', :source => branch.gsub(/^qa_/, ''))
235
+
236
+ branches = qa_branch['branches']
237
+ conflict = branches.detect { |branch| branch['conflict'] }
238
238
 
239
- if qa_branch
240
- branches = qa_branch['branches']
241
- conflict = branches.detect { |branch| branch['conflict'] }
239
+ if qa_branch && conflict
240
+ puts "Committing merge resolution of #{conflict['branch']} (issue ##{conflict['issue']}).\n".green
241
+ run("git add . && git add . -u && git commit -a -F .git/MERGE_MSG")
242
242
 
243
- if conflict
244
- puts "Committing merge resolution of #{conflict['branch']} (issue ##{conflict['issue']}).\n".green
245
- run("git add . && git add . -u && git commit -a -m 'Merge conflict resolution of #{conflict['branch']} (issue ##{conflict['issue']})'")
243
+ puts "Pushing merge resolution of #{conflict['branch']} (issue ##{conflict['issue']}).\n".green
244
+ run("git push origin qa_#{qa_branch['source']}")
246
245
 
247
- puts "Pushing merge resolution of #{conflict['branch']} (issue ##{conflict['issue']}).\n".green
248
- run("git push origin qa_#{qa_branch['source']}")
246
+ puts "\nDe-conflicting on gitcycle.\n".green
247
+ get('qa_branch',
248
+ 'issues' => branches.collect { |branch| branch['issue'] }
249
+ )
249
250
 
250
- create_qa_branch(
251
- :preserve => true,
252
- :range => (branches.index(conflict)+1..-1),
253
- :qa_branch => qa_branch
254
- )
255
- else
256
- puts "Couldn't find record of a conflicted merge.\n".red
257
- end
251
+ create_qa_branch(
252
+ :preserve => true,
253
+ :range => (branches.index(conflict)+1..-1),
254
+ :qa_branch => qa_branch
255
+ )
258
256
  else
259
257
  puts "Couldn't find record of a conflicted merge.\n".red
260
258
  end
@@ -297,17 +295,25 @@ class Gitcycle
297
295
  def reviewed(*issues)
298
296
  require_git && require_config
299
297
 
298
+ if issues.include?("fail")
299
+ issues = issues.reject{|x| x=='fail'}
300
+ label = 'Fail'
301
+ else
302
+ issues = issues.reject{|x| x=='pass'}
303
+ label = 'Pending QA'
304
+ end
305
+
300
306
  if issues.empty?
301
- puts "\nLabeling issue as 'Pending QA'.\n".green
307
+ puts "\nLabeling issue as '#{label}'.\n".green
302
308
  get('label',
303
309
  'branch[name]' => branches(:current => true),
304
- 'labels' => [ 'Pending QA' ]
310
+ 'labels' => [ label ]
305
311
  )
306
312
  else
307
- puts "\nLabeling issues as 'Pending QA'.\n".green
313
+ puts "\nLabeling issues as '#{label}'.\n".green
308
314
  get('label',
309
315
  'issues' => issues,
310
- 'labels' => [ 'Pending QA' ],
316
+ 'labels' => [ label ],
311
317
  'scope' => 'repo'
312
318
  )
313
319
  end
@@ -348,7 +354,7 @@ class Gitcycle
348
354
  run("git remote add #{owner} git@github.com:#{owner}/#{repo}.git")
349
355
  end
350
356
 
351
- puts "\nFetching remote repo '#{owner}'.\n".green
357
+ puts "Fetching remote repo '#{owner}/#{repo}'.\n".green
352
358
  run("git fetch #{owner}")
353
359
  end
354
360
 
@@ -367,23 +373,23 @@ class Gitcycle
367
373
  owner = options[:owner]
368
374
  repo = options[:repo]
369
375
  branch = options[:branch]
376
+ target = options[:target] || branch
377
+
378
+ if branches(:match => target)
379
+ unless yes?("You already have a branch called '#{target}'. Overwrite?")
380
+ run("git checkout #{target}")
381
+ run("git pull #{owner} #{target}")
382
+ return
383
+ end
384
+ end
370
385
 
371
386
  add_remote_and_fetch(options)
372
387
 
373
- puts "\nChecking out remote branch '#{branch}' from '#{owner}/#{repo}'.\n".green
388
+ puts "Checking out remote branch '#{target}' from '#{owner}/#{repo}/#{branch}'.\n".green
389
+ run("git checkout -b #{target} #{owner}/#{branch}")
374
390
 
375
- if branches(:match => branch)
376
- run("git checkout #{branch}")
377
- else
378
- run("git checkout -b #{branch} #{owner}/#{branch}")
379
- end
380
-
381
- if branches(:current => true) == branch
382
- run("git pull #{owner} #{branch}")
383
- else
384
- puts "Oops. Something bad happened.\n".red
385
- exit
386
- end
391
+ puts "Pushing '#{target}'.\n".green
392
+ run("git push origin #{target}")
387
393
  end
388
394
 
389
395
  def create_pull_request
@@ -423,27 +429,19 @@ class Gitcycle
423
429
 
424
430
  unless qa_branch['branches'].empty?
425
431
  unless options[:preserve]
426
- if branches(:current => source)
427
- # Do nothing
428
- elsif branches(:match => source)
429
- puts "Checking out source branch '#{source}'.\n".green
430
- run("git checkout #{source}")
431
- else
432
- puts "Tracking source branch '#{source}'.\n".green
433
- run("git fetch && git checkout -b #{source} origin/#{source}")
434
- end
435
-
436
- run("git pull origin #{source}")
437
-
438
432
  if branches(:match => name, :all => true)
439
433
  puts "Deleting old QA branch '#{name}'.\n".green
440
- run("git branch -D #{name}")
434
+ run("git branch -D #{name}") if branches(:match => name)
441
435
  run("git push origin :#{name}")
442
436
  end
443
-
444
- puts "Creating QA branch '#{name}'.\n".green
445
- run("git branch #{name} && git checkout #{name}")
446
437
 
438
+ checkout_remote_branch(
439
+ :owner => @git_login,
440
+ :repo => @git_repo,
441
+ :branch => source,
442
+ :target => name
443
+ )
444
+
447
445
  puts "\n"
448
446
  end
449
447
 
@@ -456,32 +454,11 @@ class Gitcycle
456
454
  output = merge_remote_branch(
457
455
  :owner => home,
458
456
  :repo => repo,
459
- :branch => branch
457
+ :branch => branch,
458
+ :issue => issue,
459
+ :issues => qa_branch['branches'].collect { |b| b['issue'] },
460
+ :type => :to_qa
460
461
  )
461
-
462
- if output.include?('CONFLICT')
463
- puts "Conflict occurred when merging '#{branch}' (issue ##{issue}).\n".red
464
- answer = q("Would you like to (s)kip or (r)esolve?")
465
-
466
- issues = qa_branch['branches'].collect { |b| b['issue'] }
467
-
468
- if answer.downcase[0..0] == 's'
469
- run("git reset --hard HEAD")
470
- issues.delete(issue)
471
-
472
- puts "\nSending QA branch information to gitcycle.\n".green
473
- get('qa_branch', 'issues' => issues, 'conflict' => issue)
474
- else
475
- puts "\nSending conflict information to gitcycle.\n".green
476
- get('qa_branch', 'issues' => issues, 'conflict' => issue)
477
-
478
- puts "Type 'gitc qa resolved' when finished resolving.\n".yellow
479
- exit
480
- end
481
- else
482
- puts "Pushing QA branch '#{name}'.\n".green
483
- run("git push origin #{name}")
484
- end
485
462
  end
486
463
 
487
464
  puts "\nType '".yellow + "gitc qa pass".green + "' to approve all issues in this branch.\n".yellow
@@ -490,6 +467,33 @@ class Gitcycle
490
467
  end
491
468
  end
492
469
 
470
+ def fix_conflict(options)
471
+ owner = options[:owner]
472
+ repo = options[:repo]
473
+ branch = options[:branch]
474
+ issue = options[:issue]
475
+ issues = options[:issues]
476
+ type = options[:type]
477
+
478
+ if $? != 0
479
+ puts "Conflict occurred when merging '#{branch}'#{" (issue ##{issue})" if issue}.\n".red
480
+
481
+ if type # from_qa or to_qa
482
+ puts "Please resolve this conflict with '#{owner}'.\n".yellow
483
+
484
+ puts "\nSending conflict information to gitcycle.\n".green
485
+ get('qa_branch', 'issues' => issues, "conflict_#{type}" => issue)
486
+
487
+ puts "Type 'gitc qa resolved' when finished resolving.\n".yellow
488
+ exit
489
+ end
490
+ elsif type # from_qa or to_qa
491
+ branch = branches(:current => true)
492
+ puts "Pushing branch '#{branch}'.\n".green
493
+ run("git push origin #{branch}")
494
+ end
495
+ end
496
+
493
497
  def get(path, hash={})
494
498
  hash.merge!(
495
499
  :login => @login,
@@ -538,6 +542,8 @@ class Gitcycle
538
542
 
539
543
  puts "\nMerging remote branch '#{branch}' from '#{owner}/#{repo}'.\n".green
540
544
  run("git merge #{owner}/#{branch}")
545
+
546
+ fix_conflict(options)
541
547
  end
542
548
 
543
549
  def remotes(options={})
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitcycle
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 10
10
- version: 0.1.10
9
+ - 11
10
+ version: 0.1.11
11
11
  platform: ruby
12
12
  authors:
13
13
  - Winton Welsh
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-20 00:00:00 -08:00
18
+ date: 2012-01-23 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency