thegarage-gitx 1.5.4 → 1.5.5.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12ad97ed250ce473831e0bec8c9bdd39ded30b53
4
- data.tar.gz: f2ec63227dd93e13a4f8d42a6b948141600ae281
3
+ metadata.gz: 1b5057c596d4343322b8f10cb5cc5ffa5d88cc5d
4
+ data.tar.gz: 0a0d051f8550bf0e3570e900bfffa4c11bf17e29
5
5
  SHA512:
6
- metadata.gz: dd9dda74370073881e10818c206e89a8c95ee8cf913d722f5998f381658d737586054615cb0998ea9d2d284ab2dd826cd0c34a548732affa5ca1205e2763f646
7
- data.tar.gz: fa758c96f712fcff8753c712071e64a0e32a62277a0763cfc774200645caa2e7baba43a681db0e6dae11c5512bdb4df1619de15c726ce5a6e256552f056c867f
6
+ metadata.gz: 363c8537bd5f8a1332a523532d4554f5b7ae72a7cab3c5e943eaf7dbd9239ab1bbe7baac6bc7a97aa8f8f8d86d1992c6c1c19e5bee3c9ed007ac0ce1ab6c28fb
7
+ data.tar.gz: a6263f625f0c130626419a035d90e8f64c6e7066ff738a1be3dfd3af4c6df791972aff7e81f96ad01859a1195977467d7c8d90827c11cfda5d08c045778d8f9a
@@ -2,8 +2,6 @@ require 'thegarage/gitx/version'
2
2
  require 'thegarage/gitx/string_extensions'
3
3
  require 'thegarage/gitx/git'
4
4
  require 'thegarage/gitx/github'
5
- require 'English'
6
-
7
5
 
8
6
  module Thegarage
9
7
  module Gitx
@@ -1,7 +1,10 @@
1
+ require 'English'
1
2
  require "thor"
2
3
  require 'rest_client'
3
4
  require 'thegarage/gitx'
5
+ require 'thegarage/gitx/git'
4
6
  require 'thegarage/gitx/github'
7
+ require 'thegarage/gitx/runner'
5
8
 
6
9
  module Thegarage
7
10
  module Gitx
@@ -9,10 +12,6 @@ module Thegarage
9
12
  include Thor::Actions
10
13
  add_runtime_options!
11
14
 
12
- include Thegarage::Gitx::Git
13
-
14
- TAGGABLE_BRANCHES = %w(master staging)
15
-
16
15
  method_option :trace, :type => :boolean, :aliases => '-v'
17
16
  def initialize(*args)
18
17
  super(*args)
@@ -28,87 +27,53 @@ module Thegarage
28
27
  def reviewrequest
29
28
  fail 'Github authorization token not found' unless github.authorization_token
30
29
 
31
- pull_request = github.find_pull_request(current_branch)
30
+ branch = git.current_branch.name
31
+ pull_request = github.find_pull_request(branch)
32
32
  if pull_request.nil?
33
- update
34
- changelog = run_cmd "git log #{Thegarage::Gitx::BASE_BRANCH}...#{current_branch} --no-merges --pretty=format:'* %s%n%b'"
35
- pull_request = github.create_pull_request(current_branch, changelog, options)
33
+ git.update
34
+ changelog = runner.run_cmd "git log #{Thegarage::Gitx::BASE_BRANCH}...#{branch} --no-merges --pretty=format:'* %s%n%b'"
35
+ pull_request = github.create_pull_request(branch, changelog, options)
36
36
  say 'Pull request created: '
37
37
  say pull_request['html_url'], :green
38
38
  end
39
39
  github.assign_pull_request(pull_request, options[:assignee]) if options[:assignee]
40
40
 
41
- run_cmd "open #{pull_request['html_url']}" if options[:open]
41
+ runner.run_cmd "open #{pull_request['html_url']}" if options[:open]
42
42
  end
43
43
 
44
- # TODO: use --no-edit to skip merge messages
45
- # TODO: use pull --rebase to skip merge commit
46
44
  desc 'update', 'Update the current branch with latest changes from the remote feature branch and master'
47
45
  def update
48
- branch = current_branch
49
-
50
- say 'updating '
51
- say "#{branch} ", :green
52
- say "to have most recent changes from "
53
- say Thegarage::Gitx::BASE_BRANCH, :green
54
-
55
- run_cmd "git pull origin #{branch}", :allow_failure => true
56
- run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
57
- run_cmd 'git push origin HEAD'
46
+ git.update
58
47
  end
59
48
 
60
49
  desc 'cleanup', 'Cleanup branches that have been merged into master from the repo'
61
50
  def cleanup
62
- run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
63
- run_cmd "git pull"
64
- run_cmd 'git remote prune origin'
65
-
66
- say "Deleting branches that have been merged into "
67
- say Thegarage::Gitx::BASE_BRANCH, :green
68
- branches(:merged => true, :remote => true).each do |branch|
69
- run_cmd "git push origin --delete #{branch}" unless aggregate_branch?(branch)
70
- end
71
- branches(:merged => true).each do |branch|
72
- run_cmd "git branch -d #{branch}" unless aggregate_branch?(branch)
73
- end
51
+ git.cleanup
74
52
  end
75
53
 
76
54
  desc 'track', 'set the current branch to track the remote branch with the same name'
77
55
  def track
78
- track_branch current_branch
56
+ git.track
79
57
  end
80
58
 
81
59
  desc 'start', 'start a new git branch with latest changes from master'
82
60
  def start(branch_name = nil)
83
- unless branch_name
84
- example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.shuffle.first
85
- repo = Grit::Repo.new(Dir.pwd)
86
- remote_branches = repo.remotes.collect {|b| b.name.split('/').last }
87
- until branch_name = ask("What would you like to name your branch? (ex: #{example_branch})") {|q|
88
- q.validate = Proc.new { |branch|
89
- branch =~ /^[A-Za-z0-9\-_]+$/ && !remote_branches.include?(branch)
90
- }
91
- }
92
- end
61
+ until git.valid_new_branch_name?(branch_name)
62
+ example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.sample
63
+ branch_name = ask("What would you like to name your branch? (ex: #{example_branch})")
93
64
  end
94
65
 
95
- run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
96
- run_cmd 'git pull'
97
- run_cmd "git checkout -b #{branch_name}"
66
+ git.start branch_name
98
67
  end
99
68
 
100
69
  desc 'share', 'Share the current branch in the remote repository'
101
70
  def share
102
- share_branch current_branch
71
+ git.share
103
72
  end
104
73
 
105
74
  desc 'integrate', 'integrate the current branch into one of the aggregate development branches'
106
75
  def integrate(target_branch = 'staging')
