thegarage-gitx 1.5.5.pre1 → 2.0.0.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 +4 -4
- data/Guardfile +8 -0
- data/README.md +2 -0
- data/bin/git-buildtag +3 -2
- data/bin/git-cleanup +4 -2
- data/bin/git-integrate +3 -2
- data/bin/git-nuke +3 -2
- data/bin/git-release +3 -2
- data/bin/git-reviewrequest +3 -2
- data/bin/git-share +3 -2
- data/bin/git-start +3 -2
- data/bin/git-track +3 -2
- data/bin/git-update +3 -2
- data/lib/thegarage/gitx/cli/base_command.rb +74 -0
- data/lib/thegarage/gitx/cli/buildtag_command.rb +39 -0
- data/lib/thegarage/gitx/cli/cleanup_command.rb +36 -0
- data/lib/thegarage/gitx/cli/integrate_command.rb +40 -0
- data/lib/thegarage/gitx/cli/nuke_command.rb +64 -0
- data/lib/thegarage/gitx/cli/release_command.rb +31 -0
- data/lib/thegarage/gitx/cli/review_request_command.rb +203 -0
- data/lib/thegarage/gitx/cli/share_command.rb +17 -0
- data/lib/thegarage/gitx/cli/start_command.rb +31 -0
- data/lib/thegarage/gitx/cli/track_command.rb +16 -0
- data/lib/thegarage/gitx/cli/update_command.rb +23 -0
- data/lib/thegarage/gitx/version.rb +1 -1
- data/lib/thegarage/gitx.rb +0 -2
- data/spec/spec_helper.rb +3 -1
- data/spec/thegarage/gitx/cli/buildtag_command_spec.rb +71 -0
- data/spec/thegarage/gitx/cli/cleanup_command_spec.rb +38 -0
- data/spec/thegarage/gitx/cli/integrate_command_spec.rb +65 -0
- data/spec/thegarage/gitx/cli/nuke_command_spec.rb +105 -0
- data/spec/thegarage/gitx/cli/release_command_spec.rb +56 -0
- data/spec/thegarage/gitx/cli/review_request_command_spec.rb +188 -0
- data/spec/thegarage/gitx/cli/share_command_spec.rb +32 -0
- data/spec/thegarage/gitx/cli/start_command_spec.rb +61 -0
- data/spec/thegarage/gitx/cli/track_command_spec.rb +31 -0
- data/spec/thegarage/gitx/cli/update_command_spec.rb +33 -0
- data/thegarage-gitx.gemspec +3 -0
- metadata +76 -11
- data/lib/thegarage/gitx/cli.rb +0 -117
- data/lib/thegarage/gitx/git.rb +0 -210
- data/lib/thegarage/gitx/github.rb +0 -185
- data/spec/thegarage/gitx/cli_spec.rb +0 -257
- data/spec/thegarage/gitx/git_spec.rb +0 -231
- data/spec/thegarage/gitx/github_spec.rb +0 -91
@@ -1,185 +0,0 @@
|
|
1
|
-
require 'rest_client'
|
2
|
-
require 'json'
|
3
|
-
require 'tempfile'
|
4
|
-
|
5
|
-
module Thegarage
|
6
|
-
module Gitx
|
7
|
-
class Github
|
8
|
-
CLIENT_NAME = 'The Garage Git eXtensions'
|
9
|
-
CLIENT_URL = 'https://github.com/thegarage/thegarage-gitx'
|
10
|
-
PULL_REQUEST_FOOTER = <<-EOS.dedent
|
11
|
-
# Pull Request Protips(tm):
|
12
|
-
# * Include description of how this change accomplishes the task at hand.
|
13
|
-
# * Use GitHub flavored Markdown http://github.github.com/github-flavored-markdown/
|
14
|
-
# * Review CONTRIBUTING.md for recommendations of artifacts, links, images, screencasts, etc.
|
15
|
-
#
|
16
|
-
# This footer will automatically be stripped from the pull request description
|
17
|
-
EOS
|
18
|
-
|
19
|
-
attr_reader :repo, :shell
|
20
|
-
|
21
|
-
def initialize(repo, shell)
|
22
|
-
@repo = repo
|
23
|
-
@shell = shell
|
24
|
-
end
|
25
|
-
|
26
|
-
# returns [Hash] data structure of created pull request
|
27
|
-
# request github authorization token
|
28
|
-
# User-Agent is required
|
29
|
-
# store the token in local git config
|
30
|
-
# @returns [String] auth token stored in git (current repo, user config or installed global settings)
|
31
|
-
# @see http://developer.github.com/v3/oauth/#scopes
|
32
|
-
# @see http://developer.github.com/v3/#user-agent-required
|
33
|
-
def authorization_token
|
34
|
-
auth_token = repo.config['thegarage.gitx.githubauthtoken']
|
35
|
-
return auth_token unless auth_token.to_s.blank?
|
36
|
-
|
37
|
-
fail "Github user not configured. Run: `git config --global github.user 'me@email.com'`" unless username
|
38
|
-
password = shell.ask("Github password for #{username}: ", :echo => false)
|
39
|
-
|
40
|
-
payload = {
|
41
|
-
:scopes => ['repo'],
|
42
|
-
:note => CLIENT_NAME,
|
43
|
-
:note_url => CLIENT_URL
|
44
|
-
}.to_json
|
45
|
-
response = RestClient::Request.new({
|
46
|
-
:url => "https://api.github.com/authorizations",
|
47
|
-
:method => "POST",
|
48
|
-
:user => username,
|
49
|
-
:password => password,
|
50
|
-
:payload => payload,
|
51
|
-
:headers => {
|
52
|
-
:accept => :json,
|
53
|
-
:content_type => :json,
|
54
|
-
:user_agent => 'thegarage/gitx'
|
55
|
-
}
|
56
|
-
}).execute
|
57
|
-
data = JSON.parse response.body
|
58
|
-
token = data['token']
|
59
|
-
repo.config['thegarage.gitx.githubauthtoken'] = token
|
60
|
-
token
|
61
|
-
rescue RestClient::Exception => e
|
62
|
-
process_error e
|
63
|
-
end
|
64
|
-
|
65
|
-
# @see http://developer.github.com/v3/pulls/
|
66
|
-
def create_pull_request(branch, changelog, options = {})
|
67
|
-
body = pull_request_body(changelog, options[:description])
|
68
|
-
|
69
|
-
shell.say "Creating pull request for "
|
70
|
-
shell.say "#{branch} ", :green
|
71
|
-
shell.say "against "
|
72
|
-
shell.say "#{Thegarage::Gitx::BASE_BRANCH} ", :green
|
73
|
-
shell.say "in "
|
74
|
-
shell.say remote_origin_name, :green
|
75
|
-
|
76
|
-
payload = {
|
77
|
-
:title => branch,
|
78
|
-
:base => Thegarage::Gitx::BASE_BRANCH,
|
79
|
-
:head => branch,
|
80
|
-
:body => body
|
81
|
-
}.to_json
|
82
|
-
response = RestClient::Request.new(:url => pull_request_url, :method => "POST", :payload => payload, :headers => request_headers).execute
|
83
|
-
pull_request = JSON.parse response.body
|
84
|
-
|
85
|
-
pull_request
|
86
|
-
rescue RestClient::Exception => e
|
87
|
-
process_error e
|
88
|
-
end
|
89
|
-
|
90
|
-
def assign_pull_request(pull_request, assignee)
|
91
|
-
shell.say "Assigning pull request to "
|
92
|
-
shell.say assignee, :green
|
93
|
-
|
94
|
-
branch = pull_request['head']['ref']
|
95
|
-
payload = {
|
96
|
-
:title => branch,
|
97
|
-
:assignee => assignee
|
98
|
-
}.to_json
|
99
|
-
RestClient::Request.new(:url => pull_request['issue_url'], :method => "PATCH", :payload => payload, :headers => request_headers).execute
|
100
|
-
rescue RestClient::Exception => e
|
101
|
-
process_error e
|
102
|
-
end
|
103
|
-
|
104
|
-
# @returns [Hash] data structure of pull request info if found
|
105
|
-
# @returns nil if no pull request found
|
106
|
-
def find_pull_request(branch)
|
107
|
-
head_reference = [remote_origin_name.split('/').first, branch].join(':')
|
108
|
-
params = {
|
109
|
-
head: head_reference,
|
110
|
-
state: 'open'
|
111
|
-
}
|
112
|
-
response = RestClient::Request.new(:url => pull_request_url, :method => "GET", :headers => request_headers.merge(params: params)).execute
|
113
|
-
data = JSON.parse(response.body)
|
114
|
-
data.first
|
115
|
-
rescue RestClient::Exception => e
|
116
|
-
process_error e
|
117
|
-
end
|
118
|
-
|
119
|
-
private
|
120
|
-
|
121
|
-
def process_error(e)
|
122
|
-
data = JSON.parse e.http_body
|
123
|
-
shell.say "Github request failed: #{data['message']}", :red
|
124
|
-
throw e
|
125
|
-
end
|
126
|
-
|
127
|
-
def pull_request_url
|
128
|
-
"https://api.github.com/repos/#{remote_origin_name}/pulls"
|
129
|
-
end
|
130
|
-
|
131
|
-
def request_headers
|
132
|
-
{
|
133
|
-
:accept => :json,
|
134
|
-
:content_type => :json,
|
135
|
-
'Authorization' => "token #{authorization_token}"
|
136
|
-
}
|
137
|
-
end
|
138
|
-
|
139
|
-
# @returns [String] github username (ex: 'wireframe') of the current github.user
|
140
|
-
# @returns empty [String] when no github.user is set on the system
|
141
|
-
def username
|
142
|
-
repo.config['github.user']
|
143
|
-
end
|
144
|
-
|
145
|
-
# lookup the current repository of the PWD
|
146
|
-
# ex: git@github.com:socialcast/thegarage/gitx.git OR https://github.com/socialcast/thegarage/gitx.git
|
147
|
-
def remote_origin_name
|
148
|
-
remote = repo.config['remote.origin.url']
|
149
|
-
remote.to_s.gsub(/\.git$/,'').split(/[:\/]/).last(2).join('/')
|
150
|
-
end
|
151
|
-
|
152
|
-
def pull_request_body(changelog, description = nil)
|
153
|
-
description_template = []
|
154
|
-
description_template << "#{description}\n" if description
|
155
|
-
description_template << '### Changelog'
|
156
|
-
description_template << changelog
|
157
|
-
description_template << PULL_REQUEST_FOOTER
|
158
|
-
|
159
|
-
body = input_from_editor(description_template.join("\n"))
|
160
|
-
body.gsub(PULL_REQUEST_FOOTER, '').chomp.strip
|
161
|
-
end
|
162
|
-
|
163
|
-
# launch configured editor to retreive message/string
|
164
|
-
def input_from_editor(initial_text = '')
|
165
|
-
Tempfile.open('reviewrequest.md') do |f|
|
166
|
-
f << initial_text
|
167
|
-
f.flush
|
168
|
-
|
169
|
-
editor = repo.config['core.editor'] || ENV['EDITOR'] || 'vi'
|
170
|
-
flags = case editor
|
171
|
-
when 'mate', 'emacs', 'subl'
|
172
|
-
'-w'
|
173
|
-
when 'mvim'
|
174
|
-
'-f'
|
175
|
-
else
|
176
|
-
''
|
177
|
-
end
|
178
|
-
pid = fork { exec([editor, flags, f.path].join(' ')) }
|
179
|
-
Process.waitpid(pid)
|
180
|
-
File.read(f.path)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
@@ -1,257 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'timecop'
|
3
|
-
|
4
|
-
describe Thegarage::Gitx::CLI do
|
5
|
-
let(:args) { [] }
|
6
|
-
let(:options) { {} }
|
7
|
-
let(:config) do
|
8
|
-
{
|
9
|
-
pretend: true
|
10
|
-
}
|
11
|
-
end
|
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') }
|
17
|
-
|
18
|
-
before do
|
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)
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#update' do
|
26
|
-
before do
|
27
|
-
expect(git).to receive(:update)
|
28
|
-
|
29
|
-
cli.update
|
30
|
-
end
|
31
|
-
it 'runs expected commands' do
|
32
|
-
should meet_expectations
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#integrate' do
|
37
|
-
context 'when target branch is ommitted' do
|
38
|
-
before do
|
39
|
-
expect(git).to receive(:integrate).with('staging')
|
40
|
-
|
41
|
-
cli.integrate
|
42
|
-
end
|
43
|
-
it 'defaults to staging branch' do
|
44
|
-
should meet_expectations
|
45
|
-
end
|
46
|
-
end
|
47
|
-
context 'when target branch == prototype' do
|
48
|
-
before do
|
49
|
-
expect(git).to receive(:integrate).with('prototype')
|
50
|
-
|
51
|
-
cli.integrate 'prototype'
|
52
|
-
end
|
53
|
-
it 'runs expected commands' do
|
54
|
-
should meet_expectations
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '#release' do
|
60
|
-
context 'when user rejects release' do
|
61
|
-
before do
|
62
|
-
expect(cli).to receive(:yes?).and_return(false)
|
63
|
-
|
64
|
-
expect(git).to_not receive(:release)
|
65
|
-
|
66
|
-
cli.release
|
67
|
-
end
|
68
|
-
it 'only runs update commands' do
|
69
|
-
should meet_expectations
|
70
|
-
end
|
71
|
-
end
|
72
|
-
context 'when user confirms release' do
|
73
|
-
before do
|
74
|
-
expect(cli).to receive(:yes?).and_return(true)
|
75
|
-
expect(git).to receive(:release)
|
76
|
-
cli.release
|
77
|
-
end
|
78
|
-
it 'runs expected commands' do
|
79
|
-
should meet_expectations
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
describe '#nuke' do
|
85
|
-
context 'when target branch == prototype and --destination == master' do
|
86
|
-
let(:options) do
|
87
|
-
{
|
88
|
-
destination: good_branch
|
89
|
-
}
|
90
|
-
end
|
91
|
-
let(:good_branch) { 'master' }
|
92
|
-
let(:bad_branch) { 'prototype' }
|
93
|
-
let(:buildtag) { 'build-master-2013-10-01-01' }
|
94
|
-
before do
|
95
|
-
expect(cli).to receive(:yes?).and_return(true)
|
96
|
-
|
97
|
-
expect(git).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
|
98
|
-
expect(git).to receive(:nuke).with(bad_branch, buildtag)
|
99
|
-
|
100
|
-
cli.nuke bad_branch
|
101
|
-
end
|
102
|
-
it 'runs expected commands' do
|
103
|
-
should meet_expectations
|
104
|
-
end
|
105
|
-
end
|
106
|
-
context 'when target branch == prototype and destination prompt == nil' do
|
107
|
-
let(:good_branch) { 'master' }
|
108
|
-
let(:bad_branch) { 'prototype' }
|
109
|
-
let(:buildtag) { 'build-master-2013-10-01-01' }
|
110
|
-
before do
|
111
|
-
expect(cli).to receive(:ask).and_return(good_branch)
|
112
|
-
expect(cli).to receive(:yes?).and_return(true)
|
113
|
-
|
114
|
-
expect(git).to receive(:current_build_tag).with(good_branch).and_return(buildtag)
|
115
|
-
expect(git).to receive(:nuke).with(bad_branch, buildtag)
|
116
|
-
|
117
|
-
cli.nuke 'prototype'
|
118
|
-
end
|
119
|
-
it 'defaults to prototype and should run expected commands' do
|
120
|
-
should meet_expectations
|
121
|
-
end
|
122
|
-
end
|
123
|
-
context 'when user does not confirm nuking the target branch' do
|
124
|
-
let(:buildtag) { 'build-master-2013-10-01-01' }
|
125
|
-
before do
|
126
|
-
expect(cli).to receive(:ask).and_return('master')
|
127
|
-
expect(cli).to receive(:yes?).and_return(false)
|
128
|
-
|
129
|
-
expect(git).to receive(:current_build_tag).with('master').and_return(buildtag)
|
130
|
-
expect(git).to_not receive(:nuke)
|
131
|
-
|
132
|
-
cli.nuke 'prototype'
|
133
|
-
end
|
134
|
-
it 'runs expected commands' do
|
135
|
-
should meet_expectations
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe '#reviewrequest' do
|
141
|
-
let(:pull_request) do
|
142
|
-
{
|
143
|
-
'html_url' => 'https://path/to/new/pull/request',
|
144
|
-
'head' => {
|
145
|
-
'ref' => 'branch_name'
|
146
|
-
}
|
147
|
-
}
|
148
|
-
end
|
149
|
-
context 'when pull request does not exist' do
|
150
|
-
let(:authorization_token) { '123123' }
|
151
|
-
let(:changelog) { '* made some fixes' }
|
152
|
-
before do
|
153
|
-
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
154
|
-
expect(github).to receive(:find_pull_request).and_return(nil)
|
155
|
-
expect(github).to receive(:create_pull_request).and_return(pull_request)
|
156
|
-
|
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
|
159
|
-
cli.reviewrequest
|
160
|
-
end
|
161
|
-
it 'creates github pull request' do
|
162
|
-
should meet_expectations
|
163
|
-
end
|
164
|
-
it 'runs expected commands' do
|
165
|
-
should meet_expectations
|
166
|
-
end
|
167
|
-
end
|
168
|
-
context 'when authorization_token is missing' do
|
169
|
-
let(:authorization_token) { nil }
|
170
|
-
it do
|
171
|
-
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
172
|
-
expect { cli.reviewrequest }.to raise_error(/token not found/)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
context 'when pull request already exists' do
|
176
|
-
let(:authorization_token) { '123123' }
|
177
|
-
before do
|
178
|
-
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
179
|
-
expect(github).to receive(:find_pull_request).and_return(pull_request)
|
180
|
-
expect(github).to_not receive(:create_pull_request)
|
181
|
-
|
182
|
-
cli.reviewrequest
|
183
|
-
end
|
184
|
-
it 'does not create new pull request' do
|
185
|
-
should meet_expectations
|
186
|
-
end
|
187
|
-
end
|
188
|
-
context 'when --assignee option passed' do
|
189
|
-
let(:options) do
|
190
|
-
{
|
191
|
-
assignee: 'johndoe'
|
192
|
-
}
|
193
|
-
end
|
194
|
-
let(:authorization_token) { '123123' }
|
195
|
-
before do
|
196
|
-
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
197
|
-
expect(github).to receive(:find_pull_request).and_return(pull_request)
|
198
|
-
expect(github).to receive(:assign_pull_request)
|
199
|
-
|
200
|
-
cli.reviewrequest
|
201
|
-
end
|
202
|
-
it 'calls assign_pull_request method' do
|
203
|
-
should meet_expectations
|
204
|
-
end
|
205
|
-
end
|
206
|
-
context 'when --open flag passed' do
|
207
|
-
let(:options) do
|
208
|
-
{
|
209
|
-
open: true
|
210
|
-
}
|
211
|
-
end
|
212
|
-
let(:authorization_token) { '123123' }
|
213
|
-
before do
|
214
|
-
expect(github).to receive(:authorization_token).and_return(authorization_token)
|
215
|
-
expect(github).to receive(:find_pull_request).and_return(pull_request)
|
216
|
-
|
217
|
-
expect(runner).to receive(:run_cmd).with("open #{pull_request['html_url']}").ordered
|
218
|
-
cli.reviewrequest
|
219
|
-
end
|
220
|
-
it 'runs open command with pull request url' do
|
221
|
-
should meet_expectations
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
describe '#track' do
|
227
|
-
it 'calls git.track' do
|
228
|
-
expect(git).to receive(:track)
|
229
|
-
cli.track
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
describe '#share' do
|
234
|
-
it 'calls git.share' do
|
235
|
-
expect(git).to receive(:share)
|
236
|
-
cli.share
|
237
|
-
end
|
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'
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
describe '#buildtag' do
|
252
|
-
it 'calls git.buildtag' do
|
253
|
-
expect(git).to receive(:buildtag)
|
254
|
-
cli.buildtag
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
@@ -1,231 +0,0 @@
|
|
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
|