prima-twig 0.2.27 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/twig-feature +477 -327
- data/bin/twig-open-pr +1 -11
- data/bin/twig-pick-issue +21 -29
- data/lib/prima_twig.rb +10 -3
- metadata +22 -24
- data/bin/twig-release +0 -227
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76aeaf72c0f6f23b244156bcd17bd599d4740ac8
|
4
|
+
data.tar.gz: fe846e2f48d383ee1b2f7a676b72139d578f001f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67d67bf6c16e34bbb93990e8f8f1b3ca39f6f5afd9474d74c26091b05228059bdbb843e571a8c4aeefc14747dc0589899d9699a1da38b52ebe1f565538e3bf2b
|
7
|
+
data.tar.gz: f97e7ceeb4246ebf87465e3488c223997337c43f20afdddd92a95fad8d8a23c648d6655e92358333293439f7149550f7ea07b13b9fb7ae50e8e44f3a3359ee7b
|
data/bin/twig-feature
CHANGED
@@ -3,34 +3,33 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require_relative '../lib/prima_twig.rb'
|
5
5
|
require 'launchy'
|
6
|
+
require 'digest'
|
7
|
+
require 'pp'
|
6
8
|
|
7
9
|
class Release
|
8
10
|
include Command
|
9
11
|
|
10
12
|
def initialize
|
11
13
|
@prima = Prima.new
|
12
|
-
@
|
14
|
+
@cf = Aws::CloudFormation::Client.new
|
15
|
+
@elb = Aws::ElasticLoadBalancing::Client.new
|
13
16
|
@ec2 = Aws::EC2::Client.new
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@environment_name = sanitize_environment_name(@s3_key.gsub('.zip', ''))
|
19
|
-
@git_rev = `git rev-parse HEAD`
|
20
|
-
@version_label = @environment_name + '-' + @git_rev[0,5]
|
21
|
-
@user = `git config user.name`.downcase
|
22
|
-
@user = @user[0,1] + @user.split(' ').last
|
17
|
+
@ecs = Aws::ECS::Client.new
|
18
|
+
@s3 = Aws::S3::Client.new
|
19
|
+
@asg = Aws::AutoScaling::Client.new
|
20
|
+
@s3_bucket = 'prima-artifacts'
|
23
21
|
@artifact_path = '/tmp/prima-artifact.zip'
|
24
|
-
@
|
25
|
-
@
|
22
|
+
@qa_cluster = 'ecs-cluster-qa-ECSCluster-ROF3QJNLOXGG'
|
23
|
+
@import_db_task = 'arn:aws:ecs:eu-west-1:001575623345:task-definition/ecs-task-dbrestore-TaskDefinitionDbRestore-2NOTCW35ZOTF:1'
|
24
|
+
@prima_built = false
|
25
|
+
@urania_built = false
|
26
|
+
@backoffice_built = false
|
26
27
|
end
|
27
28
|
|
28
29
|
def execute! args
|
29
|
-
possible_args = ["
|
30
|
+
possible_args = ["deploy"]
|
30
31
|
stop_if args.empty?, [:wrong_args, possible_args]
|
31
|
-
stop_if args.length >
|
32
|
-
|
33
|
-
stop_if @prima.head_detached?, :detached_head
|
32
|
+
stop_if args.length > 1, [:wrong_args, possible_args]
|
34
33
|
|
35
34
|
case args[0]
|
36
35
|
when "start"
|
@@ -41,8 +40,7 @@ class Release
|
|
41
40
|
if ['terminate', 'stop', 'shutdown', 'halt', 'destroy'].include? args[1]
|
42
41
|
deploy_shutdown!
|
43
42
|
else
|
44
|
-
|
45
|
-
deploy_feature! ignoranza
|
43
|
+
deploy_feature!
|
46
44
|
end
|
47
45
|
else
|
48
46
|
stop_if true, [:wrong_args, possible_args]
|
@@ -50,119 +48,274 @@ class Release
|
|
50
48
|
end
|
51
49
|
|
52
50
|
def start_feature!
|
51
|
+
branch_name = @prima.clean_branch_name(ask('Inserisci il nome del branch (puoi omettere feature/): '.cyan))
|
52
|
+
stop_unless branch_name.length > 0, 'Devi inserire il nome del branch'
|
53
|
+
branch_name.prepend 'feature/' unless branch_name.include? 'feature'
|
54
|
+
|
55
|
+
output "Il nome del branch sarà " + branch_name.yellow
|
56
|
+
|
57
|
+
exec_step "git checkout master"
|
58
|
+
exec_step "git pull origin master"
|
59
|
+
exec_step "git checkout -b " + branch_name
|
53
60
|
end
|
54
61
|
|
55
62
|
def finish_feature!
|
56
|
-
|
63
|
+
current_branch_name = @prima.twig.current_branch_name
|
64
|
+
stop_unless (current_branch_name =~ /^feature\//), "Non sei su un branch di feature, non posso mergiare nulla"
|
57
65
|
|
58
|
-
|
66
|
+
# Mergia la PR
|
67
|
+
pr = @prima.get_pr
|
68
|
+
stop_unless pr, 'Pull Request not found'
|
69
|
+
@prima.merge_pull_request pr
|
59
70
|
|
60
|
-
|
71
|
+
output "La Pull Request e' stata mergiata!".green
|
61
72
|
|
62
|
-
|
73
|
+
# Chiude la issue
|
74
|
+
issue_number = @prima.twig.get_branch_property(current_branch_name, 'issue')
|
75
|
+
@prima.close_issue(issue_number) if issue_number
|
63
76
|
|
64
|
-
|
77
|
+
# Rimuove il branch remoto
|
78
|
+
exec_step "git push origin :#{current_branch_name}" if @prima.yesno "Vuoi eliminare il branch remoto #{current_branch_name}?".blue
|
79
|
+
end
|
65
80
|
|
66
|
-
|
67
|
-
|
81
|
+
def deploy_shutdown!
|
82
|
+
output "Not implemented yet!".red
|
83
|
+
exit
|
84
|
+
# stop_unless environment_exists?(@application_name, @environment_name), "L'environment #{@environment_name} non esiste!"
|
85
|
+
# shutdown_environment(@environment_name) if @prima.yesno("Sei sicuro di voler spegnere l'env?".blue)
|
86
|
+
# output "L'environment #{@environment_name} e' stato disrutto con successo!\n".green
|
87
|
+
# output "Potrebbe comunque passare qualche minuto prima che l'operazione finisca\n".yellow
|
88
|
+
end
|
68
89
|
|
69
|
-
|
70
|
-
|
90
|
+
def deploy_feature!
|
91
|
+
prima_branch = choose_branch_to_deploy('prima')
|
92
|
+
backoffice_branch = choose_branch_to_deploy('backoffice')
|
93
|
+
urania_branch = choose_branch_to_deploy('urania')
|
94
|
+
socket_branch = {name: "master"}
|
95
|
+
pamela_branch = {name: "master"}
|
96
|
+
|
97
|
+
tags = [
|
98
|
+
{
|
99
|
+
key: "prima",
|
100
|
+
value: prima_branch[:name]
|
101
|
+
},
|
102
|
+
{
|
103
|
+
key: "urania",
|
104
|
+
value: urania_branch[:name]
|
105
|
+
},
|
106
|
+
{
|
107
|
+
key: "backoffice",
|
108
|
+
value: backoffice_branch[:name]
|
109
|
+
}
|
110
|
+
]
|
111
|
+
|
112
|
+
deploy_id = Digest::MD5.hexdigest(prima_branch[:name] + backoffice_branch[:name] + urania_branch[:name] + socket_branch[:name] + pamela_branch[:name])
|
113
|
+
|
114
|
+
asg_stack_name = "ecs-asg-allinone-qa-#{deploy_id}"
|
115
|
+
create_asg_stack(asg_stack_name) unless stack_exists?(asg_stack_name)
|
116
|
+
|
117
|
+
stack_name_db = "ecs-task-db-qa-#{deploy_id}"
|
118
|
+
stack_body = IO.read('cloudformation/stacks/task/db.json')
|
119
|
+
parameters = [
|
120
|
+
{
|
121
|
+
parameter_key: "Environment",
|
122
|
+
parameter_value: "qa"
|
123
|
+
}
|
124
|
+
]
|
125
|
+
create_stack(stack_name_db, stack_body, parameters, tags) unless stack_exists?(stack_name_db)
|
126
|
+
|
127
|
+
create_prima_artifact(prima_branch[:revision]) unless artifact_exists?('prima-artifacts', "prima/#{prima_branch[:revision]}")
|
128
|
+
create_urania_artifact(urania_branch[:revision]) unless artifact_exists?('prima-artifacts', "microservices/urania/#{urania_branch[:revision]}-qa.tar.gz")
|
129
|
+
|
130
|
+
wait_for_stack_ready(stack_name_db) unless stack_ready?(stack_name_db)
|
131
|
+
|
132
|
+
import_dbs unless stack_exists?("ecs-task-web-qa-#{deploy_id}")
|
133
|
+
|
134
|
+
stack_name_web = "ecs-task-web-qa-#{deploy_id}"
|
135
|
+
git_checkout_version('prima', prima_branch[:revision])
|
136
|
+
stack_body = IO.read('projects/prima/app/cloudformation/tasks/web.json')
|
137
|
+
parameters = [
|
138
|
+
{
|
139
|
+
parameter_key: "Environment",
|
140
|
+
parameter_value: "qa"
|
141
|
+
},
|
142
|
+
{
|
143
|
+
parameter_key: "ReleaseVersion",
|
144
|
+
parameter_value: prima_branch[:revision]
|
145
|
+
},
|
146
|
+
{
|
147
|
+
parameter_key: "TaskDesiredCount",
|
148
|
+
parameter_value: "1"
|
149
|
+
}
|
150
|
+
]
|
151
|
+
if stack_exists?(stack_name_web)
|
152
|
+
update_stack(stack_name_web, stack_body, parameters) if @prima_built
|
71
153
|
else
|
72
|
-
|
154
|
+
create_stack(stack_name_web, stack_body, parameters, tags)
|
73
155
|
end
|
74
156
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
157
|
+
stack_name_consumer = "ecs-task-consumer-qa-#{deploy_id}"
|
158
|
+
git_checkout_version('prima', prima_branch[:revision])
|
159
|
+
stack_body = IO.read('projects/prima/app/cloudformation/tasks/consumer.json')
|
160
|
+
parameters = [
|
161
|
+
{
|
162
|
+
parameter_key: "Environment",
|
163
|
+
parameter_value: "qa"
|
164
|
+
},
|
165
|
+
{
|
166
|
+
parameter_key: "ReleaseVersion",
|
167
|
+
parameter_value: prima_branch[:revision]
|
168
|
+
}
|
169
|
+
]
|
170
|
+
if stack_exists?(stack_name_consumer)
|
171
|
+
update_stack(stack_name_consumer, stack_body, parameters) if @prima_built
|
172
|
+
else
|
173
|
+
create_stack(stack_name_consumer, stack_body, parameters, tags)
|
174
|
+
end
|
80
175
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
176
|
+
stack_name_urania = "ecs-task-urania-qa-#{deploy_id}"
|
177
|
+
git_checkout_version('urania', urania_branch[:revision])
|
178
|
+
stack_body = IO.read('projects/urania/deploy/task.json')
|
179
|
+
parameters = [
|
180
|
+
{
|
181
|
+
parameter_key: "Environment",
|
182
|
+
parameter_value: "qa"
|
183
|
+
},
|
184
|
+
{
|
185
|
+
parameter_key: "ReleaseVersion",
|
186
|
+
parameter_value: urania_branch[:revision]
|
187
|
+
},
|
188
|
+
{
|
189
|
+
parameter_key: "TaskDesiredCount",
|
190
|
+
parameter_value: "1"
|
191
|
+
}
|
192
|
+
]
|
193
|
+
if stack_exists?(stack_name_urania)
|
194
|
+
update_stack(stack_name_urania, stack_body, parameters) if @urania_built
|
195
|
+
else
|
196
|
+
create_stack(stack_name_urania, stack_body, parameters, tags)
|
197
|
+
end
|
87
198
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
resp = @eb.create_application_version({
|
98
|
-
application_name: @application_name,
|
99
|
-
version_label: @version_label,
|
100
|
-
description: @current_branch_name,
|
101
|
-
source_bundle: {
|
102
|
-
s3_bucket: @s3_bucket,
|
103
|
-
s3_key: @s3_key,
|
199
|
+
# Dev'essere fatto qua perche' dipende dall'url di web
|
200
|
+
create_backoffice_artifact(backoffice_branch[:revision], deploy_id) unless artifact_exists?('prima-artifacts', "backoffice/#{backoffice_branch[:revision]}-#{deploy_id}.zip")
|
201
|
+
git_checkout_version('backoffice', backoffice_branch[:revision])
|
202
|
+
stack_name_backoffice = "ecs-task-backoffice-qa-#{deploy_id}"
|
203
|
+
stack_body = IO.read('projects/backoffice/deploy/task.json')
|
204
|
+
parameters = [
|
205
|
+
{
|
206
|
+
parameter_key: "Environment",
|
207
|
+
parameter_value: "qa"
|
104
208
|
},
|
105
|
-
|
106
|
-
|
209
|
+
{
|
210
|
+
parameter_key: "ReleaseVersion",
|
211
|
+
parameter_value: "#{backoffice_branch[:revision]}-#{deploy_id}"
|
212
|
+
},
|
213
|
+
{
|
214
|
+
parameter_key: "TaskDesiredCount",
|
215
|
+
parameter_value: "1"
|
216
|
+
}
|
217
|
+
]
|
218
|
+
if stack_exists?(stack_name_backoffice)
|
219
|
+
update_stack(stack_name_backoffice, stack_body, parameters) if @backoffice_built
|
220
|
+
else
|
221
|
+
create_stack(stack_name_backoffice, stack_body, parameters, tags)
|
222
|
+
end
|
107
223
|
|
108
|
-
|
224
|
+
wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
|
225
|
+
wait_for_stack_ready(stack_name_consumer) unless stack_ready?(stack_name_consumer)
|
226
|
+
wait_for_stack_ready(stack_name_urania) unless stack_ready?(stack_name_urania)
|
227
|
+
wait_for_stack_ready(stack_name_backoffice) unless stack_ready?(stack_name_backoffice)
|
109
228
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
229
|
+
update_service_defaults(stack_name_web)
|
230
|
+
update_service_defaults(stack_name_consumer)
|
231
|
+
update_service_defaults(stack_name_urania)
|
232
|
+
update_service_defaults(stack_name_backoffice)
|
233
|
+
|
234
|
+
prima_elb_url = get_elb_url(stack_name_web)
|
235
|
+
urania_elb_url = get_elb_url(stack_name_urania)
|
236
|
+
backoffice_elb_url = get_elb_url(stack_name_backoffice)
|
237
|
+
|
238
|
+
output "Prima url: #{prima_elb_url}\n".cyan
|
239
|
+
output "Urania url: #{urania_elb_url}\n".cyan
|
240
|
+
output "Backoffice url: #{backoffice_elb_url}\n".cyan
|
241
|
+
output "SSH connection: ssh ec2-user@#{ec2_ip_address(asg_stack_name)} -i ~/.ssh/ecs-cluster-qa.pem".cyan
|
242
|
+
output "Deploy effettuato, everything is awesome!\n".green
|
243
|
+
end
|
244
|
+
|
245
|
+
def ec2_ip_address(asg_stack_name)
|
246
|
+
resp = @cf.describe_stack_resource({
|
247
|
+
stack_name: asg_stack_name,
|
248
|
+
logical_resource_id: 'ECSAutoScalingGroup'
|
249
|
+
})
|
250
|
+
resp = @asg.describe_auto_scaling_groups({
|
251
|
+
auto_scaling_group_names: [resp.stack_resource_detail.physical_resource_id],
|
252
|
+
max_records: 1
|
253
|
+
})
|
254
|
+
instance_id = resp.auto_scaling_groups[0].instances[0].instance_id
|
255
|
+
resp = @ec2.describe_instances({instance_ids: [instance_id]})
|
256
|
+
resp.reservations[0].instances[0].private_ip_address
|
257
|
+
end
|
258
|
+
|
259
|
+
def get_elb_url(stack_name)
|
260
|
+
case
|
261
|
+
when stack_name.include?('web')
|
262
|
+
logical_resource_id = 'EcsElasticLoadBalancerPublic'
|
263
|
+
when stack_name.include?('urania')
|
264
|
+
logical_resource_id = 'EcsElasticLoadBalancerInternal'
|
265
|
+
when stack_name.include?('backoffice')
|
266
|
+
logical_resource_id = 'EcsElasticLoadBalancerPublic'
|
136
267
|
end
|
268
|
+
resp = @cf.describe_stack_resource({
|
269
|
+
stack_name: stack_name,
|
270
|
+
logical_resource_id: logical_resource_id
|
271
|
+
})
|
272
|
+
resp = @elb.describe_load_balancers({
|
273
|
+
load_balancer_names: [resp.stack_resource_detail.physical_resource_id],
|
274
|
+
page_size: 1
|
275
|
+
})
|
276
|
+
resp.load_balancer_descriptions[0].dns_name
|
137
277
|
end
|
138
278
|
|
139
|
-
def
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
279
|
+
def update_service_defaults(stack_name)
|
280
|
+
case
|
281
|
+
when stack_name.include?('web')
|
282
|
+
logical_resource_id = 'ECSServiceWeb'
|
283
|
+
when stack_name.include?('consumer')
|
284
|
+
logical_resource_id = 'ECSServiceConsumer'
|
285
|
+
when stack_name.include?('urania')
|
286
|
+
logical_resource_id = 'ECSServiceUrania'
|
287
|
+
when stack_name.include?('backoffice')
|
288
|
+
logical_resource_id = 'ECSServiceBackoffice'
|
147
289
|
else
|
148
|
-
|
290
|
+
raise "Service name non gestito per lo stack #{stack_name}"
|
149
291
|
end
|
292
|
+
resp = @cf.describe_stack_resource({
|
293
|
+
stack_name: stack_name,
|
294
|
+
logical_resource_id: logical_resource_id
|
295
|
+
})
|
296
|
+
resp = @ecs.update_service({
|
297
|
+
cluster: @qa_cluster,
|
298
|
+
service: resp.stack_resource_detail.physical_resource_id,
|
299
|
+
deployment_configuration: {
|
300
|
+
minimum_healthy_percent: 0,
|
301
|
+
maximum_percent: 100
|
302
|
+
}
|
303
|
+
})
|
150
304
|
end
|
151
305
|
|
152
|
-
def
|
306
|
+
def create_urania_artifact(revision)
|
307
|
+
@urania_built = true
|
153
308
|
output "Preparo l'artifact .zip\n".yellow
|
154
309
|
|
155
|
-
|
310
|
+
git_checkout_version('urania', revision)
|
311
|
+
|
312
|
+
Dir.chdir 'projects/urania'
|
313
|
+
|
156
314
|
[
|
157
|
-
"docker run -v $PWD:/
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
"#{base_cmd}php_1 ./app/console -e=prod cypress:ng-routing:dump",
|
162
|
-
"#{base_cmd}php_1 ./app/console -e=prod bazinga:js-translation:dump web",
|
163
|
-
"#{base_cmd}php_1 ./node_modules/.bin/brunch build -e staging",
|
164
|
-
"#{base_cmd}web_1 composer dump-autoload --optimize --no-dev",
|
165
|
-
"#{base_cmd}compass_1 compass compile --force -c compass/config_prod.rb compass/"
|
315
|
+
"docker run -v $PWD:/code -w /code -e MIX_ENV=qa prima/urania:1.0.2 \
|
316
|
+
'mix local.hex --force && mix hex.info && \
|
317
|
+
mix deps.get && mix compile && mix deps.compile && \
|
318
|
+
mix release.clean --implode --no-confirm && mix release'",
|
166
319
|
].each do |cmd|
|
167
320
|
output "Eseguo #{cmd}".yellow
|
168
321
|
res = %x[ #{cmd} ]
|
@@ -174,195 +327,129 @@ class Release
|
|
174
327
|
output res.send color
|
175
328
|
stop_if (color == 'red'), "Errore durante la build dell'artifact".red
|
176
329
|
end
|
177
|
-
end
|
178
330
|
|
179
|
-
|
180
|
-
|
181
|
-
application_name: application_name,
|
182
|
-
environment_names: [environment_name],
|
183
|
-
include_deleted: false
|
184
|
-
})
|
185
|
-
!resp.environments[0].nil?
|
186
|
-
end
|
331
|
+
artifact_path = Dir.glob("rel/urania/releases/*/urania.tar.gz").first
|
332
|
+
upload_artifact(artifact_path, "microservices/urania/#{revision}-qa.tar.gz")
|
187
333
|
|
188
|
-
|
189
|
-
@eb.terminate_environment({
|
190
|
-
environment_name: environment_name,
|
191
|
-
terminate_resources: true
|
192
|
-
})
|
334
|
+
Dir.chdir '../../'
|
193
335
|
end
|
194
336
|
|
195
|
-
def
|
196
|
-
|
197
|
-
|
198
|
-
stop_unless @prima.yesno("Sei sicuro di voler creare la chiave SSH in #{path}?".blue), "Non puoi continuare senza chiave SSH".red
|
199
|
-
%x[ ssh-keygen -b 2048 -t rsa -f #{path} -q -N '' ]
|
200
|
-
upload_ssh_public_key(ec2_key_name, path + '.pub')
|
201
|
-
output "Chiave SSH creata e uploadata con successo!\n".green
|
202
|
-
end
|
337
|
+
def create_backoffice_artifact(revision, deploy_id)
|
338
|
+
@backoffice_built = true
|
339
|
+
output "Preparo l'artifact .zip\n".yellow
|
203
340
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
key_name: ec2_key_name,
|
208
|
-
public_key_material: IO.read(path)
|
209
|
-
})
|
210
|
-
end
|
341
|
+
git_checkout_version('backoffice', revision)
|
342
|
+
|
343
|
+
Dir.chdir 'projects/backoffice'
|
211
344
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
resp.solution_stacks.each do |solution_stack|
|
217
|
-
match = solution_stack.match(/64bit Amazon Linux [\d\.]+ v([\d\.]+) running Multi-container Docker [\d\.]+ \(Generic\)/i)
|
218
|
-
if match
|
219
|
-
version = match.captures.first
|
220
|
-
if Gem::Version.new(version) > Gem::Version.new(latest_solution_stack[:version])
|
221
|
-
latest_solution_stack[:name] = solution_stack
|
222
|
-
latest_solution_stack[:version] = version
|
345
|
+
['node_modules'].each do |dir|
|
346
|
+
unless File.directory?(dir)
|
347
|
+
if File.directory?("../../../backoffice/#{dir}")
|
348
|
+
exec_step "rsync -a ../../../backoffice/#{dir} ."
|
223
349
|
end
|
224
350
|
end
|
225
351
|
end
|
226
|
-
stop_if latest_solution_stack[:name].empty?, "Solution stack non trovata!".red
|
227
|
-
resp = @eb.create_environment({
|
228
|
-
application_name: application_name,
|
229
|
-
environment_name: environment_name,
|
230
|
-
version_label: version_label,
|
231
|
-
solution_stack_name: latest_solution_stack[:name],
|
232
|
-
option_settings: [
|
233
|
-
{
|
234
|
-
namespace: "aws:ec2:vpc",
|
235
|
-
option_name: "VPCId",
|
236
|
-
value: "vpc-72e52b17",
|
237
|
-
},
|
238
|
-
{
|
239
|
-
namespace: "aws:ec2:vpc",
|
240
|
-
option_name: "Subnets",
|
241
|
-
value: "subnet-90dc64f5,subnet-df13e986,subnet-78db7a0f",
|
242
|
-
},
|
243
|
-
{
|
244
|
-
namespace: "aws:ec2:vpc",
|
245
|
-
option_name: "ELBSubnets",
|
246
|
-
value: "subnet-90dc64f5,subnet-df13e986,subnet-78db7a0f",
|
247
|
-
},
|
248
|
-
{
|
249
|
-
namespace: "aws:ec2:vpc",
|
250
|
-
option_name: "AssociatePublicIpAddress",
|
251
|
-
value: "true",
|
252
|
-
},
|
253
|
-
{
|
254
|
-
namespace: "aws:autoscaling:launchconfiguration",
|
255
|
-
option_name: "SecurityGroups",
|
256
|
-
value: "sg-4079f725",
|
257
|
-
},
|
258
|
-
{
|
259
|
-
namespace: "aws:autoscaling:launchconfiguration",
|
260
|
-
option_name: "IamInstanceProfile",
|
261
|
-
value: "prima-qa",
|
262
|
-
},
|
263
|
-
{
|
264
|
-
namespace: "aws:autoscaling:launchconfiguration",
|
265
|
-
option_name: "EC2KeyName",
|
266
|
-
value: ec2_key_name,
|
267
|
-
},
|
268
|
-
{
|
269
|
-
namespace: "aws:autoscaling:launchconfiguration",
|
270
|
-
option_name: "InstanceType",
|
271
|
-
value: "t2.medium",
|
272
|
-
},
|
273
|
-
{
|
274
|
-
namespace: "aws:autoscaling:asg",
|
275
|
-
option_name: "MaxSize",
|
276
|
-
value: "1",
|
277
|
-
},
|
278
|
-
{
|
279
|
-
namespace: "aws:autoscaling:asg",
|
280
|
-
option_name: "MinSize",
|
281
|
-
value: "1",
|
282
|
-
},
|
283
|
-
{
|
284
|
-
namespace: "aws:cloudformation:template:parameter",
|
285
|
-
option_name: "EnvironmentVariables",
|
286
|
-
value: "SYMFONY__PRIMA__GIT__REVISION=#{git_rev},PRIMA_ENV_NAME=web-qa,PARAMETERS_FILE=prima-deploy/parameters_qa.yml,SYMFONY_ENV=qa,PRIMA_ROLE=all",
|
287
|
-
},
|
288
|
-
{
|
289
|
-
namespace: "aws:elasticbeanstalk:application:environment",
|
290
|
-
option_name: "PARAMETERS_FILE",
|
291
|
-
value: "prima-deploy/parameters_qa.yml",
|
292
|
-
},
|
293
|
-
{
|
294
|
-
namespace: "aws:elasticbeanstalk:application:environment",
|
295
|
-
option_name: "PRIMA_ENV_NAME",
|
296
|
-
value: "web-qa",
|
297
|
-
},
|
298
|
-
{
|
299
|
-
namespace: "aws:elasticbeanstalk:application:environment",
|
300
|
-
option_name: "SYMFONY__PRIMA__GIT__REVISION",
|
301
|
-
value: git_rev,
|
302
|
-
}
|
303
|
-
],
|
304
|
-
tags: [
|
305
|
-
{
|
306
|
-
key: "user",
|
307
|
-
value: @user
|
308
|
-
}
|
309
|
-
]
|
310
|
-
})
|
311
|
-
end
|
312
352
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
environment_names: [environment_name],
|
317
|
-
include_deleted: false
|
318
|
-
})
|
319
|
-
resp.environments[0].status != 'Launching'
|
320
|
-
end
|
353
|
+
stack_name_web = "ecs-task-web-qa-#{deploy_id}"
|
354
|
+
wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
|
355
|
+
web_qa_host = get_elb_url(stack_name_web)
|
321
356
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
357
|
+
[
|
358
|
+
"docker-compose build workers",
|
359
|
+
"cd ../../ && docker run -e GIT_DIR=$PWD -v $PWD:/usr/app/src -w /usr/app/src/projects/backoffice blinkmobile/bower install --allow-root",
|
360
|
+
"docker run -v $PWD:/code -w /code --entrypoint /bin/bash backoffice_workers '-c' 'sed -i \"s/web-qa-url/#{web_qa_host}/g\" Gruntfile.js && npm install && grunt qa'",
|
361
|
+
].each do |cmd|
|
362
|
+
output "Eseguo #{cmd}".yellow
|
363
|
+
res = %x[ #{cmd} ]
|
364
|
+
if $?.exitstatus != 0
|
365
|
+
color = 'red'
|
366
|
+
else
|
367
|
+
color = 'green'
|
368
|
+
end
|
369
|
+
output res.send color
|
370
|
+
stop_if (color == 'red'), "Errore durante la build dell'artifact".red
|
371
|
+
end
|
330
372
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
environment_name: environment_name,
|
337
|
-
start_time: start_time,
|
338
|
-
end_time: end_time
|
339
|
-
})
|
340
|
-
resp.events.reverse
|
373
|
+
artifact_path = '/tmp/backoffice.zip'
|
374
|
+
exec_step "rm -f #{artifact_path} && zip -9 -r #{artifact_path} bin/"
|
375
|
+
upload_artifact(artifact_path, "backoffice/#{revision}-#{deploy_id}.zip")
|
376
|
+
|
377
|
+
Dir.chdir '../../'
|
341
378
|
end
|
342
379
|
|
343
|
-
def
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
while !ready
|
349
|
-
events = get_eb_events(application_name, environment_name, start_time)
|
350
|
-
start_time = Time.now
|
380
|
+
def create_prima_artifact(revision)
|
381
|
+
@prima_built = true
|
382
|
+
output "Preparo l'artifact .zip\n".yellow
|
383
|
+
|
384
|
+
git_checkout_version('prima', revision)
|
351
385
|
|
352
|
-
|
353
|
-
STDOUT.flush
|
386
|
+
Dir.chdir 'projects/prima'
|
354
387
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
color = 'cyan'
|
388
|
+
['vendor', 'node_modules'].each do |dir|
|
389
|
+
unless File.directory?(dir)
|
390
|
+
if File.directory?("../../../prima/#{dir}")
|
391
|
+
exec_step "rsync -a ../../../prima/#{dir} ."
|
360
392
|
end
|
361
|
-
output "#{event.event_date} - #{event.severity} #{event.message}".send color
|
362
393
|
end
|
394
|
+
end
|
395
|
+
|
396
|
+
base_cmd = 'docker run -v $PWD:/code -w /code --link redis:redis prima_'
|
397
|
+
[
|
398
|
+
"docker-compose build web php",
|
399
|
+
"docker run -d --name redis redis:2.8",
|
400
|
+
"cd ../../ && docker run -e GIT_DIR=$PWD -v $PWD:/usr/app/src -w /usr/app/src/projects/prima blinkmobile/bower install --allow-root",
|
401
|
+
"#{base_cmd}web composer install -n",
|
402
|
+
"#{base_cmd}web npm install",
|
403
|
+
"#{base_cmd}php ./app/console -e=prod assets:install web",
|
404
|
+
"#{base_cmd}php ./app/console -e=prod fos:js-routing:dump",
|
405
|
+
"#{base_cmd}php ./app/console -e=prod cypress:ng-routing:dump",
|
406
|
+
"#{base_cmd}php ./app/console -e=prod bazinga:js-translation:dump web",
|
407
|
+
"#{base_cmd}web ./node_modules/.bin/brunch build -e staging",
|
408
|
+
"#{base_cmd}web composer dump-autoload --optimize --no-dev",
|
409
|
+
"#{base_cmd}compass compass compile --force -c web/compass/config_prod.rb web/compass/",
|
410
|
+
#"docker run -v $PWD:/code -w /code -e NODE_ENV=production prima_web ./node_modules/.bin/webpack --optimize-minimize",
|
411
|
+
"docker kill redis && docker rm redis"
|
412
|
+
].each do |cmd|
|
413
|
+
output "Eseguo #{cmd}".yellow
|
414
|
+
res = %x[ #{cmd} ]
|
415
|
+
if $?.exitstatus != 0
|
416
|
+
color = 'red'
|
417
|
+
else
|
418
|
+
color = 'green'
|
419
|
+
end
|
420
|
+
output res.send color
|
421
|
+
stop_if (color == 'red'), "Errore durante la build dell'artifact".red
|
422
|
+
end
|
423
|
+
|
424
|
+
exec_step 'rsync -avd --exclude-from app/deploy/aws_docker/qa/.rsync-exclude-qa . /tmp/prima'
|
425
|
+
exec_step "rm -f #{@artifact_path}; cd /tmp/prima && zip -ryq #{@artifact_path} ."
|
426
|
+
|
427
|
+
upload_artifact(@artifact_path, "prima/#{revision}.zip")
|
428
|
+
|
429
|
+
Dir.chdir "../../"
|
430
|
+
end
|
431
|
+
|
432
|
+
def git_checkout_version(project, revision)
|
433
|
+
Dir.chdir "projects/#{project}"
|
434
|
+
exec_step "git checkout -- . && git clean -f -d && git checkout #{revision}"
|
435
|
+
Dir.chdir "../../"
|
436
|
+
end
|
363
437
|
|
364
|
-
|
438
|
+
def upload_artifact(source_path, destination_path)
|
439
|
+
output "Upload dell'artifact in corso (#{(File.size(source_path).to_f / 2**20).round(2)} MiB)\n".yellow
|
440
|
+
s3 = Aws::S3::Resource.new
|
441
|
+
obj = s3.bucket(@s3_bucket).object(destination_path)
|
442
|
+
obj.upload_file(source_path)
|
443
|
+
|
444
|
+
output "#{@s3_bucket}/#{destination_path} uploadato con successo!\n".green
|
445
|
+
end
|
365
446
|
|
447
|
+
def wait_for_stack_ready(stack_name)
|
448
|
+
ready = false
|
449
|
+
sleep_seconds = 10
|
450
|
+
output "Attendo che lo stack #{stack_name} finisca di essere inizializzato...\n".yellow
|
451
|
+
while !ready
|
452
|
+
ready = true if stack_ready?(stack_name)
|
366
453
|
seconds_elapsed = 0
|
367
454
|
while true
|
368
455
|
break if seconds_elapsed >= sleep_seconds
|
@@ -372,76 +459,139 @@ class Release
|
|
372
459
|
end
|
373
460
|
end
|
374
461
|
|
375
|
-
output "
|
462
|
+
output "\nStack #{stack_name} pronto!\n".green
|
376
463
|
end
|
377
464
|
|
378
|
-
def
|
379
|
-
|
380
|
-
|
381
|
-
})
|
382
|
-
|
383
|
-
resp = @ec2.describe_instances({instance_ids: [instance_id]})
|
384
|
-
|
385
|
-
resp.reservations[0].instances[0].public_ip_address
|
465
|
+
def stack_ready?(stack_name)
|
466
|
+
resp = @cf.describe_stacks({
|
467
|
+
stack_name: stack_name
|
468
|
+
})
|
469
|
+
['CREATE_COMPLETE', 'UPDATE_COMPLETE'].include? resp.stacks[0].stack_status
|
386
470
|
end
|
387
471
|
|
388
|
-
def
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
472
|
+
def create_asg_stack(stack_name)
|
473
|
+
stack_body = IO.read('cloudformation/stacks/asg/ecs-asg-allinone.json')
|
474
|
+
parameters = [
|
475
|
+
{
|
476
|
+
parameter_key: "Environment",
|
477
|
+
parameter_value: "qa"
|
478
|
+
},
|
479
|
+
{
|
480
|
+
parameter_key: "InstanceType",
|
481
|
+
parameter_value: "t2.large"
|
482
|
+
}
|
483
|
+
]
|
484
|
+
tags = []
|
485
|
+
create_stack(stack_name, stack_body, parameters, tags)
|
486
|
+
end
|
396
487
|
|
397
|
-
|
488
|
+
def import_dbs
|
489
|
+
resp = @ecs.run_task({
|
490
|
+
cluster: @qa_cluster,
|
491
|
+
task_definition: @import_db_task,
|
492
|
+
count: 1
|
493
|
+
})
|
494
|
+
output "Attendo che i DB vengano importati...\n".yellow
|
495
|
+
stopped_at = nil
|
496
|
+
while stopped_at.nil?
|
497
|
+
resp = @ecs.describe_tasks({
|
498
|
+
cluster: @qa_cluster,
|
499
|
+
tasks: [resp.tasks[0].task_arn]
|
500
|
+
})
|
501
|
+
stopped_at = resp.tasks[0].stopped_at
|
502
|
+
sleep_seconds = 10
|
503
|
+
seconds_elapsed = 0
|
504
|
+
while true && stopped_at.nil?
|
505
|
+
break if seconds_elapsed >= sleep_seconds
|
506
|
+
print '.'.yellow; STDOUT.flush
|
507
|
+
sleep 1
|
508
|
+
seconds_elapsed += 1
|
509
|
+
end
|
510
|
+
end
|
511
|
+
print "\n"
|
512
|
+
end
|
398
513
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
].each do |cmd|
|
408
|
-
output "Eseguo #{cmd}".yellow
|
409
|
-
res = %x[ #{cmd} ]
|
410
|
-
if $?.exitstatus != 0
|
411
|
-
color = 'red'
|
514
|
+
def stack_exists?(stack_name)
|
515
|
+
begin
|
516
|
+
res = @cf.describe_stacks({
|
517
|
+
stack_name: stack_name
|
518
|
+
})
|
519
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
520
|
+
if e.message.include? 'does not exist'
|
521
|
+
false
|
412
522
|
else
|
413
|
-
|
523
|
+
raise e
|
414
524
|
end
|
415
|
-
|
525
|
+
else
|
526
|
+
true
|
416
527
|
end
|
417
528
|
end
|
418
529
|
|
419
|
-
def
|
420
|
-
|
421
|
-
|
422
|
-
|
530
|
+
def create_stack(stack_name, stack_body, parameters = [], tags = [])
|
531
|
+
@cf.create_stack({
|
532
|
+
stack_name: stack_name,
|
533
|
+
template_body: stack_body,
|
534
|
+
parameters: parameters,
|
535
|
+
tags: tags,
|
536
|
+
capabilities: ["CAPABILITY_IAM"],
|
537
|
+
on_failure: "ROLLBACK"
|
423
538
|
})
|
424
|
-
|
539
|
+
output "La creazione dello stack #{stack_name} è stata avviata".green
|
425
540
|
end
|
426
541
|
|
427
|
-
def
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
542
|
+
def update_stack(stack_name, stack_body, parameters = [])
|
543
|
+
begin
|
544
|
+
@cf.update_stack({
|
545
|
+
stack_name: stack_name,
|
546
|
+
template_body: stack_body,
|
547
|
+
parameters: parameters,
|
548
|
+
capabilities: ["CAPABILITY_IAM"]
|
549
|
+
})
|
550
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
551
|
+
# if e.message.include? 'does not exist'
|
552
|
+
# false
|
553
|
+
# else
|
554
|
+
# raise e
|
555
|
+
# end
|
556
|
+
raise e
|
557
|
+
else
|
558
|
+
output "L'update dello stack #{stack_name} è stato avviato".green
|
440
559
|
end
|
441
|
-
|
442
|
-
|
560
|
+
end
|
561
|
+
|
562
|
+
def artifact_exists?(bucket, path)
|
563
|
+
resp = @s3.list_objects({
|
564
|
+
bucket: bucket,
|
565
|
+
max_keys: 1,
|
566
|
+
prefix: path
|
567
|
+
})
|
568
|
+
!resp.contents.empty?
|
569
|
+
end
|
570
|
+
|
571
|
+
def choose_branch_to_deploy(project_name)
|
572
|
+
Dir.chdir "projects/#{project_name}"
|
573
|
+
output "Recupero la lista dei branch del progetto #{project_name}..."
|
574
|
+
out = %x[ git fetch ]
|
575
|
+
branches = %x[ git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname) %(objectname)' | sed 's/refs\\/remotes\\/origin\\///g' ]
|
576
|
+
.split("\n").delete_if { |b| b.include?('HEAD') || b.include?('dev') }
|
577
|
+
|
578
|
+
branch_name = choose do |menu|
|
579
|
+
menu.prompt = "Scegli il branch di #{project_name} da deployare: ".cyan
|
580
|
+
menu.shell = true
|
581
|
+
|
582
|
+
branches.each do |branch|
|
583
|
+
|
584
|
+
title = @prima.reduce_size(branch, 100)
|
585
|
+
msg = "#{title}".light_blue
|
586
|
+
menu.choice(msg) { branch }
|
587
|
+
end
|
443
588
|
end
|
444
|
-
|
589
|
+
|
590
|
+
Dir.chdir "../../"
|
591
|
+
|
592
|
+
name = branch_name.split(' ').first
|
593
|
+
revision = branch_name.split(' ').last
|
594
|
+
{ name: name, revision: revision[0..14] }
|
445
595
|
end
|
446
596
|
|
447
597
|
end
|