skylight 5.0.0.beta5 → 5.1.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +401 -369
- data/CLA.md +1 -1
- data/CONTRIBUTING.md +1 -1
- data/LICENSE.md +7 -17
- data/README.md +1 -1
- data/ext/extconf.rb +42 -54
- data/ext/libskylight.yml +9 -6
- data/lib/skylight.rb +20 -30
- data/lib/skylight/api.rb +22 -18
- data/lib/skylight/cli.rb +47 -46
- data/lib/skylight/cli/doctor.rb +50 -50
- data/lib/skylight/cli/helpers.rb +19 -19
- data/lib/skylight/cli/merger.rb +141 -139
- data/lib/skylight/config.rb +267 -310
- data/lib/skylight/deprecation.rb +4 -4
- data/lib/skylight/errors.rb +3 -4
- data/lib/skylight/extensions.rb +17 -29
- data/lib/skylight/extensions/source_location.rb +128 -128
- data/lib/skylight/formatters/http.rb +1 -3
- data/lib/skylight/gc.rb +30 -40
- data/lib/skylight/helpers.rb +46 -26
- data/lib/skylight/instrumenter.rb +25 -18
- data/lib/skylight/middleware.rb +31 -35
- data/lib/skylight/native.rb +8 -10
- data/lib/skylight/native_ext_fetcher.rb +10 -12
- data/lib/skylight/normalizers.rb +43 -39
- data/lib/skylight/normalizers/action_controller/process_action.rb +24 -25
- data/lib/skylight/normalizers/action_controller/send_file.rb +7 -6
- data/lib/skylight/normalizers/action_dispatch/route_set.rb +7 -7
- data/lib/skylight/normalizers/active_job/perform.rb +48 -44
- data/lib/skylight/normalizers/active_model_serializers/render.rb +7 -3
- data/lib/skylight/normalizers/active_storage.rb +11 -13
- data/lib/skylight/normalizers/active_support/cache.rb +1 -12
- data/lib/skylight/normalizers/coach/handler_finish.rb +1 -3
- data/lib/skylight/normalizers/default.rb +1 -9
- data/lib/skylight/normalizers/faraday/request.rb +1 -3
- data/lib/skylight/normalizers/grape/endpoint.rb +13 -19
- data/lib/skylight/normalizers/grape/endpoint_run.rb +16 -18
- data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +1 -3
- data/lib/skylight/normalizers/graphql/base.rb +23 -28
- data/lib/skylight/normalizers/render.rb +19 -21
- data/lib/skylight/normalizers/shrine.rb +15 -17
- data/lib/skylight/normalizers/sql.rb +4 -4
- data/lib/skylight/probes.rb +38 -46
- data/lib/skylight/probes/action_controller.rb +32 -28
- data/lib/skylight/probes/action_dispatch/request_id.rb +9 -5
- data/lib/skylight/probes/action_dispatch/routing/route_set.rb +7 -5
- data/lib/skylight/probes/action_view.rb +9 -10
- data/lib/skylight/probes/active_job_enqueue.rb +3 -9
- data/lib/skylight/probes/active_model_serializers.rb +8 -8
- data/lib/skylight/probes/delayed_job.rb +37 -42
- data/lib/skylight/probes/elasticsearch.rb +3 -5
- data/lib/skylight/probes/excon.rb +1 -1
- data/lib/skylight/probes/excon/middleware.rb +22 -23
- data/lib/skylight/probes/graphql.rb +2 -7
- data/lib/skylight/probes/middleware.rb +14 -5
- data/lib/skylight/probes/mongo.rb +83 -91
- data/lib/skylight/probes/net_http.rb +1 -1
- data/lib/skylight/probes/redis.rb +5 -17
- data/lib/skylight/probes/sequel.rb +7 -11
- data/lib/skylight/probes/sinatra.rb +8 -5
- data/lib/skylight/probes/tilt.rb +2 -4
- data/lib/skylight/railtie.rb +121 -135
- data/lib/skylight/sidekiq.rb +4 -5
- data/lib/skylight/subscriber.rb +31 -33
- data/lib/skylight/test.rb +89 -84
- data/lib/skylight/trace.rb +121 -115
- data/lib/skylight/user_config.rb +14 -17
- data/lib/skylight/util/clock.rb +1 -0
- data/lib/skylight/util/component.rb +18 -21
- data/lib/skylight/util/deploy.rb +11 -13
- data/lib/skylight/util/http.rb +104 -105
- data/lib/skylight/util/logging.rb +4 -6
- data/lib/skylight/util/lru_cache.rb +2 -6
- data/lib/skylight/util/platform.rb +2 -6
- data/lib/skylight/util/ssl.rb +1 -25
- data/lib/skylight/version.rb +1 -1
- data/lib/skylight/vm/gc.rb +1 -9
- metadata +19 -5
data/lib/skylight/cli/doctor.rb
CHANGED
@@ -25,7 +25,8 @@ module Skylight
|
|
25
25
|
say "Alternatively, try setting `SKYLIGHT_FORCE_OWN_CERTS=1` in your environment.", :yellow
|
26
26
|
else
|
27
27
|
say "Please update your local certificates or try setting `SKYLIGHT_FORCE_OWN_CERTS=1` in your " \
|
28
|
-
|
28
|
+
"environment.",
|
29
|
+
:yellow
|
29
30
|
end
|
30
31
|
end
|
31
32
|
else
|
@@ -66,9 +67,7 @@ module Skylight
|
|
66
67
|
indent do
|
67
68
|
install_log = File.expand_path("../../ext/install.log", __dir__)
|
68
69
|
if File.exist?(install_log)
|
69
|
-
File.readlines(install_log).each
|
70
|
-
say line, :red
|
71
|
-
end
|
70
|
+
File.readlines(install_log).each { |line| say line, :red }
|
72
71
|
else
|
73
72
|
say "Reason unknown", :red
|
74
73
|
end
|
@@ -108,13 +107,16 @@ module Skylight
|
|
108
107
|
indent do
|
109
108
|
# Set this after we validate. It will give us more detailed information on start.
|
110
109
|
logger = Logger.new("/dev/null") # Rely on `say` in the formatter instead
|
110
|
+
|
111
111
|
# Log everything
|
112
112
|
logger.level = Logger::DEBUG
|
113
|
+
|
113
114
|
# Remove excess formatting
|
114
|
-
logger.formatter =
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
logger.formatter =
|
116
|
+
proc do |severity, _datetime, _progname, msg|
|
117
|
+
msg = msg.sub("[SKYLIGHT] [#{Skylight::VERSION}] ", "")
|
118
|
+
say "#{severity} - #{msg}" # Definitely non-standard
|
119
|
+
end
|
118
120
|
config.logger = logger
|
119
121
|
|
120
122
|
config.set(:'daemon.lazy_start', false)
|
@@ -165,57 +167,55 @@ module Skylight
|
|
165
167
|
|
166
168
|
private
|
167
169
|
|
168
|
-
|
169
|
-
|
170
|
-
|
170
|
+
# Overwrite the default helper method to load from Rails
|
171
|
+
def config
|
172
|
+
return @config if @config
|
171
173
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
# MEGAHAX
|
175
|
+
if rails?
|
176
|
+
# Normally auto-loaded, but we haven't loaded Rails by the time Skylight is loaded
|
177
|
+
require "skylight/railtie"
|
178
|
+
require rails_rb
|
177
179
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def mac?
|
186
|
-
Util::Platform::OS == "darwin"
|
180
|
+
railtie = Skylight::Railtie.send(:new)
|
181
|
+
@config = railtie.send(:load_skylight_config, Rails.application)
|
182
|
+
else
|
183
|
+
super
|
187
184
|
end
|
185
|
+
end
|
188
186
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
@has_rvm = system("which rvm > /dev/null")
|
193
|
-
end
|
194
|
-
@has_rvm
|
195
|
-
end
|
187
|
+
def mac?
|
188
|
+
Util::Platform::OS == "darwin"
|
189
|
+
end
|
196
190
|
|
197
|
-
|
198
|
-
|
199
|
-
|
191
|
+
# NOTE: This check won't work correctly on Windows
|
192
|
+
def rvm_present?
|
193
|
+
@has_rvm = system("which rvm > /dev/null") if @has_rvm.nil?
|
194
|
+
@has_rvm
|
195
|
+
end
|
200
196
|
|
201
|
-
|
202
|
-
|
203
|
-
|
197
|
+
def encountered_error!
|
198
|
+
@has_errors = true
|
199
|
+
end
|
204
200
|
|
205
|
-
|
206
|
-
|
207
|
-
|
201
|
+
def has_errors?
|
202
|
+
@has_errors
|
203
|
+
end
|
208
204
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
205
|
+
def done!
|
206
|
+
shell.padding = 0
|
207
|
+
say "\n\n"
|
208
|
+
|
209
|
+
if has_errors?
|
210
|
+
say "Skylight Doctor found some errors. Please review the output above.", :red
|
211
|
+
say "If you have any further questions, please contact support@skylight.io.", :yellow
|
212
|
+
exit 1
|
213
|
+
else
|
214
|
+
say "All checks passed!", :green
|
215
|
+
say "If you're still having trouble, please contact support@skylight.io.", :yellow
|
216
|
+
exit 0
|
218
217
|
end
|
218
|
+
end
|
219
219
|
end
|
220
220
|
end
|
221
221
|
end
|
data/lib/skylight/cli/helpers.rb
CHANGED
@@ -3,28 +3,28 @@ module Skylight
|
|
3
3
|
module Helpers
|
4
4
|
private
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
# Duplicated below
|
7
|
+
def rails_rb
|
8
|
+
File.expand_path("config/application.rb")
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def rails?
|
12
|
+
File.exist?(rails_rb)
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def config
|
16
|
+
# Calling .load checks ENV variables
|
17
|
+
@config ||= Config.load
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
# Sets the output padding while executing a block and resets it.
|
21
|
+
#
|
22
|
+
def indent(count = 1)
|
23
|
+
orig_padding = shell.padding
|
24
|
+
shell.padding += count
|
25
|
+
yield
|
26
|
+
shell.padding = orig_padding
|
27
|
+
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
data/lib/skylight/cli/merger.rb
CHANGED
@@ -14,7 +14,7 @@ module Skylight
|
|
14
14
|
|
15
15
|
STRINGS = {
|
16
16
|
get_token: "get your merge token from `https://www.skylight.io/merging`",
|
17
|
-
unlisted:
|
17
|
+
unlisted: "My app isn't listed here :("
|
18
18
|
}.freeze
|
19
19
|
|
20
20
|
argument :merge_token, type: :string, desc: STRINGS[:get_token]
|
@@ -23,8 +23,8 @@ module Skylight
|
|
23
23
|
say "\nHello! Welcome to the `skylight merge` CLI!\n", :green
|
24
24
|
|
25
25
|
say "This CLI is for Skylight users who already have Skylight Environments set up\n" \
|
26
|
-
|
27
|
-
|
26
|
+
"using the legacy method of creating a separate Skylight app per environment.\n" \
|
27
|
+
"Use this CLI to merge legacy environment apps into their parent apps as Environments."
|
28
28
|
end
|
29
29
|
|
30
30
|
def fetch_apps
|
@@ -40,23 +40,24 @@ module Skylight
|
|
40
40
|
rescue Skylight::Api::Unauthorized
|
41
41
|
done!(
|
42
42
|
success: false,
|
43
|
-
message:
|
44
|
-
"
|
45
|
-
|
43
|
+
message:
|
44
|
+
"Provided merge token is invalid.\n" \
|
45
|
+
"Please #{STRINGS[:get_token]}" \
|
46
|
+
"and run `skylight merge <merge token>` again."
|
46
47
|
)
|
47
48
|
end
|
48
49
|
|
49
50
|
def ask_for_parent_app
|
50
|
-
@parents ||=
|
51
|
-
|
52
|
-
|
53
|
-
h[i + 1] = OpenStruct.new(app)
|
51
|
+
@parents ||=
|
52
|
+
begin
|
53
|
+
a = (@apps + [{ name: STRINGS[:unlisted], components: [], unlisted: true }])
|
54
|
+
a.each_with_object({}).with_index { |(app, h), i| h[i + 1] = OpenStruct.new(app) }
|
54
55
|
end
|
55
|
-
end
|
56
56
|
|
57
57
|
say "\nLet's begin!\n\n" \
|
58
|
-
|
59
|
-
|
58
|
+
"Please specify the \"parent\" app.\n" \
|
59
|
+
"In most cases, this will be the production app handling web requests.",
|
60
|
+
:green
|
60
61
|
|
61
62
|
@parent_app = ask_for_app(@parents)
|
62
63
|
end
|
@@ -76,8 +77,9 @@ module Skylight
|
|
76
77
|
|
77
78
|
def ask_for_child_env
|
78
79
|
say "\nWhat environment is the child app?\n" \
|
79
|
-
|
80
|
-
|
80
|
+
"In many cases, this will be equivalent to the Rails " \
|
81
|
+
"environment, i.e., `development`.",
|
82
|
+
:green
|
81
83
|
|
82
84
|
say "1. development"
|
83
85
|
say "2. staging"
|
@@ -85,15 +87,18 @@ module Skylight
|
|
85
87
|
|
86
88
|
i = ask("\nWhich number?").chomp.to_i
|
87
89
|
|
88
|
-
@child_env =
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
90
|
+
@child_env =
|
91
|
+
case i
|
92
|
+
when 1
|
93
|
+
"development"
|
94
|
+
when 2
|
95
|
+
"staging"
|
96
|
+
when 3
|
97
|
+
specify_child_env
|
98
|
+
else
|
99
|
+
say("\nEh? Please enter 1, 2, or 3.", :red)
|
100
|
+
ask_for_child_env
|
101
|
+
end
|
97
102
|
end
|
98
103
|
|
99
104
|
def confirm_child_env
|
@@ -102,7 +107,7 @@ module Skylight
|
|
102
107
|
|
103
108
|
def confirm_everything
|
104
109
|
say "\nOk! Now we're going to merge `#{set_color(format_component(@child_app), :yellow)}` " \
|
105
|
-
|
110
|
+
"into `#{set_color(@parent_app.name, :green)}` as `#{set_color(@child_env, :yellow)}`."
|
106
111
|
end
|
107
112
|
|
108
113
|
def do_confirm
|
@@ -112,10 +117,7 @@ module Skylight
|
|
112
117
|
when "Y", ""
|
113
118
|
do_merge
|
114
119
|
when "N"
|
115
|
-
done!(
|
116
|
-
success: true,
|
117
|
-
message: "Ok, come back any time."
|
118
|
-
)
|
120
|
+
done!(success: true, message: "Ok, come back any time.")
|
119
121
|
else
|
120
122
|
say("Please respond 'Y' to merge or 'n' to cancel.", :red)
|
121
123
|
do_confirm
|
@@ -128,37 +130,43 @@ module Skylight
|
|
128
130
|
say "=======================================================\n", :yellow
|
129
131
|
|
130
132
|
say "IMPORTANT!\n" \
|
131
|
-
|
133
|
+
"If you use a config/skylight.yml file to configure Skylight:\n",
|
134
|
+
:yellow
|
132
135
|
|
133
136
|
say "The #{@child_env} environment for the #{@parent_app.name} app\n" \
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
+
"will now connect using the default authentication token for the app.\n" \
|
138
|
+
"Remove any environment-specific `authentication` configs from the\n" \
|
139
|
+
"#{@parent_app.name} #{@child_env} environment.\n",
|
140
|
+
:yellow
|
137
141
|
|
138
142
|
say "If you're running in Rails and your Rails environment exactly matches `#{@child_env}`,\n" \
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
143
|
+
"we will automatically detect and report that environment when your agent connects.\n" \
|
144
|
+
"Otherwise, you should set `env: '#{@child_env}'` as environment-specific configuration for\n" \
|
145
|
+
"#{@child_env}'s Rails environment. For example:\n" \
|
146
|
+
"```yml\n" \
|
147
|
+
"staging:\n" \
|
148
|
+
" env: staging-42\n" \
|
149
|
+
"```\n",
|
150
|
+
:yellow
|
146
151
|
|
147
152
|
say "=======================================================\n", :yellow
|
148
153
|
|
149
154
|
say "IMPORTANT!\n" \
|
150
|
-
|
155
|
+
"If you configure Skylight using environment variables:\n",
|
156
|
+
:yellow
|
151
157
|
|
152
158
|
say "Deploy the latest agent before updating your environment variables.\n", :yellow
|
153
159
|
|
154
160
|
say "The #{@child_env} environment for the #{@parent_app.name} app\n" \
|
155
|
-
|
156
|
-
|
157
|
-
|
161
|
+
"will now connect using the default authentication token for the app.\n" \
|
162
|
+
"Set `SKYLIGHT_AUTHENTICATION` in the #{@child_env} environment to the\n" \
|
163
|
+
"#{@parent_app.name} app's authentication token.\n",
|
164
|
+
:yellow
|
158
165
|
|
159
166
|
say "If you're running in Rails and your Rails environment exactly matches `#{@child_env}`,\n" \
|
160
|
-
|
161
|
-
|
167
|
+
"we will automatically detect and report that environment when your agent connects.\n" \
|
168
|
+
"Otherwise, you should set `SKYLIGHT_ENV=#{@child_env}` when running in this environment.\n",
|
169
|
+
:yellow
|
162
170
|
|
163
171
|
say "=======================================================", :yellow
|
164
172
|
|
@@ -167,136 +175,130 @@ module Skylight
|
|
167
175
|
|
168
176
|
private
|
169
177
|
|
170
|
-
|
171
|
-
|
178
|
+
def do_merge
|
179
|
+
say "Merging..."
|
172
180
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
+
api.merge_apps!(
|
182
|
+
@merge_token,
|
183
|
+
app_guid: @parent_app.guid,
|
184
|
+
component_guid: @child_app.guid,
|
185
|
+
environment: @child_env
|
186
|
+
)
|
187
|
+
rescue StandardError => e
|
188
|
+
say("Something went wrong. Please contact support@skylight.io for more information.", :red)
|
189
|
+
done!(message: e.message, success: false)
|
190
|
+
end
|
181
191
|
|
182
|
-
|
183
|
-
|
184
|
-
|
192
|
+
def done!(message: nil, success: true)
|
193
|
+
shell.padding = 0
|
194
|
+
say "\n"
|
185
195
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
end
|
196
|
+
if success
|
197
|
+
say(message, :green) if message
|
198
|
+
say "If you have any questions, please contact support@skylight.io.", :green
|
199
|
+
exit 0
|
200
|
+
else
|
201
|
+
say message || "Skylight wasn't able to merge your apps.", :red
|
202
|
+
say "If you have any questions, please contact support@skylight.io.", :yellow
|
203
|
+
exit 1
|
195
204
|
end
|
205
|
+
end
|
196
206
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
say("\t#{index}. #{formatter.call(app)}")
|
201
|
-
end
|
207
|
+
def ask_for_app(app_list, &formatter)
|
208
|
+
formatter ||= :name.to_proc
|
209
|
+
app_list.each { |index, app| say("\t#{index}. #{formatter.call(app)}") }
|
202
210
|
|
203
|
-
|
211
|
+
n = ask("\nWhich number?").chomp.to_i
|
204
212
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
)
|
213
|
-
else
|
214
|
-
app_list[n]
|
215
|
-
end
|
213
|
+
if !app_list.key?(n)
|
214
|
+
say "\nHmm?"
|
215
|
+
ask_for_app(app_list, &formatter)
|
216
|
+
elsif app_list[n].unlisted
|
217
|
+
done!(success: false, message: "Sorry, `skylight merge` is only able to merge apps that you own.")
|
218
|
+
else
|
219
|
+
app_list[n]
|
216
220
|
end
|
221
|
+
end
|
217
222
|
|
218
|
-
|
219
|
-
|
220
|
-
|
223
|
+
def api
|
224
|
+
@api ||= Skylight::Api.new(config)
|
225
|
+
end
|
221
226
|
|
222
|
-
|
223
|
-
|
227
|
+
def format_component(component)
|
228
|
+
parts =
|
229
|
+
[].tap do |ary|
|
224
230
|
ary << component.name unless component.name == "web"
|
225
231
|
ary << component.environment unless component.environment == "production"
|
226
232
|
end
|
227
233
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
234
|
+
str = ""
|
235
|
+
str << component.app_name
|
236
|
+
str << Thor::Shell::Color.new.set_color(" (#{parts.join(":")})", :yellow) if parts.any?
|
237
|
+
str
|
238
|
+
end
|
233
239
|
|
234
|
-
|
235
|
-
|
240
|
+
def validate_mergeability(child_app, child_env)
|
241
|
+
errors = []
|
236
242
|
|
237
|
-
|
238
|
-
|
239
|
-
|
243
|
+
unless valid_component?(child_app.name, child_env)
|
244
|
+
errors << "Environment can only contain letters, numbers, and hyphens."
|
245
|
+
end
|
240
246
|
|
241
|
-
|
242
|
-
|
247
|
+
if @parent_app && parent_component_fingerprints.include?([child_app.name, child_env])
|
248
|
+
errors <<
|
249
|
+
"Sorry, `#{@parent_app.name}` already has a `#{child_env}` " \
|
243
250
|
"component that conflicts with this merge request. Please choose a new environment."
|
244
|
-
|
251
|
+
end
|
245
252
|
|
246
|
-
|
253
|
+
return child_env unless errors.any?
|
247
254
|
|
248
|
-
|
255
|
+
say errors.join("\n"), :red
|
249
256
|
|
250
|
-
|
251
|
-
|
257
|
+
yield
|
258
|
+
end
|
252
259
|
|
253
|
-
|
254
|
-
|
260
|
+
def valid_component?(component_name, env)
|
261
|
+
return false unless env
|
255
262
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
263
|
+
Util::Component.new(env, component_name) && true
|
264
|
+
rescue ArgumentError
|
265
|
+
false
|
266
|
+
end
|
260
267
|
|
261
|
-
|
262
|
-
|
263
|
-
|
268
|
+
def parent_component_fingerprints
|
269
|
+
@parent_app.components.map { |x| x.values_at("name", "environment") }
|
270
|
+
end
|
264
271
|
|
265
|
-
|
266
|
-
|
272
|
+
def children
|
273
|
+
ret =
|
274
|
+
Enumerator.new do |yielder|
|
267
275
|
@parents.each do |_, app|
|
268
276
|
next if app == @parent_app
|
269
277
|
|
270
|
-
app.components.each
|
271
|
-
yielder << OpenStruct.new({ app_name: app.name }.merge(component))
|
272
|
-
end
|
278
|
+
app.components.each { |component| yielder << OpenStruct.new({ app_name: app.name }.merge(component)) }
|
273
279
|
end
|
274
280
|
|
275
281
|
yielder << OpenStruct.new(app_name: STRINGS[:unlisted], unlisted: true)
|
276
282
|
end
|
277
283
|
|
278
|
-
|
279
|
-
r[i + 1] = c
|
280
|
-
end
|
284
|
+
ret = ret.each_with_object({}).with_index { |(c, r), i| r[i + 1] = c }
|
281
285
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
end
|
286
|
+
ret.tap do |result|
|
287
|
+
if result.values.all?(&:unlisted)
|
288
|
+
done!(
|
289
|
+
success: false,
|
290
|
+
message: "Sorry, you do not have any apps that can be merged into `#{@parent_app.name}`"
|
291
|
+
)
|
289
292
|
end
|
290
293
|
end
|
294
|
+
end
|
291
295
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
end
|
299
|
-
end
|
296
|
+
def specify_child_env
|
297
|
+
validate_mergeability(
|
298
|
+
@child_app,
|
299
|
+
ask("Please enter your environment name (only lowercase letters, numbers, or hyphens): ", :green).chomp
|
300
|
+
) { specify_child_env }
|
301
|
+
end
|
300
302
|
end
|
301
303
|
end
|
302
304
|
end
|