prima-twig 0.29.9 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57cc2abfe63da8eca63003565c2dd3c41acceae3
4
- data.tar.gz: 52ce0563ce266cd396b657908a49173e031c640d
3
+ metadata.gz: 4f5c928ee0829fcbb156292bf9f0ef974b607a7b
4
+ data.tar.gz: 18897b25acdf48fa4aecf1ba8f0e9d8b68c66940
5
5
  SHA512:
6
- metadata.gz: cb98f98adc9c25d02a00f6e88fa74e66764463593726c8efcfe515856ef031958f84136a0bb081a7eea7ba4f4a3082374afbe6eaad9a38002db8c249448e03ff
7
- data.tar.gz: ed3fd49ff3540e7c015b696539002f13bea5f872b620502ce78f19a1abab78bc9e109d4a2eb20a4d43b80b21b33e566841eeaed85fe8b6d03670b0ba41055093
6
+ metadata.gz: d76b41d9ba5a96a8b4d6818721b8a292a8c96539c49d0da316a866c5959c9391ef25d716dbdae5a52d5061346a6fc1ae3eef1bd09ae630f6003e5a5bfd8e168b
7
+ data.tar.gz: fc6bcc2496b8ed3d6daeff654a1593213a3ec8ab8b52ddadbbf3f9dae69e3dfd5ea6cc9e21ae99123d6abfb0d589e471d722b34086ebe392e75466619cb1ca00
data/bin/twig-feature CHANGED
@@ -3,10 +3,11 @@
3
3
  require 'rubygems'
4
4
  require_relative '../lib/prima_twig.rb'
5
5
  require_relative '../lib/prima_aws_client.rb'
6
- require 'launchy'
7
6
  require 'digest'
8
- require 'pp'
9
7
  require 'json'
8
+ require 'launchy'
9
+ require 'pp'
10
+ require 'redis'
10
11
 
11
12
  class Release
12
13
  include Command
@@ -14,10 +15,9 @@ class Release
14
15
 
15
16
  def initialize
16
17
  @prima = Prima.new
17
- output "Controllo se ci sono aggiornamenti da fare..."
18
- stop_unless `gem outdated`.lines.grep(/^prima-twig \(.*\)/).empty?, "Devi aggiornare la gemma prima-twig!".red
18
+ output 'Controllo se ci sono aggiornamenti da fare...'
19
+ stop_unless `gem outdated`.lines.grep(/^prima-twig \(.*\)/).empty?, 'Devi aggiornare la gemma prima-twig!'.red
19
20
  @cf = Aws::CloudFormation::Client.new
20
- @elb = Aws::ElasticLoadBalancing::Client.new
21
21
  @alb = Aws::ElasticLoadBalancingV2::Client.new
22
22
  @ec2 = Aws::EC2::Client.new
23
23
  @ecs = Aws::ECS::Client.new
@@ -26,56 +26,56 @@ class Release
26
26
  @asg = Aws::AutoScaling::Client.new
27
27
  @s3_bucket = 'prima-artifacts'
28
28
  @artifact_path = '/tmp/prima-artifact.zip'
29
- @import_db_task = 'arn:aws:ecs:eu-west-1:001575623345:task-definition/ecs-task-db-restore-TaskDefinitionDbRestore-19XD5OHZGOTI3:1'
29
+ @import_db_task = 'arn:aws:ecs:eu-west-1:001575623345:task-definition/ecs-task-db-restore2-TaskDefinitionDbRestore-137UJ3IWV3S60:1'
30
30
  @dns_record_identifier = nil
31
31
  @ecs_cluster_name = nil
32
32
  @projects = {
33
- "prima" => {},
34
- "backoffice" => {},
35
- "urania" => {},
36
- "ermes" => {},
37
- "bburago" => {},
38
- "hal9000" => {},
39
- "fidaty" => {},
40
- "peano" => {},
41
- "rogoreport" => {},
42
- "assange" => {},
43
- "borat" => {}
33
+ 'prima' => {},
34
+ 'backoffice' => {},
35
+ 'urania' => {},
36
+ 'ermes' => {},
37
+ 'bburago' => {},
38
+ 'hal9000' => {},
39
+ 'fidaty' => {},
40
+ 'peano' => {},
41
+ 'rogoreport' => {},
42
+ 'assange' => {},
43
+ 'borat' => {},
44
+ 'crash' => {}
44
45
  }
45
- @stack_name_alb = "ecs-alb-http-public-qa"
46
- @stack_name_alb_ws = "ecs-alb-ws-public-qa"
46
+ @stack_name_alb = 'ecs-alb-http-public-qa'
47
+ @stack_name_alb_ws = 'ecs-alb-ws-public-qa'
47
48
  end
48
49
 
49
- def execute! args
50
+ def execute!(args)
50
51
  case args[0]
51
- when "start"
52
+ when 'start'
52
53
  start_feature!
53
- when "finish"
54
+ when 'finish'
54
55
  finish_feature!
55
- when "deploy"
56
+ when 'deploy'
56
57
  if ['terminate', 'stop', 'shutdown', 'halt', 'destroy'].include? args[1]
57
58
  deploy_shutdown!
58
- elsif "update" == args[1]
59
+ elsif 'update' == args[1]
59
60
  deploy_update!
60
- elsif "aggregator" == args[1]
61
- if args[2] and "enable" == args[2]
61
+ elsif 'aggregator' == args[1]
62
+ if args[2] && 'enable' == args[2]
62
63
  deploy_aggregator_enable!
63
- elsif args[2] and "disable" == args[2]
64
+ elsif args[2] && 'disable' == args[2]
64
65
  deploy_aggregator_disable!
65
66
  else
66
- stop_for_wrong_args()
67
+ stop_for_wrong_args
67
68
  end
68
69
  else
69
70
  if args[1]
70
71
  select_branches(args[1])
71
- deploy_feature!
72
72
  else
73
73
  select_branches
