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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ae2b2439b1eea4e4aab608aec6dc9ead04561c7
4
- data.tar.gz: 160d6f697d55a16b005eed9d10e7cbdb51554091
3
+ metadata.gz: 76aeaf72c0f6f23b244156bcd17bd599d4740ac8
4
+ data.tar.gz: fe846e2f48d383ee1b2f7a676b72139d578f001f
5
5
  SHA512:
6
- metadata.gz: 09da201f05deca5428bca7546e0303ec002ecf3f9c4154d74ed5b833a09ed5acc0edceb8a9b3e0ac447e07cd46d8a0826f1bdef729e724f08c5eddc2205f20fe
7
- data.tar.gz: 8d4b87e6d48cfb33df31cf21f41e265032cff01b34b2d2ebc6ee87cefed6eb2f8fbeff1c010249f98912df92145489ac3c9bfd398595417b9b491c3657e7a2d3
6
+ metadata.gz: 67d67bf6c16e34bbb93990e8f8f1b3ca39f6f5afd9474d74c26091b05228059bdbb843e571a8c4aeefc14747dc0589899d9699a1da38b52ebe1f565538e3bf2b
7
+ data.tar.gz: f97e7ceeb4246ebf87465e3488c223997337c43f20afdddd92a95fad8d8a23c648d6655e92358333293439f7149550f7ea07b13b9fb7ae50e8e44f3a3359ee7b
@@ -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
- @eb = Aws::ElasticBeanstalk::Client.new
14
+ @cf = Aws::CloudFormation::Client.new
15
+ @elb = Aws::ElasticLoadBalancing::Client.new
13
16
  @ec2 = Aws::EC2::Client.new
14
- @s3_bucket = 'elasticbeanstalk-eu-west-1-001575623345'
15
- @current_branch_name = @prima.twig.current_branch_name
16
- @s3_key = @current_branch_name.gsub('/', '-') + '.zip'
17
- @application_name = 'prima-qa'
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
- @ec2_key_name = "eb_#{@user}"
25
- @ssh_key_path = "#{ENV['HOME']}/.ssh/eb_#{@user}"
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 = ["start", "finish", "deploy"]
30
+ possible_args = ["deploy"]
30
31
  stop_if args.empty?, [:wrong_args, possible_args]
31
- stop_if args.length > 3, [:wrong_args, possible_args]
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
- ignoranza = args[1] == 'ignorante' ? true : false
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
- end
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
- def deploy_feature!(ignoranza=false)
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
- stop_if application_version_exists?(@application_name, @version_label), "La versione #{@version_label} esiste gia', ti sei ricordato di committare?".red unless ignoranza
71
+ output "La Pull Request e' stata mergiata!".green
61
72
 
62
- manage_ec2_keypair(@ec2_key_name, @ssh_key_path)
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
- build_release!
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
- exec_step 'rsync -avd --exclude-from app/deploy/aws_docker/qa/.rsync-exclude-qa . /tmp/prima'
67
- exec_step 'cd /tmp/prima && cp app/deploy/aws_docker/qa/Dockerrun.aws.json .'
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
- if ignoranza
70
- deploy_ignorante
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
- deploy_serio
154
+ create_stack(stack_name_web, stack_body, parameters, tags)
73
155
  end
74
156
 