107
- branch = current_branch
108
-
109
- update
110
- integrate_branch(branch, target_branch)
111
- run_cmd "git checkout #{branch}"
76
+ git.integrate target_branch
112
77
  end
113
78
 
114
79
  desc 'nuke', 'nuke the specified aggregate branch and reset it to a known good state'
@@ -117,63 +82,35 @@ module Thegarage
117
82
  good_branch = options[:destination] || ask("What branch do you want to reset #{bad_branch} to? (default: #{bad_branch})")
118
83
  good_branch = bad_branch if good_branch.length == 0
119
84
 
120
- last_known_good_tag = build_tags_for_branch(good_branch).last
121
- raise "No known good tag found for branch: #{good_branch}. Verify tag exists via `git tag -l 'build-#{good_branch}-*'`" unless last_known_good_tag
85
+ last_known_good_tag = git.current_build_tag(good_branch)
122
86
  return unless yes?("Reset #{bad_branch} to #{last_known_good_tag}? (y/n)", :green)
123
87
 
124
- nuke_branch(bad_branch, last_known_good_tag)
88
+ git.nuke bad_branch, last_known_good_tag
125
89
  end
126
90
 
127
91
  desc 'release', 'release the current branch to production'
128
92
  def release
129
- branch = current_branch
130
- assert_not_protected_branch!(branch, 'release')
131
- update
132
-
133
- return unless yes?("Release #{branch} to production? (y/n)", :green)
134
- run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
135
- run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
136
- run_cmd "git pull . #{branch}"
137
- run_cmd "git push origin HEAD"
138
- integrate_branch('master', 'staging')
139
- cleanup
93
+ return unless yes?("Release #{git.current_branch.name} to production? (y/n)", :green)
94
+ git.release
140
95
  end
141
96
 
142
97
  desc 'buildtag', 'create a tag for the current Travis-CI build and push it back to origin'
143
98
  def buildtag
144
- branch = ENV['TRAVIS_BRANCH']
145
- pull_request = ENV['TRAVIS_PULL_REQUEST']
146
-
147
- raise "Unknown branch. ENV['TRAVIS_BRANCH'] is required." unless branch
148
-
149
- if pull_request != 'false'
150
- say "Skipping creation of tag for pull request: #{pull_request}"
151
- elsif !TAGGABLE_BRANCHES.include?(branch)
152
- say "Cannot create build tag for branch: #{branch}. Only #{TAGGABLE_BRANCHES} are supported."
153
- else
154
- label = "Generated tag from TravisCI build #{ENV['TRAVIS_BUILD_NUMBER']}"
155
- create_build_tag(branch, label)
156
- end
99
+ git.buildtag
157
100
  end
158
101
 
159
102
  private
160
103
 
161
- # execute a shell command and raise an error if non-zero exit code is returned
162
- # return the string output from the command
163
- def run_cmd(cmd, options = {})
164
- output = run(cmd, capture: true)
165
- success = $CHILD_STATUS.to_i == 0
166
- fail "#{cmd} failed" unless success || options[:allow_failure]
167
- output
104
+ def github
105
+ @github ||= Thegarage::Gitx::Github.new(git.repo, shell)
168
106
  end
169
107
 
170
- # check if --pretend or -p flag passed to CLI
171
- def pretend?
172
- options[:pretend]
108
+ def git
109
+ @git ||= Thegarage::Gitx::Git.new(shell, runner)
173
110
  end
174
111
 
175
- def github
176
- @github ||= Thegarage::Gitx::Github.new(current_repo, self)
112
+ def runner
113
+ @runner ||= Thegarage::Gitx::Runner.new(shell, options)
177
114
  end
178
115
  end
179
116
  end
@@ -1,24 +1,140 @@
1
- require 'grit'
2
1
  require 'pathname'
2
+ require 'rugged'
3
3
 
4
4
  module Thegarage
5
5
  module Gitx
6
- module Git
7
- AGGREGATE_BRANCHES = %w{ staging prototype }
8
- RESERVED_BRANCHES = %w{ HEAD master next_release } + AGGREGATE_BRANCHES
6
+ class Git
7
+ AGGREGATE_BRANCHES = %w( staging prototype )
8
+ RESERVED_BRANCHES = %w( HEAD master next_release ) + AGGREGATE_BRANCHES
9
+ TAGGABLE_BRANCHES = %w( master staging )
10
+
11
+ attr_accessor :shell, :runner, :repo
12
+
13
+ def initialize(shell, runner, path = Dir.pwd)
14
+ @shell = shell
15
+ @runner = runner
16
+ root_path = Rugged::Repository.discover(path)
17
+ @repo = Rugged::Repository.new(root_path)
18
+ end
9
19
 
10
- private
11
- def assert_not_protected_branch!(branch, action)
12
- raise "Cannot #{action} reserved branch" if RESERVED_BRANCHES.include?(branch) || aggregate_branch?(branch)
20
+ def update
21
+ shell.say 'Updating '
22
+ shell.say "#{current_branch.name} ", :green
23
+ shell.say "with latest changes from "
24
+ shell.say Thegarage::Gitx::BASE_BRANCH, :green
25
+
26
+ runner.run_cmd "git pull origin #{current_branch.name}", :allow_failure => true
27
+ runner.run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
28
+ runner.run_cmd 'git push origin HEAD'
29
+ end
30
+
31
+ def track
32
+ runner.run_cmd "git branch --set-upstream-to origin/#{current_branch.name}"
33
+ end
34
+
35
+ def share
36
+ runner.run_cmd "git push origin #{current_branch.name}"
37
+ track
38
+ end
39
+
40
+ def valid_new_branch_name?(branch)
41
+ remote_branches = Rugged::Branch.each_name(repo, :remote).to_a.map { |branch| branch.split('/').last }
42
+ branch =~ /^[A-Za-z0-9\-_]+$/ && !remote_branches.include?(branch)
43
+ end
44
+
45
+ def start(branch_name)
46
+ runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
47
+ runner.run_cmd 'git pull'
48
+ runner.run_cmd "git checkout -b #{branch_name}"
13
49
  end
14
50
 