74
- deploy_feature!
75
74
  end
75
+ deploy_feature!
76
76
  end
77
77
  else
78
- stop_for_wrong_args()
78
+ stop_for_wrong_args
79
79
  end
80
80
  end
81
81
 
@@ -85,7 +85,7 @@ class Release
85
85
 
86
86
  def start_feature!
87
87
  branch_name = @prima.clean_branch_name(ask('Inserisci il nome del branch (puoi omettere feature/): '.cyan))
88
- stop_unless branch_name.length > 0, 'Devi inserire il nome del branch'
88
+ stop_unless branch_name.!empty?, 'Devi inserire il nome del branch'
89
89
  branch_name.prepend 'feature/' unless branch_name.include? 'feature'
90
90
 
91
91
  output "Il nome del branch sarà " + branch_name.yellow
@@ -96,11 +96,11 @@ class Release
96
96
  end
97
97
 
98
98
  def deploy_aggregator_disable!
99
- output "Disable aggregator"
99
+ output 'Disable aggregator'
100
100
 
101
101
  output "Recupero le informazioni relative al puntamento dei record DNS..."
102
102
  cloudflare = Rubyflare.connect_with(@prima.config['cloudflare_email'], @prima.config['cloudflare_apikey'])
103
- dns_records = cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {per_page: 100, type: "CNAME", content: get_alb_host(@stack_name_alb)})
103
+ dns_records = cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {per_page: 100, type: 'CNAME', content: get_alb_host(@stack_name_alb)})
104
104
  stop_if dns_records.body[:result].empty?, "I record DNS degli aggregatori non stanno puntando ad un QA".red
105
105
 
106
106
  output "Recupero le informazioni sui QA attivi..."
@@ -117,19 +117,19 @@ class Release
117
117
  change_hostname_priority(env_hash, hostname_pattern_priority())
118
118
  dns_to_staging()
119
119
  else
120
- output "Nessun QA trovato".red
120
+ output 'Nessun QA trovato'.red
121
121
  exit
122
122
  end
123
123
 
124
- output "Finito!".green
124
+ output 'Finito!'.green
125
125
  end
126
126
 
127
127
  def deploy_aggregator_enable!
128
- output "Enable aggregator"
128
+ output 'Enable aggregator'
129
129
 
130
- output "Recupero le informazioni relative al puntamento dei record DNS..."
130
+ output 'Recupero le informazioni relative al puntamento dei record DNS...'
131
131
  cloudflare = Rubyflare.connect_with(@prima.config['cloudflare_email'], @prima.config['cloudflare_apikey'])
132
- dns_records = cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {"per_page": 100, "type": "CNAME", "content": "staging.prima.it"})
132
+ dns_records = cloudflare.get('zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records', { per_page: 100, type: 'CNAME', content: 'staging.prima.it' })
133
133
  stop_if dns_records.body[:result].empty?, "I record DNS degli aggregatori stanno gia' puntando ad un QA".red
134
134
 
135
135
  output "Recupero le informazioni sui QA attivi..."
@@ -159,7 +159,7 @@ class Release
159
159
  dns_records.body[:result].each do |dns|
160
160
  if dns[:name] =~ /^\w+\-\w+\-staging\.prima\.it$/
161
161
  output "Changing #{dns[:name]} DNS record"
162
- cloudflare.put("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records/#{dns[:id]}", {"type": "CNAME", "name": dns[:name], "content": get_alb_host(@stack_name_alb), "proxied": true, "ttl": 1})
162
+ cloudflare.put("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records/#{dns[:id]}", {type: 'CNAME', name: dns[:name], content: get_alb_host(@stack_name_alb), proxied: true, ttl: 1})
163
163
  end
164
164
  end
165
165
 
@@ -219,11 +219,11 @@ class Release
219
219
  def dns_to_staging
220
220
  output "Recupero le informazioni relative al puntamento dei record DNS..."
221
221
  cloudflare = Rubyflare.connect_with(@prima.config['cloudflare_email'], @prima.config['cloudflare_apikey'])
222
- dns_records = cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {"per_page": 100, "type": "CNAME", "content": get_alb_host(@stack_name_alb)})
222
+ dns_records = cloudflare.get("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records", {per_page: 100, type: 'CNAME', content: get_alb_host(@stack_name_alb)})
223
223
  dns_records.body[:result].each do |dns|
224
224
  if dns[:name] =~ /^\w+\-\w+\-staging\.prima\.it$/
225
225
  output "Changing #{dns[:name]} DNS record"
226
- cloudflare.put("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records/#{dns[:id]}", {"type": "CNAME", "name": dns[:name], "content": "staging.prima.it", "proxied": true, "ttl": 1})
226
+ cloudflare.put("zones/1fb634f19c43dfb0162cc4cb91915da2/dns_records/#{dns[:id]}", {type: 'CNAME', name: dns[:name], content: 'staging.prima.it', proxied: true, ttl: 1})
227
227
  end
228
228
  end
229
229
  end
@@ -249,7 +249,7 @@ class Release
249
249
 
250
250
  def deploy_shutdown!
251
251
  output "Recupero le informazioni sui QA attivi..."
252
- stack_list, envs = get_stacks()
252
+ stack_list, envs = get_stacks
253
253
 
254
254
  env_hash = nil
255
255
  unless envs.empty?
@@ -258,16 +258,16 @@ class Release
258
258
  menu.shell = true
259
259
 
260
260
  envs.each do |key, env|
261
- title = ""
261
+ title = ''
262
262
  env.each do |e|
263
263
  title << "#{e.key}: #{e.value} "
264
264
  end
265
- msg = "#{@prima.reduce_size(title, 1000)}".light_blue
265
+ msg = @prima.reduce_size(title, 1000).to_s.light_blue
266
266
  menu.choice(msg) { key }
267
267
  end
268
268
  end
269
269
  else
270
- output "Nessun environment trovato".red
270
+ output 'Nessun environment trovato'.red
271
271
  exit