75
- endpoint_url = get_eb_endpoint_url(@application_name, @environment_name)
76
- output "Endpoint url: #{endpoint_url}\n".cyan
77
- Launchy.open(endpoint_url) if @prima.yesno 'Vuoi aprirlo nel browser?'.blue
78
- output "Deploy effettuato, everything is awesome!\n".green
79
- end
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
- def deploy_shutdown!
82
- stop_unless environment_exists?(@application_name, @environment_name), "L'environment #{@environment_name} non esiste!"
83
- shutdown_environment(@environment_name) if @prima.yesno("Sei sicuro di voler spegnere l'env?".blue)
84
- output "L'environment #{@environment_name} e' stato disrutto con successo!\n".green
85
- output "Potrebbe comunque passare qualche minuto prima che l'operazione finisca\n".yellow
86
- end
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
- def deploy_serio
89
- exec_step "rm -f #{@artifact_path}; cd /tmp/prima && zip -ryq #{@artifact_path} ."
90
- output "Upload dell'artifact in corso (#{(File.size(@artifact_path).to_f / 2**20).round(2)} MiB)\n".yellow
91
- s3 = Aws::S3::Resource.new
92
- obj = s3.bucket(@s3_bucket).object(@s3_key)
93
- obj.upload_file(@artifact_path)
94
-
95
- output "#{@s3_bucket}/#{@s3_key} uploadato con successo!\n".green
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
- auto_create_application: false,
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
- output "Application version #{@version_label} creata con successo!\n".green
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
- if environment_exists?(@application_name, @environment_name)
111
- is_eb_ready = is_eb_ready?(@application_name, @environment_name)
112
- wait_for_eb_ready(@application_name, @environment_name) unless is_eb_ready
113
- @eb.update_environment({
114
- environment_name: @environment_name,
115
- version_label: @version_label
116
- })
117
- wait_for_eb_ready(@application_name, @environment_name)
118
- output "Attendo che i container vengano riavviati...\n".yellow
119
- # Non e' veramente ready, deve restartare i container
120
- sleep_seconds = 180
121
- seconds_elapsed = 0
122
- while true
123
- break if seconds_elapsed >= sleep_seconds
124
- print '.'.yellow; STDOUT.flush
125
- sleep 1
126
- seconds_elapsed += 1
127
- end
128
- run_commands(@environment_name, @ssh_key_path)
129
- else
130
- output "Environment #{@environment_name} non presente, inizio la creazione...\n".yellow
131
- create_eb_environment(@application_name, @environment_name, @version_label, @git_rev, @ec2_key_name)
132
- output "Environment #{@environment_name} creato!\n".green
133
- is_eb_ready = is_eb_ready?(@application_name, @environment_name)
134
- wait_for_eb_ready(@application_name, @environment_name) unless is_eb_ready
135
- run_commands(@environment_name, @ssh_key_path)
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 deploy_ignorante
140
- if environment_exists?(@application_name, @environment_name)
141
- public_ip_address = get_ec2_public_ip_address @environment_name
142
- is_eb_ready = is_eb_ready?(@application_name, @environment_name)
143
- wait_for_eb_ready(@application_name, @environment_name) unless is_eb_ready
144
- exec_step "cd /tmp/prima && rsync -azd -e 'ssh -o StrictHostKeyChecking=no -i #{@ssh_key_path}' --rsync-path='sudo rsync' --exclude-from app/deploy/aws_docker/qa/.rsync-exclude-qa . ec2-user@#{public_ip_address}:/var/app/current/"
145
- exec_step "ssh -tt -o StrictHostKeyChecking=no -i #{@ssh_key_path} ec2-user@#{public_ip_address} 'sudo rm -rf /var/app/current/app/cache/*'"
146
- output "Deploy ignorante effettuato!".green
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
- output "Non puoi fare il deploy ignorante se l'environment non esiste".red
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 build_release!
306
+ def create_urania_artifact(revision)
307
+ @urania_built = true
153
308
  output "Preparo l'artifact .zip\n".yellow
154
309
 
