snap_deploy 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.init.sh +8 -0
- data/.rbenv-gemsets +1 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +100 -0
- data/LICENSE.txt +22 -0
- data/README.md +34 -0
- data/Rakefile +25 -0
- data/bin/snap-deploy +10 -0
- data/install.sh +18 -0
- data/lib/snap_deploy.rb +4 -0
- data/lib/snap_deploy/cli.rb +24 -0
- data/lib/snap_deploy/helpers.rb +74 -0
- data/lib/snap_deploy/provider.rb +8 -0
- data/lib/snap_deploy/provider/aws.rb +17 -0
- data/lib/snap_deploy/provider/aws/elastic_beanstalk.rb +156 -0
- data/lib/snap_deploy/provider/aws/ops_works.rb +98 -0
- data/lib/snap_deploy/provider/aws/s3.rb +111 -0
- data/lib/snap_deploy/provider/heroku.rb +242 -0
- data/lib/snap_deploy/provider/heroku/api.rb +1532 -0
- data/lib/snap_deploy/provider/update.rb +25 -0
- data/lib/snap_deploy/version.rb +3 -0
- data/snap_deploy.gemspec +28 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/snap_deploy/provider/aws/ops_works_spec.rb +128 -0
- data/spec/unit/snap_deploy/provider/aws/s3_spec.rb +60 -0
- data/spec/unit/snap_deploy/provider/heroku_spec.rb +189 -0
- metadata +177 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/file_utils_ext'
|
3
|
+
|
4
|
+
class SnapDeploy::Provider::Update < Clamp::Command
|
5
|
+
|
6
|
+
SnapDeploy::CLI.subcommand 'update', 'Update snap deploy', self
|
7
|
+
|
8
|
+
include SnapDeploy::CLI::DefaultOptions
|
9
|
+
include SnapDeploy::Helpers
|
10
|
+
include Rake::FileUtilsExt
|
11
|
+
|
12
|
+
option '--revision',
|
13
|
+
'REVISION',
|
14
|
+
"Update to specified revision",
|
15
|
+
:default => 'release'
|
16
|
+
|
17
|
+
def execute
|
18
|
+
cd(File.dirname(__FILE__), :verbose => !!verbose?) do
|
19
|
+
sh("sudo $(which git) fetch --all", :verbose => !!verbose?)
|
20
|
+
sh("sudo $(which git) merge --ff-only origin/#{revision}", :verbose => !!verbose?)
|
21
|
+
sh("cd \"$(git rev-parse --show-toplevel)\" && sudo ./install.sh")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/snap_deploy.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'snap_deploy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "snap_deploy"
|
8
|
+
spec.version = SnapDeploy::VERSION
|
9
|
+
spec.authors = ["Snap CI"]
|
10
|
+
spec.email = ["support@snap-ci.com"]
|
11
|
+
spec.summary = %q{Deploy your application in a Snap}
|
12
|
+
spec.description = %q{A simple rubygem to help continuously deploy your application}
|
13
|
+
spec.homepage = "https://snap-ci.com"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($\) + Dir["bundle/**/*"] - Dir["**/*.gem"] + Dir['bin/*'] - Dir["bundle/ruby/2.0.0/gems/*/{spec,test,specs,tests,examples,doc,doc-api,benchmarks,benchmark,feature,features}/**/*"]
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_runtime_dependency 'ansi'
|
23
|
+
spec.add_runtime_dependency "clamp"
|
24
|
+
spec.add_runtime_dependency "aws-sdk", '1.53.0'
|
25
|
+
spec.add_runtime_dependency "mime-types"
|
26
|
+
spec.add_runtime_dependency "heroics"
|
27
|
+
spec.add_runtime_dependency "rendezvous"
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
ENV['TEST'] = 'true'
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
add_filter '/bundle/ruby/'
|
5
|
+
add_filter '/vendor/cache/'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'snap_deploy'
|
9
|
+
require 'webmock/rspec'
|
10
|
+
|
11
|
+
module SpecHelper
|
12
|
+
def revision
|
13
|
+
@revision ||= SecureRandom.hex(32)
|
14
|
+
end
|
15
|
+
|
16
|
+
def short_revision
|
17
|
+
revision[0..7]
|
18
|
+
end
|
19
|
+
|
20
|
+
def strip_heredoc(str)
|
21
|
+
indent = str.scan(/^[ \t]*(?=\S)/).min.size || 0
|
22
|
+
str.gsub(/^[ \t]{#{indent}}/, '')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec.configure do |config|
|
27
|
+
config.include SpecHelper
|
28
|
+
config.tty = true
|
29
|
+
config.expose_dsl_globally = false
|
30
|
+
config.disable_monkey_patching!
|
31
|
+
|
32
|
+
config.before(:each) do
|
33
|
+
@original_env = ENV.to_h.dup
|
34
|
+
ENV.clear
|
35
|
+
end
|
36
|
+
|
37
|
+
config.after(:each) do
|
38
|
+
ENV.replace(@original_env)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'aws-sdk'
|
3
|
+
|
4
|
+
RSpec.describe SnapDeploy::Provider::AWS::OpsWorks do
|
5
|
+
subject(:cmd) { SnapDeploy::Provider::AWS::OpsWorks.new(nil, {}, {}) }
|
6
|
+
|
7
|
+
let(:client) { double(:ops_works_client) }
|
8
|
+
let(:app_id) { SecureRandom.uuid }
|
9
|
+
let(:deployment_id) { SecureRandom.uuid }
|
10
|
+
let(:stack_id) { SecureRandom.uuid }
|
11
|
+
|
12
|
+
let(:ops_works_app) do
|
13
|
+
{shortname: 'simplephpapp', stack_id: stack_id}
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
AWS.stub!
|
18
|
+
|
19
|
+
allow(cmd).to receive(:client).and_return(client)
|
20
|
+
|
21
|
+
allow(ENV).to receive(:[]).with('SNAP_PIPELINE_COUNTER').and_return('123')
|
22
|
+
allow(ENV).to receive(:[]).with('SNAP_COMMIT_SHORT').and_return(short_revision)
|
23
|
+
allow(ENV).to receive(:[]).with('SNAP_COMMIT').and_return(revision)
|
24
|
+
allow(ENV).to receive(:[]).with('SNAP_STAGE_TRIGGERED_BY').and_return('john-doe')
|
25
|
+
end
|
26
|
+
|
27
|
+
example 'with migrate option not specified' do
|
28
|
+
expect(client).to receive(:describe_apps).with(app_ids: [app_id]).and_return({apps: [ops_works_app]})
|
29
|
+
expect(client).to receive(:create_deployment).with(
|
30
|
+
stack_id: stack_id,
|
31
|
+
app_id: app_id,
|
32
|
+
command: {name: 'deploy'},
|
33
|
+
comment: "Deploy build 123(rev #{short_revision}) via Snap CI by john-doe",
|
34
|
+
custom_json: {"deploy"=>{"simplephpapp"=>{"migrate"=>true, "scm"=>{"revision"=>revision}}}}.to_json
|
35
|
+
).and_return({deployment_id: deployment_id})
|
36
|
+
|
37
|
+
expect(client).to receive(:describe_deployments).with({deployment_ids: [deployment_id]}).and_return(
|
38
|
+
{deployments: [status: 'running']},
|
39
|
+
{deployments: [status: 'successful']}
|
40
|
+
)
|
41
|
+
|
42
|
+
expect do
|
43
|
+
cmd.run(['--wait', '--app-id', app_id])
|
44
|
+
end.to output(strip_heredoc(<<-EOF
|
45
|
+
Deployment created: #{deployment_id}
|
46
|
+
Deploying .
|
47
|
+
Deployment successful.
|
48
|
+
EOF
|
49
|
+
)).to_stdout
|
50
|
+
end
|
51
|
+
|
52
|
+
example 'with migrate option specified' do
|
53
|
+
expect(client).to receive(:describe_apps).with(app_ids: [app_id]).and_return({apps: [ops_works_app]})
|
54
|
+
expect(client).to receive(:create_deployment).with(
|
55
|
+
stack_id: stack_id,
|
56
|
+
app_id: app_id,
|
57
|
+
command: {name: 'deploy'},
|
58
|
+
comment: "Deploy build 123(rev #{short_revision}) via Snap CI by john-doe",
|
59
|
+
custom_json: {"deploy"=>{"simplephpapp"=>{"migrate"=>true, "scm"=>{"revision"=>revision}}}}.to_json
|
60
|
+
).and_return({deployment_id: deployment_id})
|
61
|
+
|
62
|
+
expect(client).to receive(:describe_deployments).with({deployment_ids: [deployment_id]}).and_return(
|
63
|
+
{deployments: [status: 'running']},
|
64
|
+
{deployments: [status: 'successful']}
|
65
|
+
)
|
66
|
+
expect do
|
67
|
+
cmd.run(['--wait', '--migrate', '--app-id', app_id])
|
68
|
+
end.to output(strip_heredoc(<<-EOF
|
69
|
+
Deployment created: #{deployment_id}
|
70
|
+
Deploying .
|
71
|
+
Deployment successful.
|
72
|
+
EOF
|
73
|
+
)).to_stdout
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
example 'with migrate option forced off' do
|
78
|
+
expect(client).to receive(:describe_apps).with(app_ids: [app_id]).and_return({apps: [ops_works_app]})
|
79
|
+
expect(client).to receive(:create_deployment).with(
|
80
|
+
stack_id: stack_id,
|
81
|
+
app_id: app_id,
|
82
|
+
command: {name: 'deploy'},
|
83
|
+
comment: "Deploy build 123(rev #{short_revision}) via Snap CI by john-doe",
|
84
|
+
custom_json: {"deploy"=>{"simplephpapp"=>{"migrate"=>false, "scm"=>{"revision"=>revision}}}}.to_json
|
85
|
+
).and_return({deployment_id: deployment_id})
|
86
|
+
|
87
|
+
expect(client).to receive(:describe_deployments).with({deployment_ids: [deployment_id]}).and_return(
|
88
|
+
{deployments: [status: 'running']},
|
89
|
+
{deployments: [status: 'successful']}
|
90
|
+
)
|
91
|
+
|
92
|
+
expect do
|
93
|
+
cmd.run(['--wait', '--no-migrate', '--app-id', app_id])
|
94
|
+
end.to output(strip_heredoc(<<-EOF
|
95
|
+
Deployment created: #{deployment_id}
|
96
|
+
Deploying .
|
97
|
+
Deployment successful.
|
98
|
+
EOF
|
99
|
+
)).to_stdout
|
100
|
+
end
|
101
|
+
|
102
|
+
example 'when deployment fails' do
|
103
|
+
expect(client).to receive(:describe_apps).with(app_ids: [app_id]).and_return({apps: [ops_works_app]})
|
104
|
+
expect(client).to receive(:create_deployment).with(
|
105
|
+
stack_id: stack_id,
|
106
|
+
app_id: app_id,
|
107
|
+
command: {name: 'deploy'},
|
108
|
+
comment: "Deploy build 123(rev #{short_revision}) via Snap CI by john-doe",
|
109
|
+
custom_json: {"deploy"=>{"simplephpapp"=>{"migrate"=>false, "scm"=>{"revision"=>revision}}}}.to_json
|
110
|
+
).and_return({deployment_id: deployment_id})
|
111
|
+
|
112
|
+
expect(client).to receive(:describe_deployments).with({deployment_ids: [deployment_id]}).and_return(
|
113
|
+
{deployments: [status: 'running']},
|
114
|
+
{deployments: [status: 'failed']}
|
115
|
+
)
|
116
|
+
|
117
|
+
expect do
|
118
|
+
expect do
|
119
|
+
cmd.run(['--wait', '--no-migrate', '--app-id', app_id])
|
120
|
+
end.to raise_error('Deployment failed.')
|
121
|
+
end.to output(strip_heredoc(<<-EOF
|
122
|
+
Deployment created: #{deployment_id}
|
123
|
+
Deploying .
|
124
|
+
Deployment failed.
|
125
|
+
EOF
|
126
|
+
)).to_stdout
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'aws-sdk'
|
3
|
+
|
4
|
+
RSpec.describe SnapDeploy::Provider::AWS::S3 do
|
5
|
+
subject(:cmd) { SnapDeploy::Provider::AWS::S3.new(nil, {}, {}) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
AWS.stub!
|
9
|
+
|
10
|
+
allow(ENV).to receive(:[]).with(anything).and_call_original
|
11
|
+
allow(ENV).to receive(:[]).with('AWS_ACCESS_KEY_ID').and_return(SecureRandom.hex)
|
12
|
+
allow(ENV).to receive(:[]).with('AWS_SECRET_ACCESS_KEY').and_return(SecureRandom.hex)
|
13
|
+
allow(ENV).to receive(:[]).with('SNAP_PIPELINE_COUNTER').and_return('123')
|
14
|
+
allow(ENV).to receive(:[]).with('SNAP_COMMIT_SHORT').and_return(short_revision)
|
15
|
+
allow(ENV).to receive(:[]).with('SNAP_COMMIT').and_return(revision)
|
16
|
+
allow(ENV).to receive(:[]).with('SNAP_STAGE_TRIGGERED_BY').and_return('john-doe')
|
17
|
+
end
|
18
|
+
|
19
|
+
example 'with local dir not specified' do
|
20
|
+
expect(Dir).to receive(:chdir).with(Dir.pwd)
|
21
|
+
cmd.run(['--bucket', 'example.com'])
|
22
|
+
end
|
23
|
+
|
24
|
+
example 'with local dir specified' do
|
25
|
+
expect(Dir).to receive(:chdir).with('_build')
|
26
|
+
cmd.run(['--bucket', 'example.com', '--local-dir', '_build'])
|
27
|
+
end
|
28
|
+
|
29
|
+
example "Sends MIME type" do
|
30
|
+
expect(Dir).to receive(:glob).and_yield(__FILE__)
|
31
|
+
expect_any_instance_of(AWS::S3::ObjectCollection).to receive(:create).with(anything(), anything(), hash_including(:content_type => 'application/x-ruby'))
|
32
|
+
cmd.run(['--bucket', 'example.com'])
|
33
|
+
end
|
34
|
+
|
35
|
+
example "Sets Cache and Expiration" do
|
36
|
+
expect(Dir).to receive(:glob).and_yield(__FILE__)
|
37
|
+
expect_any_instance_of(AWS::S3::ObjectCollection).to receive(:create).with(anything(), anything(), hash_including(:cache_control => 'max-age=99999999', :expires => '2012-12-21 00:00:00 -0000'))
|
38
|
+
cmd.run(['--bucket', 'example.com', '--cache-control', 'max-age=99999999', '--expires', '2012-12-21 00:00:00 -0000'])
|
39
|
+
end
|
40
|
+
|
41
|
+
example "Sets ACL" do
|
42
|
+
expect(Dir).to receive(:glob).and_yield(__FILE__)
|
43
|
+
expect_any_instance_of(AWS::S3::ObjectCollection).to receive(:create).with(anything(), anything(), hash_including(:acl => "public_read"))
|
44
|
+
cmd.run(['--bucket', 'example.com', '--acl', 'public_read'])
|
45
|
+
end
|
46
|
+
|
47
|
+
example "when detect_encoding is set" do
|
48
|
+
path = 'foo.js'
|
49
|
+
expect(Dir).to receive(:glob).and_yield(path)
|
50
|
+
expect(cmd).to receive(:'`').at_least(1).times.with("file #{path}").and_return('gzip compressed')
|
51
|
+
allow(File).to receive(:read).with(path).and_return("")
|
52
|
+
expect_any_instance_of(AWS::S3::ObjectCollection).to receive(:create).with(anything(), anything(), hash_including(:content_encoding => 'gzip'))
|
53
|
+
cmd.run(['--bucket', 'example.com', '--detect-encoding'])
|
54
|
+
end
|
55
|
+
|
56
|
+
example "when dot_match is set" do
|
57
|
+
expect(Dir).to receive(:glob).with("**/*", File::FNM_DOTMATCH)
|
58
|
+
cmd.run(['--bucket', 'example.com', '--detect-encoding', '--include-dot-files'])
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SnapDeploy::Provider::Heroku do
|
4
|
+
subject(:cmd) { SnapDeploy::Provider::Heroku.new(nil, {}, {}) }
|
5
|
+
|
6
|
+
let(:token) { SecureRandom.hex }
|
7
|
+
let(:branch) { SecureRandom.hex }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(cmd).to receive(:token).and_return(token)
|
11
|
+
|
12
|
+
ENV['SNAP_BRANCH'] = branch
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'execution behavior' do
|
16
|
+
it 'should invoke methods in order' do
|
17
|
+
expect(cmd).to receive(:check_auth).ordered
|
18
|
+
expect(cmd).to receive(:maybe_create_app).ordered
|
19
|
+
expect(cmd).to receive(:setup_configuration).ordered
|
20
|
+
expect(cmd).to receive(:git_push).ordered
|
21
|
+
expect(cmd).to receive(:maybe_db_migrate).ordered
|
22
|
+
|
23
|
+
cmd.run(['--app-name', 'foo'])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'check authentication' do
|
28
|
+
it 'should raise error on auth failure' do
|
29
|
+
stub_request(:get, 'https://api.heroku.com/account').
|
30
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
31
|
+
to_return(:status => 401, :body => {}.to_json, :headers => {})
|
32
|
+
|
33
|
+
expect do
|
34
|
+
cmd.parse(['--app-name', 'foo'])
|
35
|
+
cmd.send :check_auth
|
36
|
+
end.to raise_error(RuntimeError, 'Could not connect to heroku to check your credentials. The server returned status code 401.')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should raise error when could not connect' do
|
40
|
+
stub_request(:get, 'https://api.heroku.com/account').
|
41
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
42
|
+
to_raise(EOFError)
|
43
|
+
|
44
|
+
expect do
|
45
|
+
cmd.parse(['--app-name', 'foo'])
|
46
|
+
cmd.send :check_auth
|
47
|
+
end.to raise_error(EOFError)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'create app' do
|
52
|
+
it 'should create app if one does not exist' do
|
53
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo').
|
54
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
55
|
+
to_return(:status => 404)
|
56
|
+
|
57
|
+
stub_request(:post, 'https://api.heroku.com/apps').
|
58
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" })
|
59
|
+
|
60
|
+
cmd.parse(['--app-name', 'foo'])
|
61
|
+
cmd.send(:maybe_create_app)
|
62
|
+
end
|
63
|
+
|
64
|
+
[401, 403].each do |code|
|
65
|
+
it "should raise error if we cannot verify if app exists (#{code})" do
|
66
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo').
|
67
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
68
|
+
to_return(:status => code)
|
69
|
+
|
70
|
+
allow(cmd).to receive(:setup_configuration)
|
71
|
+
allow(cmd).to receive(:git_push)
|
72
|
+
|
73
|
+
expect do
|
74
|
+
cmd.parse(['--app-name', 'foo'])
|
75
|
+
cmd.send(:maybe_create_app)
|
76
|
+
end.to raise_error(RuntimeError, "You are not authorized to check if the app exists, perhaps you don't own that app?. The server returned status code #{code}.")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should create app if one does not exist' do
|
81
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo').
|
82
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
83
|
+
to_return(:status => 404)
|
84
|
+
|
85
|
+
stub_request(:post, 'https://api.heroku.com/apps').
|
86
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" })
|
87
|
+
|
88
|
+
allow(cmd).to receive(:setup_configuration)
|
89
|
+
allow(cmd).to receive(:git_push)
|
90
|
+
|
91
|
+
cmd.parse(['--app-name', 'foo', '--region', 'jhumri-taliya', '--stack-name', 'some-stack'])
|
92
|
+
cmd.send(:maybe_create_app)
|
93
|
+
expect(a_request(:post, 'https://api.heroku.com/apps').
|
94
|
+
with(:body => { name: 'foo', region: 'jhumri-taliya', stack: 'some-stack' }, :headers => { 'Authorization' => "Bearer #{token}" })).to have_been_made
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'setup_configuration' do
|
99
|
+
it 'should not send config vars if one is not specified' do
|
100
|
+
cmd.parse(['--app-name', 'foo'])
|
101
|
+
cmd.send(:setup_configuration)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should not set any config vars if there is no delta' do
|
105
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo/config-vars').
|
106
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
107
|
+
to_return(:body => { 'FOO' => 'bar', 'BOO' => 'baz' }.to_json, :headers => { 'Content-Type' => 'application/json' })
|
108
|
+
|
109
|
+
cmd.parse(['--app-name', 'foo', '--config-var', 'FOO=bar', '--config-var', 'BOO=baz'])
|
110
|
+
cmd.send(:setup_configuration)
|
111
|
+
|
112
|
+
expect(a_request(:any, "api.heroku.com")).not_to have_been_made
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should set any config vars if there is a delta' do
|
116
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo/config-vars').
|
117
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
118
|
+
to_return(:body => { 'FOO' => 'oldfoo', 'BOO' => 'oldboo' }.to_json, :headers => { 'Content-Type' => 'application/json' })
|
119
|
+
|
120
|
+
stub_request(:patch, 'https://api.heroku.com/apps/foo/config-vars')
|
121
|
+
|
122
|
+
cmd.parse(['--app-name', 'foo', '--config-var', 'FOO=newfoo', '--config-var', 'BOO=oldboo', '--config-var', 'NEW_VAR=new_value'])
|
123
|
+
cmd.send(:setup_configuration)
|
124
|
+
|
125
|
+
expect(a_request(:patch, "https://api.heroku.com/apps/foo/config-vars").
|
126
|
+
with(:body => {'FOO' => 'newfoo', 'NEW_VAR' => 'new_value'}, :headers => { 'Authorization' => "Bearer #{token}"})).to have_been_made
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should set buildpack url if one is specified' do
|
130
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo/config-vars').
|
131
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
132
|
+
to_return(:body => { 'FOO' => 'oldfoo', 'BOO' => 'oldboo' }.to_json, :headers => { 'Content-Type' => 'application/json' })
|
133
|
+
|
134
|
+
stub_request(:patch, 'https://api.heroku.com/apps/foo/config-vars')
|
135
|
+
|
136
|
+
cmd.parse(['--app-name', 'foo', '--buildpack-url', 'https://github.com/heroku/heroku-buildpack-ruby'])
|
137
|
+
cmd.send(:setup_configuration)
|
138
|
+
|
139
|
+
expect(a_request(:patch, "https://api.heroku.com/apps/foo/config-vars").
|
140
|
+
with(:body => {'BUILDPACK_URL' => 'https://github.com/heroku/heroku-buildpack-ruby'}, :headers => { 'Authorization' => "Bearer #{token}"})).to have_been_made
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should set buildpack url if one is specified along with any configs' do
|
144
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo/config-vars').
|
145
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
146
|
+
to_return(:body => { 'FOO' => 'oldfoo', 'BOO' => 'oldboo' }.to_json, :headers => { 'Content-Type' => 'application/json' })
|
147
|
+
|
148
|
+
stub_request(:patch, 'https://api.heroku.com/apps/foo/config-vars')
|
149
|
+
|
150
|
+
cmd.parse(['--app-name', 'foo', '--config-var', 'FOO=newfoo', '--config-var', 'BOO=oldboo', '--config-var', 'NEW_VAR=new_value', '--buildpack-url', 'https://github.com/heroku/heroku-buildpack-ruby'])
|
151
|
+
cmd.send(:setup_configuration)
|
152
|
+
|
153
|
+
expect(a_request(:patch, "https://api.heroku.com/apps/foo/config-vars").
|
154
|
+
with(:body => {'FOO' => 'newfoo', 'NEW_VAR' => 'new_value', 'BUILDPACK_URL' => 'https://github.com/heroku/heroku-buildpack-ruby'}, :headers => { 'Authorization' => "Bearer #{token}"})).to have_been_made
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should work with config vars which have a "=" in their values' do
|
158
|
+
stub_request(:get, 'https://api.heroku.com/apps/foo/config-vars').
|
159
|
+
with(:headers => { 'Authorization' => "Bearer #{token}" }).
|
160
|
+
to_return(:body => { 'FOO' => 'oldfoo' }.to_json, :headers => { 'Content-Type' => 'application/json' })
|
161
|
+
|
162
|
+
stub_request(:patch, 'https://api.heroku.com/apps/foo/config-vars')
|
163
|
+
|
164
|
+
cmd.parse(['--app-name', 'foo', '--config-var', 'FOO=new=foo==bar'])
|
165
|
+
cmd.send(:setup_configuration)
|
166
|
+
|
167
|
+
expect(a_request(:patch, "https://api.heroku.com/apps/foo/config-vars").
|
168
|
+
with(:body => {'FOO' => 'new=foo==bar'}, :headers => { 'Authorization' => "Bearer #{token}"})).to have_been_made
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe 'git push' do
|
173
|
+
it 'should push to heroku via https' do
|
174
|
+
cmd.parse(['--app-name', 'foo'])
|
175
|
+
system('true')
|
176
|
+
expect(cmd).to receive(:sh).with('git push https://git.heroku.com/foo.git HEAD:refs/heads/master -f').and_yield(true, $?)
|
177
|
+
cmd.send(:git_push)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should raise error when push fails' do
|
181
|
+
cmd.parse(['--app-name', 'foo'])
|
182
|
+
system('exit -1')
|
183
|
+
expect(cmd).to receive(:sh).with('git push https://git.heroku.com/foo.git HEAD:refs/heads/master -f').and_yield(false, $?)
|
184
|
+
expect do
|
185
|
+
cmd.send(:git_push)
|
186
|
+
end.to raise_error(RuntimeError, 'Could not push to heroku remote. The exit code was 255.')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|