prima-twig 0.5.0 → 0.5.26

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,13 +2,19 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require_relative '../lib/prima_twig.rb'
5
+ require_relative '../lib/prima_aws_client.rb'
5
6
  require 'colorize'
6
7
  require 'highline/import'
7
- require 'aws-sdk'
8
+ require 'aws-sdk-batch'
9
+ require 'aws-sdk-cloudformation'
10
+ require 'aws-sdk-ecs'
11
+ require 'aws-sdk-s3'
8
12
  require 'redcarpet'
9
13
  require 'mail'
10
14
  require 'erb'
11
15
  require 'base64'
16
+ require 'rubyflare'
17
+ require 'pp'
12
18
 
13
19
  def help_content
14
20
  <<-HELP
@@ -43,17 +49,35 @@ end
43
49
 
44
50
  class Review
45
51
  include Command
52
+ include PrimaAwsClient
46
53
 
47
54
  def initialize
48
55
  @prima = Prima.new
56
+ output "Controllo se ci sono aggiornamenti da fare..."
57
+ exec "gem update prima-twig && twig deploy #{ARGV.join ' '}" unless `gem outdated`.lines.grep(/^prima-twig \(.*\)/).empty?
49
58
  @cf = Aws::CloudFormation::Client.new
50
59
  @ecs = Aws::ECS::Client.new
60
+ @s3 = Aws::S3::Client.new
61
+ @batch = Aws::Batch::Client.new
62
+ @s3_bucket = "prima-artifacts-encrypted"
51
63
  end
52
64
 
53
- def execute!
54
- stop_if @prima.head_detached?, :detached_head
65
+ def execute! args
66
+ unless args.empty?
67
+ case args[0]
68
+ when "parameters"
69
+ reload_parameters!
70
+ else
71
+ stop_if true, [:wrong_args, ['parameters']]
72
+ end
73
+ else
74
+ deploy_revision!
75
+ end
76
+ end
55
77
 
56
- `git checkout master && git pull`
78
+ def deploy_revision!
79
+ stop_if @prima.head_detached?, :detached_head
80
+ stop_if @prima.repo_has_modified_files?, "Non posso deployare con file non commitati"
57
81
 
58
82
  output "Recupero degli artifacts in corso, attendi qualche secondo...".yellow
59
83
  artifacts = get_artifacts[0..49]
@@ -70,26 +94,10 @@ class Review
70
94
  end
71
95
  end
72
96
 
73
- user = `git config user.name`
97
+ user = `git config user.name`.delete "\n"
74
98
  artifact = artifacts.select {|v| v[:rev] == artifact_rev}.first
75
99
 
76
- deploy_command = "bin/deploy #{artifact_rev}"
77
-
78
- output "Il comando per il deploy sara': #{deploy_command}".yellow
79
-
80
- exit unless @prima.yesno "Sei sicuro di voler effettuare il deploy in produzione?".blue
81
-
82
- exec_step deploy_command
83
-
84
- stack_name_web = 'ecs-task-web-production'
85
- stack_name_consumer = 'ecs-task-consumer-production'
86
- stack_name_cron = 'ecs-task-consumer-production'
87
- wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
88
- wait_for_stack_ready(stack_name_consumer) unless stack_ready?(stack_name_consumer)
89
- wait_for_stack_ready(stack_name_cron) unless stack_ready?(stack_name_cron)
90
-
91
- output "Avvio paparatzinger per gli screenshot".yellow
92
- job_name = launch_paparatzinger(artifact[:commit_msg])
100
+ do_deploy! artifact_rev
93
101
 
94
102
  mail = Mail.new do
95
103
  from 'deploy@prima.it'
@@ -97,13 +105,14 @@ class Review
97
105
  subject "#{user} ha effettuato il deploy della revision #{artifact[:rev]}"
98
106
  end
99
107
 
108
+ commit_msg = clean_commit_message(artifact[:commit_msg])
109
+
100
110
  body = "## Deploy in produzione effettuato con successo\n\n"
101
111
  body << "Data: #{Time.now.strftime('%d/%m/%Y %H:%M:%S')}\n\n"
102
112
  body << "Utente: #{user}\n\n"
103
113
  body << "Revision: [#{artifact[:rev]}](https://github.com/primait/prima/commit/#{artifact[:rev]}) del #{artifact[:created_at].strftime('%d/%m/%Y %H:%M:%S')}\n\n"
104
114
  body << "Branch: [#{artifact[:branch]}](https://github.com/primait/prima/tree/#{artifact[:branch]})\n\n"
105
- body << "Commit: #{artifact[:commit_msg].gsub(/_/, '\_')}\n\n"
106
- body << "Screenshots (tra qualche minuto): [BrowserStack](https://www.browserstack.com/automate) (Filtrare per: \"#{job_name.gsub(/_/, '\_')}\")"
115
+ body << "Commit: #{commit_msg.gsub(/_/, '\_')}\n\n"
107
116
 
108
117
  htmlBody = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render body
109
118
 
@@ -118,94 +127,122 @@ class Review
118
127
  mail.html_part = html_part
119
128
  mail.text_part = text_part
120
129
 
121
- opts = {address: 'smtp.mandrillapp.com', port: '587'}
122
- opts[:user_name] = 'deploy@prima.it'
123
- opts[:password] = @prima.config['mandrill']
130
+ opts = {address: 'email-smtp.eu-west-1.amazonaws.com', port: '587'}
131
+ opts[:user_name] = @prima.config['aws_username']
132
+ opts[:password] = @prima.config['aws_password']
133
+
134
+ exec_step "git checkout master"
124
135
 
125
136
  mail.delivery_method(:smtp, opts)
126
137
  mail.deliver
127
138
 
139
+ invalidate_prismic_cache
140
+
141
+ launch_crawler
142
+
143
+ exec_step "terminal-notifier -message 'Deploy terminato'" if which 'terminal-notifier'
144
+ end
145
+
146
+ def invalidate_prismic_cache
147
+ [
148
+ "guarantee",
149
+ "glossary",
150
+ "guide",
151
+ "faq"
152
+ ].each do |page|
153
+
154
+ exec_step "curl -X POST -H \"Content-Type: application/json\" https://www.prima.it/api/cms/update/#{page}?apikey=#{@prima.config['prima_apikey']}"
155
+ end
156
+ end
157
+
158
+ def reload_parameters!
159
+ artifact_rev = ''
160
+ resp = @cf.describe_stacks({
161
+ stack_name: "ecs-task-web-vpc-production"
162
+ })
163
+ resp.stacks[0].parameters.each do |param|
164
+ if param.parameter_key == 'ReleaseVersion'
165
+ artifact_rev = param.parameter_value
166
+ break
167
+ end
168
+ end
169
+
170
+ do_deploy!(artifact_rev, true)
171
+
172
+ output "\nFinito di aggiornare i parameters.yml\n".green
173
+ end
174
+
175
+ def do_deploy!(artifact_rev, reload_parameters=false)
176
+ deploy_command = "bin/deploy #{artifact_rev}"
177
+ deploy_command << " reloadparameters" if reload_parameters
178
+
179
+ output "Il comando per il deploy sara': #{deploy_command}".yellow
180
+ confirm_message = "Sei sicuro di voler effettuare "
181
+ reload_parameters ? (confirm_message << "il reload dei parameters ") : (confirm_message << " il deploy ")
182
+ confirm_message << "in produzione?"
183
+
184
+ exit unless @prima.yesno confirm_message.blue
185
+
186
+ exec_step "git fetch"
187
+ exec_step "git checkout #{artifact_rev}"
188
+ exec_step deploy_command
189
+
190
+ stack_name_web = 'ecs-task-web-vpc-production'
191
+ stack_name_consumer = 'ecs-task-consumer-vpc-production'
192
+ stack_name_cron = 'ecs-task-consumer-vpc-production'
193
+ stack_name_job = 'batch-job-php-production'
194
+ wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
195
+ wait_for_stack_ready(stack_name_consumer) unless stack_ready?(stack_name_consumer)
196
+ wait_for_stack_ready(stack_name_cron) unless stack_ready?(stack_name_cron)
197
+ wait_for_stack_ready(stack_name_job) unless stack_ready?(stack_name_job)
128
198
  end
129
199
 
130
200
  def get_artifacts
131
201
  artifacts = []
132
- s3 = Aws::S3::Client.new
133
- resp = s3.list_objects(bucket: 'prima-artifacts', prefix: 'prima')
202
+ resp = @s3.list_objects(bucket: @s3_bucket, prefix: 'prima')
134
203
  resp.contents.each do |l|
135
- rev = l.key.match(/(\w{15}).tar.gz$/).captures.first if l.key.match(/(\w{15}).tar.gz$/)
204
+ # aggiungiamo solo gli artefatti prodotti a partire dal branch master, riconosciuti tramite i metadata
205
+ rev = l.key.match(/^prima\/(\w{15}).tar.gz$/).captures.first if l.key.match(/^prima\/(\w{15}).tar.gz$/)
136
206
  if rev
137
- object = s3.head_object(bucket: 'prima-artifacts', key: l.key)
207
+ object = @s3.head_object(bucket: @s3_bucket, key: l.key)
138
208
  commit_msg = ''
139
209
  commit_msg = Base64.decode64(object.metadata['commit_msg']).strip if object.metadata.has_key? 'commit_msg'
140
- artifacts << {rev: rev, created_at: object.last_modified, branch: object.metadata['branch'], commit_msg: commit_msg } if object.metadata.has_key? 'branch'
210
+ artifacts << {rev: rev, created_at: object.last_modified, branch: object.metadata['branch'], commit_msg: commit_msg } if (object.metadata.has_key? 'branch') && (object.metadata['branch'] == 'master')
141
211
  end