15
- # lookup the current branch of the PWD
51
+ def cleanup
52
+ runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
53
+ runner.run_cmd "git pull"
54
+ runner.run_cmd 'git remote prune origin'
55
+
56
+ shell.say "Deleting branches that have been merged into "
57
+ shell.say Thegarage::Gitx::BASE_BRANCH, :green
58
+ branches(:merged => true, :remote => true).each do |branch|
59
+ runner.run_cmd "git push origin --delete #{branch}" unless aggregate_branch?(branch)
60
+ end
61
+ branches(:merged => true).each do |branch|
62
+ runner.run_cmd "git branch -d #{branch}" unless aggregate_branch?(branch)
63
+ end
64
+ end
65
+
66
+ def integrate(target_branch = 'staging')
67
+ update
68
+
69
+ branch = current_branch.name
70
+ integrate_branch(branch, target_branch)
71
+ runner.run_cmd "git checkout #{branch}"
72
+ end
73
+
74
+ def current_build_tag(branch)
75
+ last_build_tag = build_tags_for_branch(branch).last
76
+ raise "No known good tag found for branch: #{branch}. Verify tag exists via `git tag -l 'build-#{branch}-*'`" unless last_build_tag
77
+ last_build_tag
78
+ end
79
+
80
+ # reset the specified aggregate branch to the same set of commits as the destination branch
81
+ def nuke(outdated_branch, target_reference)
82
+ return if outdated_branch == target_reference
83
+ fail "Only aggregate branches are allowed to be reset: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(outdated_branch)
84
+ return if migrations_need_to_be_reverted?
85
+
86
+ shell.say "Resetting "
87
+ shell.say "#{outdated_branch} ", :green
88
+ shell.say "branch to "
89
+ shell.say target_reference, :green
90
+
91
+ runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
92
+ runner.run_cmd "git branch -D #{outdated_branch}", :allow_failure => true
93
+ runner.run_cmd "git push origin --delete #{outdated_branch}", :allow_failure => true
94
+ runner.run_cmd "git checkout -b #{outdated_branch} #{target_reference}"
95
+ runner.run_cmd "git push origin #{outdated_branch}"
96
+ runner.run_cmd "git branch --set-upstream-to origin/#{outdated_branch}"
97
+ runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
98
+ end
99
+
100
+ # lookup the current branch of the repo
16
101
  def current_branch
17
- Grit::Head.current(current_repo).name
102
+ repo.branches.find(&:head?)
18
103
  end
19
104
 
20
- def current_repo
21
- @repo ||= Grit::Repo.new(Dir.pwd)
105
+ def release
106
+ branch = current_branch.name
107
+ assert_not_protected_branch!(branch, 'release')
108
+ update
109
+
110
+ runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
111
+ runner.run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
112
+ runner.run_cmd "git pull . #{branch}"
113
+ runner.run_cmd "git push origin HEAD"
114
+ integrate('staging')
115
+ cleanup
116
+ end
117
+
118
+ def buildtag
119
+ branch = ENV['TRAVIS_BRANCH']
120
+ pull_request = ENV['TRAVIS_PULL_REQUEST']
121
+
122
+ raise "Unknown branch. ENV['TRAVIS_BRANCH'] is required." unless branch
123
+
124
+ if pull_request != 'false'
125
+ shell.say "Skipping creation of tag for pull request: #{pull_request}"
126
+ elsif !TAGGABLE_BRANCHES.include?(branch)
127
+ shell.say "Cannot create build tag for branch: #{branch}. Only #{TAGGABLE_BRANCHES} are supported."
128
+ else
129
+ label = "Generated tag from TravisCI build #{ENV['TRAVIS_BUILD_NUMBER']}"
130
+ create_build_tag(branch, label)
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ def assert_not_protected_branch!(branch, action)
137
+ raise "Cannot #{action} reserved branch" if RESERVED_BRANCHES.include?(branch) || aggregate_branch?(branch)
22
138
  end
23
139
 
24
140
  # retrieve a list of branches
@@ -36,56 +152,27 @@ module Thegarage
36
152
  branches.uniq
37
153
  end
38
154
 
39
- # reset the specified aggregate branch to the same set of commits as the destination branch
40
- def nuke_branch(outdated_branch, head_branch)
41
- return if outdated_branch == head_branch
42
- fail "Only aggregate branches are allowed to be reset: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(outdated_branch)
43
- return if migrations_need_to_be_reverted?
44
-
45
- say "Resetting "
46
- say "#{outdated_branch} ", :green
47
- say "branch to "
48
- say head_branch, :green
49
-
50
- run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
51
- run_cmd "git branch -D #{outdated_branch}", :allow_failure => true
52
- run_cmd "git push origin --delete #{outdated_branch}", :allow_failure => true
53
- run_cmd "git checkout -b #{outdated_branch} #{head_branch}"
54
- share_branch outdated_branch
55
- run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
56
- end
57
-
58
- # share the local branch in the remote repo
59
- def share_branch(branch)
60
- run_cmd "git push origin #{branch}"
61
- track_branch branch
62
- end
63
-
64
- def track_branch(branch)
65
- run_cmd "git branch --set-upstream-to origin/#{branch}"
66
- end
67
-
68
155
  # integrate a branch into a destination aggregate branch
69
156
  # blow away the local aggregate branch to ensure pulling into most recent "clean" branch
70
157
  def integrate_branch(branch, destination_branch)
71
158
  assert_not_protected_branch!(branch, 'integrate') unless aggregate_branch?(destination_branch)
72
159
  raise "Only aggregate branches are allowed for integration: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(destination_branch) || destination_branch == Thegarage::Gitx::BASE_BRANCH
73
- say "Integrating "
74
- say "#{branch} ", :green
75
- say "into "
76
- say destination_branch, :green
160
+ shell.say "Integrating "
161
+ shell.say "#{branch} ", :green
162
+ shell.say "into "
163
+ shell.say destination_branch, :green
77
164
 
78
165
  refresh_branch_from_remote destination_branch
79
- run_cmd "git pull . #{branch}"
80
- run_cmd "git push origin HEAD"
81
- run_cmd "git checkout #{branch}"
166
+ runner.run_cmd "git pull . #{branch}"
167
+ runner.run_cmd "git push origin HEAD"
168
+ runner.run_cmd "git checkout #{branch}"
82
169
  end
83
170
 
84
171
  # nuke local branch and pull fresh version from remote repo
85
172
  def refresh_branch_from_remote(destination_branch)
86
- run_cmd "git branch -D #{destination_branch}", :allow_failure => true
87
- run_cmd "git fetch origin"
88
- run_cmd "git checkout #{destination_branch}"
173
+ runner.run_cmd "git branch -D #{destination_branch}", :allow_failure => true
174
+ runner.run_cmd "git fetch origin"
175
+ runner.run_cmd "git checkout #{destination_branch}"
89
176
  end
90
177
 
91
178
  def aggregate_branch?(branch)
@@ -95,26 +182,26 @@ module Thegarage
95
182
  def create_build_tag(branch, label)
96
183
  timestamp = Time.now.utc.strftime '%Y-%m-%d-%H-%M-%S'
97
184
  git_tag = "build-#{branch}-#{timestamp}"
98
- run_cmd "git tag #{git_tag} -a -m '#{label}'"
99
- run_cmd "git push origin #{git_tag}"
185
+ runner.run_cmd "git tag #{git_tag} -a -m '#{label}'"
186
+ runner.run_cmd "git push origin #{git_tag}"
100
187
  end
101
188
 