155
- base_cmd = 'docker exec -it prima_'
310
+ git_checkout_version('urania', revision)
311
+
312
+ Dir.chdir 'projects/urania'
313
+
156
314
  [
157
- "docker run -v $PWD:/usr/app/src -w /usr/app/src blinkmobile/bower install --allow-root",
158
- "#{base_cmd}web_1 composer install",
159
- "#{base_cmd}php_1 ./app/console -e=prod assets:install web",
160
- "#{base_cmd}php_1 ./app/console -e=prod fos:js-routing:dump",
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
- def environment_exists?(application_name, environment_name)
180
- resp = @eb.describe_environments({
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
- def shutdown_environment(environment_name)
189
- @eb.terminate_environment({
190
- environment_name: environment_name,
191
- terminate_resources: true
192
- })
334
+ Dir.chdir '../../'
193
335
  end
194
336
 
195
- def manage_ec2_keypair(ec2_key_name, path)
196
- path = File.expand_path(path)
197
- return if File.exist?(path)
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
- def upload_ssh_public_key(ec2_key_name, path)
205
- @ec2.import_key_pair({
206
- dry_run: false,
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
- def create_eb_environment(application_name, environment_name, version_label, git_rev, ec2_key_name)
213
- # Faccio in modo di utilizzare sempre l'AMI piu' recente
214
- resp = @eb.list_available_solution_stacks
215
- latest_solution_stack = {name: '', version: 0.0}
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
- def is_eb_ready?(application_name, environment_name)
314
- resp = @eb.describe_environments({
315
- application_name: application_name,
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
- def get_eb_endpoint_url(application_name, environment_name)
323
- resp = @eb.describe_environments({
324
- application_name: application_name,
325
- environment_names: [environment_name],
326
- include_deleted: false
327
- })
328
- "http://#{resp.environments[0].endpoint_url}"
329
- end
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
- def get_eb_events(application_name, environment_name, start_time=nil, end_time=nil)
332
- start_time ||= Time.utc(1980,"jan",1,0,0,0)
333
- end_time ||= Time.now + 1
334
- resp = @eb.describe_events({
335
- application_name: application_name,
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 wait_for_eb_ready(application_name, environment_name)
344
- ready = false
345
- start_time = Time.now - 60
346
- sleep_seconds = 30
347
- output "Attendo che l'environment finisca di essere inizializzato...\n".yellow
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
- print "\n" if events.length > 0
353
- STDOUT.flush
386
+ Dir.chdir 'projects/prima'
354
387
 
355
- events.each do |event|
356
- if ["WARN", "ERROR", "FATAL"].include? event.severity
357
- color = 'red'
358
- else
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
- ready = true if is_eb_ready?(application_name, environment_name)
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 "Environment inizializzato!\n".green
462
+ output "\nStack #{stack_name} pronto!\n".green
376
463
  end
377
464
 
378
- def get_ec2_public_ip_address(environment_name)
379
- instance_id = @eb.describe_environment_resources({
380
- environment_name: environment_name,
381
- }).environment_resources.instances[0].id
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 run_commands(environment_name, ssh_key_path)
389
- public_ip_address = get_ec2_public_ip_address environment_name
390
-
391
- output "L'IP pubblico della macchina e': #{public_ip_address}\n".cyan
392
-
393
- base_cmd = "ssh -tt -o StrictHostKeyChecking=no -i #{ssh_key_path} ec2-user@#{public_ip_address}"
394
- cmd = "#{base_cmd} sudo -i docker ps --filter='name=-php-' | awk '{print $1 }' | grep -v CONTAINER"
395
- container_id = %x[ #{cmd} | grep -v 'Warning:' ].match(/([a-f0-9]{12})/).captures.first
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
- base_docker_cmd = "sudo -i docker exec #{container_id}"
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
- "#{base_cmd} #{base_docker_cmd} ./app/console fos:elastica:reset --force",
401
- "#{base_cmd} #{base_docker_cmd} ./app/console doctrine:database:drop --no-interaction --force",
402
- "#{base_cmd} #{base_docker_cmd} ./app/console doctrine:database:create --no-interaction",
403
- "#{base_cmd} #{base_docker_cmd} ./app/console doctrine:database:drop --no-interaction --connection=msa --force; true",
404
- "#{base_cmd} #{base_docker_cmd} ./app/console doctrine:database:create --no-interaction --connection=msa",
405
- "#{base_cmd} #{base_docker_cmd} ./app/console doctrine:schema:create --no-interaction",
406
- "#{base_cmd} #{base_docker_cmd} ./app/console doctrine:fixtures:load --no-interaction --fixtures=src/Prima/DataFixtures/"
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
- color = 'green'
523
+ raise e
414
524
  end
415
- output res.send color
525
+ else
526
+ true
416
527
  end
417
528
  end
418
529
 
419
- def application_version_exists?(application_name, version_label)
420
- resp = @eb.describe_application_versions({
421
- application_name: application_name,
422
- version_labels: [ version_label ]
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
- !resp.application_versions[0].nil?
539
+ output "La creazione dello stack #{stack_name} è stata avviata".green
425
540
  end
426
541
 
427
- def sanitize_environment_name(environment_name)
428
- environment_name.gsub!(/([^\w]|_)/, '-')
429
- if environment_name.length > 23
430
- if environment_name.start_with?('feature')
431
- environment_name = environment_name[8,23]
432
- elsif environment_name.start_with?('hotfix')
433
- environment_name = environment_name[7,23]
434
- else
435
- environment_name = environment_name[0,23]
436
- end
437
- end
438
- if environment_name[0] == '-'
439
- environment_name = environment_name[1..-1]
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
- if environment_name[-1] == '-'
442
- environment_name = environment_name[0..-2]
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
- environment_name
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