brut 0.18.2 → 0.19.1
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/lib/brut/cli/apps/build_assets.rb +62 -31
- data/lib/brut/cli/apps/db.rb +198 -78
- data/lib/brut/cli/apps/deploy.rb +216 -140
- data/lib/brut/cli/apps/new/app.rb +127 -41
- data/lib/brut/cli/apps/scaffold.rb +108 -105
- data/lib/brut/cli/apps/test.rb +45 -26
- data/lib/brut/cli/commands/base_command.rb +58 -22
- data/lib/brut/cli/commands/compound_command.rb +2 -4
- data/lib/brut/cli/commands/execution_context.rb +17 -10
- data/lib/brut/cli/commands/help.rb +112 -6
- data/lib/brut/cli/commands/output_error.rb +1 -1
- data/lib/brut/cli/execute_result.rb +4 -0
- data/lib/brut/cli/executor.rb +7 -7
- data/lib/brut/cli/logger.rb +122 -0
- data/lib/brut/cli/output.rb +9 -45
- data/lib/brut/cli/parsed_command_line.rb +33 -10
- data/lib/brut/cli/runner.rb +37 -8
- data/lib/brut/cli/terminal.rb +74 -0
- data/lib/brut/cli/terminal_theme.rb +131 -0
- data/lib/brut/cli.rb +7 -3
- data/lib/brut/framework/mcp.rb +4 -3
- data/lib/brut/front_end/asset_metadata.rb +9 -5
- data/lib/brut/spec_support/cli_command_support.rb +9 -3
- data/lib/brut/spec_support/e2e_test_server.rb +3 -3
- data/lib/brut/tui/script.rb +1 -1
- data/lib/brut/version.rb +1 -1
- metadata +18 -4
- data/lib/brut/cli/apps/deploy_base.rb +0 -86
- data/lib/brut/cli/apps/heroku_container_based_deploy.rb +0 -226
- data/templates/segments/Heroku/bin/deploy +0 -11
data/lib/brut/cli/apps/deploy.rb
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
require "brut/cli"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
require "pathname"
|
|
2
4
|
|
|
3
5
|
class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
6
|
+
def name = "deploy"
|
|
7
|
+
|
|
4
8
|
def description = "Deploy your Brut-powered app to production"
|
|
5
9
|
|
|
6
10
|
def default_rack_env = nil
|
|
7
11
|
|
|
8
12
|
class Heroku < Brut::CLI::Commands::BaseCommand
|
|
9
13
|
def description = "Deploy to Heroku using container-based deployment"
|
|
14
|
+
def opts = [
|
|
15
|
+
[ "--[no-]deploy", "If true, actually deploy the pushed images (default true)" ],
|
|
16
|
+
[ "--skip-checks", "If true, skip pre-build checks" ],
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
def default_rack_env = "development"
|
|
20
|
+
|
|
10
21
|
def run
|
|
22
|
+
if delegate_to_command(Brut::CLI::Apps::Deploy::Build.new) != 0
|
|
23
|
+
error "<== Build failed."
|
|
24
|
+
return 1
|
|
25
|
+
end
|
|
26
|
+
options.set_default(:deploy, true)
|
|
11
27
|
version = ""
|
|
12
28
|
git_guess = %{git rev-parse HEAD}
|
|
13
29
|
system!(git_guess) do |output|
|
|
@@ -15,57 +31,53 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
15
31
|
end
|
|
16
32
|
version.strip!.chomp!
|
|
17
33
|
if version == ""
|
|
18
|
-
|
|
34
|
+
error "Attempt to use git via command '#{git_guess}' to figure out the version failed"
|
|
19
35
|
return 1
|
|
20
36
|
end
|
|
21
37
|
short_version = version[0..7]
|
|
22
38
|
app_docker_files = AppDockerImages.new(
|
|
23
39
|
project_root: Brut.container.project_root,
|
|
24
|
-
organization: Brut.container.
|
|
40
|
+
organization: Brut.container.app_organization,
|
|
25
41
|
app_id: Brut.container.app_id,
|
|
26
42
|
short_version:
|
|
27
43
|
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
# stdout.puts ""
|
|
61
|
-
# stdout.puts " #{deploy_command}"
|
|
62
|
-
# end
|
|
63
|
-
# end
|
|
44
|
+
names = []
|
|
45
|
+
puts "Logging in to Heroku Container Registry"
|
|
46
|
+
command = %{heroku container:login}
|
|
47
|
+
system!(command)
|
|
48
|
+
app_docker_files.each do |name:, image_name:|
|
|
49
|
+
heroku_image_name = "registry.heroku.com/#{Brut.container.app_id}/#{name}"
|
|
50
|
+
puts "Tagging '#{image_name}' with '#{heroku_image_name}' for Heroku"
|
|
51
|
+
command = %{docker tag #{image_name} #{heroku_image_name}}
|
|
52
|
+
system!(command)
|
|
53
|
+
begin
|
|
54
|
+
puts "Pushing '#{heroku_image_name}'"
|
|
55
|
+
command = %{docker push #{heroku_image_name}}
|
|
56
|
+
system!(command)
|
|
57
|
+
rescue Brut::CLI::SystemExecError => ex
|
|
58
|
+
error "Failed to push image '#{heroku_image_name}' to Heroku"
|
|
59
|
+
if options.log_level != "debug"
|
|
60
|
+
error "Could be you must re-authenticate to Heroku."
|
|
61
|
+
error "Try re-running with --log-level=debug to see more details"
|
|
62
|
+
end
|
|
63
|
+
return 1
|
|
64
|
+
end
|
|
65
|
+
names << name
|
|
66
|
+
end
|
|
67
|
+
deploy_command = "heroku container:release #{names.join(' ')} -a #{Brut.container.app_id}"
|
|
68
|
+
if options.deploy?
|
|
69
|
+
puts "Deploying images to Heroku"
|
|
70
|
+
system!(deploy_command)
|
|
71
|
+
else
|
|
72
|
+
puts "Not deploying. To deploy the images just pushed:"
|
|
73
|
+
puts ""
|
|
74
|
+
puts " #{deploy_command}"
|
|
75
|
+
end
|
|
64
76
|
end
|
|
65
77
|
end
|
|
66
78
|
|
|
67
79
|
class AppDockerImages
|
|
68
|
-
attr_reader :docker_config_filename
|
|
80
|
+
attr_reader :docker_config_filename, :platform
|
|
69
81
|
def initialize(organization:, app_id:, project_root:, short_version:)
|
|
70
82
|
@docker_config_filename = project_root / "deploy" / "docker_config"
|
|
71
83
|
require_relative @docker_config_filename
|
|
@@ -74,10 +86,11 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
74
86
|
end
|
|
75
87
|
|
|
76
88
|
docker_config = DockerConfig.new
|
|
89
|
+
@platform = docker_config.platform
|
|
77
90
|
|
|
78
|
-
additional_images = (
|
|
91
|
+
additional_images = (docker_config.additional_images || {}).map { |name,config|
|
|
79
92
|
cmd = config.fetch(:cmd)
|
|
80
|
-
image_name = %{#{app_organization}/#{app_id}:#{short_version}-#{name}}
|
|
93
|
+
image_name = %{#{Brut.container.app_organization}/#{Brut.container.app_id}:#{short_version}-#{name}}
|
|
81
94
|
[
|
|
82
95
|
name,
|
|
83
96
|
{
|
|
@@ -91,12 +104,12 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
91
104
|
@images = {
|
|
92
105
|
"web" => {
|
|
93
106
|
cmd: "bin/run",
|
|
94
|
-
image_name: %{#{app_organization}/#{app_id}:#{short_version}-web},
|
|
107
|
+
image_name: %{#{Brut.container.app_organization}/#{app_id}:#{short_version}-web},
|
|
95
108
|
dockerfile: "deploy/Dockerfile.web",
|
|
96
109
|
},
|
|
97
110
|
"release" => {
|
|
98
|
-
cmd: "bin/
|
|
99
|
-
image_name: %{#{app_organization}/#{app_id}:#{short_version}-
|
|
111
|
+
cmd: "bin/release",
|
|
112
|
+
image_name: %{#{Brut.container.app_organization}/#{app_id}:#{short_version}-release},
|
|
100
113
|
dockerfile: "deploy/Dockerfile.release",
|
|
101
114
|
},
|
|
102
115
|
}.merge(additional_images)
|
|
@@ -108,7 +121,7 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
108
121
|
end
|
|
109
122
|
@images.each do |name,metadata|
|
|
110
123
|
args = {}
|
|
111
|
-
block.
|
|
124
|
+
block.parameters.each do |(_,param)|
|
|
112
125
|
if param == :name
|
|
113
126
|
args[:name] = name
|
|
114
127
|
else
|
|
@@ -121,16 +134,29 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
121
134
|
end
|
|
122
135
|
|
|
123
136
|
class Build < Brut::CLI::Commands::BaseCommand
|
|
124
|
-
def description
|
|
137
|
+
def description = Docker.new.description
|
|
138
|
+
def opts = Docker.new.opts
|
|
139
|
+
def default_rack_env = Docker.new.default_rack_env
|
|
140
|
+
def run = delegate_to_command(Docker.new)
|
|
141
|
+
|
|
142
|
+
def commands = []
|
|
125
143
|
|
|
126
144
|
class Docker < Brut::CLI::Commands::BaseCommand
|
|
127
145
|
def description = "Build a series of Docker images from a template Dockerfile"
|
|
128
146
|
def opts = [
|
|
129
147
|
[ "--platform=PLATFORM","Override default platform. Can be any Docker platform." ],
|
|
130
148
|
[ "--dry-run", "Only show what would happen, don't actually do anything" ],
|
|
149
|
+
[ "--skip-checks", "If true, skip pre-build checks (default )" ],
|
|
131
150
|
]
|
|
151
|
+
def default_rack_env = "development"
|
|
132
152
|
|
|
133
153
|
def run
|
|
154
|
+
if !options.skip_checks?
|
|
155
|
+
if delegate_to_command(Brut::CLI::Apps::Deploy::Check.new) != 0
|
|
156
|
+
puts theme.error.render("Pre-build checks failed.")
|
|
157
|
+
return 1
|
|
158
|
+
end
|
|
159
|
+
end
|
|
134
160
|
version = ""
|
|
135
161
|
git_guess = %{git rev-parse HEAD}
|
|
136
162
|
system!(git_guess) do |output|
|
|
@@ -138,24 +164,29 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
138
164
|
end
|
|
139
165
|
version.strip!.chomp!
|
|
140
166
|
if version == ""
|
|
141
|
-
|
|
167
|
+
error "Attempt to use git via command '#{git_guess}' to figure out the version failed"
|
|
142
168
|
return 1
|
|
143
169
|
end
|
|
144
170
|
short_version = version[0..7]
|
|
145
171
|
|
|
146
|
-
|
|
172
|
+
short_version = version[0..7]
|
|
173
|
+
app_docker_files = AppDockerImages.new(
|
|
147
174
|
project_root: Brut.container.project_root,
|
|
148
|
-
organization: Brut.container.
|
|
175
|
+
organization: Brut.container.app_organization,
|
|
149
176
|
app_id: Brut.container.app_id,
|
|
150
177
|
short_version:
|
|
151
178
|
)
|
|
179
|
+
options.set_default(:platform, app_docker_files.platform || "linux/amd64")
|
|
152
180
|
|
|
153
181
|
FileUtils.chdir Brut.container.project_root do
|
|
154
182
|
|
|
155
|
-
|
|
156
|
-
|
|
183
|
+
puts
|
|
184
|
+
puts theme.header.render("Generating Dockerfiles")
|
|
185
|
+
puts
|
|
186
|
+
rows = []
|
|
187
|
+
app_docker_files.each do |name:, cmd:, dockerfile:|
|
|
157
188
|
|
|
158
|
-
|
|
189
|
+
rows << [theme.subheader.render(name), theme.code.render(dockerfile), theme.code.render(cmd) ]
|
|
159
190
|
|
|
160
191
|
if !options.dry_run?
|
|
161
192
|
File.open(dockerfile,"w") do |file|
|
|
@@ -168,119 +199,165 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
168
199
|
end
|
|
169
200
|
end
|
|
170
201
|
end
|
|
202
|
+
table = Lipgloss::Table.new.headers(["Name", "Dockerfile", "CMD"]).
|
|
203
|
+
rows(rows).
|
|
204
|
+
style_func(rows: rows.length, columns: 3) { Lipgloss::Style.new.padding_right(1).padding_left(1) }
|
|
205
|
+
puts table.render
|
|
171
206
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if options.dry_run?
|
|
182
|
-
|
|
183
|
-
else
|
|
207
|
+
puts
|
|
208
|
+
puts theme.header.render("Images")
|
|
209
|
+
puts
|
|
210
|
+
rows = []
|
|
211
|
+
items = []
|
|
212
|
+
app_docker_files.each do |name:, image_name:, dockerfile:|
|
|
213
|
+
rows << [ name, theme.code.render(image_name) ]
|
|
214
|
+
command = %{docker build --build-arg app_git_sha1=#{version} --file #{Brut.container.project_root}/#{dockerfile} --platform #{options.platform} --tag #{image_name} . 2>&1}
|
|
215
|
+
items << theme.code.render(theme.wrap(command, first_indent: false, indent: 7, newline: " \\\n"))
|
|
216
|
+
if !options.dry_run?
|
|
217
|
+
puts theme.subheader.render("Building '#{name}' image")
|
|
184
218
|
system!(command)
|
|
185
219
|
end
|
|
186
220
|
end
|
|
221
|
+
if options.dry_run?
|
|
222
|
+
table = Lipgloss::Table.new.headers(["Name", "Image Name" ]).
|
|
223
|
+
rows(rows).
|
|
224
|
+
style_func(rows: rows.length, columns: 3) { Lipgloss::Style.new.padding_right(1).padding_left(1) }
|
|
225
|
+
puts table.render
|
|
226
|
+
puts
|
|
227
|
+
puts theme.subheader.render("Commands:")
|
|
228
|
+
puts
|
|
229
|
+
puts Lipgloss::List.new.items(items).item_style(theme.code).render
|
|
230
|
+
end
|
|
187
231
|
end
|
|
188
232
|
end
|
|
189
233
|
end
|
|
190
234
|
end
|
|
191
235
|
|
|
192
|
-
|
|
236
|
+
class Check < Brut::CLI::Commands::BaseCommand
|
|
193
237
|
|
|
194
|
-
|
|
195
|
-
def default_command_class = Git
|
|
196
|
-
def opts = [
|
|
197
|
-
[ "--[no-]check-branch", "If true, requires that you are on 'main' (default true)" ],
|
|
198
|
-
[ "--[no-]check-changes", "If true, requires that you have committed all local changes (default true)" ],
|
|
199
|
-
[ "--[no-]check-push", "If true, requires that you are in sync with origin/main (default true)" ],
|
|
200
|
-
]
|
|
238
|
+
def description = "Check that a deploy can be reasonably expected to succeed"
|
|
201
239
|
|
|
202
|
-
|
|
203
|
-
def
|
|
204
|
-
def
|
|
240
|
+
def opts = Git.new.opts
|
|
241
|
+
def run = delegate_to_command(Git.new)
|
|
242
|
+
def commands = []
|
|
205
243
|
|
|
206
|
-
|
|
244
|
+
class Git < Brut::CLI::Commands::BaseCommand
|
|
245
|
+
def description = "Perform the check assuming Git is the version-control system"
|
|
246
|
+
def opts = [
|
|
247
|
+
[ "--[no-]check-branch", "If true, requires that you are on 'main' (default true)" ],
|
|
248
|
+
[ "--[no-]check-changes", "If true, requires that you have committed all local changes (default true)" ],
|
|
249
|
+
[ "--[no-]check-push", "If true, requires that you are in sync with origin/main (default true)" ],
|
|
250
|
+
]
|
|
207
251
|
|
|
208
|
-
|
|
252
|
+
def run
|
|
253
|
+
puts theme.header.render("Checking Git repo to see if changes have all been pushed to main")
|
|
254
|
+
puts
|
|
209
255
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
256
|
+
options.set_default(:check_branch, true)
|
|
257
|
+
options.set_default(:check_changes, true)
|
|
258
|
+
options.set_default(:check_push, true)
|
|
213
259
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
branch
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
260
|
+
checks = []
|
|
261
|
+
|
|
262
|
+
branch = ""
|
|
263
|
+
system!("git branch --show-current") do |output|
|
|
264
|
+
branch << output
|
|
265
|
+
end
|
|
266
|
+
branch = branch.strip.chomp
|
|
267
|
+
checks << [
|
|
268
|
+
"Deploy from main",
|
|
269
|
+
]
|
|
270
|
+
if branch != "main"
|
|
271
|
+
checks.last << "Currently on #{theme.code.render(branch)}"
|
|
272
|
+
checks.last << options.check_branch?
|
|
227
273
|
end
|
|
228
|
-
end
|
|
229
274
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
end
|
|
233
|
-
local_changes = ""
|
|
234
|
-
system!("git diff-index --name-only HEAD --") do |output|
|
|
235
|
-
local_changes << output
|
|
236
|
-
end
|
|
237
|
-
if local_changes.strip != ""
|
|
238
|
-
stderr.puts "You have un-committed changes:"
|
|
239
|
-
stderr.puts
|
|
240
|
-
local_changes.split(/\n/).each do |change|
|
|
241
|
-
checks_ignored += 1
|
|
242
|
-
stderr.puts " #{change}"
|
|
275
|
+
system!("git status") do |*| # reset local caches to account for Docker/host wierdness
|
|
276
|
+
# ignore
|
|
243
277
|
end
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
278
|
+
local_changes = ""
|
|
279
|
+
system!("git diff-index --name-only HEAD --") do |output|
|
|
280
|
+
local_changes << output
|
|
281
|
+
end
|
|
282
|
+
checks << [
|
|
283
|
+
"No un-committed changes",
|
|
284
|
+
]
|
|
285
|
+
if local_changes.strip != ""
|
|
286
|
+
items = local_changes.split(/\n/)
|
|
287
|
+
list = Lipgloss::List.new.items(items).item_style(theme.error)
|
|
288
|
+
checks.last << "Files not committed:\n#{list.render.strip}\n"
|
|
289
|
+
checks.last << options.check_changes?
|
|
251
290
|
end
|
|
252
|
-
end
|
|
253
291
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
end
|
|
258
|
-
remote_ahead, local_ahead = rev_list.strip.chomp.split(/\t/,2).map(&:to_i)
|
|
259
|
-
if remote_ahead != 0
|
|
260
|
-
stderr.puts "There are commits in origin you don't have."
|
|
261
|
-
if options.check_push?
|
|
262
|
-
stderr.puts "Pull those in, re-run bin/ci, THEN deploy"
|
|
263
|
-
return 1
|
|
264
|
-
else
|
|
265
|
-
checks_ignored += 1
|
|
266
|
-
stderr.puts "Ignoring..."
|
|
292
|
+
rev_list = ""
|
|
293
|
+
system!("git rev-list --left-right --count origin/main...main") do |output|
|
|
294
|
+
rev_list << output
|
|
267
295
|
end
|
|
268
|
-
|
|
296
|
+
remote_ahead, local_ahead = rev_list.strip.chomp.split(/\t/,2).map(&:to_i)
|
|
297
|
+
checks << [
|
|
298
|
+
"Pulled from origin",
|
|
299
|
+
]
|
|
300
|
+
if remote_ahead != 0
|
|
301
|
+
if remote_ahead == 1
|
|
302
|
+
checks.last << "There is 1 commit in origin you don't have"
|
|
303
|
+
else
|
|
304
|
+
checks.last << "There are #{remote_ahead} commits in origin you don't have"
|
|
305
|
+
end
|
|
306
|
+
checks.last << options.check_push?
|
|
307
|
+
end
|
|
308
|
+
checks << [
|
|
309
|
+
"Pushed to origin",
|
|
310
|
+
]
|
|
269
311
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
312
|
+
if local_ahead != 0
|
|
313
|
+
if local_ahead == 1
|
|
314
|
+
checks.last << "There is 1 commit not pushed to origin"
|
|
315
|
+
else
|
|
316
|
+
checks.last << "There are #{local_ahead} commits not pushed to origin"
|
|
317
|
+
end
|
|
318
|
+
checks.last << options.check_push?
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
rows = []
|
|
322
|
+
checks.each do |(check,status,error)|
|
|
323
|
+
row = [ check ]
|
|
324
|
+
if status
|
|
325
|
+
if error
|
|
326
|
+
row << theme.error.render("FAILED")
|
|
327
|
+
else
|
|
328
|
+
row << theme.warning.render("Ignored")
|
|
329
|
+
end
|
|
330
|
+
row << theme.error.render(status)
|
|
331
|
+
else
|
|
332
|
+
row << theme.success.render("OK")
|
|
333
|
+
row << ""
|
|
334
|
+
end
|
|
335
|
+
rows << row
|
|
336
|
+
end
|
|
337
|
+
table = Lipgloss::Table.new.
|
|
338
|
+
headers(["Check", "Result", "Details"]).
|
|
339
|
+
rows(rows).
|
|
340
|
+
style_func(rows: rows.length, columns: 3) { |row,column|
|
|
341
|
+
if row == Lipgloss::Table::HEADER_ROW
|
|
342
|
+
Lipgloss::Style.new.inherit(theme.header).padding_left(1).padding_right(1)
|
|
343
|
+
elsif column == 0
|
|
344
|
+
Lipgloss::Style.new.inherit(theme.subheader).padding_left(1).padding_right(1).padding_bottom(1)
|
|
345
|
+
else
|
|
346
|
+
Lipgloss::Style.new.inherit(theme.none).padding_left(1).padding_right(1).padding_bottom(1)
|
|
347
|
+
end
|
|
348
|
+
}
|
|
349
|
+
puts table.render
|
|
350
|
+
checks_failed = checks.count { |(_,status,_)| status }
|
|
351
|
+
checks_failed_not_ignored = checks.count { |(_,status,error)| status && error }
|
|
352
|
+
if checks_failed > 0
|
|
353
|
+
if checks_failed_not_ignored > 0
|
|
354
|
+
puts theme.error.render("#{checks_failed} checks failed - aborting")
|
|
274
355
|
return 1
|
|
275
356
|
else
|
|
276
|
-
|
|
277
|
-
stderr.puts "Ignoring..."
|
|
357
|
+
puts theme.warning.render("#{checks_failed} checks failed but ignored")
|
|
278
358
|
end
|
|
279
|
-
end
|
|
280
|
-
if checks_ignored == 0
|
|
281
|
-
stdout.puts "All checks passed"
|
|
282
359
|
else
|
|
283
|
-
|
|
360
|
+
puts theme.success.render("All checks passed")
|
|
284
361
|
end
|
|
285
362
|
|
|
286
363
|
0
|
|
@@ -288,4 +365,3 @@ class Brut::CLI::Apps::Deploy < Brut::CLI::Commands::BaseCommand
|
|
|
288
365
|
end
|
|
289
366
|
end
|
|
290
367
|
end
|
|
291
|
-
|