prima-twig 0.2.27 → 0.3.0

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 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