fourchette 0.1.2 → 0.1.3
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/Gemfile +1 -1
- data/Guardfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +10 -0
- data/Rakefile +3 -3
- data/bin/fourchette +5 -5
- data/fourchette.gemspec +18 -18
- data/lib/fourchette.rb +10 -11
- data/lib/fourchette/fork.rb +44 -19
- data/lib/fourchette/github.rb +29 -22
- data/lib/fourchette/heroku.rb +32 -28
- data/lib/fourchette/logger.rb +1 -1
- data/lib/fourchette/pgbackups.rb +18 -9
- data/lib/fourchette/pull_request.rb +4 -4
- data/lib/fourchette/tarball.rb +6 -5
- data/lib/fourchette/version.rb +1 -1
- data/lib/fourchette/web.rb +1 -1
- data/lib/fourchette/web/hooks.rb +3 -3
- data/lib/fourchette/web/tarball.rb +6 -3
- data/spec/lib/fourchette/fork_spec.rb +27 -22
- data/spec/lib/fourchette/github_spec.rb +44 -44
- data/spec/lib/fourchette/heroku_spec.rb +82 -49
- data/spec/lib/fourchette/logger_spec.rb +1 -1
- data/spec/lib/fourchette/pull_request_spec.rb +37 -12
- data/spec/lib/fourchette/tarball_spec.rb +24 -18
- data/spec/lib/web/hooks_spec.rb +10 -10
- data/spec/lib/web/tarball_spec.rb +14 -15
- data/spec/spec_helper.rb +1 -1
- data/spec/support/silent-logger.rb +2 -2
- data/spec/support/sinatra_helper.rb +1 -1
- data/templates/Gemfile +1 -1
- data/templates/Rakefile +1 -1
- data/templates/callbacks.rb +4 -4
- data/templates/config/puma.rb +1 -1
- metadata +5 -5
data/lib/fourchette/logger.rb
CHANGED
data/lib/fourchette/pgbackups.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'heroku/client/pgbackups'
|
2
2
|
class Fourchette::Pgbackups
|
3
3
|
include Fourchette::Logger
|
4
4
|
|
@@ -6,34 +6,43 @@ class Fourchette::Pgbackups
|
|
6
6
|
@heroku = Fourchette::Heroku.new
|
7
7
|
end
|
8
8
|
|
9
|
-
def copy
|
9
|
+
def copy(from, to)
|
10
10
|
ensure_pgbackups_is_present(from)
|
11
11
|
ensure_pgbackups_is_present(to)
|
12
12
|
|
13
13
|
from_url, from_name = pg_details_for(from)
|
14
14
|
to_url, to_name = pg_details_for(to)
|
15
15
|
|
16
|
-
@client = Heroku::Client::Pgbackups.new pgbackup_url(from)+'/api'
|
16
|
+
@client = Heroku::Client::Pgbackups.new pgbackup_url(from) + '/api'
|
17
17
|
@client.create_transfer(from_url, from_name, to_url, to_name)
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
21
|
-
|
22
|
-
|
21
|
+
|
22
|
+
def ensure_pgbackups_is_present(heroku_app_name)
|
23
|
+
unless existing_backups?
|
23
24
|
logger.info "Adding pgbackups to #{heroku_app_name}"
|
24
25
|
@heroku.client.addon.create(heroku_app_name, { plan: 'pgbackups' })
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
+
def existing_backups?
|
30
|
+
@heroku.client.addon.list(heroku_app_name).select do |addon|
|
31
|
+
addon['name'] == 'pgbackups'
|
32
|
+
end.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
def pg_details_for(app_name)
|
29
36
|
@heroku.config_vars(app_name).each do |key, value|
|
30
|
-
|
37
|
+
if key.start_with?('HEROKU_POSTGRESQL_') && key.end_with?('_URL')
|
38
|
+
return [value, key]
|
39
|
+
end
|
31
40
|
end
|
32
41
|
end
|
33
42
|
|
34
|
-
def pgbackup_url
|
43
|
+
def pgbackup_url(app_name)
|
35
44
|
@heroku.config_vars(app_name).each do |k, v|
|
36
45
|
return v if k == 'PGBACKUPS_URL'
|
37
46
|
end
|
38
47
|
end
|
39
|
-
end
|
48
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Fourchette::PullRequest
|
2
2
|
include SuckerPunch::Job
|
3
3
|
|
4
|
-
def perform
|
4
|
+
def perform(params)
|
5
5
|
return if qa_skip?(params)
|
6
6
|
|
7
7
|
callbacks = Fourchette::Callbacks.new(params)
|
@@ -25,8 +25,8 @@ class Fourchette::PullRequest
|
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
-
def qa_skip?
|
29
|
-
params['pull_request']['title']
|
28
|
+
def qa_skip?(params)
|
29
|
+
pr_title = params['pull_request']['title']
|
30
|
+
pr_title.downcase.include?('[qa skip]')
|
30
31
|
end
|
31
|
-
|
32
32
|
end
|
data/lib/fourchette/tarball.rb
CHANGED
@@ -12,20 +12,21 @@ class Fourchette::Tarball
|
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
|
+
|
15
16
|
def prepare_tarball(github_git_url, branch_name)
|
16
17
|
clone_path = "tmp/#{SecureRandom.uuid}"
|
17
18
|
clone(github_git_url, branch_name, clone_path)
|
18
19
|
tar(clone_path)
|
19
20
|
end
|
20
21
|
|
21
|
-
def clone(github_git_url,branch_name, clone_path)
|
22
|
-
logger.info
|
22
|
+
def clone(github_git_url, branch_name, clone_path)
|
23
|
+
logger.info 'Cloning repository...'
|
23
24
|
repo = Git.clone(github_git_url, clone_path, recursive: true)
|
24
25
|
repo.checkout(branch_name)
|
25
26
|
end
|
26
27
|
|
27
28
|
def tar(path)
|
28
|
-
logger.info
|
29
|
+
logger.info 'Preparing tarball...'
|
29
30
|
filepath = "#{path}/#{expiration_timestamp}.tar.gz"
|
30
31
|
system("tar -zcf #{filepath} -C #{path} .")
|
31
32
|
filepath
|
@@ -36,8 +37,8 @@ class Fourchette::Tarball
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def tarball_to_url(filepath, github_repo)
|
39
|
-
logger.info
|
40
|
+
logger.info 'Tarball to URL as a service in progress...'
|
40
41
|
cleaned_path = filepath.gsub('tmp/', '').gsub('.tar.gz', '')
|
41
42
|
"#{ENV['FOURCHETTE_APP_URL']}/#{github_repo}/#{cleaned_path}"
|
42
43
|
end
|
43
|
-
end
|
44
|
+
end
|
data/lib/fourchette/version.rb
CHANGED
data/lib/fourchette/web.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require_relative 'web/hooks'
|
2
|
-
require_relative 'web/tarball'
|
2
|
+
require_relative 'web/tarball'
|
data/lib/fourchette/web/hooks.rb
CHANGED
@@ -4,7 +4,10 @@ get '/:github_user/:github_repo/:uuid/:expiration_timestamp' do
|
|
4
4
|
'Oops...'
|
5
5
|
else
|
6
6
|
logger.info('Serving a tarball!')
|
7
|
-
filepath = Fourchette::Tarball.new.filepath(
|
8
|
-
|
7
|
+
filepath = Fourchette::Tarball.new.filepath(
|
8
|
+
params['uuid'],
|
9
|
+
params['expiration_timestamp']
|
10
|
+
)
|
11
|
+
send_file filepath, type: 'application/x-tgz'
|
9
12
|
end
|
10
|
-
end
|
13
|
+
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Fourchette::Fork do
|
4
4
|
subject { described_class.new(params) }
|
5
5
|
|
6
|
-
let(:params)
|
6
|
+
let(:params) do
|
7
7
|
{
|
8
8
|
'pull_request' => {
|
9
9
|
'number' => 1,
|
@@ -12,20 +12,21 @@ describe Fourchette::Fork do
|
|
12
12
|
}
|
13
13
|
}
|
14
14
|
}
|
15
|
-
|
15
|
+
end
|
16
16
|
let(:fork_name) { 'my-fork-pr-1' }
|
17
17
|
|
18
18
|
before do
|
19
|
-
stub_const(
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
stub_const(
|
20
|
+
'ENV',
|
21
|
+
'FOURCHETTE_HEROKU_APP_PREFIX' => 'my-fork',
|
22
|
+
'FOURCHETTE_HEROKU_APP_TO_FORK' => 'my-heroku-app-name'
|
23
|
+
)
|
23
24
|
end
|
24
25
|
|
25
26
|
describe '#create' do
|
26
27
|
it 'calls #update and #create_unless_exists' do
|
27
|
-
subject.
|
28
|
-
subject.
|
28
|
+
expect(subject).to receive(:create_unless_exists)
|
29
|
+
expect(subject).to receive(:update)
|
29
30
|
subject.create
|
30
31
|
end
|
31
32
|
end
|
@@ -37,43 +38,47 @@ describe Fourchette::Fork do
|
|
37
38
|
|
38
39
|
context 'app does NOT exists' do
|
39
40
|
before do
|
40
|
-
Fourchette::Heroku.
|
41
|
+
allow_any_instance_of(Fourchette::Heroku).to receive(:app_exists?).and_return(false)
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'calls the fork creation' do
|
44
|
-
subject.
|
45
|
-
Fourchette::Heroku.
|
45
|
+
allow(subject).to receive(:post_fork_url)
|
46
|
+
expect_any_instance_of(Fourchette::Heroku).to receive(:fork)
|
47
|
+
.with('my-heroku-app-name', fork_name)
|
46
48
|
end
|
47
49
|
|
48
50
|
it 'post the URL to the fork on the GitHub PR' do
|
49
|
-
Fourchette::Heroku.
|
50
|
-
Fourchette::Heroku.
|
51
|
-
|
51
|
+
allow_any_instance_of(Fourchette::Heroku).to receive(:fork)
|
52
|
+
allow_any_instance_of(Fourchette::Heroku).to receive_message_chain(:client, :app, :info)
|
53
|
+
.and_return('web_url' => 'rainforestqa.com')
|
54
|
+
expect_any_instance_of(Fourchette::GitHub).to receive(:comment_pr)
|
55
|
+
.with(1, 'Test URL: rainforestqa.com')
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
59
|
context 'app DOES exists' do
|
56
60
|
before do
|
57
|
-
Fourchette::Heroku.
|
61
|
+
allow_any_instance_of(Fourchette::Heroku).to receive(:app_exists?).and_return(true)
|
58
62
|
end
|
59
63
|
|
60
64
|
it 'does nothing' do
|
61
|
-
Fourchette::GitHub.
|
62
|
-
Fourchette::Heroku.
|
65
|
+
expect_any_instance_of(Fourchette::GitHub).not_to receive(:comment_pr)
|
66
|
+
expect_any_instance_of(Fourchette::Heroku).not_to receive(:fork)
|
63
67
|
end
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
67
71
|
describe '#delete' do
|
68
72
|
it 'calls deletes the fork' do
|
69
|
-
Fourchette::GitHub.
|
70
|
-
Fourchette::Heroku.
|
73
|
+
allow_any_instance_of(Fourchette::GitHub).to receive(:comment_pr)
|
74
|
+
expect_any_instance_of(Fourchette::Heroku).to receive(:delete).with(fork_name)
|
71
75
|
subject.delete
|
72
76
|
end
|
73
77
|
|
74
78
|
it 'comments on the GitHub PR' do
|
75
|
-
Fourchette::Heroku.
|
76
|
-
Fourchette::GitHub.
|
79
|
+
allow_any_instance_of(Fourchette::Heroku).to receive(:delete)
|
80
|
+
expect_any_instance_of(Fourchette::GitHub).to receive(:comment_pr)
|
81
|
+
.with(1, 'Test app deleted!')
|
77
82
|
subject.delete
|
78
83
|
end
|
79
84
|
end
|
@@ -89,4 +94,4 @@ describe Fourchette::Fork do
|
|
89
94
|
describe '#pr_number' do
|
90
95
|
it { expect(subject.pr_number).to eq 1 }
|
91
96
|
end
|
92
|
-
end
|
97
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Fourchette::GitHub do
|
4
4
|
subject { described_class.new }
|
@@ -6,122 +6,122 @@ describe Fourchette::GitHub do
|
|
6
6
|
let(:fake_hooks) { [] }
|
7
7
|
|
8
8
|
let(:fake_hook) do
|
9
|
-
hook = double(
|
10
|
-
hook.
|
11
|
-
hook.
|
9
|
+
hook = double('hook')
|
10
|
+
allow(hook).to receive(:config).and_return(nil)
|
11
|
+
allow(hook).to receive(:id).and_return(123)
|
12
12
|
hook
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:fake_fourchette_hook) do
|
16
|
-
fake_hook.config.
|
16
|
+
allow(fake_hook.config).to receive(:fourchette_env).and_return('something')
|
17
17
|
fake_hook
|
18
18
|
end
|
19
19
|
|
20
20
|
let(:fake_enabled_fourchette_hook) do
|
21
|
-
fake_fourchette_hook.
|
21
|
+
allow(fake_fourchette_hook).to receive(:active).and_return(true)
|
22
22
|
fake_fourchette_hook
|
23
23
|
end
|
24
24
|
|
25
25
|
let(:fake_disabled_fourchette_hook) do
|
26
|
-
fake_fourchette_hook.
|
26
|
+
allow(fake_fourchette_hook).to receive(:active).and_return(false)
|
27
27
|
fake_fourchette_hook
|
28
28
|
end
|
29
29
|
|
30
30
|
before do
|
31
31
|
allow_message_expectations_on_nil
|
32
|
-
subject.
|
33
|
-
Octokit::Client.
|
32
|
+
allow(subject).to receive(:hooks).and_return(fake_hooks)
|
33
|
+
allow_any_instance_of(Octokit::Client).to receive(:edit_hook)
|
34
34
|
end
|
35
35
|
|
36
|
-
describe
|
37
|
-
context
|
36
|
+
describe '#enable_hook' do
|
37
|
+
context 'when there is alerady a Fourchette hook' do
|
38
38
|
|
39
|
-
context
|
39
|
+
context 'when the hook was enabled' do
|
40
40
|
let(:fake_hooks) { [fake_enabled_fourchette_hook] }
|
41
41
|
|
42
|
-
it
|
43
|
-
Octokit::Client.
|
42
|
+
it 'does NOT enable the hook' do
|
43
|
+
expect_any_instance_of(Octokit::Client).not_to receive(:edit_hook)
|
44
44
|
|
45
45
|
subject.enable_hook
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
context
|
49
|
+
context 'when the hook was disabled' do
|
50
50
|
let(:fake_hooks) { [fake_disabled_fourchette_hook] }
|
51
51
|
|
52
|
-
it
|
53
|
-
Octokit::Client.
|
52
|
+
it 'enables the hook' do
|
53
|
+
expect_any_instance_of(Octokit::Client).to receive(:edit_hook)
|
54
54
|
|
55
55
|
subject.enable_hook
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
context
|
61
|
-
it
|
62
|
-
Octokit::Client.
|
60
|
+
context 'when there is no Fourchette hook yet' do
|
61
|
+
it 'adds a hook' do
|
62
|
+
expect_any_instance_of(Octokit::Client).to receive(:create_hook)
|
63
63
|
|
64
64
|
subject.enable_hook
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
describe
|
70
|
-
context
|
69
|
+
describe '#disable_hook' do
|
70
|
+
context 'where there is an active Fourchette hook' do
|
71
71
|
let(:fake_hooks) { [fake_enabled_fourchette_hook] }
|
72
72
|
|
73
|
-
it
|
74
|
-
Octokit::Client.
|
73
|
+
it 'disables the hook' do
|
74
|
+
expect_any_instance_of(Octokit::Client).to receive(:edit_hook)
|
75
75
|
|
76
76
|
subject.disable_hook
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
context
|
80
|
+
context 'when there is a disabled Fourchette hook' do
|
81
81
|
let(:fake_hooks) { [fake_disabled_fourchette_hook] }
|
82
|
-
it
|
83
|
-
subject.
|
82
|
+
it 'does not try to disable a hook' do
|
83
|
+
expect(subject).not_to receive(:disable)
|
84
84
|
subject.disable_hook
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
context
|
89
|
-
it
|
90
|
-
subject.
|
88
|
+
context 'when there is no Fourchette hook' do
|
89
|
+
it 'does not try to disable a hook' do
|
90
|
+
expect(subject).not_to receive(:disable)
|
91
91
|
subject.disable_hook
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
describe
|
96
|
+
describe '#update_hook' do
|
97
97
|
let(:fake_hooks) { [fake_enabled_fourchette_hook] }
|
98
98
|
|
99
|
-
it
|
100
|
-
subject
|
101
|
-
.
|
99
|
+
it 'calls toggle_active_state_to' do
|
100
|
+
expect(subject)
|
101
|
+
.to receive(:toggle_active_state_to)
|
102
102
|
subject.update_hook
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
-
describe
|
107
|
-
it
|
108
|
-
subject.
|
109
|
-
Octokit::Client.
|
106
|
+
describe '#delete_hook' do
|
107
|
+
it 'deletes the hook on GitHub' do
|
108
|
+
allow(subject).to receive(:fourchette_hook).and_return(fake_hook)
|
109
|
+
expect_any_instance_of(Octokit::Client).to receive(:remove_hook)
|
110
110
|
|
111
111
|
subject.delete_hook
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
-
describe
|
115
|
+
describe '#comment_pr' do
|
116
116
|
before do
|
117
|
-
stub_const(
|
117
|
+
stub_const('ENV', 'FOURCHETTE_GITHUB_PROJECT' => 'my-project')
|
118
118
|
end
|
119
119
|
|
120
|
-
it
|
121
|
-
Octokit::Client
|
122
|
-
.
|
120
|
+
it 'adds a comment' do
|
121
|
+
expect_any_instance_of(Octokit::Client)
|
122
|
+
.to receive(:add_comment).with('my-project', 1, 'yo!')
|
123
123
|
|
124
|
-
subject.comment_pr(1,
|
124
|
+
subject.comment_pr(1, 'yo!')
|
125
125
|
end
|
126
126
|
end
|
127
127
|
end
|
@@ -14,14 +14,16 @@ describe Fourchette::Heroku do
|
|
14
14
|
before do
|
15
15
|
client = double('client')
|
16
16
|
client_app = double('client')
|
17
|
-
client_app.
|
18
|
-
client.
|
17
|
+
allow(client_app).to receive(:list).and_return(app_list)
|
18
|
+
allow(client).to receive(:app).and_return(client_app)
|
19
19
|
config_var = double('config_var')
|
20
|
-
client.
|
20
|
+
allow(client).to receive(:config_var).and_return(config_var)
|
21
21
|
|
22
|
-
client.app.
|
22
|
+
allow(client.app).to receive(:info).and_return(
|
23
|
+
'git_url' => 'git@heroku.com/something.git'
|
24
|
+
)
|
23
25
|
|
24
|
-
heroku.
|
26
|
+
allow(heroku).to receive(:client).and_return(client)
|
25
27
|
end
|
26
28
|
|
27
29
|
describe '#app_exists?' do
|
@@ -32,42 +34,46 @@ describe Fourchette::Heroku do
|
|
32
34
|
|
33
35
|
describe '#fork' do
|
34
36
|
before do
|
35
|
-
heroku.
|
36
|
-
heroku.
|
37
|
-
heroku.
|
38
|
-
heroku.
|
39
|
-
heroku.
|
37
|
+
allow(heroku).to receive(:create_app)
|
38
|
+
allow(heroku).to receive(:copy_config)
|
39
|
+
allow(heroku).to receive(:copy_add_ons)
|
40
|
+
allow(heroku).to receive(:copy_pg)
|
41
|
+
allow(heroku).to receive(:copy_rack_and_rails_env_again)
|
40
42
|
end
|
41
43
|
|
42
|
-
|
44
|
+
%w(
|
45
|
+
create_app copy_config copy_add_ons copy_pg copy_rack_and_rails_env_again
|
46
|
+
).each do |method_name|
|
43
47
|
it "calls `#{method_name}'" do
|
44
|
-
heroku.
|
48
|
+
expect(heroku).to receive(method_name)
|
45
49
|
heroku.fork(from_app_name, to_app_name)
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
50
54
|
describe '#git_url' do
|
51
|
-
it
|
55
|
+
it 'returns the correct git URL' do
|
56
|
+
expect(heroku.git_url(to_app_name)).to eq 'git@heroku.com/something.git'
|
57
|
+
end
|
52
58
|
end
|
53
59
|
|
54
60
|
describe '#delete' do
|
55
61
|
it 'calls delete on the Heroku client' do
|
56
|
-
heroku.client.app.
|
62
|
+
expect(heroku.client.app).to receive(:delete).with(to_app_name)
|
57
63
|
heroku.delete(to_app_name)
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
67
|
describe '#config_vars' do
|
62
68
|
it 'calls config_var.info on the Heroku client' do
|
63
|
-
heroku.client.config_var.
|
69
|
+
expect(heroku.client.config_var).to receive(:info).with(from_app_name)
|
64
70
|
heroku.config_vars(from_app_name)
|
65
71
|
end
|
66
72
|
end
|
67
73
|
|
68
74
|
describe '#create_app' do
|
69
75
|
it 'calls app.create on the Heroku client' do
|
70
|
-
heroku.client.app.
|
76
|
+
expect(heroku.client.app).to receive(:create).with(name: to_app_name)
|
71
77
|
heroku.create_app(to_app_name)
|
72
78
|
end
|
73
79
|
end
|
@@ -80,37 +86,41 @@ describe Fourchette::Heroku do
|
|
80
86
|
'DATABASE_URL' => 'FAIL@POSTGRES/DB'
|
81
87
|
}
|
82
88
|
end
|
83
|
-
let(:cleaned_vars) { { 'WHATEVER' => 'ok'} }
|
89
|
+
let(:cleaned_vars) { { 'WHATEVER' => 'ok' } }
|
84
90
|
|
85
91
|
it 'calls #config_vars' do
|
86
|
-
heroku.client.config_var.
|
87
|
-
heroku.
|
92
|
+
allow(heroku.client.config_var).to receive(:update)
|
93
|
+
expect(heroku).to receive(:config_vars).with(from_app_name).and_return(vars)
|
88
94
|
heroku.copy_config(from_app_name, to_app_name)
|
89
95
|
end
|
90
96
|
|
91
97
|
it 'updates config vars without postgres URLs' do
|
92
|
-
heroku.client.config_var.
|
93
|
-
|
98
|
+
expect(heroku.client.config_var).to receive(:update)
|
99
|
+
.with(to_app_name, cleaned_vars)
|
100
|
+
allow(heroku).to receive(:config_vars).and_return(vars)
|
94
101
|
heroku.copy_config('from', to_app_name)
|
95
102
|
end
|
96
103
|
end
|
97
104
|
|
98
105
|
describe '#copy_add_ons' do
|
99
|
-
let(:addon_list) { [
|
106
|
+
let(:addon_list) { [{ 'plan' => { 'name' => 'redistogo' } }] }
|
100
107
|
|
101
108
|
before do
|
102
|
-
heroku.client.
|
103
|
-
heroku.client.addon.
|
104
|
-
heroku.client.addon.
|
109
|
+
allow(heroku.client).to receive(:addon).and_return(double('addon'))
|
110
|
+
allow(heroku.client.addon).to receive(:create)
|
111
|
+
allow(heroku.client.addon).to receive(:list).and_return(addon_list)
|
105
112
|
end
|
106
113
|
|
107
114
|
it 'gets the addon list' do
|
108
|
-
heroku.client.addon.
|
115
|
+
expect(heroku.client.addon).to receive(:list).with(from_app_name)
|
116
|
+
.and_return(addon_list)
|
109
117
|
heroku.copy_add_ons(from_app_name, to_app_name)
|
110
118
|
end
|
111
119
|
|
112
120
|
it 'creates addons' do
|
113
|
-
heroku.client.addon.
|
121
|
+
expect(heroku.client.addon).to receive(:create).with(
|
122
|
+
to_app_name, plan: 'redistogo'
|
123
|
+
)
|
114
124
|
heroku.copy_add_ons(from_app_name, to_app_name)
|
115
125
|
end
|
116
126
|
end
|
@@ -118,16 +128,32 @@ describe Fourchette::Heroku do
|
|
118
128
|
describe '#copy_pg' do
|
119
129
|
|
120
130
|
before do
|
121
|
-
heroku.client.
|
122
|
-
heroku.client.addon.
|
131
|
+
allow(heroku.client).to receive(:addon).and_return(double('addon'))
|
132
|
+
allow(heroku.client.addon).to receive(:list).and_return(addon_list)
|
123
133
|
end
|
124
134
|
|
125
135
|
context 'when a heroku-postgresql addon is enabled' do
|
126
|
-
let(:addon_list) { [{ 'addon_service' => { 'name' =>
|
136
|
+
let(:addon_list) { [{ 'addon_service' => { 'name' => addon_name } }] }
|
137
|
+
|
138
|
+
shared_examples 'app with pg' do
|
139
|
+
it 'calls Fourchette::Pgbackups#copy' do
|
140
|
+
expect_any_instance_of(Fourchette::Pgbackups).to receive(:copy).with(
|
141
|
+
from_app_name, to_app_name
|
142
|
+
)
|
143
|
+
heroku.copy_pg(from_app_name, to_app_name)
|
144
|
+
end
|
145
|
+
end
|
127
146
|
|
128
|
-
|
129
|
-
|
130
|
-
|
147
|
+
context "when the addon name is 'Heroku Postgres'" do
|
148
|
+
let(:addon_name) { 'Heroku Postgres' }
|
149
|
+
|
150
|
+
it_behaves_like 'app with pg'
|
151
|
+
end
|
152
|
+
|
153
|
+
context "when the addon name is 'heroku-postgresql'" do
|
154
|
+
let(:addon_name) { 'heroku-postgresql' }
|
155
|
+
|
156
|
+
it_behaves_like 'app with pg'
|
131
157
|
end
|
132
158
|
end
|
133
159
|
|
@@ -135,51 +161,58 @@ describe Fourchette::Heroku do
|
|
135
161
|
let(:addon_list) { [{ 'addon_service' => { 'name' => 'redistogo' } }] }
|
136
162
|
|
137
163
|
it 'does not call Fourchette::Pgbackups#copy' do
|
138
|
-
# Had to work around lack of support for any_instance and
|
139
|
-
#
|
164
|
+
# Had to work around lack of support for any_instance and
|
165
|
+
# should_not_receive
|
166
|
+
# See https://github.com/rspec/rspec-mocks/issues/164 for more details
|
140
167
|
count = 0
|
141
|
-
Fourchette::Pgbackups.
|
142
|
-
|
143
|
-
|
168
|
+
allow_any_instance_of(Fourchette::Pgbackups).to receive(:copy) do |_from_app_name, _to_app_name|
|
169
|
+
count += 1
|
170
|
+
end
|
144
171
|
heroku.copy_pg(from_app_name, to_app_name)
|
145
|
-
count.
|
172
|
+
expect(count).to eq(0)
|
146
173
|
end
|
147
174
|
end
|
148
175
|
end
|
149
176
|
|
150
|
-
describe '#
|
177
|
+
describe '#copy_rack_and_rails_env_again' do
|
151
178
|
context 'with RACK_ENV or RAILS_ENV setup' do
|
152
179
|
before do
|
153
|
-
heroku.
|
180
|
+
allow(heroku).to receive(:get_original_env).and_return('RACK_ENV' => 'qa')
|
154
181
|
end
|
155
182
|
|
156
183
|
it 'updates the config vars' do
|
157
|
-
heroku.client.config_var.
|
158
|
-
|
184
|
+
expect(heroku.client.config_var).to receive(:update).with(
|
185
|
+
to_app_name, 'RACK_ENV' => 'qa'
|
186
|
+
)
|
187
|
+
heroku.copy_rack_and_rails_env_again(from_app_name, to_app_name)
|
159
188
|
end
|
160
189
|
end
|
161
190
|
|
162
191
|
context 'with NO env setup' do
|
163
192
|
before do
|
164
|
-
heroku.
|
193
|
+
allow(heroku).to receive(:get_original_env).and_return({})
|
165
194
|
end
|
166
195
|
|
167
196
|
it 'does not update config vars' do
|
168
|
-
heroku.client.config_var.
|
169
|
-
heroku.
|
197
|
+
expect(heroku.client.config_var).not_to receive(:update)
|
198
|
+
heroku.copy_rack_and_rails_env_again(from_app_name, to_app_name)
|
170
199
|
end
|
171
200
|
end
|
172
201
|
end
|
173
202
|
|
174
203
|
describe '#get_original_env' do
|
175
204
|
before do
|
176
|
-
stub_cong_var = {
|
177
|
-
|
205
|
+
stub_cong_var = {
|
206
|
+
'RACK_ENV' => 'qa',
|
207
|
+
'RAILS_ENV' => 'staging',
|
208
|
+
'DATABASE_URL' => 'postgres://....'
|
209
|
+
}
|
210
|
+
allow(heroku).to receive_message_chain(:client, :config_var, :info).and_return(stub_cong_var)
|
178
211
|
end
|
179
212
|
|
180
213
|
it 'returns the set env vars' do
|
181
214
|
return_value = heroku.get_original_env(from_app_name)
|
182
|
-
expect(return_value).to eq(
|
215
|
+
expect(return_value).to eq('RACK_ENV' => 'qa', 'RAILS_ENV' => 'staging')
|
183
216
|
end
|
184
217
|
end
|
185
218
|
end
|