102
189
  def build_tags_for_branch(branch)
103
- run_cmd "git fetch --tags"
104
- build_tags = run_cmd("git tag -l 'build-#{branch}-*'").split
190
+ runner.run_cmd "git fetch --tags"
191
+ build_tags = runner.run_cmd("git tag -l 'build-#{branch}-*'").split
105
192
  build_tags.sort
106
193
  end
107
194
 
108
195
  def migrations_need_to_be_reverted?
109
196
  return false unless File.exists?('db/migrate')
110
- outdated_migrations = run_cmd("git diff #{head_branch}...#{outdated_branch} --name-only db/migrate").split
197
+ outdated_migrations = runner.run_cmd("git diff #{head_branch}...#{outdated_branch} --name-only db/migrate").split
111
198
  return false if outdated_migrations.empty?
112
199
 
113
- say "#{outdated_branch} contains migrations that may need to be reverted. Ensure any reversable migrations are reverted on affected databases before nuking.", :red
114
- say 'Example commands to revert outdated migrations:'
200
+ shell.say "#{outdated_branch} contains migrations that may need to be reverted. Ensure any reversable migrations are reverted on affected databases before nuking.", :red
201
+ shell.say 'Example commands to revert outdated migrations:'
115
202
  outdated_migrations.reverse.each do |migration|
116
203
  version = File.basename(migration).split('_').first
117
- say "rake db:migrate:down VERSION=#{version}"
204
+ shell.say "rake db:migrate:down VERSION=#{version}"
118
205
  end
119
206
  !yes?("Are you sure you want to nuke #{outdated_branch}? (y/n) ", :green)
120
207
  end
@@ -0,0 +1,24 @@
1
+ require 'English'
2
+
3
+ module Thegarage
4
+ module Gitx
5
+ class Runner
6
+ attr_accessor :shell, :options
7
+
8
+ def initialize(shell, options = {})
9
+ @shell = shell
10
+ @options = options
11
+ end
12
+
13
+ # execute a shell command and raise an error if non-zero exit code is returned
14
+ # return the string output from the command
15
+ def run_cmd(cmd, options = {})
16
+ shell.say "$ #{cmd}"
17
+ output = `#{cmd}`
18
+ success = $CHILD_STATUS.to_i == 0
19
+ fail "#{cmd} failed" unless success || options[:allow_failure]
20
+ output
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  module Thegarage
2
2
  module Gitx
3
- VERSION = '1.5.4'
3
+ VERSION = '1.5.5.pre1'
4
4
  end
5
5
  end
@@ -10,17 +10,21 @@ describe Thegarage::Gitx::CLI do
10
10
  }
11
11
  end
12
12
  let(:cli) { Thegarage::Gitx::CLI.new(args, options, config) }
13
+ let(:git) { double('fake git') }
14
+ let(:github) { double('fake github') }
15
+ let(:runner) { double('fake runner') }
16
+ let(:branch) { double('fake branch', name: 'feature-branch') }
13
17
 
14
18
  before do
15
- # default current branch to: feature-branch
16
- allow(cli).to receive(:current_branch).and_return('feature-branch')
19
+ allow(cli).to receive(:git).and_return(git)
20
+ allow(cli).to receive(:runner).and_return(runner)
21
+ allow(cli).to receive(:github).and_return(github)
22
+ allow(git).to receive(:current_branch).and_return(branch)
17
23
  end
18
24
 
19
25
  describe '#update' do
20
26
  before do
21
- expect(cli).to receive(:run).with('git pull origin feature-branch', capture: true).ordered
22
- expect(cli).to receive(:run).with('git pull origin master', capture: true).ordered
23
- expect(cli).to receive(:run).with('git push origin HEAD', capture: true).ordered
27
+ expect(git).to receive(:update)
24
28
 
25
29
  cli.update
26
30
  end
@@ -32,16 +36,7 @@ describe Thegarage::Gitx::CLI do
32
36
  describe '#integrate' do
33
37
  context 'when target branch is ommitted' do
34
38
  before do
35
- expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
36
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
37
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
38
- expect(cli).to receive(:run).with("git branch -D staging", capture: true).ordered
39
- expect(cli).to receive(:run).with("git fetch origin", capture: true).ordered
40
- expect(cli).to receive(:run).with("git checkout staging", capture: true).ordered
41
- expect(cli).to receive(:run).with("git pull . feature-branch", capture: true).ordered
42
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
43
- expect(cli).to receive(:run).with("git checkout feature-branch", capture: true).ordered
44
- expect(cli).to receive(:run).with("git checkout feature-branch", capture: true).ordered
39
+ expect(git).to receive(:integrate).with('staging')
45
40
 
46
41
  cli.integrate
47
42
  end
@@ -51,16 +46,7 @@ describe Thegarage::Gitx::CLI do
51
46
  end
52
47
  context 'when target branch == prototype' do
53
48
  before do
54
- expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
55
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
56
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
57
- expect(cli).to receive(:run).with("git branch -D prototype", capture: true).ordered
58
- expect(cli).to receive(:run).with("git fetch origin", capture: true).ordered
59
- expect(cli).to receive(:run).with("git checkout prototype", capture: true).ordered
60
- expect(cli).to receive(:run).with("git pull . feature-branch", capture: true).ordered
61
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
62
- expect(cli).to receive(:run).with("git checkout feature-branch", capture: true).ordered
63
- expect(cli).to receive(:run).with("git checkout feature-branch", capture: true).ordered
49
+ expect(git).to receive(:integrate).with('prototype')
64
50
 
65
51
  cli.integrate 'prototype'
66
52
  end
@@ -68,17 +54,6 @@ describe Thegarage::Gitx::CLI do
68
54
  should meet_expectations
69
55
  end
70
56
  end
71
- context 'when target branch != staging || prototype' do
72
- it 'raises an error' do
73
- expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
74
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
75
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
76
-
77
- lambda {
78
- cli.integrate 'some-other-branch'
79
- }.should raise_error(/Only aggregate branches are allowed for integration/)
80
- end
81
- end
82
57
  end
83
58
 
84
59
  describe '#release' do
@@ -86,9 +61,7 @@ describe Thegarage::Gitx::CLI do
86
61
  before do
87
62
  expect(cli).to receive(:yes?).and_return(false)
88
63
 
89
- expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
90
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
91
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
64
+ expect(git).to_not receive(:release)
92
65
 
93
66
  cli.release
94
67
  end
@@ -99,27 +72,7 @@ describe Thegarage::Gitx::CLI do
99
72
  context 'when user confirms release' do
100
73
  before do
101
74
  expect(cli).to receive(:yes?).and_return(true)