142
212
  end
143
213
  artifacts.sort_by { |v| v[:created_at] }.reverse
144
214
  end
145
215
 
146
- def wait_for_stack_ready(stack_name)
147
- ready = false
148
- sleep_seconds = 5
149
- output "Attendo che lo stack #{stack_name} finisca di essere deployato...\n".yellow
150
- while !ready
151
- ready = true if stack_ready?(stack_name)
152
- seconds_elapsed = 0
153
- while true
154
- break if seconds_elapsed >= sleep_seconds
155
- print '.'.yellow; STDOUT.flush
156
- sleep 1
157
- seconds_elapsed += 1
158
- end
159
- end
216
+ def launch_crawler()
217
+ resp = describe_stack_resource('batch-job-crawler-production', 'JobDefinition')
160
218
 
161
- output "\nStack #{stack_name} deployato con successo!\n".green
162
- end
163
-
164
- def stack_ready?(stack_name)
165
- resp = @cf.describe_stacks({
166
- stack_name: stack_name
219
+ @batch.submit_job({
220
+ job_name: "crawler", # required
221
+ job_queue: "tools-production", # required
222
+ job_definition: resp.stack_resource_detail.physical_resource_id # required
167
223
  })
168
- ['CREATE_COMPLETE', 'UPDATE_COMPLETE'].include? resp.stacks[0].stack_status
169
- end
170
224
 
171
- def launch_paparatzinger(job_name)
172
- job_name.gsub! /Merge pull request /i, ''
173
- job_name.gsub! /from primait\/feature\//i, ''
174
- job_name[0..99].gsub! /[^0-9a-z]/i, '\_'
225
+ output "Crawler lanciato con successo!\n".green
226
+ end
175
227
 
176
- logical_resource_id = 'TaskDefinitionPaparatzinger'
177
- resp = @cf.describe_stack_resource({
178
- stack_name: 'ecs-task-paparatzinger-production',
179
- logical_resource_id: logical_resource_id
180
- })
228
+ end
181
229
 
182
- resp = @ecs.run_task({
183
- cluster: 'ecs-cluster-microservices-production-ECSCluster-N4APBU860IA1',
184
- task_definition: resp.stack_resource_detail.physical_resource_id,
185
- overrides: {
186
- container_overrides: [
187
- {
188
- name: 'paparatzinger',
189
- environment: [
190
- {
191
- name: 'JOB_NAME',
192
- value: job_name,
193
- },
194
- {
195
- name: 'VERSION',
196
- value: '1.0.6',
197
- }
198
- ]
199
- }
200
- ]
201
- },
202
- count: 1
203
- })
204
- output "paparatzinger lanciato con successo\n".green
230
+ def clean_commit_message(commit_msg)
231
+ commit_msg.gsub! /Merge pull request /i, ''
232
+ commit_msg.gsub! /from primait\/feature\//i, ''
233
+ commit_msg = commit_msg[/.+?\(#\d+\)/m] unless commit_msg[/.+?\(#\d+\)/m].nil? # rimuove tutto quello che sta dopo la fine del numero di issue
234
+ commit_msg[0..99]
235
+ end
205
236
 
206
- job_name
237
+ def which(cmd)
238
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
239
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
240
+ exts.each { |ext|
241
+ exe = File.join(path, "#{cmd}#{ext}")
242
+ return exe if File.executable?(exe) && !File.directory?(exe)
243
+ }
207
244
  end
208
-
245
+ return nil
209
246
  end
210
247
 
211
- Review.new.execute!
248
+ Review.new.execute! args
@@ -2,53 +2,110 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require_relative '../lib/prima_twig.rb'
5
- require 'launchy'
5
+ require_relative '../lib/prima_aws_client.rb'
6
6
  require 'digest'
7
+ require 'json'
8
+ require 'launchy'
7
9
  require 'pp'
10
+ require 'redis'
8
11
 
9
12
  class Release
10
13
  include Command
14
+ include PrimaAwsClient
11
15
 
12
- def initialize
16
+ def initialize(update_gem=true)
13
17
  @prima = Prima.new
14
- @cf = Aws::CloudFormation::Client.new
15
- @elb = Aws::ElasticLoadBalancing::Client.new
16
- @ec2 = Aws::EC2::Client.new
17
- @ecs = Aws::ECS::Client.new
18
- @s3 = Aws::S3::Client.new
19
- @asg = Aws::AutoScaling::Client.new
20
- @s3_bucket = 'prima-artifacts'
21
- @artifact_path = '/tmp/prima-artifact.zip'
22
- @import_db_task = 'arn:aws:ecs:eu-west-1:001575623345:task-definition/ecs-task-db-restore-TaskDefinitionDbRestore-8A9N41PAYMJ2:1'
23
- @prima_built = false
24
- @urania_built = false
25
- @ermes_built = false
26
- @bburago_built = false
27
- @backoffice_built = false
18
+ if update_gem
19
+ output 'Controllo se ci sono aggiornamenti da fare (potrebbe richiedere qualche minuto)'
20
+ unless `gem update prima-twig`=="Updating installed gems\nNothing to update\n"
21
+ output 'Gemma prima-twig aggiornata'
22
+ exec "twig feature #{ARGV.join ' '}"
23
+ end
24
+ end
28
25
  @dns_record_identifier = nil
29
26
  @ecs_cluster_name = nil
27
+ @deploy_update = false
28
+ @projects = {
29
+ 'prima' => {},
30
+ 'urania' => {},
31
+ 'ermes' => {},
32
+ 'bburago' => {},
33
+ 'hal9000' => {},
34
+ 'fidaty' => {},
35
+ 'peano' => {},
36
+ # 'rogoreport' => {},
37
+ 'assange' => {},
38
+ 'borat' => {},
39
+ 'crash' => {},
40
+ 'activia' => {},
41
+ 'skynet' => {},
42
+ 'roger' => {},
43
+ 'rachele' => {},
44
+ 'leftorium' => {},
45
+ 'pyxis-npm' => {},
46
+ 'starsky' => {},
47
+ 'hutch' => {},
48
+ 'maia' => {},
49
+ 'legion' => {}
50
+ }
51
+ @base_stack_name_alb = 'ecs-alb-http-public-qa-'
52
+ @base_stack_name_alb_ws = 'ecs-alb-ws-public-qa-'
53
+ @git_branch = ''
54
+ @cloudflare = Rubyflare.connect_with(ENV['CLOUDFLARE_EMAIL'], ENV['CLOUDFLARE_APIKEY'])
30
55
  end
31
56
 
32
- def execute! args
57
+ def execute!(args)
33
58
  case args[0]
34
- when "start"
59
+ when 'start'
35
60
  start_feature!
36
- when "finish"
61
+ when 'finish'
37
62
  finish_feature!
38
- when "deploy"
63
+ when 'qainit'
64
+ abort('Non sei nella cartella di qainit') unless Dir.pwd.match 'qainit$' or Dir.pwd.match '/drone/src'
39
65
  if ['terminate', 'stop', 'shutdown', 'halt', 'destroy'].include? args[1]
40
- deploy_shutdown!
66
+ qainit_deploy_shutdown!
67
+ elsif 'update' == args[1]
68
+ qainit_deploy_update!
41
69
  else
42
- deploy_feature!
70
+ if args[1]
71
+ select_branches(args[1..-1])
72
+ else
73
+ select_branches
74
+ end
75
+ qainit_deploy!
76
+ end
77
+ when 'suite'
78
+ abort('Non sei nella cartella di qainit') unless Dir.pwd.match 'qainit$'
79
+ if 'deploy' == args[1]
80
+ suite_py_branches(args[2])
81
+ qainit_deploy!(true)
82
+ end
83
+ when 'deploy'
84
+ abort('Non sei nella cartella di artemide') unless Dir.pwd.match 'artemide$'
85
+ if 'lock' == args[1]
86
+ deploy_lock!
87
+ end
88
+ when 'aggregator'
89
+ if 'enable' == args[1]
90
+ aggregator_enable!
91
+ elsif 'disable' == args[1]
92
+ aggregator_disable!
93
+ else
94
+ stop_for_wrong_args
43
95
  end
44
96
  else
45
- stop_if true, [:wrong_args, ['start', 'finish', 'deploy', 'deploy stop']]
97
+ stop_for_wrong_args
46
98
  end
47
99
  end
48
100
 
101
+ def stop_for_wrong_args
102
+ puts help_content
103
+ stop_if true, [:wrong_args, ['start', 'finish', 'deploy', 'deploy project_name', 'deploy stop', 'deploy update', 'aggregator enable', 'aggregator disable']]
104
+ end
105
+
49
106
  def start_feature!
50
107
  branch_name = @prima.clean_branch_name(ask('Inserisci il nome del branch (puoi omettere feature/): '.cyan))
51
- stop_unless branch_name.length > 0, 'Devi inserire il nome del branch'
108
+ stop_unless !branch_name.empty?, 'Devi inserire il nome del branch'
52
109
  branch_name.prepend 'feature/' unless branch_name.include? 'feature'
53
110
 
54
111
  output "Il nome del branch sarà " + branch_name.yellow
@@ -58,6 +115,135 @@ class Release
58
115
  exec_step "git checkout -b " + branch_name
59
116
  end
60
117
 
118
+ def aggregator_disable!
119
+ output 'Disable aggregator'
120
+
121
+ output "Recupero le informazioni relative al puntamento dei record DNS..."
122
+ output "Recupero le informazioni sui QA attivi..."
123
+ stack_list, envs = get_stacks()
124
+
125
+ env_hash = nil
126
+ unless envs.empty?
127
+ env_hash = envs.detect do |key, tags|
128
+ aggregator_enabled = tags.detect do |tag|
129
+ tag.key === "hostname_pattern_priority" and tag.value === "1"
130
+ end.is_a?(Aws::CloudFormation::Types::Tag)
131
+ aggregator_enabled
132
+ end[0]
133
+ dns_records = @cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {per_page: 100, type: 'CNAME', content: get_alb_host(@base_stack_name_alb + env_hash[3..8])})
134
+ stop_if dns_records.body[:result].empty?, "I record DNS degli aggregatori non stanno puntando ad un QA".red
135
+ change_hostname_priority(env_hash, hostname_pattern_priority())
136
+ dns_to_staging(env_hash)
137
+ else
138
+ output 'Nessun QA trovato'.red
139
+ exit
140
+ end
141
+
142
+ output 'Finito!'.green
143
+ end
144
+
145
+ def aggregator_enable!
146
+ output 'Enable aggregator'
147
+
148
+ output 'Recupero le informazioni relative al puntamento dei record DNS...'
149
+ dns_records = @cloudflare.get('zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records', { per_page: 100, type: 'CNAME', content: 'staging.prima.it' })
150
+ stop_if dns_records.body[:result].empty?, "I record DNS degli aggregatori stanno gia' puntando ad un QA".red
151
+
152
+ output "Recupero le informazioni sui QA attivi..."
153
+ stack_list, envs = get_stacks()
154
+
155
+ env_hash = nil
156
+ unless envs.empty?
157
+ env_hash = choose do |menu|
158
+ menu.prompt = "Scegli il QA al quale vuoi far puntare gli ambienti di staging dei comparatori: ".cyan
159
+ menu.shell = true
160
+ envs.each do |key, env|
161
+ title = ""
162
+ env.each do |e|
163
+ title << "\n#{e.key.upcase}: #{e.value}"
164
+ end
165
+ msg = "#{@prima.reduce_size(title, 1000)}".light_blue
166
+ menu.choice(msg) { key }
167
+ end
168
+ end
169
+ else
170
+ output "Nessun QA trovato".red
171
+ exit
172
+ end
173
+
174
+ change_hostname_priority(env_hash, "1")
175
+
176
+ dns_records.body[:result].each do |dns|
177
+ if dns[:name] =~ /^\w+\-\w+\-staging\.prima\.it$/
178
+ output "Changing #{dns[:name]} DNS record"
179
+ @cloudflare.put("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records/#{dns[:id]}", {type: 'CNAME', name: dns[:name], content: get_alb_host(@base_stack_name_alb + env_hash[3..8]), proxied: true, ttl: 1})
180
+ end
181
+ end
182
+
183
+ output "Finito!".green
184
+ end
185
+
186
+ def change_hostname_priority(env_hash, hostname_pattern_priority)
187
+ cluster_stack_name = "ecs-cluster-#{env_hash}"
188
+ tags = get_stack_tags(cluster_stack_name).map do |tag|
189
+ if tag.key === "hostname_pattern_priority"
190
+ {
191
+ key: "hostname_pattern_priority",
192
+ value: hostname_pattern_priority
193
+ }
194
+ else
195
+ tag
196
+ end
197
+ end
198
+
199
+ stack_list = stack_list()
200
+
201
+ stack_list.each do |stack|
202
+ if stack.stack_name.match(/#{env_hash}$/)
203
+ stack_name = stack.stack_name
204
+ update_stack(stack_name, get_stack_template(stack_name), get_stack_parameters(stack_name), tags)
205
+ end
206
+ end
207
+
208
+ stack_list.each do |stack|
209
+ if stack.stack_name.match(/#{env_hash}$/)
210
+ wait_for_stack_ready(stack.stack_name) unless stack_ready?(stack.stack_name)
211
+ end
212
+ end
213
+
214
+ stack_name_web = "ecs-task-web-#{env_hash}"
215
+ parameters = get_stack_parameters(stack_name_web).map do |param|
216
+ if param.parameter_key === "HostnamePatternPriority"
217
+ {
218
+ parameter_key: "HostnamePatternPriority",
219
+ parameter_value: hostname_pattern_priority
220
+ }
221
+ elsif param.parameter_key === "HostnamePatternAggregatorPriority"
222
+ {
223
+ parameter_key: "HostnamePatternAggregatorPriority",
224
+ parameter_value: (hostname_pattern_priority.to_i + 1).to_s
225
+ }
226
+ else
227
+ param
228
+ end
229
+ end
230
+
231
+ update_stack(stack_name_web, get_stack_template(stack_name_web), parameters)
232
+
233
+ wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
234
+ end
235
+
236
+ def dns_to_staging(env_hash)
237
+ output "Recupero le informazioni relative al puntamento dei record DNS..."
238
+ dns_records = @cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {per_page: 100, type: 'CNAME', content: get_alb_host(@base_stack_name_alb + env_hash[3..8])})
239
+ dns_records.body[:result].each do |dns|
240
+ if dns[:name] =~ /^\w+\-\w+\-staging\.prima\.it$/
241
+ output "Changing #{dns[:name]} DNS record"
242
+ @cloudflare.put("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records/#{dns[:id]}", {type: 'CNAME', name: dns[:name], content: 'staging.prima.it', proxied: true, ttl: 1})
243
+ end
244
+ end
245
+ end
246
+
61
247
  def finish_feature!
62
248
  current_branch_name = @prima.twig.current_branch_name
63
249
  stop_unless (current_branch_name =~ /^feature\//), "Non sei su un branch di feature, non posso mergiare nulla"
@@ -78,11 +264,8 @@ class Release
78
264
  end
79
265
 
80
266
  def deploy_shutdown!
81
- envs = {}
82
- stack_list.each do |stack|
83
- env_hash = stack.stack_name.match(/qa-(\w+)$/)[0]
84
- envs[env_hash] = stack.tags unless envs.has_key?(env_hash)
85
- end
267
+ output "Recupero le informazioni sui QA attivi..."
268
+ stack_list, envs = get_stacks
86
269
 
87
270
  env_hash = nil
88
271
  unless envs.empty?
@@ -91,775 +274,509 @@ class Release
91
274
  menu.shell = true
92
275
 
93
276
  envs.each do |key, env|
94
- title = @prima.reduce_size("#{env[0].key}: #{env[0].value} #{env[1].key}: #{env[1].value} #{env[2].key}: #{env[2].value} #{env[3].key}: #{env[3].value}", 100)
95
- msg = "#{title}".light_blue
277
+ title = ''
278
+ env.each do |e|
279
+ title << "\n#{e.key}: #{e.value} "
280
+ end
281
+ msg = @prima.reduce_size(title, 1000).to_s.light_blue
96
282
  menu.choice(msg) { key }
97
283
  end
98
284
  end
99
285
  else
100
- output "Nessun environment trovato".red
286
+ output 'Nessun environment trovato'.red
101
287
  exit
102
288
  end
103
289
 
104
290
  cluster_stack_name = nil
291
+ stacks_to_delete = []
105
292
  stack_list.each do |stack|
106
293
  if stack.stack_name.match(/#{env_hash}$/)
107
294
  if stack.stack_name.match(/ecs-cluster/)
108
295
  cluster_stack_name = stack.stack_name
109
296
  else
110
- delete_stack(stack.stack_name) if stack.stack_name.match(/#{env_hash}$/)
297
+ break unless stack.stack_name.match(/#{env_hash}$/)
298
+ stacks_to_delete.push(stack.stack_name)
299
+ delete_stack(stack.stack_name)
111
300
  end
112
301
  end
113
302
  end
114
303
 
304
+ cluster_stack_name = "ecs-cluster-#{env_hash}"
305
+ aggregator_enabled = get_stack_tags(cluster_stack_name).detect do |tag|
306
+ tag.key === "hostname_pattern_priority" and tag.value === "1"
307
+ end.is_a?(Aws::CloudFormation::Types::Tag)
308
+
309
+ if aggregator_enabled
310
+ dns_to_staging(env_hash)
311
+ end
312
+
115
313
  # Se non ha finito di cancellare le altre non si puo' cancellare il cluster
116
- output "Attendo 60 secondi per poter eliminare il cluster ECS"
117
- sleep 60
314
+ output "Attendo 10 secondi per poter eliminare il cluster ECS"
315
+
316
+ while stacks_to_delete.length > 0
317
+ sleep 13
318
+ stacks_to_delete.each do |stack_name|
319
+ stacks_to_delete = stacks_to_delete - [stack_name] unless stack_exists?(stack_name)
320
+ end
321
+ output "Stack ancora attivi: #{stacks_to_delete.length.to_s}. Attendo altri 10 secondi per eliminare il cluster ECS"
322
+ end
323
+
118
324
  delete_stack(cluster_stack_name)
325
+ delete_stack(@base_stack_name_alb + env_hash[3..8])
326
+ delete_stack(@base_stack_name_alb_ws + env_hash[3..8])
119
327
  output "Finito!".green
120
328
  end
121
329
 
122
- def deploy_feature!
123
- `sudo true` # cosi' non chiede la password dopo
330
+ def deploy_lock!
331
+ output "Deploy update menu"
124
332
  `git pull && git submodule init && git submodule update`
125
- prima_branch = choose_branch_to_deploy('prima')
126
- backoffice_branch = choose_branch_to_deploy('backoffice')
127
- urania_branch = choose_branch_to_deploy('urania')
128
- ermes_branch = choose_branch_to_deploy('ermes')
129
- bburago_branch = choose_branch_to_deploy('bburago')
130
- socket_branch = {name: "master"}
131
- pamela_branch = {name: "master"}
132
-
133
- @dns_record_identifier = "#{@prima.clean_branch_name(prima_branch[:name])}-#{@prima.clean_branch_name(backoffice_branch[:name])}-#{@prima.clean_branch_name(urania_branch[:name])}-#{@prima.clean_branch_name(ermes_branch[:name])}-#{@prima.clean_branch_name(bburago_branch[:name])}".gsub(/feature./, '')[0..35].gsub(/(-+$)/, '')
134
-
135
- tags = [
136
- {
137
- key: "prima",
138
- value: prima_branch[:name]
139
- },
140
- {
141
- key: "urania",
142
- value: urania_branch[:name]
143
- },
144
- {
145
- key: "backoffice",
146
- value: backoffice_branch[:name]
147
- },
148
- {
149
- key: "ermes",
150
- value: ermes_branch[:name]
151
- },
152
- {
153
- key: "bburago",
154
- value: bburago_branch[:name]
155
- }
156
- ]
157
-
158
- deploy_id = Digest::MD5.hexdigest(prima_branch[:name] + backoffice_branch[:name] + urania_branch[:name] + socket_branch[:name] + pamela_branch[:name] + ermes_branch[:name] + bburago_branch[:name])
159
-
160
- cluster_stack_name = "ecs-cluster-qa-#{deploy_id}"
161
- create_cluster_stack(cluster_stack_name, tags) unless stack_exists?(cluster_stack_name)
162
- wait_for_stack_ready(cluster_stack_name) unless stack_ready?(cluster_stack_name)
163
-
164
- resp = @cf.describe_stack_resource({stack_name: cluster_stack_name, logical_resource_id: 'ECSCluster'})
165
- @ecs_cluster_name = resp.stack_resource_detail.physical_resource_id
166
-
167
- asg_stack_name = "ecs-asg-allinone-qa-#{deploy_id}"
168
- create_asg_stack(asg_stack_name, tags) unless stack_exists?(asg_stack_name)
169
-
170
- stack_name_db = "ecs-task-db-qa-#{deploy_id}"
171
- stack_body = IO.read('cloudformation/stacks/task/db.json')
172
- parameters = [
173
- {
174
- parameter_key: "Environment",
175
- parameter_value: "qa"
176
- },
177
- {
178
- parameter_key: "ECSClusterName",
179
- parameter_value: @ecs_cluster_name
180
- }
181
- ]
182
- create_stack(stack_name_db, stack_body, parameters, tags) unless stack_exists?(stack_name_db)
183
-
184
- create_prima_artifact(prima_branch[:revision], prima_branch[:name]) unless artifact_exists?('prima-artifacts', "prima/#{prima_branch[:revision]}")
185
- create_urania_artifact(urania_branch[:revision]) unless artifact_exists?('prima-artifacts', "microservices/urania/#{urania_branch[:revision]}-qa.tar.gz")
186
- create_ermes_artifact(ermes_branch[:revision]) unless artifact_exists?('prima-artifacts', "microservices/ermes/ermes_#{ermes_branch[:revision]}.tar.gz")
187
- create_bburago_artifact(bburago_branch[:revision]) unless artifact_exists?('prima-artifacts', "microservices/bburago/bburago_#{bburago_branch[:revision]}.tar.gz")
188
- create_backoffice_artifact(backoffice_branch[:revision], deploy_id) unless artifact_exists?('prima-artifacts', "backoffice/#{backoffice_branch[:revision]}-#{deploy_id}.zip")
189
-
190
- wait_for_stack_ready(stack_name_db) unless stack_ready?(stack_name_db)
191
-
192
- import_dbs(ec2_ip_address(asg_stack_name)) unless stack_exists?("ecs-task-web-qa-#{deploy_id}")
193
-
194
- stack_name_web = "ecs-task-web-qa-#{deploy_id}"
195
- git_checkout_version('prima', prima_branch[:revision])
196
- stack_body = IO.read('projects/prima/app/cloudformation/tasks/web.json')
197
- parameters = [
198
- {
199
- parameter_key: "Environment",
200
- parameter_value: "qa"
201
- },
202
- {
203
- parameter_key: "ReleaseVersion",
204
- parameter_value: prima_branch[:revision]
205
- },
206
- {
207
- parameter_key: "TaskDesiredCount",
208
- parameter_value: "1"
209
- },
210
- {
211
- parameter_key: "ECSClusterName",
212
- parameter_value: @ecs_cluster_name
213
- }
214
- ]
215
- if stack_exists?(stack_name_web)
216
- update_stack(stack_name_web, stack_body, parameters) if @prima_built
217
- else
218
- create_stack(stack_name_web, stack_body, parameters, tags)
219
- end
220
-
221
- stack_name_consumer = "ecs-task-consumer-qa-#{deploy_id}"
222
- git_checkout_version('prima', prima_branch[:revision])
223
- stack_body = IO.read('projects/prima/app/cloudformation/tasks/consumer.json')
224
- parameters = [
225
- {
226
- parameter_key: "Environment",
227
- parameter_value: "qa"
228
- },
229
- {
230
- parameter_key: "ReleaseVersion",
231
- parameter_value: prima_branch[:revision]
232
- },
233
- {
234
- parameter_key: "ECSClusterName",
235
- parameter_value: @ecs_cluster_name
236
- }
237
- ]
238
- if stack_exists?(stack_name_consumer)
239
- update_stack(stack_name_consumer, stack_body, parameters) if @prima_built
240
- else
241
- create_stack(stack_name_consumer, stack_body, parameters, tags)
242
- end
243
-
244
- stack_name_urania = "ecs-task-urania-qa-#{deploy_id}"
245
- git_checkout_version('urania', urania_branch[:revision])
246
- stack_body = IO.read('projects/urania/deploy/task.json')
247
- parameters = [
248
- {
249
- parameter_key: "Environment",
250
- parameter_value: "qa"
251
- },
252
- {
253
- parameter_key: "ReleaseVersion",
254
- parameter_value: urania_branch[:revision]
255
- },
256
- {
257
- parameter_key: "TaskDesiredCount",
258
- parameter_value: "1"
259
- },
260
- {
261
- parameter_key: "ECSClusterName",
262
- parameter_value: @ecs_cluster_name
263
- }
264
- ]
265
- if stack_exists?(stack_name_urania)
266
- update_stack(stack_name_urania, stack_body, parameters) if @urania_built
267
- else
268
- create_stack(stack_name_urania, stack_body, parameters, tags)
269
- end
270
-
271
- stack_name_ermes = "ecs-task-ermes-qa-#{deploy_id}"
272
- git_checkout_version('ermes', ermes_branch[:revision])
273
- stack_body = IO.read('projects/ermes/deploy/task.json')
274
- parameters = [
275
- {
276
- parameter_key: "Environment",
277
- parameter_value: "qa"
278
- },
279
- {
280
- parameter_key: "ReleaseVersion",
281
- parameter_value: ermes_branch[:revision]
282
- },
283
- {
284
- parameter_key: "ECSClusterName",
285
- parameter_value: @ecs_cluster_name
286
- }
287
- ]
288
- if stack_exists?(stack_name_ermes)
289
- update_stack(stack_name_ermes, stack_body, parameters) if @ermes_built
290
- else
291
- create_stack(stack_name_ermes, stack_body, parameters, tags)
292
- end
293
-
294
- stack_name_bburago = "ecs-task-bburago-qa-#{deploy_id}"
295
- git_checkout_version('bburago', bburago_branch[:revision])
296
- stack_body = IO.read('projects/bburago/deploy/task.json')
297
- parameters = [
298
- {
299
- parameter_key: "Environment",
300
- parameter_value: "qa"
301
- },
302
- {
303
- parameter_key: "ReleaseVersion",
304
- parameter_value: bburago_branch[:revision]
305
- },
306
- {
307
- parameter_key: "ECSClusterName",
308
- parameter_value: @ecs_cluster_name
309
- },
310
- {
311
- parameter_key: "TaskDesiredCount",
312
- parameter_value: "1"
313
- }
314
- ]
315
- if stack_exists?(stack_name_bburago)
316
- update_stack(stack_name_bburago, stack_body, parameters) if @bburago_built
317
- else
318
- create_stack(stack_name_bburago, stack_body, parameters, tags)
319
- end
320
-
321
- git_checkout_version('backoffice', backoffice_branch[:revision])
322
- stack_name_backoffice = "ecs-task-backoffice-qa-#{deploy_id}"
323
- stack_body = IO.read('projects/backoffice/deploy/task.json')
324
- parameters = [
325
- {
326
- parameter_key: "Environment",
327
- parameter_value: "qa"
328
- },
329
- {
330
- parameter_key: "ReleaseVersion",
331
- parameter_value: "#{backoffice_branch[:revision]}-#{deploy_id}"
332
- },
333
- {
334
- parameter_key: "TaskDesiredCount",
335
- parameter_value: "1"
336
- },
337
- {
338
- parameter_key: "ECSClusterName",
339
- parameter_value: @ecs_cluster_name
340
- }
341
- ]
342
- if stack_exists?(stack_name_backoffice)
343
- update_stack(stack_name_backoffice, stack_body, parameters) if @backoffice_built
344
- else
345
- create_stack(stack_name_backoffice, stack_body, parameters, tags)
346
- end
347
333
 
348
- wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
349
- wait_for_stack_ready(stack_name_consumer) unless stack_ready?(stack_name_consumer)
350
- wait_for_stack_ready(stack_name_urania) unless stack_ready?(stack_name_urania)
351
- wait_for_stack_ready(stack_name_backoffice) unless stack_ready?(stack_name_backoffice)
352
- wait_for_stack_ready(stack_name_ermes) unless stack_ready?(stack_name_ermes)
353
- wait_for_stack_ready(stack_name_bburago) unless stack_ready?(stack_name_bburago)
354
-
355
- update_service_defaults(stack_name_web)
356
- update_service_defaults(stack_name_consumer)
357
- update_service_defaults(stack_name_urania)
358
- update_service_defaults(stack_name_backoffice)
359
- update_service_defaults(stack_name_ermes)
360
- update_service_defaults(stack_name_bburago)
361
-
362
- stack_name_route53 = "ecs-route53-qa-#{deploy_id}"
363
- stack_body = IO.read('cloudformation/stacks/route53/qa.json')
364
- parameters = [
365
- {
366
- parameter_key: "DnsRecordIdentifier",
367
- parameter_value: @dns_record_identifier
368
- },
369
- {
370
- parameter_key: "PrimaElbHostname",
371
- parameter_value: get_elb_host(stack_name_web)
372
- },
373
- {
374
- parameter_key: "BackofficeElbHostname",
375
- parameter_value: get_elb_host(stack_name_backoffice)
376
- },
377
- {
378
- parameter_key: "UraniaElbHostname",
379
- parameter_value: get_elb_host(stack_name_urania)
380
- },
381
- {
382
- parameter_key: "BburagoElbHostname",
383
- parameter_value: get_elb_host(stack_name_bburago)
384
- }
385
- ]
386
- create_stack(stack_name_route53, stack_body, parameters, tags) unless stack_exists?(stack_name_route53)
387
-
388
- prima_hostname = get_route53_hostname(stack_name_web)
389
- urania_hostname = get_route53_hostname(stack_name_urania)
390
- bburago_hostname = get_route53_hostname(stack_name_bburago)
391
- backoffice_hostname = get_route53_hostname(stack_name_backoffice)
392
-
393
- wait_for_stack_ready(stack_name_route53) unless stack_ready?(stack_name_route53)
394
-
395
- output "Prima url: #{prima_hostname}\n".cyan
396
- output "Urania url: #{urania_hostname}\n".cyan
397
- output "Backoffice url: #{backoffice_hostname}\n".cyan
398
- output "Bburago url: #{bburago_hostname}\n".cyan
399
- output "SSH connection: ssh ec2-user@#{ec2_ip_address(asg_stack_name)} -i ~/.ssh/ecs-cluster-qa.pem".cyan
400
- output "Deploy effettuato, everything is awesome!\n".green
401
- end
402
-
403
- def get_route53_hostname(stack_name)
404
- case
405
- when stack_name.include?('web')
406
- host = "www.#{@dns_record_identifier}.qa.colaster.com"
407
- when stack_name.include?('urania')
408
- host = "urania.#{@dns_record_identifier}.qa.colaster.com"
409
- when stack_name.include?('backoffice')
410
- host = "backoffice.#{@dns_record_identifier}.qa.colaster.com"
411
- when stack_name.include?('bburago')
412
- host = "bburago.#{@dns_record_identifier}.qa.colaster.com"
413
- end
414
- host
415
- end
334
+ @deploy_update = true
416
335
 
417
- def ec2_ip_address(asg_stack_name)
418
- resp = @cf.describe_stack_resource({
419
- stack_name: asg_stack_name,
420
- logical_resource_id: 'ECSAutoScalingGroup'
421
- })
422
- resp = @asg.describe_auto_scaling_groups({
423
- auto_scaling_group_names: [resp.stack_resource_detail.physical_resource_id],
424
- max_records: 1
425
- })
426
- instance_id = resp.auto_scaling_groups[0].instances[0].instance_id
427
- resp = @ec2.describe_instances({instance_ids: [instance_id]})
428
- resp.reservations[0].instances[0].private_ip_address
429
- end
336
+ output "Recupero le informazioni sui QA attivi..."
337
+ stack_list, envs = get_clusters()
430
338
 
431
- def get_elb_host(stack_name)
432
- case
433
- when stack_name.include?('web')
434
- logical_resource_id = 'EcsElasticLoadBalancerPublic'
435
- when stack_name.include?('urania')
436
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
437
- when stack_name.include?('backoffice')
438
- logical_resource_id = 'EcsElasticLoadBalancerPublic'
439
- when stack_name.include?('bburago')
440
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
339
+ env_hash = nil
340
+ unless envs.empty?
341
+ env_hash = choose do |menu|
342
+ menu.prompt = "Scegli il QA che vuoi proteggere dallo spegnimento automatico: ".cyan
343
+ menu.shell = true
344
+ envs.each do |key, env|
345
+ title = ""
346
+ env.each do |e|
347
+ title << "#{e.value}" if e.key == 'qainit'
348
+ end
349
+ msg = "#{@prima.reduce_size(title, 1000)}".light_blue
350
+ menu.choice(msg) { key }
351
+ end
352
+ end
353
+ else
354
+ output "Nessun QA trovato".red
355
+ exit
441
356
  end
442
- resp = @cf.describe_stack_resource({
443
- stack_name: stack_name,
444
- logical_resource_id: logical_resource_id
445
- })
446
- resp = @elb.describe_load_balancers({
447
- load_balancer_names: [resp.stack_resource_detail.physical_resource_id],
448
- page_size: 1
449
- })
450
- resp.load_balancer_descriptions[0].dns_name
451
- end
452
357
 
453
- def update_service_defaults(stack_name)
454
- case
455
- when stack_name.include?('web')
456
- logical_resource_id = 'ECSServiceWeb'
457
- when stack_name.include?('consumer')
458
- logical_resource_id = 'ECSServiceConsumer'
459
- when stack_name.include?('urania')
460
- logical_resource_id = 'ECSServiceUrania'
461
- when stack_name.include?('backoffice')
462
- logical_resource_id = 'ECSServiceBackoffice'
463
- when stack_name.include?('ermes')
464
- logical_resource_id = 'ECSServiceErmes'
465
- when stack_name.include?('bburago')
466
- logical_resource_id = 'ECSServiceBburago'
467
- else
468
- raise "Service name non gestito per lo stack #{stack_name}"
469
- end
470
- resp = @cf.describe_stack_resource({
471
- stack_name: stack_name,
472
- logical_resource_id: logical_resource_id
473
- })
474
- resp = @ecs.update_service({
475
- cluster: @ecs_cluster_name,
476
- service: resp.stack_resource_detail.physical_resource_id,
477
- deployment_configuration: {
478
- minimum_healthy_percent: 0,
479
- maximum_percent: 100
480
- }
481
- })
482
- end
483
-
484
- def create_urania_artifact(revision)
485
- @urania_built = true
486
- output "Preparo l'artifact .zip\n".yellow
487
-
488
- git_checkout_version('urania', revision)
489
-
490
- Dir.chdir 'projects/urania'
491
-
492
- [
493
- "docker-compose build web",
494
- "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh urania_web \
495
- '-c' 'mix local.hex --force && mix hex.info && \
496
- mix deps.get && mix compile && mix deps.compile && \
497
- mix release.clean --implode --no-confirm && mix release'",
498
- "sudo chown -R `whoami` ."
499
- ].each do |cmd|
500
- output "Eseguo #{cmd}".yellow
501
- res = %x[ #{cmd} ]
502
- if $?.exitstatus != 0
503
- color = 'red'
504
- else
505
- color = 'green'
506
- end
507
- output res.send color
508
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
358
+ cluster_stack_name = "ecs-cluster-#{env_hash}"
359
+ if stack_exists?(cluster_stack_name)
360
+ tags = get_stack_tags(cluster_stack_name)
361
+ tag_keep_data = Aws::CloudFormation::Types::Tag.new({key:'AUTOMATIC_DELETION_PROTECTION', value:'true'})
362
+ tags.push tag_keep_data
509
363
  end
510
364
 
511
- artifact_path = Dir.glob("rel/urania/releases/*/urania.tar.gz").first
512
- upload_artifact(artifact_path, "microservices/urania/#{revision}-qa.tar.gz")
365
+ update_cluster_stack(cluster_stack_name, tags)
513
366
 
514
- Dir.chdir '../../'
367
+ output "Finito!".green
515
368
  end
516
369
 
517
- def create_ermes_artifact(revision)
518
- @ermes_built = true
519
- output "Preparo l'artifact .zip\n".yellow
370
+ def deploy_update!
371
+ output "Deploy update menu"
372
+ `git pull && git submodule init && git submodule update`
520
373
 
521
- git_checkout_version('ermes', revision)
374
+ @deploy_update = true
522
375
 
523
- Dir.chdir 'projects/ermes'
376
+ output "Recupero le informazioni sui QA attivi..."
377
+ stack_list, envs = get_stacks()
524
378
 
525
- [
526
- "docker-compose build app",
527
- "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh ermes_app \
528
- '-c' 'mix local.hex --force && mix hex.info && \
529
- mix deps.get && mix compile && mix deps.compile && \
530
- mix release.clean --implode --no-confirm && mix release'",
531
- "sudo chown -R `whoami` ."
532
- ].each do |cmd|
533
- output "Eseguo #{cmd}".yellow
534
- res = %x[ #{cmd} ]
535
- if $?.exitstatus != 0
536
- color = 'red'
537
- else
538
- color = 'green'
379
+ env_hash = nil
380
+ unless envs.empty?
381
+ env_hash = choose do |menu|
382
+ menu.prompt = "Scegli il QA che vuoi aggiornare: ".cyan
383
+ menu.shell = true
384
+ envs.each do |key, env|
385
+ title = ""
386
+ env.each do |e|
387
+ title << "\n#{e.key.upcase}: #{e.value}"
388
+ end
389
+ msg = "#{@prima.reduce_size(title, 1000)}".light_blue
390
+ menu.choice(msg) { key }
391
+ end
539
392
  end
540
- output res.send color
541
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
393
+ else
394
+ output "Nessun QA trovato".red
395
+ exit
542
396
  end
543
397
 
544
- artifact_path = Dir.glob("rel/ermes/releases/*/ermes.tar.gz").first
545
- upload_artifact(artifact_path, "microservices/ermes/ermes_#{revision}.tar.gz")
398
+ envs[env_hash].each do |env|
399
+ unless ['hostname_pattern_priority', 'AUTOMATIC_DELETION_PROTECTION'].include? env.key
400
+ @projects[env.key] = select_branch_to_deploy(env.key, env.value)
401
+ end
402
+ end
403
+ deploy_feature!
546
404
 
547
- Dir.chdir '../../'
405
+ output "Finito!".green
548
406
  end
549
407
 
550
- def create_bburago_artifact(revision)
551
- @bburago_built = true
552
- output "Preparo l'artifact .zip\n".yellow
408
+ def get_default_branch_name(projects)
409
+ projects.each_key do |project|
410
+ return projects[project]['name'] if not projects[project]['default_branch']
411
+ end
412
+ end
553
413
 
554
- git_checkout_version('bburago', revision)
414
+ def suite_py_branches(args_json)
415
+ arg_projects = JSON.parse(args_json)
555
416
 
556
- Dir.chdir 'projects/bburago'
417
+ @projects.merge!(arg_projects)
557
418
 
558
- [
559
- "docker-compose build web",
560
- "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh bburago_web \
561
- '-c' 'mix local.hex --force && mix hex.info && \
562
- mix deps.get && mix compile && mix deps.compile && \
563
- mix release.clean --implode --no-confirm && mix release'",
564
- "sudo chown -R `whoami` ."
565
- ].each do |cmd|
566
- output "Eseguo #{cmd}".yellow
567
- res = %x[ #{cmd} ]
568
- if $?.exitstatus != 0
569
- color = 'red'
570
- else
571
- color = 'green'
419
+ @projects.each_key do |project|
420
+ if @projects[project].empty?
421
+ @projects[project] = choose_branch_to_deploy(project, true)
572
422
  end
573
- output res.send color
574
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
575
423
  end
424
+ end
576
425
 
577
- artifact_path = Dir.glob("rel/bburago/releases/*/bburago.tar.gz").first
578
- upload_artifact(artifact_path, "microservices/bburago/bburago_#{revision}.tar.gz")
426
+ def get_git_user()
427
+ `git config user.name`.gsub(/[^A-Za-z]/, '').gsub("\n", '')
428
+ end
579
429
 
580
- Dir.chdir '../../'
430
+ def get_git_mail()
431
+ `git config user.email`.gsub("\n", '')
581
432
  end
582
433
 
583
- def create_backoffice_artifact(revision, deploy_id)
584
- @backoffice_built = true
585
- output "Preparo l'artifact .zip\n".yellow
434
+ def qainit_deploy!(quiet = false)
435
+ `git checkout master && git pull && git submodule update --init --recursive && git remote prune origin`
586
436
 
587
- git_checkout_version('backoffice', revision)
437
+ default_name = get_default_branch_name @projects
438
+ feature_number = ''
439
+ unless quiet
440
+ output "Inserisci la feature a cui si riferisce il QA: [#{default_name}]".cyan
441
+ feature_number = String(STDIN.gets.chomp)
442
+ end
443
+ feature_number = default_name if feature_number.empty?
444
+ branch_name = get_git_user + '_' + feature_number
588
445
 
589
- Dir.chdir 'projects/backoffice'
446
+ if `git branch -l | grep #{branch_name}`.size > 0
447
+ `git checkout #{branch_name} && git pull`
448
+ else
449
+ `git checkout -b #{branch_name}`
450
+ end
590
451
 
591
- ['node_modules'].each do |dir|
592
- unless File.directory?(dir)
593
- if File.directory?("../../../backoffice/#{dir}")
594
- exec_step "rsync -a ../../../backoffice/#{dir} ."
595
- end
452
+ @git_branch = branch_name
453
+
454
+ File.open('branch_names', 'w') { |file| file.write(JSON.generate(@projects)) }
455
+
456
+ update_drone_yml!
457
+
458
+ `git add projects && \
459
+ git add branch_names .drone.yml && \
460
+ git commit -m '#{branch_name}' && \
461
+ git push -f --set-upstream origin #{branch_name} && \
462
+ git checkout master`
463
+ end
464
+
465
+ def qainit_deploy_update!
466
+ `git checkout master && git pull`
467
+ # cancelliamo tutti i branch che non sono più sul repo remoto
468
+ `git fetch -p && for branch in \`git branch -vv | grep ': gone]' | awk '{print $1}'\`; do git branch -D $branch; done`
469
+ # leggiamo i nomi dei branch superstiti
470
+ former_branches = `git branch -a | grep remotes/ | grep -v HEAD | sed 's/ remotes\\/origin\\///g'`.split "\n"
471
+ git_user = get_git_user
472
+ # stampiamo la lista
473
+ chosen_branch = choose do |menu|
474
+ menu.prompt = "Scegli il QA che vuoi aggiornare: ".cyan
475
+ menu.shell = true
476
+ former_branches.delete('master')
477
+ former_branches.each_with_index do |branch, index|
478
+ msg = index.odd? ? branch.white : branch.light_yellow # uno bianco e uno giallo alternati
479
+ msg = branch.start_with?(git_user) ? msg.on_blue : msg.on_black # i branch creati da chi lancia l'update sono su sfondo più chiaro
480
+ menu.choice(msg) { branch }
596
481
  end
597
482
  end
483
+ # checkout master, checkout branch, pull branch
484
+ `git checkout master && git checkout #{chosen_branch} && git pull`
598
485
 
599
- stack_name_web = "ecs-task-web-qa-notneeded"
600
- web_qa_host = get_route53_hostname(stack_name_web)
486
+ # aggiornare il commit (revision a cui fa riferimento)
601
487
 
602
- [
603
- "docker-compose build workers",
604
- "cd ../../ && docker run -e GIT_DIR=$PWD -v $PWD:/usr/app/src -w /usr/app/src/projects/backoffice blinkmobile/bower install --allow-root",
605
- "docker run -v $PWD:/code -w /code -e PHANTOMJS_BIN=/code/node_modules/grunt-selenium-webdriver/node_modules/phantomjs/bin/phantomjs --entrypoint /bin/bash backoffice_workers '-c' 'sed -i \"s/web-qa-url/#{web_qa_host}/g\" Gruntfile.js && npm install && grunt qa'",
606
- "sudo chown -R `whoami` ."
607
- ].each do |cmd|
608
- output "Eseguo #{cmd}".yellow
609
- res = %x[ #{cmd} ]
610
- if $?.exitstatus != 0
611
- color = 'red'
612
- else
613
- color = 'green'
488
+ # leggo il file branch_names / recupero i nomi dei branch / riscrivo tutto
489
+ projects = ''
490
+ File.open('branch_names', 'r') do |file|
491
+ file.each_line do |line|
492
+ projects = JSON.parse(line)
614
493
  end
615
- output res.send color
616
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
617
494
  end
618
495
 
619
- artifact_path = '/tmp/backoffice.zip'
620
- exec_step "rm -f #{artifact_path} && zip -9 -r #{artifact_path} bin/"
621
- upload_artifact(artifact_path, "backoffice/#{revision}-#{deploy_id}.zip")
496
+ projects.each do |key, project|
497
+ @projects[key] = select_branch_to_deploy(key, project['name'])
498
+ @projects[key]['default_branch'] = project['default_branch']
499
+ end
500
+
501
+ File.open('branch_names', 'w') { |file| file.write(JSON.generate(@projects)) }
622
502
 
623
- Dir.chdir '../../'
503
+ update_drone_yml!
504
+
505
+ `git add branch_names .drone.yml`
506
+ `git commit -m 'update'`
507
+ `git push && git checkout master`
624
508
  end
625
509
 
626
- def create_prima_artifact(revision, branch_name)
627
- @prima_built = true
628
- output "Preparo l'artifact .zip\n".yellow
510
+ def qainit_deploy_shutdown!(selection = nil)
511
+ `git checkout master && git pull && git remote prune origin`
512
+ # leggiamo i nomi dei branch
513
+ former_branches = `git branch -a | grep remotes/ | grep -v HEAD | sed 's/ remotes\\/origin\\///g'`.split "\n"
514
+ if selection.nil?
515
+ # stampiamo la lista
516
+ chosen_branch = choose do |menu|
517
+ menu.prompt = "Scegli il QA che vuoi spegnere: ".cyan
518
+ menu.shell = true
519
+ git_user = get_git_user
520
+ former_branches.delete('master')
521
+ former_branches.each_with_index do |branch, index|
522
+ msg = index.odd? ? branch.white : branch.light_yellow # uno bianco e uno giallo alternati
523
+ msg = branch.start_with?(git_user) ? msg.on_blue : msg.on_black # i branch creati da chi lancia l'update sono su sfondo blu
524
+ menu.choice(msg) { branch }
525
+ end
526
+ end
527
+ else
528
+ chosen_branch = selection
529
+ end
530
+ # checkout master, checkout branch, pull branch, push sul branch con commit vuoto
531
+ `git checkout master && git checkout #{chosen_branch} && git pull`
532
+ `git commit --allow-empty -m 'shutdown' && git push && git checkout master`
533
+ end
629
534
 
630
- git_checkout_version('prima', revision)
535
+ def qainit_drone_shutdown!
536
+ output "Recupero le informazioni sui QA attivi..."
537
+ stack_list, envs = get_stacks
631
538
 
632
- Dir.chdir 'projects/prima'
539
+ env_hash = "qa-" + get_deploy_id
633
540
 
634
- ['vendor'].each do |dir|
635
- unless File.directory?(dir)
636
- if File.directory?("../../../prima/#{dir}")
637
- exec_step "rsync -a ../../../prima/#{dir} ."
541
+ cluster_stack_name = nil
542
+ stacks_to_delete = []
543
+ stack_list.each do |stack|
544
+ if stack.stack_name.match(/#{env_hash}$/)
545
+ if stack.stack_name.match(/ecs-cluster/)
546
+ cluster_stack_name = stack.stack_name
547
+ else
548
+ break unless stack.stack_name.match(/#{env_hash}$/)
549
+ stacks_to_delete.push(stack.stack_name)
550
+ delete_stack(stack.stack_name)
638
551
  end
639
552
  end
640
553
  end
641
554
 
642
- stack_name_backoffice = "ecs-task-backoffice-qa-notneeded"
643
- backoffice_qa_host = get_route53_hostname(stack_name_backoffice)
555
+ cluster_stack_name = "ecs-cluster-#{env_hash}"
556
+ if stack_exists?(cluster_stack_name)
557
+ aggregator_enabled = get_stack_tags(cluster_stack_name).detect do |tag|
558
+ tag.key === "hostname_pattern_priority" and tag.value === "1"
559
+ end.is_a?(Aws::CloudFormation::Types::Tag)
644
560
 
645
- [
646
- "bin/local_build_artifact.sh #{branch_name}"
647
- ].each do |cmd|
648
- output "Eseguo #{cmd}".yellow
649
- res = %x[ #{cmd} ]
650
- if $?.exitstatus != 0
651
- color = 'red'
652
- else
653
- color = 'green'
561
+ if aggregator_enabled
562
+ dns_to_staging(env_hash)
654
563
  end
655
- output res.send color
656
- exec_step "docker stop redis" if color == 'red'
657
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
658
564
  end
659
565
 
660
- Dir.chdir "../../"
661
- end
566
+ # Se non ha finito di cancellare le altre non si puo' cancellare il cluster
567
+ output "Attendo 10 secondi per poter eliminare il cluster ECS"
662
568
 
663
- def git_checkout_version(project, revision)
664
- Dir.chdir "projects/#{project}"
665
- exec_step "git checkout -- . && git clean -f -d && git checkout #{revision}"
666
- Dir.chdir "../../"
569
+ while stacks_to_delete.length > 0
570
+ sleep 13
571
+ stacks_to_delete.each do |stack_name|
572
+ stacks_to_delete = stacks_to_delete - [stack_name] unless stack_exists?(stack_name)
573
+ end
574
+ output "Stack ancora attivi: #{stacks_to_delete.length.to_s}. Attendo altri 10 secondi per eliminare il cluster ECS"
575
+ end
576
+
577
+ delete_stack(cluster_stack_name) if stack_exists?(cluster_stack_name)
578
+ delete_stack(@base_stack_name_alb + env_hash[3..8]) if stack_exists?(@base_stack_name_alb + env_hash[3..8])
579
+ delete_stack(@base_stack_name_alb_ws + env_hash[3..8]) if stack_exists?(@base_stack_name_alb_ws + env_hash[3..8])
580
+ `git checkout master && git push origin --delete ${DRONE_BRANCH}`
581
+ output "Cancello il record DNS utilizzato da Lighthouse"
582
+ delete_lighthouse_dns()
583
+ output "Finito!".green
667
584
  end
668
585
 
669
- def upload_artifact(source_path, destination_path)
670
- output "Upload dell'artifact in corso (#{(File.size(source_path).to_f / 2**20).round(2)} MiB)\n".yellow
671
- s3 = Aws::S3::Resource.new
672
- obj = s3.bucket(@s3_bucket).object(destination_path)
673
- obj.upload_file(source_path)
586
+ def qainit_write_output(file_message, output_message)
587
+ `mkdir -p /etc/qainit-output`
588
+ qa_file_name = "/etc/qainit-output/url_qa"
589
+ File.open(qa_file_name + '.txt', 'w') { |file| file.write(file_message) }
590
+ output "#{output_message} #{qa_file_name}".green
591
+ end
674
592
 
675
- output "#{@s3_bucket}/#{destination_path} uploadato con successo!\n".green
593
+ def update_drone_yml!()
594
+ drone_yml = File.read('.drone.yml')
595
+ @projects.each do |key, project|
596
+ drone_yml = drone_yml.gsub(/#{key}@.+\n/, "#{key}@#{project['revision']}\n")
597
+ end
598
+ File.open(".drone.yml", "w") do |f|
599
+ f.write(drone_yml)
600
+ end
676
601
  end
677
602
 
678
- def wait_for_stack_ready(stack_name)
679
- ready = false
680
- sleep_seconds = 10
681
- output "Attendo che lo stack #{stack_name} finisca di essere inizializzato...\n".yellow
682
- while !ready
683
- ready = true if stack_ready?(stack_name)
684
- seconds_elapsed = 0
685
- while true
686
- break if seconds_elapsed >= sleep_seconds
687
- print '.'.yellow; STDOUT.flush
688
- sleep 1
689
- seconds_elapsed += 1
690
- end
603
+ def get_deploy_id
604
+ if @deploy_id
605
+ @deploy_id
606
+ else
607
+ @deploy_id = Digest::MD5.hexdigest(ENV['DRONE_BRANCH'])
608
+ @deploy_id
691
609
  end
610
+ end
692
611
 
693
- output "\nStack #{stack_name} pronto!\n".green
694
- end
695
-
696
- def stack_list
697
- resp = @cf.describe_stacks
698
- stacks = resp.stacks
699
- stacks.keep_if { |stack| stack.stack_name.include? '-qa-' }
700
- stacks
701
- end
702
-
703
- def delete_stack(stack_name)
704
- @cf.delete_stack({stack_name: stack_name})
705
- output "Stack #{stack_name} spenta con successo\n".green
706
- end
707
-
708
- def stack_ready?(stack_name)
709
- resp = @cf.describe_stacks({
710
- stack_name: stack_name
711
- })
712
- ['CREATE_COMPLETE', 'UPDATE_COMPLETE'].include? resp.stacks[0].stack_status
713
- end
714
-
715
- def create_asg_stack(stack_name, tags = [])
716
- pp @ecs_cluster_name
717
-
718
- stack_body = IO.read('cloudformation/stacks/asg/ecs-asg-allinone.json')
719
- parameters = [
720
- {
721
- parameter_key: "Environment",
722
- parameter_value: "qa"
723
- },
724
- {
725
- parameter_key: "InstanceType",
726
- parameter_value: "t2.large"
727
- },
728
- {
729
- parameter_key: "ECSClusterName",
730
- parameter_value: @ecs_cluster_name
731
- }
732
- ]
733
- create_stack(stack_name, stack_body, parameters, tags)
734
- end
735
-
736
- def create_cluster_stack(stack_name, tags = [])
737
- stack_body = IO.read('cloudformation/stacks/ecs-cluster.json')
738
- create_stack(stack_name, stack_body, [], tags)
739
- end
740
-
741
- def import_dbs(ip_address)
742
- resp = @ecs.run_task({
743
- cluster: @ecs_cluster_name,
744
- task_definition: @import_db_task,
745
- overrides: {
746
- container_overrides: [
747
- {
748
- name: 'dbrestore',
749
- environment: [
750
- {
751
- name: 'EC2_IP_ADDRESS',
752
- value: ip_address,
753
- }
754
- ]
755
- }
756
- ]
757
- },
758
- count: 1
759
- })
760
- output "Attendo che i DB vengano importati...\n".yellow
761
- stopped_at = nil
762
- while stopped_at.nil?
763
- resp = @ecs.describe_tasks({
764
- cluster: @ecs_cluster_name,
765
- tasks: [resp.tasks[0].task_arn]
766
- })
767
- stopped_at = resp.tasks[0].stopped_at
768
- sleep_seconds = 10
769
- seconds_elapsed = 0
770
- while true && stopped_at.nil?
771
- break if seconds_elapsed >= sleep_seconds
772
- print '.'.yellow; STDOUT.flush
773
- sleep 1
774
- seconds_elapsed += 1
775
- end
612
+ def get_alb_host(stack_name)
613
+ case
614
+ when stack_name.include?('web')
615
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
616
+ when stack_name.include?('urania')
617
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
618
+ when stack_name.include?('backoffice')
619
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
620
+ when stack_name.include?('bburago')
621
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
622
+ when stack_name.include?('hal9000')
623
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
624
+ when stack_name.include?('fidaty')
625
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
626
+ when stack_name.include?('activia')
627
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
628
+ when stack_name.include?('skynet')
629
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
630
+ when stack_name.include?('roger')
631
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
632
+ when stack_name.include?('alb-http-public')
633
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
634
+ when stack_name.include?('alb-ws-public')
635
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
636
+ when stack_name.include?('peano')
637
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
638
+ when stack_name.include?('leftorium')
639
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
640
+ when stack_name.include?('assange')
641
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
642
+ when stack_name.include?('borat')
643
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
644
+ when stack_name.include?('crash')
645
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
646
+ when stack_name.include?('rachele')
647
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
648
+ when stack_name.include?('starsky')
649
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
650
+ when stack_name.include?('hutch')
651
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
652
+ when stack_name.include?('maia')
653
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
654
+ when stack_name.include?('legion')
655
+ logical_resource_id = 'EcsApplicationLoadBalancerInternal'
776
656
  end
777
- print "\n"
657
+ resp = describe_stack_resource(stack_name, logical_resource_id)
658
+ resp = describe_load_balancers([resp.stack_resource_detail.physical_resource_id])
659
+ resp.load_balancers[0].dns_name
778
660
  end
779
661
 
780
- def stack_exists?(stack_name)
781
- begin
782
- res = @cf.describe_stacks({
783
- stack_name: stack_name
784
- })
785
- rescue Aws::CloudFormation::Errors::ValidationError => e
786
- if e.message.include? 'does not exist'
787
- false
788
- else
789
- raise e
790
- end
791
- else
792
- true
793
- end
794
- end
795
-
796
- def create_stack(stack_name, stack_body, parameters = [], tags = [])
797
- @cf.create_stack({
798
- stack_name: stack_name,
799
- template_body: stack_body,
800
- parameters: parameters,
801
- tags: tags,
802
- capabilities: ["CAPABILITY_IAM"],
803
- on_failure: "ROLLBACK"
804
- })
805
- output "La creazione dello stack #{stack_name} è stata avviata".green
806
- end
807
-
808
- def update_stack(stack_name, stack_body, parameters = [])
809
- begin
810
- @cf.update_stack({
811
- stack_name: stack_name,
812
- template_body: stack_body,
813
- parameters: parameters,
814
- capabilities: ["CAPABILITY_IAM"]
815
- })
816
- rescue Aws::CloudFormation::Errors::ValidationError => e
817
- # if e.message.include? 'does not exist'
818
- # false
819
- # else
820
- # raise e
821
- # end
822
- raise e
662
+ def deploy_pyxis?
663
+ if defined? @deploy_pyxis
664
+ @deploy_pyxis
823
665
  else
824
- output "L'update dello stack #{stack_name} è stato avviato".green
666
+ pyxis_updated = `git log -p -1 --unified=0 | grep pyxis-npm:`.length > 0
667
+
668
+ update_pyxis = !@projects['pyxis-npm'].empty? && @projects['pyxis-npm']['name'] != 'master' && pyxis_updated
669
+
670
+ @deploy_pyxis = update_pyxis
671
+ return update_pyxis
825
672
  end
826
673
  end
827
674
 
828
- def artifact_exists?(bucket, path)
829
- resp = @s3.list_objects({
830
- bucket: bucket,
831
- max_keys: 1,
832
- prefix: path
833
- })
834
- !resp.contents.empty?
675
+ def update_cluster_stack(stack_name, tags = [])
676
+ stack_body = IO.read('cloudformation/stacks/ecs-cluster.yml')
677
+ update_stack(stack_name, stack_body, [], tags)
835
678
  end
836
679
 
837
- def choose_branch_to_deploy(project_name)
680
+ def choose_branch_to_deploy(project_name, select_master = false)
838
681
  Dir.chdir "projects/#{project_name}"
839
682
  output "Recupero la lista dei branch del progetto #{project_name}..."
683
+ `git remote prune origin`
840
684
  out = %x[ git fetch ]
841
- branches = %x[ git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname) %(objectname)' | sed 's/refs\\/remotes\\/origin\\///g' ]
842
- .split("\n").delete_if { |b| b.include?('HEAD') || b.include?('dev') }[0..49]
685
+ branches = %x[ git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname) %(objectname) %(committeremail)' | sed 's/refs\\/remotes\\/origin\\///g' ]
686
+ .split("\n").delete_if { |b| b.include?('HEAD') }[0..49]
687
+
688
+ master_branch = nil
843
689
 
844
- branch_name = choose do |menu|
845
- menu.prompt = "Scegli il branch di #{project_name} da deployare: ".cyan
846
- menu.shell = true
690
+ branches.each do |branch|
691
+ master_branch = branch if branch.match(/^master\s+/)
692
+ break unless master_branch.nil?
693
+ end
847
694
 
848
- branches.each do |branch|
695
+ if select_master || branches.length == 1
696
+ branch_name = master_branch
697
+ else
698
+ branches.insert(0, branches.delete(master_branch))
699
+ branch_name = choose do |menu|
700
+ menu.prompt = "Scegli il branch di #{project_name} da deployare: ".cyan
701
+ menu.shell = true
849
702
 
850
- title = @prima.reduce_size(branch, 100)
851
- msg = "#{title}".light_blue
852
- menu.choice(msg) { branch }
703
+ git_mail = get_git_mail
704
+
705
+ branches.each_with_index do |branch, index|
706
+ title = @prima.reduce_size(branch, 100)
707
+ msg = index.odd? ? title.white : title.light_yellow # uno bianco e uno giallo alternati
708
+ msg = branch.include?(git_mail) ? msg.on_blue : msg.on_black # i branch aggiornati da chi lancia la creazione sono su sfondo blu
709
+ menu.choice(msg) { branch }
710
+ menu.default = branch if branch == master_branch
711
+ end
853
712
  end
854
713
  end
855
714
 
856
715
  Dir.chdir "../../"
857
716
 
858
- name = branch_name.split(' ').first
859
- revision = branch_name.split(' ').last
860
- { name: name, revision: revision[0..14] }
717
+ name = branch_name.split(' ')[0]
718
+ revision = branch_name.split(' ')[1]
719
+ committer_email = branch_name.split(' ')[2].tr('<>', '')
720
+ { 'name' => name, 'revision' => revision[0..14], 'committer' => committer_email, 'default_branch' => select_master }
861
721
  end
862
722
 
723
+ def select_branch_to_deploy(project_name, branch_name)
724
+ Dir.chdir "projects/#{project_name}"
725
+ output "Recupero il branch #{project_name}:#{branch_name} ..."
726
+ `git remote prune origin`
727
+ out = %x[ git fetch ]
728
+ branch_name = %x[ git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname) %(objectname) %(committeremail)' | sed 's/refs\\/remotes\\/origin\\///g' ]
729
+ .split("\n").delete_if { |b| !b.match("^#{Regexp.escape(branch_name)}") }[0..49]
730
+ .first
731
+
732
+ Dir.chdir "../../"
733
+ name = branch_name.split(' ')[0]
734
+ revision = branch_name.split(' ')[1]
735
+ committer_email = branch_name.split(' ')[2].tr('<>', '')
736
+ { 'name' => name, 'revision' => revision[0..14], 'committer' => committer_email }
737
+ end
738
+
739
+ def get_stacks()
740
+ envs = {}
741
+ stack_list = stack_list()
742
+ stack_list.each do |stack|
743
+ unless stack.stack_name.match(/spotfleet-allinone-qa-(\w+)$/)
744
+ env_hash = stack.stack_name.match(/qa-(\w+)$/)[0]
745
+ envs[env_hash] = stack.tags unless envs.has_key?(env_hash) || stack.tags.empty?
746
+ end
747
+ end
748
+ return stack_list, envs
749
+ end
750
+
751
+ def get_clusters()
752
+ envs = {}
753
+ cluster_list = cluster_list()
754
+ cluster_list.each do |stack|
755
+ unless stack.stack_name.match(/spotfleet-allinone-qa-(\w+)$/)
756
+ env_hash = stack.stack_name.match(/qa-(\w+)$/)[0]
757
+ envs[env_hash] = stack.tags unless envs.has_key?(env_hash) || stack.tags.empty?
758
+ end
759
+ end
760
+ return cluster_list, envs
761
+ end
762
+
763
+ def hostname_pattern_priority()
764
+ (Time.now.to_i.to_s[-4..-1].to_i + Random.rand(40000)).to_s
765
+ end
766
+
767
+ def select_branches(project_names = nil)
768
+ output "Deploy feature menu"
769
+ if project_names.nil?
770
+ @projects.each{ |key, value| @projects[key] = choose_branch_to_deploy(key) }
771
+ else
772
+ project_names.each do |project|
773
+ @projects[project] = choose_branch_to_deploy(project)
774
+ end
775
+ @projects.each_key do |branch_project|
776
+ @projects[branch_project] = choose_branch_to_deploy(branch_project, true) unless project_names.include? branch_project
777
+ end
778
+ end
779
+ end
863
780
  end
864
781
 
865
782
  def help_content
@@ -876,14 +793,24 @@ Synopsis
876
793
  twig release start
877
794
  twig release finish
878
795
  twig release deploy
796
+ twig release aggregator
879
797
 
880
798
  Description
881
799
  -----------
882
800
 
883
- start creates a new feature branch
884
- finish finishes the feature by merging to dev and master
885
- deploy deploys the feature branch to a temporary AWS Elastic Beanstalk env
886
- deploy stop destroys the AWS Elastic Beanstalk env
801
+ start creates a new feature branch
802
+ finish finishes the feature by merging to dev and master
803
+ qainit deploys a new environment with selected branches from every project
804
+ qainit $PROJECT_NAME deploys a new environment allowing to selected a branch from the input project (everything else is master)
805
+ qainit shutdown deletes a specific qa environment
806
+
807
+ Available only to devops (from artemide)
808
+ -----------
809
+ deploy deploys the feature branch to a temporary AWS Elastic Beanstalk env
810
+ deploy stop destroys the AWS Elastic Beanstalk env
811
+ deploy update updates a feature branch with current branches
812
+ deploy lock protects a qa environment from automatic deletion
813
+ aggregator enable/disable directs comparator's staging environments to a qa/staging
887
814
 
888
815
  Subcommand for Twig: <http://rondevera.github.io/twig/>
889
816
  Author: Andrea Usuelli <https://github.com/andreausu>
@@ -898,4 +825,11 @@ if args.include?('--help')
898
825
  exit
899
826
  end
900
827
 
901
- Release.new.execute!(args)
828
+ gem_update = true
829
+ if args.include?('no-gem-update')
830
+ gem_update = false
831
+ end
832
+
833
+ args.delete('no-gem-update')
834
+
835
+ Release.new(gem_update).execute!(args)