dpl 2.0.0.alpha.2 → 2.0.0.alpha.5
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/CHANGELOG.md +34 -1
- data/Gemfile.lock +13 -8
- data/NOTES.md +1 -74
- data/README.md +464 -193
- data/lib/dpl/assets/convox/install +11 -0
- data/lib/dpl/assets/dpl/README.erb.md +4 -0
- data/lib/dpl/cli.rb +54 -18
- data/lib/dpl/ctx/test.rb +7 -3
- data/lib/dpl/helper/env.rb +67 -18
- data/lib/dpl/helper/wrap.rb +9 -0
- data/lib/dpl/provider.rb +11 -9
- data/lib/dpl/provider/dsl.rb +3 -1
- data/lib/dpl/provider/status.rb +6 -6
- data/lib/dpl/providers.rb +3 -1
- data/lib/dpl/providers/anynines.rb +5 -3
- data/lib/dpl/providers/azure_web_apps.rb +1 -1
- data/lib/dpl/providers/bintray.rb +2 -0
- data/lib/dpl/providers/bluemixcloudfoundry.rb +5 -3
- data/lib/dpl/providers/boxfuse.rb +1 -1
- data/lib/dpl/providers/cargo.rb +10 -1
- data/lib/dpl/providers/chef_supermarket.rb +3 -1
- data/lib/dpl/providers/cloud66.rb +2 -0
- data/lib/dpl/providers/cloudfiles.rb +2 -0
- data/lib/dpl/providers/cloudformation.rb +278 -0
- data/lib/dpl/providers/cloudfoundry.rb +6 -4
- data/lib/dpl/providers/codedeploy.rb +5 -5
- data/lib/dpl/providers/convox.rb +121 -0
- data/lib/dpl/providers/datica.rb +1 -1
- data/lib/dpl/providers/engineyard.rb +2 -0
- data/lib/dpl/providers/gae.rb +6 -7
- data/lib/dpl/providers/gcs.rb +5 -3
- data/lib/dpl/providers/gleis.rb +70 -0
- data/lib/dpl/providers/hackage.rb +2 -0
- data/lib/dpl/providers/hephy.rb +3 -1
- data/lib/dpl/providers/heroku.rb +4 -8
- data/lib/dpl/providers/heroku/api.rb +4 -2
- data/lib/dpl/providers/heroku/git.rb +3 -1
- data/lib/dpl/providers/lambda.rb +4 -4
- data/lib/dpl/providers/launchpad.rb +3 -1
- data/lib/dpl/providers/netlify.rb +2 -0
- data/lib/dpl/providers/npm.rb +2 -0
- data/lib/dpl/providers/openshift.rb +2 -0
- data/lib/dpl/providers/opsworks.rb +1 -1
- data/lib/dpl/providers/packagecloud.rb +2 -0
- data/lib/dpl/providers/pages.rb +4 -7
- data/lib/dpl/providers/pages/api.rb +16 -12
- data/lib/dpl/providers/pages/git.rb +16 -12
- data/lib/dpl/providers/puppetforge.rb +2 -0
- data/lib/dpl/providers/pypi.rb +2 -0
- data/lib/dpl/providers/releases.rb +8 -6
- data/lib/dpl/providers/rubygems.rb +3 -1
- data/lib/dpl/providers/s3.rb +7 -7
- data/lib/dpl/providers/scalingo.rb +2 -0
- data/lib/dpl/providers/testfairy.rb +2 -0
- data/lib/dpl/providers/transifex.rb +2 -0
- data/lib/dpl/version.rb +1 -1
- metadata +7 -3
- data/lib/dpl/providers/atlas.rb +0 -49
@@ -22,10 +22,12 @@ module Dpl
|
|
22
22
|
gem 'net-telnet', '~> 0.1.0' if ruby_pre?('2.3')
|
23
23
|
gem 'rack'
|
24
24
|
|
25
|
+
env :chef
|
26
|
+
|
25
27
|
opt '--user_id ID', 'Chef Supermarket user name', required: true
|
26
|
-
opt '--client_key KEY', 'Client API key file name', required: true
|
27
28
|
opt '--name NAME', 'Cookbook name', note: 'defaults to the name given in metadata.json or metadata.rb', alias: :cookbook_name, deprecated: :cookbook_name
|
28
29
|
opt '--category CAT', 'Cookbook category in Supermarket', required: true, see: 'https://docs.getchef.com/knife_cookbook_site.html#id12', alias: :cookbook_category, deprecated: :cookbook_category
|
30
|
+
opt '--client_key KEY', 'Client API key file name', default: 'client.pem'
|
29
31
|
opt '--dir DIR', 'Directory containing the cookbook', default: '.'
|
30
32
|
|
31
33
|
URL = "https://supermarket.chef.io/api/v1/cookbooks"
|
@@ -13,6 +13,8 @@ module Dpl
|
|
13
13
|
gem 'fog-core', '= 2.1.0', require: 'fog/core'
|
14
14
|
gem 'fog-rackspace', '~> 0.1.6', require: 'fog/rackspace'
|
15
15
|
|
16
|
+
env :cloudfiles
|
17
|
+
|
16
18
|
opt '--username USER', 'Rackspace username', required: true
|
17
19
|
opt '--api_key KEY', 'Rackspace API key', required: true, secret: true
|
18
20
|
opt '--region REGION', 'Cloudfiles region', required: true, enum: %w(ord dfw syd iad hkg)
|
@@ -0,0 +1,278 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Cloudformation < Provider
|
4
|
+
status :dev
|
5
|
+
|
6
|
+
full_name 'AWS CloudFormation'
|
7
|
+
|
8
|
+
description sq(<<-str)
|
9
|
+
tbd
|
10
|
+
str
|
11
|
+
|
12
|
+
gem 'aws-sdk-cloudformation', '~> 1.0'
|
13
|
+
|
14
|
+
env :aws, :cloudformation
|
15
|
+
config '~/.aws/credentials', prefix: 'aws'
|
16
|
+
|
17
|
+
opt '--access_key_id ID', 'AWS Access Key ID', required: true, secret: true
|
18
|
+
opt '--secret_access_key KEY', 'AWS Secret Key', required: true, secret: true
|
19
|
+
opt '--region REGION', 'AWS Region to deploy to', default: 'us-east-1'
|
20
|
+
opt '--template STR', 'CloudFormation template file', required: true, note: 'can be either a local path or an S3 URL'
|
21
|
+
opt '--stack_name NAME', 'CloudFormation Stack Name.', required: true
|
22
|
+
opt '--stack_name_prefix STR', 'CloudFormation Stack Name Prefix.'
|
23
|
+
opt '--promote', 'Deploy changes', default: true, note: 'otherwise a change set is created'
|
24
|
+
opt '--role_arn ARN', 'AWS Role ARN'
|
25
|
+
opt '--sts_assume_role ARN', 'AWS Role ARN for cross account deployments (assumed by travis using given AWS credentials).'
|
26
|
+
opt '--capabilities STR', 'CloudFormation allowed capabilities', type: :array, enum: %w(CAPABILITY_IAM CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND), sep: ',', see: 'https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html'
|
27
|
+
opt '--wait', 'Wait for CloutFormation to finish the stack creation and update', default: true
|
28
|
+
opt '--wait_timeout SEC', 'How many seconds to wait for stack creation and update.', type: :integer, default: 3600
|
29
|
+
opt '--create_timeout SEC', 'How many seconds to wait before the stack status becomes CREATE_FAILED', type: :integer, default: 3600, note: 'valid only when creating a stack'
|
30
|
+
# if passing a session_token is not recommended in CI/CD why do we add it to dpl?
|
31
|
+
opt '--session_token STR', 'AWS Session Access Token if using STS assume role', note: 'Not recommended on CI/CD'
|
32
|
+
opt '--parameters STR', 'key=value pairs or ENV var names', type: :array, sep: ',', eg: 'one=1 or ENV_VAR_TWO'
|
33
|
+
opt '--output_file PATH', 'Path to output file to store CloudFormation outputs to'
|
34
|
+
|
35
|
+
msgs login: 'Using Access Key: %{access_key_id}',
|
36
|
+
create_stack: 'Creating stack ...',
|
37
|
+
promote_stack: 'Promoting stack ...',
|
38
|
+
create_change_set: 'Creating change set ...',
|
39
|
+
stack_up_to_date: 'Stack already up to date.',
|
40
|
+
delete_change_set: 'No changes in stack. Removing changeset.',
|
41
|
+
done: 'Done.',
|
42
|
+
missing_template: 'File does not exist: %{template}',
|
43
|
+
invalid_creds: 'Invalid credentials'
|
44
|
+
|
45
|
+
strs change_set_name: 'travis-ci-build-%{build_number}-%{now}',
|
46
|
+
change_set_desc: 'Changeset created by Travis CI job for build #%{build_number} (%{git_sha})'
|
47
|
+
|
48
|
+
def login
|
49
|
+
info :login
|
50
|
+
end
|
51
|
+
|
52
|
+
def deploy
|
53
|
+
stack_exists? ? update : create
|
54
|
+
store_events if output_file?
|
55
|
+
rescue Aws::CloudFormation::Errors::InvalidAccessKeyId
|
56
|
+
error :invalid_creds
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def update
|
62
|
+
promote? ? promote : create_change_set(:update)
|
63
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
64
|
+
raise e unless e.message.start_with?('No updates are to be performed')
|
65
|
+
info :stack_up_to_date
|
66
|
+
end
|
67
|
+
|
68
|
+
def promote
|
69
|
+
info :promote_stack
|
70
|
+
client.update_stack(common_params)
|
71
|
+
stream_events(stack_name, :stack_update_complete) if wait?
|
72
|
+
info :done
|
73
|
+
end
|
74
|
+
|
75
|
+
def create
|
76
|
+
promote? ? create_stack : create_change_set(:create)
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_stack
|
80
|
+
info :create_stack
|
81
|
+
params = { timeout_in_minutes: create_timeout, on_failure: 'ROLLBACK' }
|
82
|
+
client.create_stack(common_params.merge(params))
|
83
|
+
stream_events(stack_name, :stack_create_complete) if wait?
|
84
|
+
info :done
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_change_set(type)
|
88
|
+
info :create_change_set
|
89
|
+
set = client.create_change_set(common_params.merge(change_set_params(type)))
|
90
|
+
wait_for(:change_set_create_complete, change_set_name: set.id) if wait? && !test?
|
91
|
+
info :done
|
92
|
+
rescue Aws::Waiters::Errors::FailureStateError => e
|
93
|
+
raise e unless change_set_contains_changes?(set)
|
94
|
+
info :delete_change_set
|
95
|
+
client.delete_change_set(change_set_name: set.id)
|
96
|
+
end
|
97
|
+
|
98
|
+
def change_set_params(type)
|
99
|
+
{
|
100
|
+
change_set_type: type.to_s.upcase,
|
101
|
+
change_set_name: interpolate(str(:change_set_name)),
|
102
|
+
description: interpolate(str(:change_set_desc))
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def change_set_contains_changes?(change_set)
|
107
|
+
data = client.describe_change_set(change_set_name: change_set.id)
|
108
|
+
data.status_reason.start_with?(%(The submitted information didn't contain changes))
|
109
|
+
end
|
110
|
+
|
111
|
+
def stack_exists?
|
112
|
+
stack = last_stack
|
113
|
+
stack && stack.stack_status != 'REVIEW_IN_PROGRESS'
|
114
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
115
|
+
raise e unless e.message.include?('does not exist')
|
116
|
+
false
|
117
|
+
end
|
118
|
+
|
119
|
+
def stream_events(stack_name, condition)
|
120
|
+
stream = EventStream.new(client, stack_name, method(:info))
|
121
|
+
wait_for(condition, stack_name: stack_name) unless test? # hmm.
|
122
|
+
ensure
|
123
|
+
stream.stop unless stream.nil?
|
124
|
+
end
|
125
|
+
|
126
|
+
def wait_for(cond, params)
|
127
|
+
started_at = Time.now
|
128
|
+
timeout = lambda { |*| throw :failure if Time.now - started_at > wait_timeout }
|
129
|
+
# params = params.merge(max_attempts: nil, delay: 5, before_wait: timeout)
|
130
|
+
client.wait_until(cond, params) { |w| w.before_wait(&timeout) }
|
131
|
+
end
|
132
|
+
|
133
|
+
def store_events
|
134
|
+
logs = last_stack.outputs || {}
|
135
|
+
logs = logs.map { |log| "#{log[:output_key]}=#{log[:output_value]}" }
|
136
|
+
File.write(output_file, logs.join("\n"))
|
137
|
+
end
|
138
|
+
|
139
|
+
def last_stack
|
140
|
+
client.describe_stacks(stack_name: stack_name)[:stacks].first
|
141
|
+
end
|
142
|
+
|
143
|
+
def common_params
|
144
|
+
params = {
|
145
|
+
stack_name: stack_name,
|
146
|
+
role_arn: role_arn,
|
147
|
+
capabilities: capabilities,
|
148
|
+
parameters: parameters
|
149
|
+
}
|
150
|
+
params.merge!(template_param)
|
151
|
+
@common_params ||= compact(params)
|
152
|
+
end
|
153
|
+
|
154
|
+
def parameters
|
155
|
+
@parameters ||= Array(super).map do |str|
|
156
|
+
key, value = str.split('=', 2)
|
157
|
+
{ parameter_key: key, parameter_value: value || ENV[key] }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def create_timeout
|
162
|
+
super / 60
|
163
|
+
end
|
164
|
+
|
165
|
+
def stack_name
|
166
|
+
@stack_name ||= "#{stack_name_prefix}#{super}"
|
167
|
+
end
|
168
|
+
|
169
|
+
def template_param
|
170
|
+
str = template
|
171
|
+
return { template_url: str } if url?(str)
|
172
|
+
return { template_body: read(str) } if file?(str)
|
173
|
+
error(:missing_template)
|
174
|
+
end
|
175
|
+
|
176
|
+
def client
|
177
|
+
@client ||= Aws::CloudFormation::Client.new(client_options)
|
178
|
+
end
|
179
|
+
|
180
|
+
def client_options
|
181
|
+
params = { region: region, credentials: credentials }
|
182
|
+
params = params.merge(credentials: assume_role(params)) if sts_assume_role?
|
183
|
+
params
|
184
|
+
end
|
185
|
+
|
186
|
+
def credentials
|
187
|
+
Aws::Credentials.new(access_key_id, secret_access_key, session_token)
|
188
|
+
end
|
189
|
+
|
190
|
+
def assume_role(params)
|
191
|
+
assumed_role = Aws::STS::Client.new(params).assume_role(
|
192
|
+
role_arn: sts_assume_role,
|
193
|
+
role_session_name: "travis-build-#{build_number}"
|
194
|
+
)
|
195
|
+
Aws::Credentials.new(
|
196
|
+
assumed_role.credentials.access_key_id,
|
197
|
+
assumed_role.credentials.secret_access_key,
|
198
|
+
assumed_role.credentials.session_token
|
199
|
+
)
|
200
|
+
end
|
201
|
+
|
202
|
+
def now
|
203
|
+
Time.now.strftime('%Y-%m-%dT%H:%M:%S')
|
204
|
+
end
|
205
|
+
|
206
|
+
def url?(str)
|
207
|
+
str =~ %r(^https?://)
|
208
|
+
end
|
209
|
+
|
210
|
+
class EventStream < Struct.new(:client, :stack_name, :handler)
|
211
|
+
attr_reader :thread
|
212
|
+
|
213
|
+
def initialize(*)
|
214
|
+
super
|
215
|
+
@event = describe_stack_events.stack_events.first
|
216
|
+
@thread = Thread.new(&method(:process))
|
217
|
+
end
|
218
|
+
|
219
|
+
def stop
|
220
|
+
mutex.synchronize { @stop = true }
|
221
|
+
thread.join
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
|
+
def process
|
227
|
+
until mutex.synchronize { @stop }
|
228
|
+
@event, events = events_since(@event)
|
229
|
+
events.each { |e| handler.call(format_event(e)) }
|
230
|
+
sleep 5 unless ENV['ENV'] == 'test'
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# source: https://github.com/rvedotrc/cfn-events/blob/master/lib/cfn-events/runner.rb
|
235
|
+
def events_since(event)
|
236
|
+
described_stack = describe_stack_events
|
237
|
+
stack_events = described_stack.stack_events
|
238
|
+
return [event, []] if stack_events.first.event_id == event.event_id
|
239
|
+
|
240
|
+
events = []
|
241
|
+
described_stack.each_page do |page|
|
242
|
+
|
243
|
+
|
244
|
+
if (oldest_new = page.stack_events.index { |e| e.event_id == event.event_id })
|
245
|
+
events.concat(page.stack_events[0..oldest_new - 1])
|
246
|
+
return [events.first, events.reverse]
|
247
|
+
end
|
248
|
+
events.concat(page.stack_events)
|
249
|
+
end
|
250
|
+
|
251
|
+
warn %(Last-seen stack event is no longer returned by AWS. Please raise this as a provider's bug.)
|
252
|
+
[events.first, events.reverse]
|
253
|
+
end
|
254
|
+
|
255
|
+
def describe_stack_events
|
256
|
+
client.describe_stack_events(stack_name: stack_name)
|
257
|
+
end
|
258
|
+
|
259
|
+
def mutex
|
260
|
+
@mutex ||= Mutex.new
|
261
|
+
end
|
262
|
+
|
263
|
+
EVENT_KEYS = %i(timestamp resource_type resource_status logical_resource_id
|
264
|
+
physical_resource_id resource_status_reason)
|
265
|
+
|
266
|
+
def format_event(event)
|
267
|
+
parts = EVENT_KEYS.map { |key| event.send(key) }
|
268
|
+
parts[0] = format_timestamp(parts[0])
|
269
|
+
parts.join(' ')
|
270
|
+
end
|
271
|
+
|
272
|
+
def format_timestamp(timestamp)
|
273
|
+
timestamp.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
@@ -9,13 +9,15 @@ module Dpl
|
|
9
9
|
tbd
|
10
10
|
str
|
11
11
|
|
12
|
+
env :cloudfoundry
|
13
|
+
|
12
14
|
opt '--username USER', 'Cloud Foundry username', required: true
|
13
15
|
opt '--password PASS', 'Cloud Foundry password', required: true, secret: true
|
14
|
-
opt '--organization ORG', 'Cloud Foundry
|
15
|
-
opt '--space SPACE', 'Cloud Foundry
|
16
|
-
opt '--api URL', 'Cloud Foundry api URL',
|
16
|
+
opt '--organization ORG', 'Cloud Foundry organization', required: true
|
17
|
+
opt '--space SPACE', 'Cloud Foundry space', required: true
|
18
|
+
opt '--api URL', 'Cloud Foundry api URL', default: 'https://api.run.pivotal.io'
|
17
19
|
opt '--app_name APP', 'Application name'
|
18
|
-
opt '--buildpack PACK', '
|
20
|
+
opt '--buildpack PACK', 'Buildpack name or Git URL'
|
19
21
|
opt '--manifest FILE', 'Path to the manifest'
|
20
22
|
opt '--skip_ssl_validation', 'Skip SSL validation'
|
21
23
|
opt '--v3', 'Use the v3 API version to push the application'
|
@@ -14,7 +14,7 @@ module Dpl
|
|
14
14
|
gem 'aws-sdk-codedeploy', '~> 1.0'
|
15
15
|
gem 'aws-sdk-s3', '~> 1.0'
|
16
16
|
|
17
|
-
env :aws
|
17
|
+
env :aws, :codedeploy
|
18
18
|
config '~/.aws/credentials', '~/.aws/config', prefix: 'aws'
|
19
19
|
|
20
20
|
opt '--access_key_id ID', 'AWS access key', required: true, secret: true
|
@@ -28,10 +28,10 @@ module Dpl
|
|
28
28
|
opt '--region REGION', 'AWS availability zone', default: 'us-east-1'
|
29
29
|
opt '--file_exists_behavior STR', 'How to handle files that already exist in a deployment target location', enum: %w(disallow overwrite retain), default: 'disallow'
|
30
30
|
opt '--wait_until_deployed', 'Wait until the deployment has finished'
|
31
|
-
opt '--bundle_type TYPE'
|
32
|
-
opt '--
|
33
|
-
opt '--
|
34
|
-
opt '--
|
31
|
+
opt '--bundle_type TYPE', 'Bundle type of the revision'
|
32
|
+
opt '--key KEY', 'S3 bucket key of the revision'
|
33
|
+
opt '--description DESCR', 'Description of the revision'
|
34
|
+
opt '--endpoint ENDPOINT', 'S3 endpoint url'
|
35
35
|
|
36
36
|
msgs login: 'Using Access Key: %{access_key_id}',
|
37
37
|
deploy_triggered: 'Deployment triggered: %s',
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Convox < Provider
|
4
|
+
status :dev
|
5
|
+
|
6
|
+
description sq(<<-str)
|
7
|
+
tbd
|
8
|
+
str
|
9
|
+
|
10
|
+
gem 'json'
|
11
|
+
|
12
|
+
env :convox
|
13
|
+
|
14
|
+
# needs descriptions
|
15
|
+
opt '--host HOST', default: 'console.convox.com'
|
16
|
+
opt '--app APP', required: true
|
17
|
+
opt '--rack RACK', required: true
|
18
|
+
opt '--password PASS', required: true
|
19
|
+
opt '--install_url URL', default: 'https://convox.com/cli/linux/convox'
|
20
|
+
opt '--update_cli'
|
21
|
+
opt '--create'
|
22
|
+
opt '--promote', default: true
|
23
|
+
opt '--env VARS', type: :array, sep: ','
|
24
|
+
opt '--env_file FILE'
|
25
|
+
opt '--description STR'
|
26
|
+
opt '--generation NUM', type: :int, default: '2'
|
27
|
+
|
28
|
+
# if app and rack are exported to the env, do they need to be passed to these commands?
|
29
|
+
cmds login: 'convox version --rack %{rack}',
|
30
|
+
validate: 'convox apps info --rack %{rack} --app %{app}',
|
31
|
+
create: 'convox apps create %{app} --generation %{generation} --rack %{rack} --wait',
|
32
|
+
update: 'convox update',
|
33
|
+
set_env: 'convox env set %{env} --rack %{rack} --app %{app} --replace',
|
34
|
+
build: 'convox build --rack %{rack} --app %{app} --id --description %{escaped_description}',
|
35
|
+
deploy: 'convox deploy --rack %{rack} --app %{app} --wait --id --description %{escaped_description}'
|
36
|
+
|
37
|
+
msgs create: 'Application %{app} does not exist on rack %{rack}. Creating it ...',
|
38
|
+
missing: 'Application %{app} does not exist on rack %{rack}.',
|
39
|
+
env_file: 'The given env_file does not exist.',
|
40
|
+
deploy: 'Building and promoting application ...',
|
41
|
+
build: 'Building application ...'
|
42
|
+
|
43
|
+
errs login: 'Login failed.'
|
44
|
+
|
45
|
+
def install
|
46
|
+
script :install
|
47
|
+
shell :update if update_cli?
|
48
|
+
export
|
49
|
+
end
|
50
|
+
|
51
|
+
def login
|
52
|
+
shell :login
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate
|
56
|
+
shell :validate, assert: false and return
|
57
|
+
error :missing unless create?
|
58
|
+
shell :create
|
59
|
+
end
|
60
|
+
|
61
|
+
def deploy
|
62
|
+
shell :set_env, echo: false unless env.empty?
|
63
|
+
shell promote ? :deploy : :build, echo: false
|
64
|
+
end
|
65
|
+
|
66
|
+
# not sure about this api. i like that there is an api for people to include
|
67
|
+
# env vars from the current build env, but maybe it would be better to expose
|
68
|
+
# FOO=$FOO? is mapping a bare env key to a key/value pair a concept in convox?
|
69
|
+
#
|
70
|
+
# def env
|
71
|
+
# env = env_file.concat(super || []) # TODO Cl should return an empty array, shouldn't it?
|
72
|
+
# env = env.map { |str| str.include?('=') ? str : "#{str}=#{ENV[str]}" }
|
73
|
+
# env.map { |str| escape(str) }.join(' ')
|
74
|
+
# end
|
75
|
+
|
76
|
+
# here's an alternative implementation that would expose FOO=$FOO:
|
77
|
+
gem 'sh_vars', '~> 1.0.2'
|
78
|
+
|
79
|
+
def env
|
80
|
+
env = env_file.concat(super || [])
|
81
|
+
env = env.map { |str| ShVars.parse(str).to_h }.inject(&:merge) || {}
|
82
|
+
env.map { |key, value| "#{key}=#{value.inspect}" }.join(' ')
|
83
|
+
end
|
84
|
+
|
85
|
+
def env_file
|
86
|
+
return [] unless env_file?
|
87
|
+
error :env_file unless file?(super)
|
88
|
+
lines = read(super).split("\n").map(&:strip)
|
89
|
+
lines.reject(&:empty?)
|
90
|
+
end
|
91
|
+
|
92
|
+
def description
|
93
|
+
description? ? super : JSON.dump(
|
94
|
+
repo_slug: repo_slug,
|
95
|
+
git_commit_sha: git_sha,
|
96
|
+
git_commit_message: git_commit_msg,
|
97
|
+
git_commit_author: git_author_name,
|
98
|
+
git_tag: git_tag,
|
99
|
+
branch: git_branch,
|
100
|
+
travis_build_id: ENV['TRAVIS_BUILD_ID'],
|
101
|
+
travis_build_number: ENV['TRAVIS_BUILD_NUMBER'],
|
102
|
+
pull_request: ENV['TRAVIS_PULL_REQUEST']
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
def export
|
107
|
+
env_vars.each { |key, value| ENV[key.to_s] = value.to_s }
|
108
|
+
end
|
109
|
+
|
110
|
+
def env_vars
|
111
|
+
{
|
112
|
+
CONVOX_HOST: host,
|
113
|
+
CONVOX_PASSWORD: password,
|
114
|
+
CONVOX_APP: app,
|
115
|
+
CONVOX_RACK: rack,
|
116
|
+
CONVOX_CLI: 'convox'
|
117
|
+
}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|