272
272
  end
273
273
 
@@ -350,7 +350,6 @@ class Release
350
350
 
351
351
  def deploy_feature!
352
352
  `git pull && git submodule init && git submodule update`
353
-
354
353
  deploy_id = Digest::MD5.hexdigest(
355
354
  @projects["prima"][:name] +
356
355
  @projects["backoffice"][:name] +
@@ -362,7 +361,8 @@ class Release
362
361
  @projects["peano"][:name] +
363
362
  @projects["rogoreport"][:name] +
364
363
  @projects["assange"][:name] +
365
- @projects["borat"][:name]
364
+ @projects["borat"][:name] +
365
+ @projects['crash'][:name]
366
366
  )
367
367
  @dns_record_identifier = deploy_id
368
368
  hostname_pattern_priority = hostname_pattern_priority()
@@ -414,6 +414,10 @@ class Release
414
414
  {
415
415
  key: "borat",
416
416
  value: @projects["borat"][:name]
417
+ },
418
+ {
419
+ key: 'crash',
420
+ value: @projects['crash'][:name]
417
421
  }
418
422
  ]
419
423
 
@@ -422,7 +426,7 @@ class Release
422
426
  if stack_exists?(cluster_stack_name)
423
427
  tags = get_stack_tags(cluster_stack_name)
424
428
  hostname_pattern_priority = tags.detect do |tag|
425
- tag.key === "hostname_pattern_priority"
429
+ tag.key == 'hostname_pattern_priority'
426
430
  end.value
427
431
  end
428
432
 
@@ -453,6 +457,7 @@ class Release
453
457
  create_stack(stack_name_db, stack_body, parameters, tags) unless stack_exists?(stack_name_db)
454
458
 
455
459
  create_prima_artifact(@projects["prima"][:revision], @projects["prima"][:name], deploy_id) unless artifact_exists?('prima-artifacts', "prima/#{@projects["prima"][:revision]}-#{deploy_id}.tar.gz")
460
+ create_crash_artifact(@projects['crash'][:revision], deploy_id) unless !deploy_crash? || artifact_exists?('prima-artifacts', "microservices/crash/#{@projects['crash'][:revision]}-#{deploy_id}-qa.tar.gz")
456
461
  create_urania_artifact(@projects["urania"][:revision]) unless artifact_exists?('prima-artifacts', "microservices/urania/#{@projects["urania"][:revision]}-qa.tar.gz")
457
462
  create_ermes_artifact(@projects["ermes"][:revision]) unless artifact_exists?('prima-artifacts', "microservices/ermes/#{@projects["ermes"][:revision]}-qa.tar.gz")
458
463
  create_bburago_artifact(@projects["bburago"][:revision]) unless artifact_exists?('prima-artifacts', "microservices/bburago/#{@projects["bburago"][:revision]}-qa.tar.gz")
@@ -467,6 +472,8 @@ class Release
467
472
  wait_for_stack_ready(stack_name_db) unless stack_ready?(stack_name_db)
468
473
  import_dbs(ec2_ip_address(asg_stack_name)) unless stack_exists?("ecs-task-web-qa-#{deploy_id}")
469
474
 
475
+ import_redis_crash(ec2_ip_address(asg_stack_name))
476
+
470
477
  wait_for_stack_ready(@stack_name_alb) unless stack_ready?(@stack_name_alb)
471
478
  wait_for_stack_ready(@stack_name_alb_ws) unless stack_ready?(@stack_name_alb_ws)
472
479
 
@@ -924,6 +931,47 @@ class Release
924
931
  create_stack(stack_name_backoffice, stack_body, parameters, tags)
925
932
  end
926
933
 
934
+ if deploy_crash?
935
+ git_checkout_version('crash', @projects['crash'][:revision])
936
+ stack_name_crash = "ecs-task-crash-qa-#{deploy_id}"
937
+ stack_body = IO.read('projects/crash/deploy/task.yml')
938
+ parameters = [
939
+ {
940
+ parameter_key: 'Environment',
941
+ parameter_value: 'qa'
942
+ },
943
+ {
944
+ parameter_key: 'ReleaseVersion',
945
+ parameter_value: "#{@projects['crash'][:revision]}-#{deploy_id}"
946
+ },
947
+ {
948
+ parameter_key: 'TaskDesiredCount',
949
+ parameter_value: '1'
950
+ },
951
+ {
952
+ parameter_key: 'ECSClusterName',
953
+ parameter_value: @ecs_cluster_name
954
+ },
955
+ {
956
+ parameter_key: 'ALBShortName',
957
+ parameter_value: "crash-qa-#{deploy_id}"[0..31]
958
+ },
959
+ {
960
+ parameter_key: 'HostnamePattern',
961
+ parameter_value: "crash-#{@dns_record_identifier}.qa.colaster.com"
962
+ },
963
+ {
964
+ parameter_key: 'HostnamePatternPriority',
965
+ parameter_value: (hostname_pattern_priority.to_i + 10).to_s
966
+ }
967
+ ]
968
+ if stack_exists?(stack_name_crash)
969
+ update_stack(stack_name_crash, stack_body, parameters)
970
+ else
971
+ create_stack(stack_name_crash, stack_body, parameters, tags)
972
+ end
973
+ end
974
+
927
975
  wait_for_stack_ready(stack_name_web) unless stack_ready?(stack_name_web)
928
976
  wait_for_stack_ready(stack_name_consumer) unless stack_ready?(stack_name_consumer)
929
977
  wait_for_stack_ready(stack_name_urania) unless stack_ready?(stack_name_urania)
@@ -936,6 +984,7 @@ class Release
936
984
  wait_for_stack_ready(stack_name_rogoreport) unless stack_ready?(stack_name_rogoreport)
937
985
  wait_for_stack_ready(stack_name_assange) unless stack_ready?(stack_name_assange)
938
986
  wait_for_stack_ready(stack_name_borat) unless stack_ready?(stack_name_borat)