102
- expect(cli).to receive(:branches).and_return(%w( old-merged-feature )).twice
103
-
104
- expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
105
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
106
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
107
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
108
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
109
- expect(cli).to receive(:run).with("git pull . feature-branch", capture: true).ordered
110
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
111
- expect(cli).to receive(:run).with("git branch -D staging", capture: true).ordered
112
- expect(cli).to receive(:run).with("git fetch origin", capture: true).ordered
113
- expect(cli).to receive(:run).with("git checkout staging", capture: true).ordered
114
- expect(cli).to receive(:run).with("git pull . master", capture: true).ordered
115
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
116
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
117
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
118
- expect(cli).to receive(:run).with("git pull", capture: true).ordered
119
- expect(cli).to receive(:run).with("git remote prune origin", capture: true).ordered
120
- expect(cli).to receive(:run).with("git push origin --delete old-merged-feature", capture: true).ordered
121
- expect(cli).to receive(:run).with("git branch -d old-merged-feature", capture: true).ordered
122
-
75
+ expect(git).to receive(:release)
123
76
  cli.release
124
77
  end
125
78
  it 'runs expected commands' do
@@ -132,76 +85,34 @@ describe Thegarage::Gitx::CLI do
132
85
  context 'when target branch == prototype and --destination == master' do
133
86
  let(:options) do
134
87
  {
135
- destination: 'master'
136
- }
137
- end
138
- let(:buildtags) do
139
- %w( build-master-2013-10-01-01 ).join("\n")
140
- end
141
- before do
142
- expect(cli).to receive(:yes?).and_return(true)
143
-
144
- expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
145
- expect(cli).to receive(:run).with("git tag -l 'build-master-*'", capture: true).and_return(buildtags).ordered
146
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
147
- expect(cli).to receive(:run).with("git branch -D prototype", capture: true).ordered
148
- expect(cli).to receive(:run).with("git push origin --delete prototype", capture: true).ordered
149
- expect(cli).to receive(:run).with("git checkout -b prototype build-master-2013-10-01-01", capture: true).ordered
150
- expect(cli).to receive(:run).with("git push origin prototype", capture: true).ordered
151
- expect(cli).to receive(:run).with("git branch --set-upstream-to origin/prototype", capture: true).ordered
152
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
153
-
154
- cli.nuke 'prototype'
155
- end
156
- it 'runs expected commands' do
157
- should meet_expectations
158
- end
159
- end
160
- context 'when target branch == staging and --destination == staging' do
161
- let(:options) do
162
- {
163
- destination: 'staging'
88
+ destination: good_branch
164
89
  }
165
90
  end
166
- let(:buildtags) do
167
- %w( build-staging-2013-10-02-02 ).join("\n")
168
- end
91
+ let(:good_branch) { 'master' }
92
+ let(:bad_branch) { 'prototype' }
93
+ let(:buildtag) { 'build-master-2013-10-01-01' }
169
94
  before do
170
95
  expect(cli).to receive(:yes?).and_return(true)
171
96
 
172
- expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
173
- expect(cli).to receive(:run).with("git tag -l 'build-staging-*'", capture: true).and_return(buildtags).ordered
174
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
175
- expect(cli).to receive(:run).with("git branch -D staging", capture: true).ordered
176
- expect(cli).to receive(:run).with("git push origin --delete staging", capture: true).ordered
177
- expect(cli).to receive(:run).with("git checkout -b staging build-staging-2013-10-02-02", capture: true).ordered
178
- expect(cli).to receive(:run).with("git push origin staging", capture: true).ordered
179
- expect(cli).to receive(:run).with("git branch --set-upstream-to origin/staging", capture: true).ordered
180
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
97
+ expect(git).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
98
+ expect(git).to receive(:nuke).with(bad_branch, buildtag)
181
99
 
182
- cli.nuke 'staging'
100
+ cli.nuke bad_branch
183
101
  end
184
102
  it 'runs expected commands' do
185
103
  should meet_expectations
186
104
  end
187
105
  end
188
106
  context 'when target branch == prototype and destination prompt == nil' do
189
- let(:buildtags) do
190
- %w( build-prototype-2013-10-03-03 ).join("\n")
191
- end
107
+ let(:good_branch) { 'master' }
108
+ let(:bad_branch) { 'prototype' }
109
+ let(:buildtag) { 'build-master-2013-10-01-01' }
192
110
  before do
193
- expect(cli).to receive(:ask).and_return('')
111
+ expect(cli).to receive(:ask).and_return(good_branch)
194
112
  expect(cli).to receive(:yes?).and_return(true)
195
113
 
196
- expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
197
- expect(cli).to receive(:run).with("git tag -l 'build-prototype-*'", capture: true).and_return(buildtags).ordered
198
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
199
- expect(cli).to receive(:run).with("git branch -D prototype", capture: true).ordered
200
- expect(cli).to receive(:run).with("git push origin --delete prototype", capture: true).ordered
201
- expect(cli).to receive(:run).with("git checkout -b prototype build-prototype-2013-10-03-03", capture: true).ordered
202
- expect(cli).to receive(:run).with("git push origin prototype", capture: true).ordered
203
- expect(cli).to receive(:run).with("git branch --set-upstream-to origin/prototype", capture: true).ordered
204
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
114
+ expect(git).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
115
+ expect(git).to receive(:nuke).with(bad_branch, buildtag)
205
116
 
206
117
  cli.nuke 'prototype'
207
118
  end
@@ -209,49 +120,14 @@ describe Thegarage::Gitx::CLI do
209
120
  should meet_expectations
210
121
  end
211
122
  end
212
- context 'when target branch == prototype and destination prompt = master' do
213
- let(:buildtags) do
214
- %w( build-master-2013-10-01-01 ).join("\n")
215
- end
216
- before do
217
- expect(cli).to receive(:ask).and_return('master')
218
- expect(cli).to receive(:yes?).and_return(true)
219
-
220
- expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
221
- expect(cli).to receive(:run).with("git tag -l 'build-master-*'", capture: true).and_return(buildtags).ordered
222
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
223
- expect(cli).to receive(:run).with("git branch -D prototype", capture: true).ordered
224
- expect(cli).to receive(:run).with("git push origin --delete prototype", capture: true).ordered
225
- expect(cli).to receive(:run).with("git checkout -b prototype build-master-2013-10-01-01", capture: true).ordered
226
- expect(cli).to receive(:run).with("git push origin prototype", capture: true).ordered
227
- expect(cli).to receive(:run).with("git branch --set-upstream-to origin/prototype", capture: true).ordered
228
- expect(cli).to receive(:run).with("git checkout master", capture: true).ordered
229
-
230
- cli.nuke 'prototype'
231
- end
232
- it 'runs expected commands' do
233
- should meet_expectations
234
- end
235
- end
236
- context 'when target branch != staging || prototype' do
237
- it 'raises error' do
238
- lambda {
239
- expect(cli).to receive(:ask).and_return('master')
240
- expect(cli).to receive(:yes?).and_return(true)
241
- cli.nuke 'not-an-integration-branch'
242
- }.should raise_error(/Only aggregate branches are allowed to be reset/)
243
- end
244
- end
245
123
  context 'when user does not confirm nuking the target branch' do
