prima-twig 0.5.0 → 0.5.26

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.
@@ -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)