987
+ wait_for_stack_ready(stack_name_crash) unless stack_ready?(stack_name_crash) || !deploy_crash?
939
988
 
940
989
  update_service_defaults(stack_name_web)
941
990
  update_service_defaults(stack_name_consumer)
@@ -949,6 +998,7 @@ class Release
949
998
  update_service_defaults(stack_name_rogoreport)
950
999
  update_service_defaults(stack_name_assange)
951
1000
  update_service_defaults(stack_name_borat)
1001
+ update_service_defaults(stack_name_crash) unless stack_ready?(stack_name_crash) || !deploy_crash?
952
1002
 
953
1003
  stack_name_route53 = "ecs-route53-qa-#{deploy_id}"
954
1004
  stack_body = IO.read('cloudformation/stacks/route53/qa.yml')
@@ -996,8 +1046,13 @@ class Release
996
1046
  {
997
1047
  parameter_key: "BoratElbHostname",
998
1048
  parameter_value: get_alb_host(@stack_name_alb_ws)
1049
+ },
1050
+ {
1051
+ parameter_key: 'CrashElbHostname',
1052
+ parameter_value: get_alb_host(@stack_name_alb_ws)
999
1053
  }
1000
1054
  ]
1055
+
1001
1056
  create_stack(stack_name_route53, stack_body, parameters, tags) unless stack_exists?(stack_name_route53)
1002
1057
 
1003
1058
  prima_hostname = get_route53_hostname(stack_name_web)
@@ -1009,12 +1064,13 @@ class Release
1009
1064
  backoffice_hostname = get_route53_hostname(stack_name_backoffice)
1010
1065
  assange_hostname = get_route53_hostname(stack_name_assange)
1011
1066
  borat_hostname = get_route53_hostname(stack_name_borat)
1067
+ deploy_crash? && crash_hostname = get_route53_hostname(stack_name_crash)
1012
1068
 
1013
1069
  wait_for_stack_ready(stack_name_route53) unless stack_ready?(stack_name_route53)
1014
1070
 
1015
- launch_marley()
1071
+ launch_marley
1016
1072
 
1017
- output "
1073
+ projects_text = "
1018
1074
  > Prima url: https://#{prima_hostname}
1019
1075
  > Prima RI url: https://#{prima_hostname.sub("www", "wwwri")}
1020
1076
  > Backoffice (Borat) url: https://#{borat_hostname}
@@ -1024,8 +1080,12 @@ class Release
1024
1080
  > Fidaty url: http://#{fidaty_hostname}:10021
1025
1081
  > Peano url: http://#{peano_hostname}:10039
1026
1082
  > Assange url: https://#{assange_hostname}
1027
- > Backoffice (legacy) url: https://#{backoffice_hostname}
1028
- > SSH connection: ssh ec2-user@#{ec2_ip_address(asg_stack_name)} -i ~/.ssh/ecs-cluster-qa.pem\n".cyan
1083
+ > Backoffice (legacy) url: https://#{backoffice_hostname}"
1084
+ projects_text.concat "
1085
+ > Crash url: https://#{crash_hostname}" if deploy_crash?
1086
+ projects_text.concat "
1087
+ > SSH connection: ssh ec2-user@#{ec2_ip_address(asg_stack_name)} -i ~/.ssh/ecs-cluster-qa.pem\n"
1088
+ output projects_text.cyan
1029
1089
  output "Deploy effettuato, everything is awesome!\n".green
1030
1090
  end
1031
1091
 
@@ -1049,6 +1109,8 @@ class Release
1049
1109
  host = "assange-#{@dns_record_identifier}.qa.colaster.com"
1050
1110
  when stack_name.include?('borat')
1051
1111
  host = "backoffice-#{@dns_record_identifier}.qa.colaster.com"
1112
+ when stack_name.include?('crash')
1113
+ host = "crash-#{@dns_record_identifier}.qa.colaster.com"
1052
1114
  end
1053
1115
  host
1054
1116
  end
@@ -1091,6 +1153,8 @@ class Release
1091
1153
  logical_resource_id = 'EcsApplicationLoadBalancerPublic'
1092
1154
  when stack_name.include?('borat')
1093
1155
  logical_resource_id = 'EcsApplicationLoadBalancerPublic'
1156
+ when stack_name.include?('crash')
1157
+ logical_resource_id = 'EcsApplicationLoadBalancerPublic'
1094
1158
  end