246
- let(:buildtags) do
247
- %w( build-master-2013-10-01-01 ).join("\n")
248
- end
124
+ let(:buildtag) { 'build-master-2013-10-01-01' }
249
125
  before do
250
126
  expect(cli).to receive(:ask).and_return('master')
251
127
  expect(cli).to receive(:yes?).and_return(false)
252
128
 
253
- expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
254
- expect(cli).to receive(:run).with("git tag -l 'build-master-*'", capture: true).and_return(buildtags).ordered
129
+ expect(git).to receive(:current_build_tag).with('master').and_return(buildtag)
130
+ expect(git).to_not receive(:nuke)
255
131
 
256
132
  cli.nuke 'prototype'
257
133
  end
@@ -259,23 +135,9 @@ describe Thegarage::Gitx::CLI do
259
135
  should meet_expectations
260
136
  end
261
137
  end
262
- context 'when no known good build tag found' do
263
- let(:buildtags) do
264
- ''
265
- end
266
- it 'raises error' do
267
- expect(cli).to receive(:ask).and_return('master')
268
-
269
- expect(cli).to receive(:run).with("git fetch --tags", capture: true).ordered
270
- expect(cli).to receive(:run).with("git tag -l 'build-master-*'", capture: true).and_return(buildtags).ordered
271
-
272
- expect { cli.nuke('prototype') }.to raise_error(/No known good tag found for branch/)
273
- end
274
- end
275
138
  end
276
139
 
277
140
  describe '#reviewrequest' do
278
- let(:github) { double('fake github') }
279
141
  let(:pull_request) do
280
142
  {
281
143
  'html_url' => 'https://path/to/new/pull/request',
@@ -284,9 +146,6 @@ describe Thegarage::Gitx::CLI do
284
146
  }
285
147
  }
286
148
  end
287
- before do
288
- allow(cli).to receive(:github).and_return(github)
289
- end
290
149
  context 'when pull request does not exist' do
291
150
  let(:authorization_token) { '123123' }
292
151
  let(:changelog) { '* made some fixes' }
@@ -295,10 +154,8 @@ describe Thegarage::Gitx::CLI do
295
154
  expect(github).to receive(:find_pull_request).and_return(nil)
296
155
  expect(github).to receive(:create_pull_request).and_return(pull_request)
297
156
 
298
- expect(cli).to receive(:run).with("git pull origin feature-branch", capture: true).ordered
299
- expect(cli).to receive(:run).with("git pull origin master", capture: true).ordered
300
- expect(cli).to receive(:run).with("git push origin HEAD", capture: true).ordered
301
- expect(cli).to receive(:run).with("git log master...feature-branch --no-merges --pretty=format:'* %s%n%b'", capture: true).and_return("2013-01-01 did some stuff").ordered
157
+ expect(git).to receive(:update)
158
+ expect(runner).to receive(:run_cmd).with("git log master...feature-branch --no-merges --pretty=format:'* %s%n%b'").and_return("2013-01-01 did some stuff").ordered
302
159
  cli.reviewrequest
303
160
  end
304
161
  it 'creates github pull request' do
@@ -357,7 +214,7 @@ describe Thegarage::Gitx::CLI do
357
214
  expect(github).to receive(:authorization_token).and_return(authorization_token)
358
215
  expect(github).to receive(:find_pull_request).and_return(pull_request)
359
216
 
360
- expect(cli).to receive(:run).with("open #{pull_request['html_url']}", capture: true).ordered
217
+ expect(runner).to receive(:run_cmd).with("open #{pull_request['html_url']}").ordered
361
218
  cli.reviewrequest
362
219
  end
363
220
  it 'runs open command with pull request url' do
@@ -366,56 +223,35 @@ describe Thegarage::Gitx::CLI do
366
223
  end
367
224
  end
368
225
 
369
- describe '#buildtag' do
370
- let(:env_travis_branch) { nil }
371
- let(:env_travis_pull_request) { nil }
372
- let(:env_travis_build_number) { nil }
373
- before do
374
- ENV['TRAVIS_BRANCH'] = env_travis_branch
375
- ENV['TRAVIS_PULL_REQUEST'] = env_travis_pull_request
376
- ENV['TRAVIS_BUILD_NUMBER'] = env_travis_build_number
226
+ describe '#track' do
227
+ it 'calls git.track' do
228
+ expect(git).to receive(:track)
229
+ cli.track
377
230
  end
378
- context 'when ENV[\'TRAVIS_BRANCH\'] is nil' do
379
- it 'raises Unknown Branch error' do
380
- expect { cli.buildtag }.to raise_error "Unknown branch. ENV['TRAVIS_BRANCH'] is required."
381
- end
382
- end
383
- context 'when the travis branch is master and the travis pull request is not false' do
384
- let(:env_travis_branch) { 'master' }
385
- let(:env_travis_pull_request) { '45' }
386
- before do
387
- expect(cli).to receive(:say).with("Skipping creation of tag for pull request: #{ENV['TRAVIS_PULL_REQUEST']}")
388
- cli.buildtag
389
- end
390
- it 'tells us that it is skipping the creation of the tag' do
391
- should meet_expectations
392
- end
231
+ end
232
+
233
+ describe '#share' do
234
+ it 'calls git.share' do
235
+ expect(git).to receive(:share)
236
+ cli.share
393
237
  end
