slugforge 4.0.0
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 +7 -0
- data/README.md +316 -0
- data/bin/slugforge +9 -0
- data/lib/slugforge.rb +19 -0
- data/lib/slugforge/build.rb +4 -0
- data/lib/slugforge/build/build_project.rb +31 -0
- data/lib/slugforge/build/export_upstart.rb +85 -0
- data/lib/slugforge/build/package.rb +63 -0
- data/lib/slugforge/cli.rb +125 -0
- data/lib/slugforge/commands.rb +130 -0
- data/lib/slugforge/commands/build.rb +20 -0
- data/lib/slugforge/commands/config.rb +24 -0
- data/lib/slugforge/commands/deploy.rb +383 -0
- data/lib/slugforge/commands/project.rb +21 -0
- data/lib/slugforge/commands/tag.rb +148 -0
- data/lib/slugforge/commands/wrangler.rb +142 -0
- data/lib/slugforge/configuration.rb +125 -0
- data/lib/slugforge/helper.rb +186 -0
- data/lib/slugforge/helper/build.rb +46 -0
- data/lib/slugforge/helper/config.rb +37 -0
- data/lib/slugforge/helper/enumerable.rb +46 -0
- data/lib/slugforge/helper/fog.rb +90 -0
- data/lib/slugforge/helper/git.rb +89 -0
- data/lib/slugforge/helper/path.rb +76 -0
- data/lib/slugforge/helper/project.rb +86 -0
- data/lib/slugforge/models/host.rb +233 -0
- data/lib/slugforge/models/host/fog_host.rb +33 -0
- data/lib/slugforge/models/host/hostname_host.rb +9 -0
- data/lib/slugforge/models/host/ip_address_host.rb +9 -0
- data/lib/slugforge/models/host_group.rb +65 -0
- data/lib/slugforge/models/host_group/aws_tag_group.rb +22 -0
- data/lib/slugforge/models/host_group/ec2_instance_group.rb +21 -0
- data/lib/slugforge/models/host_group/hostname_group.rb +16 -0
- data/lib/slugforge/models/host_group/ip_address_group.rb +16 -0
- data/lib/slugforge/models/host_group/security_group_group.rb +20 -0
- data/lib/slugforge/models/logger.rb +36 -0
- data/lib/slugforge/models/tag_manager.rb +125 -0
- data/lib/slugforge/slugins.rb +125 -0
- data/lib/slugforge/version.rb +9 -0
- data/scripts/post-install.sh +143 -0
- data/scripts/unicorn-shepherd.sh +305 -0
- data/spec/fixtures/array.yaml +3 -0
- data/spec/fixtures/fog_credentials.yaml +4 -0
- data/spec/fixtures/invalid_syntax.yaml +1 -0
- data/spec/fixtures/one.yaml +3 -0
- data/spec/fixtures/two.yaml +3 -0
- data/spec/fixtures/valid.yaml +4 -0
- data/spec/slugforge/commands/deploy_spec.rb +72 -0
- data/spec/slugforge/commands_spec.rb +33 -0
- data/spec/slugforge/configuration_spec.rb +200 -0
- data/spec/slugforge/helper/fog_spec.rb +81 -0
- data/spec/slugforge/helper/git_spec.rb +152 -0
- data/spec/slugforge/models/host_group/aws_tag_group_spec.rb +54 -0
- data/spec/slugforge/models/host_group/ec2_instance_group_spec.rb +51 -0
- data/spec/slugforge/models/host_group/hostname_group_spec.rb +20 -0
- data/spec/slugforge/models/host_group/ip_address_group_spec.rb +54 -0
- data/spec/slugforge/models/host_group/security_group_group_spec.rb +52 -0
- data/spec/slugforge/models/tag_manager_spec.rb +75 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/env.rb +3 -0
- data/spec/support/example_groups/configuration_writer.rb +24 -0
- data/spec/support/example_groups/helper_provider.rb +10 -0
- data/spec/support/factories.rb +18 -0
- data/spec/support/fog.rb +15 -0
- data/spec/support/helpers.rb +18 -0
- data/spec/support/mock_logger.rb +6 -0
- data/spec/support/ssh.rb +8 -0
- data/spec/support/streams.rb +13 -0
- data/templates/foreman/master.conf.erb +21 -0
- data/templates/foreman/process-master.conf.erb +2 -0
- data/templates/foreman/process.conf.erb +19 -0
- metadata +344 -0
@@ -0,0 +1 @@
|
|
1
|
+
foo: -
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe Slugforge::Commands::Deploy, :config => true do
|
5
|
+
|
6
|
+
describe "deployment via" do
|
7
|
+
let(:project) { "zany" }
|
8
|
+
let(:host) { "example.com" }
|
9
|
+
let(:opts) { %w(--force --json) }
|
10
|
+
let(:config) { %w() }
|
11
|
+
let(:cmd) { ["deploy", operation, target, "--project", project, host, opts, config].flatten }
|
12
|
+
let(:stdout) { StringIO.new }
|
13
|
+
let(:stderr) { StringIO.new }
|
14
|
+
let(:output) { capture(:stdout, stdout) { capture(:stderr, stderr) { Slugforge::Cli.start(cmd) } } }
|
15
|
+
let(:result) { JSON.parse(output) }
|
16
|
+
let(:s3_root) { "s3://#{helpers.config.values[:slug_bucket]}/#{project}" }
|
17
|
+
|
18
|
+
shared_examples_for "a deployment method" do
|
19
|
+
it "should succeed" do
|
20
|
+
begin
|
21
|
+
result["success"].should == true
|
22
|
+
rescue SystemExit
|
23
|
+
fail stderr.string
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has a full slug path" do
|
28
|
+
Slugforge::Commands::Deploy.any_instance.should_receive(:deploy).with(anything, anything, hash_including(locator))
|
29
|
+
output
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#file" do
|
34
|
+
let(:operation) { "file" }
|
35
|
+
let(:target) { "artifact.slug" }
|
36
|
+
let(:locator) { {:filename => target} }
|
37
|
+
|
38
|
+
it_should_behave_like "a deployment method"
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#tag" do
|
42
|
+
let(:operation) { "tag" }
|
43
|
+
let(:target) { "testing" }
|
44
|
+
let(:slug_name) { "123.slug" }
|
45
|
+
let(:locator) { {:s3_url => "#{s3_root}/#{slug_name}"} }
|
46
|
+
|
47
|
+
context "with existing tagged slug" do
|
48
|
+
before(:each) do
|
49
|
+
create_slug project, slug_name
|
50
|
+
create_tag project, target, slug_name
|
51
|
+
end
|
52
|
+
|
53
|
+
it_should_behave_like "a deployment method"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#name" do
|
58
|
+
let(:operation) { "name" }
|
59
|
+
let(:target) { "123456" }
|
60
|
+
let(:locator) { {:s3_url => "#{s3_root}/#{target}.slug"} }
|
61
|
+
|
62
|
+
context "with existing named slug" do
|
63
|
+
before(:each) do
|
64
|
+
create_slug project, "#{target}"
|
65
|
+
end
|
66
|
+
|
67
|
+
it_should_behave_like "a deployment method"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slugforge::Command do
|
4
|
+
let(:command_class) { Class.new(Slugforge::Command) }
|
5
|
+
let(:stdout) { StringIO.new }
|
6
|
+
let(:stderr) { StringIO.new }
|
7
|
+
let(:args) { [] }
|
8
|
+
let(:command) { capture(:stdout, stdout) { capture(:stderr, stderr) { command_class.start(args) } } }
|
9
|
+
|
10
|
+
describe "slugin loading" do
|
11
|
+
context "in a command" do
|
12
|
+
it "should only activate slugins once" do
|
13
|
+
Slugforge::SluginManager.any_instance.should_receive(:activate_slugins).once
|
14
|
+
command
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "in a subcommand" do
|
19
|
+
let(:subcommand_class) { Class.new(Slugforge::SubCommand) }
|
20
|
+
let(:args) { [ 'sub' ] }
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
command_class.desc 'sub [THING]', 'test subcommand'
|
24
|
+
command_class.subcommand 'sub', subcommand_class
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should only activate slugins once" do
|
28
|
+
Slugforge::SluginManager.any_instance.should_receive(:activate_slugins).once
|
29
|
+
command
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slugforge::Configuration do
|
4
|
+
|
5
|
+
# Use a subclass that can be safely modified without destroying other specs
|
6
|
+
let(:described_class) do
|
7
|
+
Class.new(Slugforge::Configuration) do
|
8
|
+
self.configuration_files = []
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { described_class.new }
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
# Ensure we have a clean configuration object for each test
|
16
|
+
described_class.instance_variable_set(:@options, {})
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.option' do
|
20
|
+
it 'defines an instance method with the option name' do
|
21
|
+
described_class.option(:test_option, {})
|
22
|
+
subject.should respond_to(:test_option)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'raies an error if a duplicate option is defined' do
|
26
|
+
described_class.option(:test_option, {})
|
27
|
+
expect { described_class.option(:test_option, {}) }.to raise_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'programatically defined methods' do
|
32
|
+
describe 'on the instance' do
|
33
|
+
it 'returns the options value' do
|
34
|
+
described_class.option(:test_option, {})
|
35
|
+
subject.instance_variable_set(:@values, {:test_option => 'test'})
|
36
|
+
subject.test_option.should == 'test'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "loading config" do
|
42
|
+
let!(:option) { described_class.option(:test_option, {:default => 'test' }) }
|
43
|
+
|
44
|
+
it 'applies default values' do
|
45
|
+
subject.test_option.should == 'test'
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'from conf files' do
|
49
|
+
before(:each) do
|
50
|
+
FakeFS.deactivate!
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should fail with invalid YAML" do
|
54
|
+
described_class.configuration_files = [ fixture_file("invalid_syntax.yaml") ]
|
55
|
+
expect { subject }.to raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should gracefully handle non-hash contents" do
|
59
|
+
described_class.configuration_files = [ fixture_file("array.yaml") ]
|
60
|
+
expect { subject }.to_not raise_error
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with a missing configuration file" do
|
64
|
+
before(:each) do
|
65
|
+
described_class.configuration_files = [ "xxxxx.yaml" ]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "applies the defaults" do
|
69
|
+
subject.test_option.should == "test"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with single configuration file" do
|
74
|
+
let!(:option) { described_class.option(:test_option, {:default => 'test', :key => 'test'}) }
|
75
|
+
|
76
|
+
before(:each) do
|
77
|
+
described_class.configuration_files = [ fixture_file("valid.yaml") ]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should load values mapped by their configuration key" do
|
81
|
+
subject.test_option.should == 'foo'
|
82
|
+
end
|
83
|
+
|
84
|
+
context "and a dotted conf key" do
|
85
|
+
let!(:option) { described_class.option(:test_option, {:key => 'foo.bar'}) }
|
86
|
+
|
87
|
+
it "should load nested value" do
|
88
|
+
subject.test_option.should == 'baz'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "with multiple configuration files" do
|
94
|
+
let!(:option) { described_class.option(:test_option, {:key => 'test_option'}) }
|
95
|
+
|
96
|
+
before(:each) do
|
97
|
+
described_class.configuration_files = [ fixture_file("one.yaml"), fixture_file("two.yaml") ]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should override the values in the first file with values from the second" do
|
101
|
+
subject.test_option.should == 2
|
102
|
+
end
|
103
|
+
|
104
|
+
context "and a dotted conf key" do
|
105
|
+
let!(:option) { described_class.option(:test_option, {:key => 'foo.bar'}) }
|
106
|
+
|
107
|
+
it "should load and override nested values" do
|
108
|
+
subject.test_option.should == "baz"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "from ENV" do
|
115
|
+
let!(:option) { described_class.option(:test_option, {:default => 'test', :key => 'test_option', :env => 'TEST_OPTION'}) }
|
116
|
+
|
117
|
+
around(:each) do |example|
|
118
|
+
with_env('TEST_OPTION' => 'foo') { example.run }
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should assign values from mapped variables' do
|
122
|
+
subject.test_option.should == 'foo'
|
123
|
+
end
|
124
|
+
|
125
|
+
context "with conf file" do
|
126
|
+
before(:each) do
|
127
|
+
described_class.configuration_files = [ fixture_file("one.yaml") ]
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should prefer ENV" do
|
131
|
+
subject.test_option.should == 'foo'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "from CLI options" do
|
137
|
+
let!(:option) { described_class.option(:test_option, {:default => 'test', :option => :'test-option'}) }
|
138
|
+
|
139
|
+
subject { described_class.new :'test-option' => 'foo' }
|
140
|
+
|
141
|
+
it "should load value from mapped option" do
|
142
|
+
subject.test_option.should == 'foo'
|
143
|
+
end
|
144
|
+
|
145
|
+
context "with ENV present" do
|
146
|
+
let!(:option) { described_class.option(:test_option, {:default => 'test', :option => :'test-option', :env => 'TEST_OPTION'}) }
|
147
|
+
|
148
|
+
around(:each) do |example|
|
149
|
+
with_env('TEST_OPTION' => 'bar') { example.run }
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should prefer setting from CLI' do
|
153
|
+
subject.test_option.should == 'foo'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe '#update_with' do
|
160
|
+
it 'yields for every option' do
|
161
|
+
options = {
|
162
|
+
:a => {:key => 'a'},
|
163
|
+
:b => {:key => 'b'}
|
164
|
+
}
|
165
|
+
|
166
|
+
described_class.option(:a, options[:a])
|
167
|
+
described_class.option(:b, options[:b])
|
168
|
+
expect { |b| subject.send(:update_with, &b) }.to yield_successive_args(options[:a], options[:b])
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'when the block returns a value' do
|
172
|
+
it 'updates the options value' do
|
173
|
+
described_class.option(:a, {})
|
174
|
+
subject.instance_variable_set(:@values, {:a => 'false'} )
|
175
|
+
blk = proc { |c| 'true' }
|
176
|
+
subject.send(:update_with, &blk)
|
177
|
+
subject.a.should == 'true'
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'same for "falsey" but not nil' do
|
181
|
+
described_class.option(:a, {})
|
182
|
+
subject.instance_variable_set(:@values, {:a => 'false'} )
|
183
|
+
blk = proc { |c| false }
|
184
|
+
subject.send(:update_with, &blk)
|
185
|
+
subject.a.should == false
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'when the block does not return a value' do
|
190
|
+
it 'leaves the options value as-is' do
|
191
|
+
described_class.option(:a, {})
|
192
|
+
subject.instance_variable_set(:@values, {:a => 'false'} )
|
193
|
+
blk = proc { |c| nil }
|
194
|
+
subject.send(:update_with, &blk)
|
195
|
+
subject.a.should == 'false'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slugforge::Helper::Fog, :config => false do
|
4
|
+
let(:command_class) do
|
5
|
+
Class.new(Slugforge::Command) do
|
6
|
+
include Slugforge::Helper::Config
|
7
|
+
include Slugforge::Helper::Fog
|
8
|
+
|
9
|
+
desc 'test', 'An example command'
|
10
|
+
def test; end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:options) {{ 'aws-access-key-id' => 'abc', 'aws-region' => 'north-pole-9', 'aws-secret-key' => '123', 'slug-bucket' => 'bucket' }}
|
15
|
+
|
16
|
+
let(:command) { command_class.new [], options }
|
17
|
+
|
18
|
+
context "#aws_credentials" do
|
19
|
+
subject(:aws_credentials) { command.aws_credentials }
|
20
|
+
|
21
|
+
it "should error without access key" do
|
22
|
+
options.delete('aws-access-key-id')
|
23
|
+
expect { aws_credentials }.to raise_error(/access key/)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should error without secret key" do
|
27
|
+
options.delete('aws-secret-key')
|
28
|
+
expect { aws_credentials }.to raise_error(/secret key/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not error without session token" do
|
32
|
+
expect { aws_credentials }.to_not raise_error
|
33
|
+
end
|
34
|
+
|
35
|
+
context "response hash" do
|
36
|
+
it "should include key and secret" do
|
37
|
+
expect(aws_credentials).to eq({:aws_access_key_id => 'abc', :aws_secret_access_key => '123'})
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when session token is set" do
|
41
|
+
let(:options) {{ 'aws-access-key-id' => 'abc', 'aws-secret-key' => '123', 'aws-session-token' => 'xyz' }}
|
42
|
+
|
43
|
+
it "should include session token" do
|
44
|
+
expect(aws_credentials).to eq({
|
45
|
+
:aws_session_token => 'xyz',
|
46
|
+
:aws_access_key_id => 'abc',
|
47
|
+
:aws_secret_access_key => '123'})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "#aws_session" do
|
54
|
+
# Fog doesn't have an STS mock yet
|
55
|
+
let(:response) { build_sts_response }
|
56
|
+
let(:session) { response.body }
|
57
|
+
let(:username) { 'user name' }
|
58
|
+
let(:sts) { double(::Fog::AWS::STS, :get_federation_token => response) }
|
59
|
+
|
60
|
+
before(:each) do
|
61
|
+
::Fog::AWS::STS.stub(:new) { sts }
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should exchange aws credentials for a federation session token" do
|
65
|
+
command.stub(:username).and_return(username)
|
66
|
+
::Fog::AWS::STS.should_receive(:new).with(command.aws_credentials) { sts }
|
67
|
+
sts.should_receive(:get_federation_token).with(username, instance_of(Hash), instance_of(Fixnum))
|
68
|
+
|
69
|
+
command.aws_session
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return a session hash matching what fog expects for credentials" do
|
73
|
+
expect(command.aws_session).to eq({
|
74
|
+
:aws_access_key_id => session['AccessKeyId'],
|
75
|
+
:aws_region => options['aws-region'],
|
76
|
+
:aws_secret_access_key => session['SecretAccessKey'],
|
77
|
+
:aws_session_token => session['SessionToken']
|
78
|
+
})
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slugforge::Helper::Git do
|
4
|
+
class DummyClass
|
5
|
+
attr_accessor :options
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:dummy_class) { DummyClass.new }
|
9
|
+
let(:git_account) { 'GitAccount' }
|
10
|
+
let(:git_repository) { 'repository' }
|
11
|
+
let(:git_branch) { 'master' }
|
12
|
+
let(:git_remote) { 'remote' }
|
13
|
+
let(:git_url) { "git@github.com:#{git_account}/#{git_repository}.git" }
|
14
|
+
let(:git_sha) { '0123456789abcdef0123456789abcdef01234567' }
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
dummy_class.extend(subject)
|
18
|
+
dummy_class.stub(:error_class).and_return(Thor::Error)
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'not inside work tree' do
|
22
|
+
before(:each) { dummy_class.stub(:git_inside_work_tree?).and_return(false) }
|
23
|
+
|
24
|
+
it '#git_account returns nil' do
|
25
|
+
dummy_class.git_account.should be_nil
|
26
|
+
end
|
27
|
+
it '#git_repository returns nil' do
|
28
|
+
dummy_class.git_repository.should be_nil
|
29
|
+
end
|
30
|
+
it '#git_branch returns nil' do
|
31
|
+
dummy_class.git_branch.should be_nil
|
32
|
+
end
|
33
|
+
it '#git_remote returns nil' do
|
34
|
+
dummy_class.git_remote.should be_nil
|
35
|
+
end
|
36
|
+
it '#git_remote_sha returns nil' do
|
37
|
+
dummy_class.git_remote_sha.should be_nil
|
38
|
+
end
|
39
|
+
it '#git_url returns empty' do
|
40
|
+
dummy_class.git_url.should be_empty
|
41
|
+
end
|
42
|
+
it '#git_sha raises' do
|
43
|
+
expect { dummy_class.git_sha }.to raise_error(Thor::Error)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'inside work tree' do
|
48
|
+
before(:each) { dummy_class.stub(:git_inside_work_tree?).and_return(true) }
|
49
|
+
context 'git_url is empty' do
|
50
|
+
before(:each) { dummy_class.stub(:git_url).and_return('') }
|
51
|
+
|
52
|
+
it '#git_account returns nil' do
|
53
|
+
dummy_class.git_account.should be_nil
|
54
|
+
end
|
55
|
+
it '#git_repository returns nil' do
|
56
|
+
dummy_class.git_repository.should be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'git_url is valid (SSH)' do
|
61
|
+
before(:each) { dummy_class.stub(:git_url).and_return(git_url) }
|
62
|
+
|
63
|
+
it '#git_accout returns account' do
|
64
|
+
dummy_class.git_account.should == git_account
|
65
|
+
end
|
66
|
+
it '#git_repository returns repository' do
|
67
|
+
dummy_class.git_repository.should == git_repository
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'git_url is valid (HTTPS)' do
|
72
|
+
let(:git_url) { "https://github.com/#{git_account}/#{git_repository}" }
|
73
|
+
|
74
|
+
before(:each) { dummy_class.stub(:git_url).and_return(git_url) }
|
75
|
+
|
76
|
+
it '#git_accout returns account' do
|
77
|
+
dummy_class.git_account.should == git_account
|
78
|
+
end
|
79
|
+
it '#git_repository returns repository' do
|
80
|
+
dummy_class.git_repository.should == git_repository
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#git_remote_sha' do
|
85
|
+
before(:each) do
|
86
|
+
dummy_class.stub(:git_command).and_return(git_sha)
|
87
|
+
dummy_class.stub(:git_url).and_return(git_url)
|
88
|
+
dummy_class.stub(:git_branch).and_return(git_branch)
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'no options specified' do
|
92
|
+
it 'returns first 10 characters of SHA' do
|
93
|
+
dummy_class.git_remote_sha.should == git_sha.slice(0...10)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'sha_length specified' do
|
98
|
+
it 'returns first character when sha_length=1' do
|
99
|
+
dummy_class.git_remote_sha(:sha_length => 1).should == git_sha.slice(0...1)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns all characters when sha_length=40' do
|
103
|
+
dummy_class.git_remote_sha(:sha_length => 40).should == git_sha.slice(0...40)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'returns all characters when sha_length>40' do
|
107
|
+
dummy_class.git_remote_sha(:sha_length => 50).should == git_sha.slice(0...40)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'url specified' do
|
112
|
+
it 'git_command receives url' do
|
113
|
+
test_url = 'test_url'
|
114
|
+
dummy_class.git_remote_sha(:url => test_url)
|
115
|
+
dummy_class.should have_received(:git_command).with("ls-remote #{test_url} #{git_branch}")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'branch specified' do
|
120
|
+
it 'git_command receives branch' do
|
121
|
+
test_branch = 'test_branch'
|
122
|
+
dummy_class.git_remote_sha(:branch => test_branch)
|
123
|
+
dummy_class.should have_received(:git_command).with("ls-remote #{git_url} #{test_branch}")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#git_sha' do
|
129
|
+
before(:each) { dummy_class.stub(:git_command).and_return(git_sha) }
|
130
|
+
|
131
|
+
context 'no options specified' do
|
132
|
+
it 'returns first 10 characters of SHA' do
|
133
|
+
dummy_class.git_sha.should == git_sha.slice(0...10)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'sha_length specified' do
|
138
|
+
it 'returns first character when sha_length=1' do
|
139
|
+
dummy_class.git_sha(:sha_length => 1).should == git_sha.slice(0...1)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'returns all characters when sha_length=40' do
|
143
|
+
dummy_class.git_sha(:sha_length => 40).should == git_sha.slice(0...40)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'returns all characters when sha_length>40' do
|
147
|
+
dummy_class.git_sha(:sha_length => 50).should == git_sha.slice(0...40)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|