thegarage-gitx 1.5.4 → 1.5.5.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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