1095
1159
  resp = @cf.describe_stack_resource({
1096
1160
  stack_name: stack_name,
@@ -1102,38 +1166,6 @@ class Release
1102
1166
  resp.load_balancers[0].dns_name
1103
1167
  end
1104
1168
 
1105
- def get_elb_host(stack_name)
1106
- case
1107
- when stack_name.include?('web')
1108
- logical_resource_id = 'EcsElasticLoadBalancerPublic'
1109
- when stack_name.include?('urania')
1110
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
1111
- when stack_name.include?('backoffice')
1112
- logical_resource_id = 'EcsElasticLoadBalancerPublic'
1113
- when stack_name.include?('bburago')
1114
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
1115
- when stack_name.include?('hal9000')
1116
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
1117
- when stack_name.include?('fidaty')
1118
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
1119
- when stack_name.include?('peano')
1120
- logical_resource_id = 'EcsElasticLoadBalancerInternal'
1121
- when stack_name.include?('assange')
1122
- logical_resource_id = 'EcsApplicationLoadBalancerPublic'
1123
- when stack_name.include?('borat')
1124
- logical_resource_id = 'EcsApplicationLoadBalancerPublic'
1125
- end
1126
- resp = @cf.describe_stack_resource({
1127
- stack_name: stack_name,
1128
- logical_resource_id: logical_resource_id
1129
- })
1130
- resp = @elb.describe_load_balancers({
1131
- load_balancer_names: [resp.stack_resource_detail.physical_resource_id],
1132
- page_size: 1
1133
- })
1134
- resp.load_balancer_descriptions[0].dns_name
1135
- end
1136
-
1137
1169
  def update_service_defaults(stack_name)
1138
1170
  case
1139
1171
  when stack_name.include?('web')
@@ -1160,21 +1192,23 @@ class Release
1160
1192
  logical_resource_id = 'ECSServiceAssange'
1161
1193
  when stack_name.include?('borat')
1162
1194
  logical_resource_id = 'ECSServiceBorat'
1195
+ when stack_name.include?('crash')
1196
+ logical_resource_id = 'ECSServiceCrash'
1163
1197
  else
1164
1198
  raise "Service name non gestito per lo stack #{stack_name}"
1165
1199
  end
1166
- resp = @cf.describe_stack_resource({
1200
+ resp = @cf.describe_stack_resource(
1167
1201
  stack_name: stack_name,
1168
1202
  logical_resource_id: logical_resource_id
1169
- })
1170
- resp = @ecs.update_service({
1203
+ )
1204
+ @ecs.update_service(
1171
1205
  cluster: @ecs_cluster_name,
1172
1206
  service: resp.stack_resource_detail.physical_resource_id,
1173
1207
  deployment_configuration: {
1174
1208
  minimum_healthy_percent: 0,
1175
1209
  maximum_percent: 100
1176
1210
  }
1177
- })
1211
+ )
1178
1212
  end
1179
1213
 
1180
1214
  def create_urania_artifact(revision)
@@ -1184,8 +1218,6 @@ class Release
1184
1218
 
1185
1219
  Dir.chdir 'projects/urania'
1186
1220
 
1187
- stop_unless is_branch_compatible_with_current_twig_version?("urania"), "Il tuo branch del progetto urania non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1188
-
1189
1221
  [
1190
1222
  "docker-compose build web",
1191
1223
  "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh urania_web \
@@ -1194,15 +1226,7 @@ class Release
1194
1226
  rm -rf _build/qa/rel/ && \
1195
1227
  mix release --env=qa'"
1196
1228
  ].each do |cmd|
1197
- output "Eseguo #{cmd}".yellow
1198
- res = %x[ #{cmd} ]
1199
- if $?.exitstatus != 0
1200
- color = 'red'
1201
- else
1202
- color = 'green'
1203
- end
1204
- output res.send color
1205
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1229
+ execute_command cmd
1206
1230
  end
1207
1231
 
1208
1232
  artifact_path = Dir.glob("_build/qa/rel/urania/releases/*/urania.tar.gz").first
@@ -1226,15 +1250,7 @@ class Release
1226
1250
  rm -rf _build/qa/rel/ && \
1227
1251
  mix release --env=qa'"
1228
1252
  ].each do |cmd|
1229
- output "Eseguo #{cmd}".yellow
1230
- res = %x[ #{cmd} ]
1231
- if $?.exitstatus != 0
1232
- color = 'red'
1233
- else
1234
- color = 'green'
1235
- end
1236
- output res.send color
1237
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1253
+ execute_command cmd
1238
1254
  end
1239
1255
 
1240
1256
  artifact_path = Dir.glob("_build/qa/rel/ermes/releases/*/ermes.tar.gz").first
@@ -1243,6 +1259,52 @@ class Release
1243
1259
  Dir.chdir '../../'
1244
1260
  end
1245
1261
 
1262
+ def deploy_crash?
1263
+ @projects['crash'][:name] != 'master'
1264
+ end
1265
+
1266
+ def create_crash_artifact(revision, deploy_id)
1267
+ output "Preparo l'artifact crash .zip\n".yellow
1268
+
1269
+ git_checkout_version('crash', revision)
1270
+
1271
+ Dir.chdir 'projects/crash'
1272
+
1273
+ stack_name_web = 'ecs-task-web-qa-notneeded'
1274
+ web_qa_host = get_route53_hostname(stack_name_web)
1275
+ stack_name_crash = 'ecs-task-crash-qa-notneeded'
1276
+ crash_qa_host = get_route53_hostname(stack_name_crash)
1277
+
1278
+ ws_endpoint = "wss://#{crash_qa_host}/socket/websocket?vsn=1.0.0"
1279
+ frontend_endpoint = "https://#{crash_qa_host}/"
1280
+
1281
+ [
1282
+ 'docker-compose build web',
1283
+ "docker-compose run -w $PWD -e WS_ENDPOINT=#{ws_endpoint} -e GRAPHQL_ENDPOINT=#{frontend_endpoint} -e MIX_ENV=qa web \
1284
+ '-c' 'sed -i \"s/web-qa-host/#{web_qa_host}/g\" config/qa.exs && \
1285
+ sed -i \"s/crash-qa-host/#{crash_qa_host}/g\" config/qa.exs && \
1286
+ mix local.hex --force && mix hex.info && \
1287
+ mix deps.get && \
1288
+ cd assets && \
1289
+ yarn --cache-folder ~/.cache/yarn && \
1290
+ ./node_modules/.bin/elm-github-install && \
1291
+ NODE_ENV=production sysconfcpus -n 2 ./node_modules/.bin/webpack -p --config config/webpack.config.prod.js && \
1292
+ cd ../ && \
1293
+ mix release.clean --implode --no-confirm && \
1294
+ mix phx.digest && \
1295
+ mix deps.clean --all && \
1296
+ mix deps.get && \
1297
+ mix compile && mix release --env=qa'"
1298
+ ].each do |cmd|
1299
+ execute_command cmd
1300
+ end
1301
+
1302
+ artifact_path = Dir.glob('_build/qa/rel/crash/releases/*/crash.tar.gz').first
1303
+ upload_artifact(artifact_path, "microservices/crash/#{revision}-#{deploy_id}-qa.tar.gz")
1304
+
1305
+ Dir.chdir '../../'
1306
+ end
1307
+
1246
1308
  def create_bburago_artifact(revision)
1247
1309
  output "Preparo l'artifact bburago .zip\n".yellow
1248
1310
 
@@ -1250,8 +1312,6 @@ class Release
1250
1312
 
1251
1313
  Dir.chdir 'projects/bburago'
1252
1314
 
1253
- stop_unless is_branch_compatible_with_current_twig_version?("bburago"), "Il tuo branch del progetto bburago non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1254
-
1255
1315
  [
1256
1316
  "docker-compose build web",
1257
1317
  "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh bburago_web \
@@ -1260,15 +1320,7 @@ class Release
1260
1320
  rm -rf _build/qa/rel/ && \
1261
1321
  mix release --env=qa'"
1262
1322
  ].each do |cmd|
1263
- output "Eseguo #{cmd}".yellow
1264
- res = %x[ #{cmd} ]
1265
- if $?.exitstatus != 0
1266
- color = 'red'
1267
- else
1268
- color = 'green'
1269
- end
1270
- output res.send color
1271
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1323
+ execute_command cmd
1272
1324
  end
1273
1325
 
1274
1326
  artifact_path = Dir.glob("_build/qa/rel/bburago/releases/*/bburago.tar.gz").first
@@ -1284,8 +1336,6 @@ class Release
1284
1336
 
1285
1337
  Dir.chdir 'projects/hal9000'
1286
1338
 
1287
- stop_unless is_branch_compatible_with_current_twig_version?("hal9000"), "Il tuo branch del progetto hal9000 non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1288
-
1289
1339
  [
1290
1340
  "docker-compose build web",
1291
1341
  "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh hal9000_web \
@@ -1295,15 +1345,7 @@ class Release
1295
1345
  rm -rf _build/qa/rel/ && \
1296
1346
  mix release --env=qa'"
1297
1347
  ].each do |cmd|
1298
- output "Eseguo #{cmd}".yellow
1299
- res = %x[ #{cmd} ]
1300
- if $?.exitstatus != 0
1301
- color = 'red'
1302
- else
1303
- color = 'green'
1304
- end
1305
- output res.send color
1306
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1348
+ execute_command cmd
1307
1349
  end
1308
1350
 
1309
1351
  artifact_path = Dir.glob("_build/qa/rel/hal9000/releases/*/hal9000.tar.gz").first
@@ -1319,8 +1361,6 @@ class Release
1319
1361
 
1320
1362
  Dir.chdir 'projects/fidaty'
1321
1363
 
1322
- stop_unless is_branch_compatible_with_current_twig_version?("fidaty"), "Il tuo branch del progetto fidaty non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1323
-
1324
1364
  stack_name_web = "ecs-task-web-qa-notneeded"
1325
1365
  web_qa_host = get_route53_hostname(stack_name_web)
1326
1366
 
@@ -1334,15 +1374,7 @@ class Release
1334
1374
  rm -rf _build/qa/rel/ && \
1335
1375
  mix release --env=qa'"
1336
1376
  ].each do |cmd|
1337
- output "Eseguo #{cmd}".yellow
1338
- res = %x[ #{cmd} ]
1339
- if $?.exitstatus != 0
1340
- color = 'red'
1341
- else
1342
- color = 'green'
1343
- end
1344
- output res.send color
1345
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1377
+ execute_command cmd
1346
1378
  end
1347
1379
 
1348
1380
  artifact_path = Dir.glob("_build/qa/rel/fidaty/releases/*/fidaty.tar.gz").first
@@ -1372,15 +1404,7 @@ class Release
1372
1404
  rm -rf _build/qa/rel/ && \
1373
1405
  mix release --env=qa'"
1374
1406
  ].each do |cmd|
1375
- output "Eseguo #{cmd}".yellow
1376
- res = %x[ #{cmd} ]
1377
- if $?.exitstatus != 0
1378
- color = 'red'
1379
- else
1380
- color = 'green'
1381
- end
1382
- output res.send color
1383
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1407
+ execute_command cmd
1384
1408
  end
1385
1409
 
1386
1410
  artifact_path = Dir.glob("_build/qa/rel/peano/releases/*/peano.tar.gz").first
@@ -1409,15 +1433,7 @@ class Release
1409
1433
  rm -rf _build/qa/rel/ && \
1410
1434
  mix release --name=rogoreport_qa --env=qa'"
1411
1435
  ].each do |cmd|
1412
- output "Eseguo #{cmd}".yellow
1413
- res = %x[ #{cmd} ]
1414
- if $?.exitstatus != 0
1415
- color = 'red'
1416
- else
1417
- color = 'green'
1418
- end
1419
- output res.send color
1420
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1436
+ execute_command cmd
1421
1437
  end
1422
1438
 
1423
1439
  artifact_path = Dir.glob("_build/qa/rel/rogoreport*/releases/*/rogoreport*.tar.gz").first
@@ -1433,8 +1449,6 @@ class Release
1433
1449
 
1434
1450
  Dir.chdir 'projects/assange'
1435
1451
 
1436
- stop_unless is_branch_compatible_with_current_twig_version?("assange"), "Il tuo branch del progetto assange non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1437
-
1438
1452
  [
1439
1453
  "docker-compose build web",
1440
1454
  "docker run -v $PWD:/code -w /code -e MIX_ENV=qa --entrypoint /bin/sh assange_web \
@@ -1444,15 +1458,7 @@ class Release
1444
1458
  rm -rf _build/qa/rel/ && \
1445
1459
  mix release --env=qa'"
1446
1460
  ].each do |cmd|
1447
- output "Eseguo #{cmd}".yellow
1448
- res = %x[ #{cmd} ]
1449
- if $?.exitstatus != 0
1450
- color = 'red'
1451
- else
1452
- color = 'green'
1453
- end
1454
- output res.send color
1455
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1461
+ execute_command cmd
1456
1462
  end
1457
1463
 
1458
1464
  artifact_path = Dir.glob("_build/qa/rel/assange/releases/*/assange.tar.gz").first
@@ -1503,15 +1509,7 @@ class Release
1503
1509
  rm -rf _build/qa/rel/ && \
1504
1510
  mix release --env=qa'"
1505
1511
  ].each do |cmd|
1506
- output "Eseguo #{cmd}".yellow
1507
- res = %x[ #{cmd} ]
1508
- if $?.exitstatus != 0
1509
- color = 'red'
1510
- else
1511
- color = 'green'
1512
- end
1513
- output res.send color
1514
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1512
+ execute_command cmd
1515
1513
  end
1516
1514
 
1517
1515
  artifact_path = Dir.glob("_build/qa/rel/backend/releases/*/backend.tar.gz").first
@@ -1527,8 +1525,6 @@ class Release
1527
1525
 
1528
1526
  Dir.chdir 'projects/backoffice'
1529
1527
 
1530
- stop_unless is_branch_compatible_with_current_twig_version?("backoffice"), "Il tuo branch del progetto backoffice non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1531
-
1532
1528
  ['node_modules'].each do |dir|
1533
1529
  unless File.directory?(dir)
1534
1530
  if File.directory?("../../../backoffice/#{dir}")
@@ -1547,15 +1543,7 @@ class Release
1547
1543
  "cd ../../ && docker run -e GIT_DIR=$PWD -v $PWD:/usr/app/src -w /usr/app/src/projects/backoffice blinkmobile/bower install --allow-root",
1548
1544
  "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 && sed -i \"s/web-qa-ri-url/#{webri_qa_host}/g\" Gruntfile.js && npm install && grunt qa'"
1549
1545
  ].each do |cmd|
1550
- output "Eseguo #{cmd}".yellow
1551
- res = %x[ #{cmd} ]
1552
- if $?.exitstatus != 0
1553
- color = 'red'
1554
- else
1555
- color = 'green'
1556
- end
1557
- output res.send color
1558
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1546
+ execute_command cmd
1559
1547
  end
1560
1548
 
1561
1549
  artifact_path = '/tmp/backoffice.zip'
@@ -1572,8 +1560,6 @@ class Release
1572
1560
 
1573
1561
  Dir.chdir 'projects/prima'
1574
1562
 
1575
- stop_unless is_branch_compatible_with_current_twig_version?("prima"), "Il tuo branch del progetto prima non e' compatibile con questa versione di twig, devi REBASARE DA MASTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".red
1576
-
1577
1563
  ['vendor'].each do |dir|
1578
1564
  unless File.directory?(dir)
1579
1565
  if File.directory?("../../../prima/#{dir}")
@@ -1589,15 +1575,7 @@ class Release
1589
1575
  [
1590
1576
  "bin/local_build_artifact.sh #{branch_name} #{web_qa_host} #{backoffice_qa_host} #{assange_qa_host} #{deploy_id}"
1591
1577
  ].each do |cmd|
1592
- output "Eseguo #{cmd}".yellow
1593
- res = %x[ #{cmd} ]
1594
- if $?.exitstatus != 0
1595
- color = 'red'
1596
- else
1597
- color = 'green'
1598
- end
1599
- output res.send color
1600
- stop_if (color == 'red'), "Errore durante la build dell'artifact".red
1578
+ execute_command cmd
1601
1579
  end
1602
1580
 
1603
1581
  Dir.chdir "../../"
@@ -1648,6 +1626,20 @@ class Release
1648
1626
  create_stack(stack_name, stack_body, parameters)
1649
1627
  end
1650
1628
 
1629
+ def import_redis_crash(qa_ip_address)
1630
+ output "Importo dump di Redis da staging\n".yellow
1631
+
1632
+ redis_qa = Redis.new(:url => "redis://#{qa_ip_address}:6379/10")
1633
+
1634
+ return unless redis_qa.keys('CODICI').empty?
1635
+
1636
+ redis_staging = Redis.new(:url => 'redis://staging.cache-1.prima.it:6379/10')
1637
+
1638
+ dump_staging = redis_staging.dump 'CODICI'
1639
+
1640
+ redis_qa.restore 'CODICI', 0, dump_staging
1641
+ end
1642
+
1651
1643
  def import_dbs(ip_address)
1652
1644
  resp = @ecs.run_task({
1653
1645
  cluster: @ecs_cluster_name,
@@ -1659,7 +1651,7 @@ class Release
1659
1651
  environment: [
1660
1652
  {
1661
1653
  name: 'EC2_IP_ADDRESS',
1662
- value: ip_address,
1654
+ value: ip_address
1663
1655
  }
1664
1656
  ]
1665
1657
  }
@@ -1691,7 +1683,7 @@ class Release
1691
1683
  Dir.chdir "projects/#{project_name}"
1692
1684
  output "Recupero la lista dei branch del progetto #{project_name}..."
1693
1685
  out = %x[ git fetch ]
1694
- branches = %x[ git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname) %(objectname)' | sed 's/refs\\/remotes\\/origin\\///g' ]
1686
+ branches = %x[ git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname) %(objectname) %(committeremail)' | sed 's/refs\\/remotes\\/origin\\///g' ]
1695
1687
  .split("\n").delete_if { |b| b.include?('HEAD') || b.include?('dev') }[0..49]
1696
1688
 
1697
1689
  master_branch = nil
@@ -1719,9 +1711,10 @@ class Release
1719
1711
 
1720
1712
  Dir.chdir "../../"
1721
1713
 
1722
- name = branch_name.split(' ').first
1723
- revision = branch_name.split(' ').last
1724
- { name: name, revision: revision[0..14] }
1714
+ name = branch_name.split(' ')[0]
1715
+ revision = branch_name.split(' ')[1]
1716
+ committer_email = branch_name.split(' ')[2].tr('<>', '')
1717
+ { name: name, revision: revision[0..14], committer: committer_email }
1725
1718
  end
1726
1719
 
1727
1720
  def select_branch_to_deploy(project_name, branch_name)
@@ -1734,8 +1727,9 @@ class Release
1734
1727
 
1735
1728
  Dir.chdir "../../"
1736
1729
 
1737
- name = branch_name.split(' ').first
1738
- revision = branch_name.split(' ').last
1730
+ name = branch_name.split(' ')[0]
1731
+ revision = branch_name.split(' ')[1]
1732
+
1739
1733
  { name: name, revision: revision[0..14] }
1740
1734
  end
1741
1735
 
@@ -1759,6 +1753,8 @@ class Release
1759
1753
  File.readlines("deploy/deploy").grep(/HOSTNAME_PATTERN/).size > 0
1760
1754
  when project == 'borat'
1761
1755
  File.readlines("deploy/deploy").grep(/HOSTNAME_PATTERN/).size > 0
1756
+ when project == 'crash'
1757
+ File.readlines("deploy/deploy").grep(/HOSTNAME_PATTERN/).size > 0
1762
1758
  end
1763
1759
  end
1764
1760
 
@@ -1830,6 +1826,7 @@ class Release
1830
1826
  @projects["rogoreport"] = choose_branch_to_deploy('rogoreport')
1831
1827
  @projects["assange"] = choose_branch_to_deploy('assange')
1832
1828
  @projects["borat"] = choose_branch_to_deploy('borat')
1829
+ @projects['crash'] = choose_branch_to_deploy('crash')
1833
1830
  else
1834
1831
  stop_unless File.directory?("./projects/#{project_name}"), "progetto #{project_name} inesistente o non supportato"
1835
1832
  @projects[project_name] = choose_branch_to_deploy(project_name)
data/lib/command.rb CHANGED
@@ -1,60 +1,72 @@
1
1
  require 'colorize'
2
+ require 'English'
2
3
  require 'optparse'
3
4
 
4
- module Command
5
- def exec_step command, output = nil
5
+ module Command
6
+ # executes command and exits if status != 0
7
+ def exec_step(command, output = nil)
6
8
  if output
7
9
  puts output
8
10
  else
9
- puts "exec > ".green + "#{command}".yellow
11
+ puts 'exec > '.green + command.to_s.yellow
10
12
  end
11
13
  `#{command}`
12
- exit($?.exitstatus) unless 0 === $?.exitstatus
14
+ exit($CHILD_STATUS.exitstatus) unless $CHILD_STATUS.exitstatus.zero?
13
15
  end
14
16
 
15
- def output msg
16
- puts "twig binaries > ".black + msg
17
+ def output(msg)
18
+ puts 'twig binaries > '.black + msg
17
19
  end
18
20
 
19
- def stop_if check, msg
21
+ def stop_if(check, msg)
20
22
  if check
21
- output_msg = case msg
22
- when Symbol
23
- symbol_message msg
24
- when Array
25
- array_message msg
26
- else
27
- msg
28
- end
29
- puts "there was a problem > ".red + output_msg
23
+ output_msg =
24
+ case msg
25
+ when Symbol
26
+ symbol_message msg
27
+ when Array
28
+ array_message msg
29
+ else
30
+ msg
31
+ end
32
+ puts 'there was a problem > '.red + output_msg
30
33
  exit(1)
31
34
  end
32
35
  end
33
36
 
34
- def symbol_message s
37
+ def symbol_message(s)
35
38
  case s
36
39
  when :clean
37
- "hai dei file non committati...non posso continuare'"
40
+ 'hai dei file non committati...non posso continuare'
38
41
  when :detached_head
39
42
  "repo in stato 'head detached'"
40
43
  when :wrong_args
41
- "argomento non corretto"
44
+ 'argomento non corretto'
42
45
  end
43
46
  end
44
47
 
45
- def array_message arr
48
+ def array_message(arr)
46
49
  case arr[0]
47
50
  when :wrong_args
48
51
  msg = symbol_message arr[0]
49
52
  msg += "\n"
50
- msg += " valore possibile: "
51
- values = "[ " + arr[1].join(" | ").yellow + " ]"
53
+ msg += ' valore possibile: '
54
+ values = '[ ' + arr[1].join(' | ').yellow + ' ]'
52
55
  msg += values
53
56
  msg
54
57
  end
55
58
  end
56
59
 
57
- def stop_unless check, msg
58
- stop_if (not check), msg
60
+ def stop_unless(check, msg)
61
+ stop_if !check, msg
62
+ end
63
+
64
+ # executes command and returns properly colored output
65
+ def execute_command(cmd)
66
+ output "Eseguo #{cmd}".yellow
67
+ res = `#{cmd}`
68
+ color = $CHILD_STATUS.exitstatus.zero? ? 'green' : 'red'
69
+ output res.send color
70
+ stop_if (color == 'red'), "Errore durante la build dell'artifact".red
59
71
  end
60
72
  end
@@ -6,13 +6,17 @@ module PrimaAwsClient
6
6
  @s3 ||= Aws::S3::Client.new
7
7
  end
8
8
 
9
+ def cf_client
10
+ @cf ||= Aws::CloudFormation::Client.new
11
+ end
12
+
9
13
  def stack_list
10
14
  stacks = []
11
15
  next_token = ''
12
16
  loop do
13
17
  print '.'.yellow; STDOUT.flush
14
18
  options = next_token != '' ? { next_token: next_token } : {}
15
- resp = @cf.describe_stacks(options)
19
+ resp = cf_client.describe_stacks(options)
16
20
  stacks += resp.stacks
17
21
  break unless resp.next_token
18
22
  next_token = resp.next_token
@@ -22,10 +26,6 @@ module PrimaAwsClient
22
26
  stacks
23
27
  end
24
28
 
25
- def cf_client
26
- @cf ||= Aws::CloudFormation::Client.new
27
- end
28
-
29
29
  def create_stack(stack_name, stack_body, parameters = [], tags = [])
30
30
  cf_client.create_stack(
31
31
  stack_name: stack_name,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prima-twig
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.9
4
+ version: 0.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matteo Giachino