shopify-cli 1.0.5 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/CONTRIBUTING.md +1 -1
- data/CHANGELOG.md +20 -0
- data/bin/load_shopify.rb +3 -1
- data/bin/shopify +2 -0
- data/docs/core/index.md +16 -0
- data/docs/getting-started/index.md +3 -2
- data/docs/getting-started/install/index.md +55 -9
- data/docs/getting-started/uninstall/index.md +1 -1
- data/docs/getting-started/upgrade/index.md +8 -4
- data/ext/shopify-cli/extconf.rb +40 -20
- data/lib/project_types/extension/cli.rb +6 -1
- data/lib/project_types/extension/commands/register.rb +1 -1
- data/lib/project_types/extension/features/argo/admin.rb +20 -0
- data/lib/project_types/extension/features/argo/base.rb +129 -0
- data/lib/project_types/extension/features/argo/checkout.rb +20 -0
- data/lib/project_types/extension/features/argo_config.rb +60 -0
- data/lib/project_types/extension/messages/messages.rb +11 -2
- data/lib/project_types/extension/models/type.rb +4 -0
- data/lib/project_types/extension/models/types/checkout_post_purchase.rb +6 -3
- data/lib/project_types/extension/models/types/product_subscription.rb +24 -0
- data/lib/project_types/node/commands/create.rb +4 -4
- data/lib/project_types/node/commands/deploy/heroku.rb +6 -1
- data/lib/project_types/node/commands/generate/billing.rb +7 -5
- data/lib/project_types/node/commands/generate/page.rb +9 -5
- data/lib/project_types/node/commands/generate/webhook.rb +5 -1
- data/lib/project_types/node/commands/serve.rb +5 -5
- data/lib/project_types/node/messages/messages.rb +5 -1
- data/lib/project_types/rails/commands/create.rb +56 -5
- data/lib/project_types/rails/commands/generate.rb +1 -0
- data/lib/project_types/rails/commands/generate/webhook.rb +3 -2
- data/lib/project_types/rails/commands/serve.rb +11 -7
- data/lib/project_types/rails/gem.rb +61 -6
- data/lib/project_types/rails/messages/messages.rb +32 -12
- data/lib/project_types/script/config/extension_points.yml +4 -4
- data/lib/project_types/script/forms/create.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +36 -1
- data/lib/project_types/script/layers/infrastructure/errors.rb +7 -0
- data/lib/project_types/script/layers/infrastructure/script_service.rb +6 -2
- data/lib/project_types/script/messages/messages.rb +12 -37
- data/lib/project_types/script/ui/error_handler.rb +13 -5
- data/lib/rubygems_plugin.rb +18 -10
- data/lib/shopify-cli/admin_api/populate_resource_command.rb +1 -1
- data/lib/shopify-cli/commands/config.rb +33 -1
- data/lib/shopify-cli/commands/connect.rb +1 -1
- data/lib/shopify-cli/commands/system.rb +9 -8
- data/lib/shopify-cli/context.rb +68 -0
- data/lib/shopify-cli/core/entry_point.rb +3 -0
- data/lib/shopify-cli/git.rb +1 -1
- data/lib/shopify-cli/heroku.rb +18 -2
- data/lib/shopify-cli/js_deps.rb +2 -2
- data/lib/shopify-cli/js_system.rb +24 -7
- data/lib/shopify-cli/messages/messages.rb +39 -11
- data/lib/shopify-cli/process_supervision.rb +52 -15
- data/lib/shopify-cli/project.rb +17 -9
- data/lib/shopify-cli/tunnel.rb +19 -4
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +6 -2
- data/shopify-cli.gemspec +4 -1
- data/vendor/deps/cli-kit/REVISION +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit.rb +1 -1
- data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +2 -2
- data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +12 -6
- data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +9 -11
- data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +8 -2
- data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +7 -7
- data/vendor/deps/cli-kit/lib/cli/kit/system.rb +48 -17
- data/vendor/deps/cli-ui/REVISION +1 -1
- data/vendor/deps/cli-ui/lib/cli/ui.rb +5 -4
- data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +9 -3
- data/vendor/deps/cli-ui/lib/cli/ui/color.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -2
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +13 -5
- data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +29 -2
- data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +21 -10
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +63 -0
- data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +11 -2
- data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +1 -0
- data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -3
- data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +6 -8
- data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +2 -0
- data/vendor/gen/lib/gen.rb +39 -0
- data/vendor/gen/lib/gen/commands.rb +18 -0
- data/vendor/gen/lib/gen/commands/help.rb +20 -0
- data/vendor/gen/lib/gen/commands/new.rb +21 -0
- data/vendor/gen/lib/gen/entry_point.rb +10 -0
- data/vendor/gen/lib/gen/generator.rb +165 -0
- data/vendor/gen/template/.gitignore +2 -0
- data/vendor/gen/template/Gemfile +10 -0
- data/vendor/gen/template/README.md +1 -0
- data/vendor/gen/template/bin/testunit +23 -0
- data/vendor/gen/template/bin/update-deps +97 -0
- data/vendor/gen/template/dev-gems.yml +3 -0
- data/vendor/gen/template/dev-vendor.yml +4 -0
- data/vendor/gen/template/exe/__app__-gems +17 -0
- data/vendor/gen/template/exe/__app__-vendor +18 -0
- data/vendor/gen/template/lib/__app__.rb +33 -0
- data/vendor/gen/template/lib/__app__/commands.rb +18 -0
- data/vendor/gen/template/lib/__app__/commands/example.rb +19 -0
- data/vendor/gen/template/lib/__app__/commands/help.rb +21 -0
- data/vendor/gen/template/lib/__app__/entry_point.rb +10 -0
- data/vendor/gen/template/test/example_test.rb +17 -0
- data/vendor/gen/template/test/test_helper.rb +22 -0
- metadata +30 -6
- data/Vagrantfile +0 -17
- data/lib/project_types/extension/features/argo.rb +0 -48
- data/lib/project_types/extension/models/types/subscription_management.rb +0 -20
- data/lib/project_types/script/forms/script_form.rb +0 -69
|
@@ -8,7 +8,7 @@ module ShopifyCli
|
|
|
8
8
|
# a string or a symbol to identify this process by
|
|
9
9
|
attr_reader :identifier
|
|
10
10
|
# process ID for the running process
|
|
11
|
-
|
|
11
|
+
attr_accessor :pid
|
|
12
12
|
# starttime of the process
|
|
13
13
|
attr_reader :time
|
|
14
14
|
# filepath to the pidfile for this process
|
|
@@ -58,15 +58,37 @@ module ShopifyCli
|
|
|
58
58
|
#
|
|
59
59
|
def start(identifier, args)
|
|
60
60
|
return for_ident(identifier) if running?(identifier)
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
|
|
62
|
+
# Windows doesn't support forking process without extra gems, so we resort to spawning a new child process -
|
|
63
|
+
# that means that it dies along with the original process if it is interrupted. On UNIX, we fork the process so
|
|
64
|
+
# that it doesn't have to be restarted on every run.
|
|
65
|
+
if Context.new.windows?
|
|
66
|
+
pid_file = new(identifier)
|
|
67
|
+
|
|
68
|
+
# Make sure the file exists and is empty, otherwise Windows fails
|
|
69
|
+
File.open(pid_file.log_path, 'w') {}
|
|
70
|
+
pid = Process.spawn(
|
|
71
|
+
*args,
|
|
72
|
+
out: pid_file.log_path,
|
|
73
|
+
err: pid_file.log_path,
|
|
74
|
+
in: Context.new.windows? ? "nul" : "/dev/null",
|
|
75
|
+
)
|
|
76
|
+
pid_file.pid = pid
|
|
63
77
|
pid_file.write
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
78
|
+
|
|
79
|
+
Process.detach(pid)
|
|
80
|
+
else
|
|
81
|
+
fork do
|
|
82
|
+
pid_file = new(identifier, pid: Process.pid)
|
|
83
|
+
pid_file.write
|
|
84
|
+
STDOUT.reopen(pid_file.log_path, "w")
|
|
85
|
+
STDERR.reopen(pid_file.log_path, "w")
|
|
86
|
+
STDIN.reopen("/dev/null", "r")
|
|
87
|
+
Process.setsid
|
|
88
|
+
exec(*args)
|
|
89
|
+
end
|
|
69
90
|
end
|
|
91
|
+
|
|
70
92
|
sleep(0.1)
|
|
71
93
|
for_ident(identifier)
|
|
72
94
|
end
|
|
@@ -106,10 +128,11 @@ module ShopifyCli
|
|
|
106
128
|
end
|
|
107
129
|
end
|
|
108
130
|
|
|
109
|
-
def initialize(identifier, pid
|
|
131
|
+
def initialize(identifier, pid: nil, time: Time.now.strftime('%s')) # :nodoc:
|
|
110
132
|
@identifier = identifier
|
|
111
133
|
@pid = pid
|
|
112
134
|
@time = time
|
|
135
|
+
FileUtils.mkdir_p(ShopifyCli::ProcessSupervision.run_dir)
|
|
113
136
|
@pid_path = File.join(ShopifyCli::ProcessSupervision.run_dir, "#{identifier}.pid")
|
|
114
137
|
@log_path = File.join(ShopifyCli::ProcessSupervision.run_dir, "#{identifier}.log")
|
|
115
138
|
end
|
|
@@ -117,13 +140,17 @@ module ShopifyCli
|
|
|
117
140
|
##
|
|
118
141
|
# will attempt to shutdown a running process
|
|
119
142
|
#
|
|
143
|
+
# #### Parameters
|
|
144
|
+
#
|
|
145
|
+
# * `ctx` - the context of this command
|
|
146
|
+
#
|
|
120
147
|
# #### Returns
|
|
121
148
|
#
|
|
122
149
|
# * `stopped` - [true, false]
|
|
123
150
|
#
|
|
124
151
|
def stop
|
|
125
|
-
unlink
|
|
126
152
|
kill_proc
|
|
153
|
+
unlink
|
|
127
154
|
true
|
|
128
155
|
rescue
|
|
129
156
|
false
|
|
@@ -159,7 +186,11 @@ module ShopifyCli
|
|
|
159
186
|
end
|
|
160
187
|
|
|
161
188
|
def kill_proc
|
|
162
|
-
|
|
189
|
+
if Context.new.windows?
|
|
190
|
+
kill(pid)
|
|
191
|
+
else
|
|
192
|
+
kill(-pid) # process group
|
|
193
|
+
end
|
|
163
194
|
rescue Errno::ESRCH
|
|
164
195
|
begin
|
|
165
196
|
kill(pid)
|
|
@@ -169,12 +200,18 @@ module ShopifyCli
|
|
|
169
200
|
end
|
|
170
201
|
|
|
171
202
|
def kill(id)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
203
|
+
ctx = Context.new
|
|
204
|
+
|
|
205
|
+
# Windows does not handle SIGTERM, go straight to SIGKILL
|
|
206
|
+
unless ctx.windows?
|
|
207
|
+
Process.kill('TERM', id)
|
|
208
|
+
50.times do
|
|
209
|
+
sleep 0.1
|
|
210
|
+
break unless stat(id)
|
|
211
|
+
end
|
|
176
212
|
end
|
|
177
213
|
Process.kill('KILL', id) if stat(id)
|
|
214
|
+
sleep(0.1) if ctx.windows? # Give Windows a second to actually close the process
|
|
178
215
|
end
|
|
179
216
|
|
|
180
217
|
def stat(id)
|
data/lib/shopify-cli/project.rb
CHANGED
|
@@ -15,6 +15,10 @@ module ShopifyCli
|
|
|
15
15
|
# will get an instance of the project that the user is currently operating
|
|
16
16
|
# on. This is used for access to project resources.
|
|
17
17
|
#
|
|
18
|
+
# #### Parameters
|
|
19
|
+
#
|
|
20
|
+
# * `force_reload` - whether to force a reload of the project files
|
|
21
|
+
#
|
|
18
22
|
# #### Returns
|
|
19
23
|
#
|
|
20
24
|
# * `project` - a Project instance if the user is currently in the project.
|
|
@@ -29,8 +33,8 @@ module ShopifyCli
|
|
|
29
33
|
#
|
|
30
34
|
# project = ShopifyCli::Project.current
|
|
31
35
|
#
|
|
32
|
-
def current
|
|
33
|
-
at(Dir.pwd)
|
|
36
|
+
def current(force_reload: false)
|
|
37
|
+
at(Dir.pwd, force_reload: force_reload)
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
##
|
|
@@ -93,13 +97,17 @@ module ShopifyCli
|
|
|
93
97
|
|
|
94
98
|
private
|
|
95
99
|
|
|
96
|
-
def directory(dir)
|
|
100
|
+
def directory(dir, force_reload: false)
|
|
101
|
+
@dir = nil if force_reload
|
|
102
|
+
|
|
97
103
|
@dir ||= Hash.new { |h, k| h[k] = __directory(k) }
|
|
98
104
|
@dir[dir]
|
|
99
105
|
end
|
|
100
106
|
|
|
101
|
-
def at(dir)
|
|
102
|
-
|
|
107
|
+
def at(dir, force_reload: false)
|
|
108
|
+
@at = nil if force_reload
|
|
109
|
+
|
|
110
|
+
proj_dir = directory(dir, force_reload: force_reload)
|
|
103
111
|
unless proj_dir
|
|
104
112
|
raise(ShopifyCli::Abort, Context.message('core.project.error.not_in_project'))
|
|
105
113
|
end
|
|
@@ -109,7 +117,7 @@ module ShopifyCli
|
|
|
109
117
|
|
|
110
118
|
def __directory(curr)
|
|
111
119
|
loop do
|
|
112
|
-
return nil if curr == '/'
|
|
120
|
+
return nil if curr == '/' || /^[A-Z]:\/$/.match?(curr)
|
|
113
121
|
file = File.join(curr, '.shopify-cli.yml')
|
|
114
122
|
return curr if File.exist?(file)
|
|
115
123
|
curr = File.dirname(curr)
|
|
@@ -158,7 +166,7 @@ module ShopifyCli
|
|
|
158
166
|
@config ||= begin
|
|
159
167
|
config = load_yaml_file('.shopify-cli.yml')
|
|
160
168
|
unless config.is_a?(Hash)
|
|
161
|
-
raise ShopifyCli::Abort, Context.message('core.
|
|
169
|
+
raise ShopifyCli::Abort, Context.message('core.yaml.error.not_hash', '.shopify-cli.yml')
|
|
162
170
|
end
|
|
163
171
|
|
|
164
172
|
# The app_type key was deprecated in favour of project_type, so replace it
|
|
@@ -179,12 +187,12 @@ module ShopifyCli
|
|
|
179
187
|
begin
|
|
180
188
|
YAML.load_file(f)
|
|
181
189
|
rescue Psych::SyntaxError => e
|
|
182
|
-
raise(ShopifyCli::Abort, Context.message('core.
|
|
190
|
+
raise(ShopifyCli::Abort, Context.message('core.yaml.error.invalid', relative_path, e.message))
|
|
183
191
|
# rescue Errno::EACCES => e
|
|
184
192
|
# TODO
|
|
185
193
|
# Dev::Helpers::EaccesHandler.diagnose_and_raise(f, e, mode: :read)
|
|
186
194
|
rescue Errno::ENOENT
|
|
187
|
-
raise ShopifyCli::Abort, Context.message('core.
|
|
195
|
+
raise ShopifyCli::Abort, Context.message('core.yaml.error.not_found', f)
|
|
188
196
|
end
|
|
189
197
|
end
|
|
190
198
|
end
|
data/lib/shopify-cli/tunnel.rb
CHANGED
|
@@ -21,6 +21,7 @@ module ShopifyCli
|
|
|
21
21
|
DOWNLOAD_URLS = {
|
|
22
22
|
mac: 'https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip',
|
|
23
23
|
linux: 'https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip',
|
|
24
|
+
windows: 'https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-windows-amd64.zip',
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
NGROK_TUNNELS_URI = URI.parse('http://localhost:4040/api/tunnels')
|
|
@@ -122,14 +123,21 @@ module ShopifyCli
|
|
|
122
123
|
private
|
|
123
124
|
|
|
124
125
|
def install(ctx)
|
|
125
|
-
return if File.exist?(File.join(ShopifyCli.cache_dir, 'ngrok'))
|
|
126
|
+
return if File.exist?(File.join(ShopifyCli.cache_dir, ctx.windows? ? 'ngrok.exe' : 'ngrok'))
|
|
127
|
+
check_prereq_command(ctx, 'curl')
|
|
128
|
+
check_prereq_command(ctx, ctx.linux? ? 'unzip' : 'tar')
|
|
126
129
|
spinner = CLI::UI::SpinGroup.new
|
|
127
130
|
spinner.add('Installing ngrok...') do
|
|
128
131
|
zip_dest = File.join(ShopifyCli.cache_dir, 'ngrok.zip')
|
|
129
132
|
unless File.exist?(zip_dest)
|
|
130
133
|
ctx.system('curl', '-o', zip_dest, DOWNLOAD_URLS[ctx.os], chdir: ShopifyCli.cache_dir)
|
|
131
134
|
end
|
|
132
|
-
|
|
135
|
+
args = if ctx.linux?
|
|
136
|
+
%W(unzip -u #{zip_dest})
|
|
137
|
+
else
|
|
138
|
+
%W(tar -xf #{zip_dest})
|
|
139
|
+
end
|
|
140
|
+
ctx.system(*args, chdir: ShopifyCli.cache_dir)
|
|
133
141
|
ctx.rm(zip_dest)
|
|
134
142
|
end
|
|
135
143
|
spinner.wait
|
|
@@ -143,7 +151,7 @@ module ShopifyCli
|
|
|
143
151
|
end
|
|
144
152
|
|
|
145
153
|
def ngrok_command(port)
|
|
146
|
-
"
|
|
154
|
+
"\"#{File.join(ShopifyCli.cache_dir, 'ngrok')}\" http -inspect=false -log=stdout -log-level=debug #{port}"
|
|
147
155
|
end
|
|
148
156
|
|
|
149
157
|
def seconds_to_hm(seconds)
|
|
@@ -163,6 +171,13 @@ module ShopifyCli
|
|
|
163
171
|
end
|
|
164
172
|
start_ngrok(ctx, port)
|
|
165
173
|
end
|
|
174
|
+
|
|
175
|
+
def check_prereq_command(ctx, command)
|
|
176
|
+
cmd_path = ctx.which(command)
|
|
177
|
+
ctx.abort(ctx.message('core.tunnel.error.prereq_command_required', command)) if cmd_path.nil?
|
|
178
|
+
ctx.done(ctx.message('core.tunnel.prereq_command_location', command, cmd_path))
|
|
179
|
+
end
|
|
180
|
+
|
|
166
181
|
class LogParser # :nodoc:
|
|
167
182
|
TIMEOUT = 10
|
|
168
183
|
|
|
@@ -195,7 +210,7 @@ module ShopifyCli
|
|
|
195
210
|
end
|
|
196
211
|
|
|
197
212
|
def parse_account
|
|
198
|
-
account, timeout, _ = @log.match(/AccountName:([\w\s]*) SessionDuration:([\d]+) PlanName/)&.captures
|
|
213
|
+
account, timeout, _ = @log.match(/AccountName:([\w\s\d@._\-]*) SessionDuration:([\d]+) PlanName/)&.captures
|
|
199
214
|
@account = account&.empty? ? nil : account
|
|
200
215
|
@timeout = timeout&.empty? ? 0 : timeout.to_i
|
|
201
216
|
end
|
data/lib/shopify-cli/version.rb
CHANGED
data/lib/shopify_cli.rb
CHANGED
|
@@ -127,8 +127,10 @@ module ShopifyCli
|
|
|
127
127
|
def self.cache_dir
|
|
128
128
|
cache_dir = if ENV.key?('RUNNING_SHOPIFY_CLI_TESTS')
|
|
129
129
|
TEMP_DIR
|
|
130
|
-
|
|
130
|
+
elsif ENV['LOCALAPPDATA'].nil?
|
|
131
131
|
File.join(File.expand_path(ENV.fetch('XDG_CACHE_HOME', '~/.cache')), TOOL_NAME)
|
|
132
|
+
else
|
|
133
|
+
File.join(File.expand_path(ENV['LOCALAPPDATA']), TOOL_NAME)
|
|
132
134
|
end
|
|
133
135
|
|
|
134
136
|
# Make sure the cache dir always exists
|
|
@@ -140,8 +142,10 @@ module ShopifyCli
|
|
|
140
142
|
def self.tool_config_path
|
|
141
143
|
if ENV.key?('RUNNING_SHOPIFY_CLI_TESTS')
|
|
142
144
|
TEMP_DIR
|
|
143
|
-
|
|
145
|
+
elsif ENV['APPDATA'].nil?
|
|
144
146
|
File.join(File.expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config')), TOOL_NAME)
|
|
147
|
+
else
|
|
148
|
+
File.join(File.expand_path(ENV['APPDATA']), TOOL_NAME)
|
|
145
149
|
end
|
|
146
150
|
end
|
|
147
151
|
|
data/shopify-cli.gemspec
CHANGED
|
@@ -26,7 +26,10 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
# Specify which files should be added to the gem when it is released.
|
|
27
27
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
28
28
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
29
|
-
%x(git ls-files -z).split("\x0").reject
|
|
29
|
+
%x(git ls-files -z).split("\x0").reject do |f|
|
|
30
|
+
f.match(%r{^(test|spec|features|packaging)/}) ||
|
|
31
|
+
f.match(%r{^bin/(update-deps|shopify.bat)$})
|
|
32
|
+
end
|
|
30
33
|
end
|
|
31
34
|
spec.bindir = "bin"
|
|
32
35
|
spec.require_paths = ["lib", "vendor"]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1013aa5c5664e7034ca3f02fd2e0513361b07e95 (dirty)
|
|
@@ -51,7 +51,7 @@ module CLI
|
|
|
51
51
|
# 1. rescue Abort or Bug
|
|
52
52
|
# 2. Print a contextualized error message
|
|
53
53
|
# 3. Re-raise AbortSilent or BugSilent respectively.
|
|
54
|
-
GenericAbort = Class.new(Exception)
|
|
54
|
+
GenericAbort = Class.new(Exception) # rubocop:disable Lint/InheritException
|
|
55
55
|
Abort = Class.new(GenericAbort)
|
|
56
56
|
Bug = Class.new(GenericAbort)
|
|
57
57
|
BugSilent = Class.new(GenericAbort)
|
|
@@ -22,11 +22,11 @@ module CLI
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def handle_exception(error)
|
|
25
|
-
if notify_with = exception_for_submission(error)
|
|
25
|
+
if (notify_with = exception_for_submission(error))
|
|
26
26
|
logs = begin
|
|
27
27
|
File.read(@log_file)
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
rescue => e
|
|
29
|
+
"(#{e.class}: #{e.message})"
|
|
30
30
|
end
|
|
31
31
|
exception_reporter.report(notify_with, logs)
|
|
32
32
|
end
|
|
@@ -56,7 +56,7 @@ module CLI
|
|
|
56
56
|
# if it was `exit 30`, translate the exit code to 1, and submit nothing.
|
|
57
57
|
# 30 is used to signal normal failures that are not indicative of bugs.
|
|
58
58
|
# However, users should see it presented as 1.
|
|
59
|
-
exit
|
|
59
|
+
exit(1)
|
|
60
60
|
else
|
|
61
61
|
# A weird termination status happened. `error.exception "message"` will maintain backtrace
|
|
62
62
|
# but allow us to set a message
|
|
@@ -83,7 +83,7 @@ module CLI
|
|
|
83
83
|
|
|
84
84
|
CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
85
85
|
rescue Interrupt
|
|
86
|
-
|
|
86
|
+
stderr_puts_message('Interrupt')
|
|
87
87
|
CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
88
88
|
rescue Errno::ENOSPC
|
|
89
89
|
message = if @tool_name
|
|
@@ -91,10 +91,16 @@ module CLI
|
|
|
91
91
|
else
|
|
92
92
|
"Your disk is full - free space is required to operate"
|
|
93
93
|
end
|
|
94
|
-
|
|
94
|
+
stderr_puts_message(message)
|
|
95
95
|
CLI::Kit::EXIT_FAILURE_BUT_NOT_BUG
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
+
def stderr_puts_message(message)
|
|
99
|
+
$stderr.puts(format_error_message(message))
|
|
100
|
+
rescue Errno::EPIPE
|
|
101
|
+
nil
|
|
102
|
+
end
|
|
103
|
+
|
|
98
104
|
def exception_reporter
|
|
99
105
|
if @exception_reporter_or_proc.respond_to?(:report)
|
|
100
106
|
@exception_reporter_or_proc
|
|
@@ -13,19 +13,17 @@ module CLI
|
|
|
13
13
|
def call(command, command_name, args)
|
|
14
14
|
with_traps do
|
|
15
15
|
with_logging do |id|
|
|
16
|
+
command.call(args, command_name)
|
|
17
|
+
rescue => e
|
|
16
18
|
begin
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Outputting to stderr is best-effort. Avoid raising another error when outputting debug info so that
|
|
24
|
-
# we can detect and log the original error, which may even be the source of this error.
|
|
25
|
-
nil
|
|
26
|
-
end
|
|
27
|
-
raise e
|
|
19
|
+
$stderr.puts "This command ran with ID: #{id}"
|
|
20
|
+
$stderr.puts "Please include this information in any issues/report along with relevant logs"
|
|
21
|
+
rescue SystemCallError
|
|
22
|
+
# Outputting to stderr is best-effort. Avoid raising another error when outputting debug info so that
|
|
23
|
+
# we can detect and log the original error, which may even be the source of this error.
|
|
24
|
+
nil
|
|
28
25
|
end
|
|
26
|
+
raise e
|
|
29
27
|
end
|
|
30
28
|
end
|
|
31
29
|
end
|
|
@@ -10,9 +10,10 @@ module CLI
|
|
|
10
10
|
# Constructor for CLI::Kit::Logger
|
|
11
11
|
#
|
|
12
12
|
# @param debug_log_file [String] path to the file where debug logs should be stored
|
|
13
|
-
def initialize(debug_log_file:)
|
|
13
|
+
def initialize(debug_log_file:, env_debug_name: 'DEBUG')
|
|
14
14
|
FileUtils.mkpath(File.dirname(debug_log_file))
|
|
15
15
|
@debug_logger = ::Logger.new(debug_log_file, MAX_NUM_LOGS, MAX_LOG_SIZE)
|
|
16
|
+
@env_debug_name = env_debug_name
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
# Functionally equivalent to Logger#info
|
|
@@ -60,7 +61,7 @@ module CLI
|
|
|
60
61
|
#
|
|
61
62
|
# @param msg [String] the message to log
|
|
62
63
|
def debug(msg)
|
|
63
|
-
$stdout.puts CLI::UI.fmt(msg) if
|
|
64
|
+
$stdout.puts CLI::UI.fmt(msg) if is_debug?
|
|
64
65
|
@debug_logger.debug(format_debug(msg))
|
|
65
66
|
end
|
|
66
67
|
|
|
@@ -71,6 +72,11 @@ module CLI
|
|
|
71
72
|
return msg unless CLI::UI::StdoutRouter.current_id
|
|
72
73
|
"[#{CLI::UI::StdoutRouter.current_id[:id]}] #{msg}"
|
|
73
74
|
end
|
|
75
|
+
|
|
76
|
+
def is_debug?
|
|
77
|
+
val = ENV[@env_debug_name]
|
|
78
|
+
val && val != '0' && val != ''
|
|
79
|
+
end
|
|
74
80
|
end
|
|
75
81
|
end
|
|
76
82
|
end
|
|
@@ -10,7 +10,7 @@ module CLI
|
|
|
10
10
|
def assert_all_commands_run(should_raise: true)
|
|
11
11
|
errors = CLI::Kit::System.error_message
|
|
12
12
|
CLI::Kit::System.reset!
|
|
13
|
-
assert
|
|
13
|
+
assert(false, errors) if should_raise && !errors.nil?
|
|
14
14
|
errors
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -196,22 +196,22 @@ module CLI
|
|
|
196
196
|
|
|
197
197
|
unless errors[:unexpected].empty?
|
|
198
198
|
final_error << CLI::UI.fmt(<<~EOF)
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
{{bold:Unexpected command invocations:}}
|
|
200
|
+
{{command:#{errors[:unexpected].join("\n")}}}
|
|
201
201
|
EOF
|
|
202
202
|
end
|
|
203
203
|
|
|
204
204
|
unless errors[:not_run].empty?
|
|
205
205
|
final_error << CLI::UI.fmt(<<~EOF)
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
{{bold:Expected commands were not run:}}
|
|
207
|
+
{{command:#{errors[:not_run].join("\n")}}}
|
|
208
208
|
EOF
|
|
209
209
|
end
|
|
210
210
|
|
|
211
211
|
unless errors[:other].empty?
|
|
212
212
|
final_error << CLI::UI.fmt(<<~EOF)
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
{{bold:Commands were not run as expected:}}
|
|
214
|
+
#{errors[:other].map { |cmd, msg| "{{command:#{cmd}}}\n#{msg}" }.join("\n\n")}
|
|
215
215
|
EOF
|
|
216
216
|
end
|
|
217
217
|
|