394
- context 'when the travis branch is NOT master and is not a pull request' do
395
- let(:env_travis_branch) { 'random-branch' }
396
- let(:env_travis_pull_request) { 'false' }
397
- before do
398
- expect(cli).to receive(:say).with(/Cannot create build tag for branch: #{ENV['TRAVIS_BRANCH']}/)
399
- cli.buildtag
400
- end
401
- it 'tells us that the branch is not supported' do
402
- should meet_expectations
238
+ end
239
+
240
+ describe '#start' do
241
+ context 'when user inputs branch that is valid' do
242
+ it 'calls git.start' do
243
+ expect(git).to receive(:valid_new_branch_name?).with('new-branch').and_return(true)
244
+ expect(git).to receive(:start).with('new-branch')
245
+
246
+ cli.start 'new-branch'
403
247
  end
404
248
  end
405
- context 'when the travis branch is master and not a pull request' do
406
- let(:env_travis_branch) { 'master' }
407
- let(:env_travis_pull_request) { 'false' }
408
- let(:env_travis_build_number) { '24' }
409
- before do
410
- Timecop.freeze(Time.utc(2013, 10, 30, 10, 21, 28)) do
411
- expect(cli).to receive(:run).with("git tag build-master-2013-10-30-10-21-28 -a -m 'Generated tag from TravisCI build 24'", capture: true).ordered
412
- expect(cli).to receive(:run).with("git push origin build-master-2013-10-30-10-21-28", capture: true).ordered
413
- cli.buildtag
414
- end
415
- end
416
- it 'creates a tag for the branch and push it to github' do
417
- should meet_expectations
418
- end
249
+ end
250
+
251
+ describe '#buildtag' do
252
+ it 'calls git.buildtag' do
253
+ expect(git).to receive(:buildtag)
254
+ cli.buildtag
419
255
  end
420
256
  end
421
257
  end
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+ require 'timecop'
3
+
4
+ describe Thegarage::Gitx::Git do
5
+ let(:runner) { double('fake runner') }
6
+ let(:shell) { double('fake shell', say: nil) }
7
+ let(:branch) { double('fake git branch', name: 'feature-branch') }
8
+ subject { Thegarage::Gitx::Git.new(shell, runner) }
9
+
10
+ # default current branch to: feature-branch
11
+ before do
12
+ allow(subject).to receive(:current_branch).and_return(branch)
13
+ end
14
+
15
+ describe '#update' do
16
+ before do
17
+ allow(shell).to receive(:say)
18
+
19
+ expect(runner).to receive(:run_cmd).with('git pull origin feature-branch', allow_failure: true).ordered
20
+ expect(runner).to receive(:run_cmd).with('git pull origin master').ordered
21
+ expect(runner).to receive(:run_cmd).with('git push origin HEAD').ordered
22
+
23
+ subject.update
24
+ end
25
+ it 'runs expected commands' do
26
+ should meet_expectations
27
+ end
28
+ end
29
+
30
+ describe '#track' do
31
+ before do
32
+ expect(runner).to receive(:run_cmd).with('git branch --set-upstream-to origin/feature-branch').ordered
33
+
34
+ subject.track
35
+ end
36
+ it 'runs expected commands' do
37
+ should meet_expectations
38
+ end
39
+ end
40
+
41
+ describe '#share' do
42
+ before do
43
+ expect(runner).to receive(:run_cmd).with('git push origin feature-branch').ordered
44
+ expect(runner).to receive(:run_cmd).with('git branch --set-upstream-to origin/feature-branch').ordered
45
+
46
+ subject.share
47
+ end
48
+ it 'runs expected commands' do
49
+ should meet_expectations
50
+ end
51
+ end
52
+
53
+ describe '#integrate' do
54
+ context 'when target branch is ommitted' do
55
+ before do
56
+ expect(subject).to receive(:update)
57
+
58
+ expect(runner).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
59
+ expect(runner).to receive(:run_cmd).with("git fetch origin").ordered
60
+ expect(runner).to receive(:run_cmd).with("git checkout staging").ordered
61
+ expect(runner).to receive(:run_cmd).with("git pull . feature-branch").ordered
62
+ expect(runner).to receive(:run_cmd).with("git push origin HEAD").ordered
63
+ expect(runner).to receive(:run_cmd).with("git checkout feature-branch").ordered
64
+ expect(runner).to receive(:run_cmd).with("git checkout feature-branch").ordered
65
+
66
+ subject.integrate
67
+ end
68
+ it 'defaults to staging branch' do
69
+ should meet_expectations
70
+ end
71
+ end
72
+ context 'when target branch == prototype' do
73
+ before do
74
+ expect(subject).to receive(:update)
75
+
76
+ expect(runner).to receive(:run_cmd).with("git branch -D prototype", allow_failure: true).ordered
77
+ expect(runner).to receive(:run_cmd).with("git fetch origin").ordered
78
+ expect(runner).to receive(:run_cmd).with("git checkout prototype").ordered
79
+ expect(runner).to receive(:run_cmd).with("git pull . feature-branch").ordered
80
+ expect(runner).to receive(:run_cmd).with("git push origin HEAD").ordered
81
+ expect(runner).to receive(:run_cmd).with("git checkout feature-branch").ordered
82
+ expect(runner).to receive(:run_cmd).with("git checkout feature-branch").ordered
83
+
84
+ subject.integrate 'prototype'
85
+ end
86
+ it 'runs expected commands' do
87
+ should meet_expectations
88
+ end
89
+ end
90
+ context 'when target branch != staging || prototype' do
91
+ it 'raises an error' do
92
+ expect(subject).to receive(:update)
93
+
94
+ expect { subject.integrate('some-other-branch') }.to raise_error(/Only aggregate branches are allowed for integration/)
95
+ end
96
+ end
97
+ end
98
+
99
+ describe '#release' do
100
+ it 'merges feature branch into master' do
101
+ expect(subject).to receive(:update)
102
+
103
+ expect(runner).to receive(:run_cmd).with("git checkout master").ordered
104
+ expect(runner).to receive(:run_cmd).with("git pull origin master").ordered
105
+ expect(runner).to receive(:run_cmd).with("git pull . feature-branch").ordered
106
+ expect(runner).to receive(:run_cmd).with("git push origin HEAD").ordered
107
+
108
+ expect(subject).to receive(:integrate).with('staging')
109
+ expect(subject).to receive(:cleanup)
110
+
111
+ subject.release
112
+ end
113
+ end
114
+
115
+ describe '#nuke' do
116
+ context 'when target branch == prototype and head is a valid buildtag' do
117
+ let(:buildtag) { 'build-master-2013-10-01-01' }
118
+ before do
119
+ expect(runner).to receive(:run_cmd).with("git checkout master").ordered
120
+ expect(runner).to receive(:run_cmd).with("git branch -D prototype", allow_failure: true).ordered
121
+ expect(runner).to receive(:run_cmd).with("git push origin --delete prototype", allow_failure: true).ordered
122
+ expect(runner).to receive(:run_cmd).with("git checkout -b prototype build-master-2013-10-01-01").ordered
123
+ expect(runner).to receive(:run_cmd).with("git push origin prototype").ordered
124
+ expect(runner).to receive(:run_cmd).with("git branch --set-upstream-to origin/prototype").ordered
125
+ expect(runner).to receive(:run_cmd).with("git checkout master").ordered
126
+
127
+ subject.nuke 'prototype', buildtag
128
+ end
129
+ it 'runs expected commands' do
130
+ should meet_expectations
131
+ end
132
+ end
133
+ context 'when target branch == staging and head is a valid buildtag' do
134
+ let(:buildtag) { 'build-master-2013-10-02-02' }
135
+ before do
136
+ expect(runner).to receive(:run_cmd).with("git checkout master").ordered
137
+ expect(runner).to receive(:run_cmd).with("git branch -D staging", allow_failure: true).ordered
138
+ expect(runner).to receive(:run_cmd).with("git push origin --delete staging", allow_failure: true).ordered
139
+ expect(runner).to receive(:run_cmd).with("git checkout -b staging build-master-2013-10-02-02").ordered
140
+ expect(runner).to receive(:run_cmd).with("git push origin staging").ordered
141
+ expect(runner).to receive(:run_cmd).with("git branch --set-upstream-to origin/staging").ordered
142
+ expect(runner).to receive(:run_cmd).with("git checkout master").ordered
143
+
144
+ subject.nuke 'staging', buildtag
145
+ end
146
+ it 'runs expected commands' do
147
+ should meet_expectations
148
+ end
149
+ end
150
+ context 'when target branch != staging || prototype' do
151
+ it 'raises error' do
152
+ expect { subject.nuke('not-an-integration-branch', 'master') }.to raise_error(/Only aggregate branches are allowed to be reset/)
153
+ end
154
+ end
155
+ end
156
+
157
+ describe '#current_build_tag' do
158
+ context 'when multiple build tags returned' do
159
+ let(:buildtags) { %w( build-master-2013-01-01-01 build-master-2013-01-01-02 ).join("\n") }
160
+ it 'returns the last one' do
161
+ expect(runner).to receive(:run_cmd).with("git fetch --tags").ordered
162
+ expect(runner).to receive(:run_cmd).with("git tag -l 'build-master-*'").and_return(buildtags).ordered
163
+
164
+ result = subject.current_build_tag 'master'
165
+ expect(result).to eq 'build-master-2013-01-01-02'
166
+ end
167
+ end
168
+ context 'when no known good build tag found' do
169
+ let(:buildtags) { '' }
170
+ it 'raises error' do
171
+ expect(runner).to receive(:run_cmd).with("git fetch --tags").ordered
172
+ expect(runner).to receive(:run_cmd).with("git tag -l 'build-master-*'").and_return(buildtags).ordered
173
+
174
+ expect { subject.current_build_tag('master') }.to raise_error(/No known good tag found for branch/)
175
+ end
176
+ end
177
+ end
178
+
179
+ describe '#buildtag' do
180
+ let(:env_travis_branch) { nil }
181
+ let(:env_travis_pull_request) { nil }
182
+ let(:env_travis_build_number) { nil }
183
+ before do
184
+ ENV['TRAVIS_BRANCH'] = env_travis_branch
185
+ ENV['TRAVIS_PULL_REQUEST'] = env_travis_pull_request
186
+ ENV['TRAVIS_BUILD_NUMBER'] = env_travis_build_number
187
+ end
188
+ context 'when ENV[\'TRAVIS_BRANCH\'] is nil' do
189
+ it 'raises Unknown Branch error' do
190
+ expect { subject.buildtag }.to raise_error "Unknown branch. ENV['TRAVIS_BRANCH'] is required."
191
+ end
192
+ end
193
+ context 'when the travis branch is master and the travis pull request is not false' do
194
+ let(:env_travis_branch) { 'master' }
195
+ let(:env_travis_pull_request) { '45' }
196
+ before do
197
+ expect(shell).to receive(:say).with("Skipping creation of tag for pull request: #{ENV['TRAVIS_PULL_REQUEST']}")
198
+ subject.buildtag
199
+ end
200
+ it 'tells us that it is skipping the creation of the tag' do
201
+ should meet_expectations
202
+ end
203
+ end
204
+ context 'when the travis branch is NOT master and is not a pull request' do
205
+ let(:env_travis_branch) { 'random-branch' }
206
+ let(:env_travis_pull_request) { 'false' }
207
+ before do
208
+ expect(shell).to receive(:say).with(/Cannot create build tag for branch: #{ENV['TRAVIS_BRANCH']}/)
209
+ subject.buildtag
210
+ end
211
+ it 'tells us that the branch is not supported' do
212
+ should meet_expectations
213
+ end
214
+ end
215
+ context 'when the travis branch is master and not a pull request' do
216
+ let(:env_travis_branch) { 'master' }
217
+ let(:env_travis_pull_request) { 'false' }
218
+ let(:env_travis_build_number) { '24' }
219
+ before do
220
+ Timecop.freeze(Time.utc(2013, 10, 30, 10, 21, 28)) do
221
+ expect(runner).to receive(:run_cmd).with("git tag build-master-2013-10-30-10-21-28 -a -m 'Generated tag from TravisCI build 24'").ordered
222
+ expect(runner).to receive(:run_cmd).with("git push origin build-master-2013-10-30-10-21-28").ordered
223
+ subject.buildtag
224
+ end
225
+ end
226
+ it 'creates a tag for the branch and push it to github' do
227
+ should meet_expectations
228
+ end
229
+ end
230
+ end
231
+ end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_runtime_dependency "grit"
21
+ spec.add_runtime_dependency "rugged"
22
22
  spec.add_runtime_dependency "rest-client", ">= 1.4.0"
23
23
  spec.add_runtime_dependency "thor"
24
24
 
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thegarage-gitx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.4
4
+ version: 1.5.5.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Sonnek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-27 00:00:00.000000000 Z
11
+ date: 2014-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: grit
14
+ name: rugged
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - '>='
@@ -178,11 +178,13 @@ files:
178
178
  - lib/thegarage/gitx/cli.rb
179
179
  - lib/thegarage/gitx/git.rb
180
180
  - lib/thegarage/gitx/github.rb
181
+ - lib/thegarage/gitx/runner.rb
181
182
  - lib/thegarage/gitx/string_extensions.rb
182
183
  - lib/thegarage/gitx/version.rb
183
184
  - spec/spec_helper.rb
184
185
  - spec/support/meet_expectations_matcher.rb
185
186
  - spec/thegarage/gitx/cli_spec.rb
187
+ - spec/thegarage/gitx/git_spec.rb
186
188
  - spec/thegarage/gitx/github_spec.rb
187
189
  - thegarage-gitx.gemspec
188
190
  homepage: ''
@@ -200,9 +202,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
202
  version: '0'
201
203
  required_rubygems_version: !ruby/object:Gem::Requirement
202
204
  requirements:
203
- - - '>='
205
+ - - '>'
204
206
  - !ruby/object:Gem::Version
205
- version: '0'
207
+ version: 1.3.1
206
208
  requirements: []
207
209
  rubyforge_project:
208
210
  rubygems_version: 2.0.3
@@ -213,4 +215,5 @@ test_files:
213
215
  - spec/spec_helper.rb
214
216
  - spec/support/meet_expectations_matcher.rb
215
217
  - spec/thegarage/gitx/cli_spec.rb
218
+ - spec/thegarage/gitx/git_spec.rb
216
219
  - spec/thegarage/gitx/github_spec.rb