squared 0.5.4 → 0.5.6
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/CHANGELOG.md +149 -63
- data/README.md +662 -1273
- data/lib/squared/common/base.rb +1 -1
- data/lib/squared/common/format.rb +7 -4
- data/lib/squared/common/prompt.rb +1 -1
- data/lib/squared/common/shell.rb +7 -2
- data/lib/squared/common/system.rb +1 -1
- data/lib/squared/config.rb +8 -8
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +29 -9
- data/lib/squared/workspace/project/base.rb +104 -27
- data/lib/squared/workspace/project/docker.rb +109 -68
- data/lib/squared/workspace/project/git.rb +156 -127
- data/lib/squared/workspace/project/node.rb +18 -19
- data/lib/squared/workspace/project/python.rb +36 -19
- data/lib/squared/workspace/project/ruby.rb +100 -55
- data/lib/squared/workspace/project/support/class.rb +81 -4
- data/lib/squared/workspace/repo.rb +72 -36
- data/squared.gemspec +2 -2
- metadata +5 -6
- data/README.ruby.md +0 -728
@@ -4,7 +4,7 @@ module Squared
|
|
4
4
|
module Workspace
|
5
5
|
module Project
|
6
6
|
class Docker < Base
|
7
|
-
COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml
|
7
|
+
COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml docker-compose.yml].freeze
|
8
8
|
BAKEFILE = %w[docker-bake.json docker-bake.hcl docker-bake.override.json docker-bake.override.hcl].freeze
|
9
9
|
DIR_DOCKER = (COMPOSEFILE + BAKEFILE).freeze
|
10
10
|
OPT_DOCKER = {
|
@@ -12,56 +12,57 @@ module Squared
|
|
12
12
|
tlskey=p].freeze,
|
13
13
|
buildx: {
|
14
14
|
common: %w[builder=b D|debug],
|
15
|
-
build: %w[
|
16
|
-
network=b no-cache-filter=b o|output=q platform=b
|
17
|
-
target=b ulimit=q].freeze,
|
18
|
-
bake: %w[
|
19
|
-
shared: %w[check no-cache allow=q call=b? f|file=p progress=b provenance=q
|
15
|
+
build: %w[add-host=q annotation=q attest=q build-arg=qq build-context=qq cache-from=q cache-to=q
|
16
|
+
cgroup-parent=b ent=q iidfile=p label=q a-file=p network=b no-cache-filter=b o|output=q platform=b
|
17
|
+
q|quiet secret=qq shm-size=b ssh=qq t|tag=b target=b ulimit=q].freeze,
|
18
|
+
bake: %w[print list=q set=q].freeze,
|
19
|
+
shared: %w[check load no-cache pull push allow=q call=b? f|file=p metadata-file=p progress=b provenance=q
|
20
|
+
sbom=q].freeze
|
20
21
|
}.freeze,
|
21
22
|
compose: {
|
22
|
-
common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=
|
23
|
+
common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=n profile=b progress=b
|
23
24
|
project-directory=p p|project-name=e].freeze,
|
24
|
-
build: %w[check no-cache pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b
|
25
|
-
ssh=qq].freeze,
|
26
|
-
exec: %w[
|
27
|
-
run: %w[build
|
28
|
-
|
29
|
-
u|user=e v|volume=q w|workdir=q].freeze,
|
30
|
-
up: %w[
|
31
|
-
d|detach
|
32
|
-
quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch attach=b
|
33
|
-
no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze
|
25
|
+
build: %w[check no-cache print pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b
|
26
|
+
provenance=q sbom=q ssh=qq].freeze,
|
27
|
+
exec: %w[d|detach privileged e|env=qq index=i T|no-TTY=b? user=e w|workdir=q].freeze,
|
28
|
+
run: %w[build d|detach no-deps q|quiet quiet-build quiet-pull remove-orphans rm P|service-ports use-aliases
|
29
|
+
cap-add=b cap-drop=b q e|env=qq env-from-file=p i|interactive=b? l|label=q name=b T|no-TTY=b?
|
30
|
+
p|publish=e pull=b u|user=e v|volume=q w|workdir=q].freeze,
|
31
|
+
up: %w[abort-on-container-exit abort-on-container-failure always-recreate-deps attach-dependencies build
|
32
|
+
d|detach force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start quiet-build
|
33
|
+
quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch y|yes attach=b
|
34
|
+
exit-code-from=b no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze,
|
35
|
+
down: %w[remove-orphans v|volumes rmi=b t|timeout=i].freeze
|
34
36
|
}.freeze,
|
35
37
|
container: {
|
36
38
|
create: %w[init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet read-only
|
37
|
-
rm runtime t|tty use-api-socket io-maxbandwidth=b io-maxiops=b add-host=q annotation=q
|
38
|
-
|
39
|
-
|
39
|
+
rm runtime t|tty use-api-socket io-maxbandwidth=b io-maxiops=b add-host=q annotation=q a|attach=b
|
40
|
+
blkio-weight=i blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p
|
41
|
+
device=q device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q
|
40
42
|
device-write-iops=q disable-content-trust=b? dns=e dns-option=e dns-search=e domainname=b
|
41
|
-
entrypoint=q e|env=qq env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
volume-driver=b volumes-from=b w|workdir=q].freeze,
|
43
|
+
entrypoint=q e|env=qq env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b ip6=e
|
44
|
+
ipc=b isolation=b kernel-memory=b l|label=q label-file=p link=b link-local-ip=b log-driver=b
|
45
|
+
log-opt=q mac-address=e m|memory=b memory-reservation=b memory-swap=n memory-swappiness=n
|
46
|
+
mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n platform=b
|
47
|
+
p|publish=e pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b stop-timeout=i
|
48
|
+
storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q volume-driver=b
|
49
|
+
volumes-from=b w|workdir=q].freeze,
|
49
50
|
run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
|
50
|
-
exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
|
51
|
-
w|workdir=q].freeze,
|
52
51
|
update: %w[blkio-weight=i cpu-period=i cpu-quota=i cpu-rt-period=i cpu-rt-runtime=i c|cpu-shares=i cpus=f
|
53
52
|
cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
|
54
53
|
restart=q].freeze,
|
54
|
+
exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
|
55
|
+
w|workdir=q].freeze,
|
55
56
|
commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
|
56
57
|
inspect: %w[s|size f|format=q].freeze,
|
57
58
|
start: %w[a|attach i|interactive detach-keys=q].freeze,
|
58
59
|
stop: %w[s|signal=b t|time=i t|timeout=i].freeze,
|
59
60
|
restart: %w[s|signal=b t|time=i t|timeout=i].freeze,
|
60
61
|
kill: %w[s|signal=b].freeze,
|
61
|
-
stats: %w[no-trunc format|q].freeze
|
62
|
+
stats: %w[a|all no-stream no-trunc format|q].freeze
|
62
63
|
}.freeze,
|
63
64
|
image: {
|
64
|
-
list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
|
65
|
+
list: %w[a|all q|quiet digests no-trunc tree f|filter=q format=q].freeze,
|
65
66
|
push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
|
66
67
|
rm: %w[f|force no-prune platform=b].freeze,
|
67
68
|
save: %w[o|output=p platform=b].freeze
|
@@ -96,7 +97,7 @@ module Squared
|
|
96
97
|
|
97
98
|
subtasks({
|
98
99
|
'build' => %i[tag context].freeze,
|
99
|
-
'compose' => %i[build run exec up].freeze,
|
100
|
+
'compose' => %i[build run exec up down].freeze,
|
100
101
|
'bake' => %i[build check].freeze,
|
101
102
|
'image' => %i[list rm push tag save].freeze,
|
102
103
|
'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
|
@@ -147,11 +148,11 @@ module Squared
|
|
147
148
|
end
|
148
149
|
end
|
149
150
|
when 'bake'
|
150
|
-
|
151
|
+
break unless bake?
|
151
152
|
|
152
153
|
case flag
|
153
154
|
when :build
|
154
|
-
format_desc action, flag, '
|
155
|
+
format_desc action, flag, 'opts*,target*,context?|:'
|
155
156
|
task flag do |_, args|
|
156
157
|
args = args.to_a
|
157
158
|
if args.first == ':'
|
@@ -168,16 +169,16 @@ module Squared
|
|
168
169
|
end
|
169
170
|
end
|
170
171
|
when 'compose'
|
171
|
-
|
172
|
+
break unless compose?
|
172
173
|
|
173
174
|
case flag
|
174
|
-
when :build, :up
|
175
|
-
format_desc action, flag, 'opts*,service
|
175
|
+
when :build, :up, :down
|
176
|
+
format_desc action, flag, 'opts*,service*|:'
|
176
177
|
task flag do |_, args|
|
177
178
|
compose! flag, args.to_a
|
178
179
|
end
|
179
180
|
when :exec, :run
|
180
|
-
format_desc action, flag, "service
|
181
|
+
format_desc action, flag, "service|:,command#{flag == :exec ? '' : '?'}|::,args*,opts*"
|
181
182
|
task flag, [:service] do |_, args|
|
182
183
|
service = param_guard(action, flag, args: args, key: :service)
|
183
184
|
compose!(flag, args.extras, service: service)
|
@@ -186,7 +187,7 @@ module Squared
|
|
186
187
|
when 'container'
|
187
188
|
case flag
|
188
189
|
when :exec, :commit
|
189
|
-
format_desc(action, flag, flag == :exec ? 'id/name,opts*,args
|
190
|
+
format_desc(action, flag, flag == :exec ? 'id/name,opts*,args+|:' : 'id/name,tag?,opts*')
|
190
191
|
task flag, [:id] do |_, args|
|
191
192
|
if flag == :exec && !args.id
|
192
193
|
choice_command flag
|
@@ -196,7 +197,7 @@ module Squared
|
|
196
197
|
end
|
197
198
|
end
|
198
199
|
when :run, :create
|
199
|
-
format_desc action, flag, 'image,opts*,args
|
200
|
+
format_desc action, flag, 'image,opts*,args*|:'
|
200
201
|
task flag, [:image] do |_, args|
|
201
202
|
if args.image
|
202
203
|
container(flag, args.extras, id: args.image)
|
@@ -222,7 +223,8 @@ module Squared
|
|
222
223
|
format_desc(action, flag, case flag
|
223
224
|
when :rm, :save then 'id*,opts*'
|
224
225
|
when :tag then 'version?'
|
225
|
-
else 'opts*,args*'
|
226
|
+
else 'opts*,args*'
|
227
|
+
end)
|
226
228
|
task flag do |_, args|
|
227
229
|
args = args.to_a
|
228
230
|
if args.empty? && flag != :list
|
@@ -259,12 +261,11 @@ module Squared
|
|
259
261
|
|
260
262
|
ret = docker_session
|
261
263
|
if from == :run
|
262
|
-
|
263
|
-
when 1, 2
|
264
|
+
if bake?(n = filetype)
|
264
265
|
ret << 'buildx' << 'bake'
|
265
266
|
append_file n
|
266
267
|
from = :bake
|
267
|
-
|
268
|
+
elsif compose?(n)
|
268
269
|
ret << 'compose' << 'build'
|
269
270
|
append_file n
|
270
271
|
from = :compose
|
@@ -335,7 +336,7 @@ module Squared
|
|
335
336
|
op.push(val)
|
336
337
|
end
|
337
338
|
end
|
338
|
-
op.append(args, escape: true)
|
339
|
+
op.append(args, escape: true, strip: /^:/)
|
339
340
|
contextdir context if context
|
340
341
|
end
|
341
342
|
end
|
@@ -348,15 +349,27 @@ module Squared
|
|
348
349
|
op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
|
349
350
|
append_file filetype unless op.arg?('f', 'file')
|
350
351
|
op << flag
|
351
|
-
op.parse(OPT_DOCKER[:compose][
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
352
|
+
op.parse(OPT_DOCKER[:compose].fetch(flag, []))
|
353
|
+
multiple = case flag
|
354
|
+
when :build, :up, :down then true
|
355
|
+
else false
|
356
|
+
end
|
357
|
+
if op.remove(':') || service == ':'
|
358
|
+
keys = Set.new
|
359
|
+
read_composefile('services', target: op.values_of('f', 'file')) { |data| keys.merge(data.keys) }
|
360
|
+
service = unless keys.empty?
|
361
|
+
choice_index('Add services', keys, multiple: multiple, force: !multiple,
|
362
|
+
attempts: multiple ? 1 : 5)
|
363
|
+
end
|
358
364
|
end
|
359
|
-
|
365
|
+
if multiple
|
366
|
+
op.concat(service) if service
|
367
|
+
op.append(delim: true, escape: true, strip: /^:/)
|
368
|
+
else
|
369
|
+
raise_error('no services were found', hint: flag) unless service
|
370
|
+
append_command(flag, service, op.extras, prompt: '::')
|
371
|
+
end
|
372
|
+
run(from: :"compose:#{flag}")
|
360
373
|
end
|
361
374
|
|
362
375
|
def container(flag, opts = [], id: nil)
|
@@ -388,10 +401,10 @@ module Squared
|
|
388
401
|
elsif all.include?(k)
|
389
402
|
unless type
|
390
403
|
run.each_pair do |key, val|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
404
|
+
next unless val.include?(k)
|
405
|
+
|
406
|
+
type = key.to_s unless key == :common
|
407
|
+
break
|
395
408
|
end
|
396
409
|
end
|
397
410
|
case k
|
@@ -414,7 +427,7 @@ module Squared
|
|
414
427
|
append_command(flag, id || tagmain, op.extras)
|
415
428
|
when :update
|
416
429
|
raise_error('missing container', hint: flag) if op.empty?
|
417
|
-
op.append(escape: true)
|
430
|
+
op.append(escape: true, strip: /^:/)
|
418
431
|
when :commit
|
419
432
|
latest = op.shift || tagmain
|
420
433
|
cmd << id << latest
|
@@ -467,7 +480,7 @@ module Squared
|
|
467
480
|
end
|
468
481
|
return
|
469
482
|
else
|
470
|
-
op.append(escape: true)
|
483
|
+
op.append(escape: true, strip: /^:/)
|
471
484
|
end
|
472
485
|
end
|
473
486
|
run(from: from)
|
@@ -544,7 +557,7 @@ module Squared
|
|
544
557
|
|
545
558
|
def network(flag, opts = [], target: nil)
|
546
559
|
cmd, opts = docker_session('network', flag, opts: opts)
|
547
|
-
op = OptionPartition.new(opts, OPT_DOCKER[:network][
|
560
|
+
op = OptionPartition.new(opts, OPT_DOCKER[:network].fetch(flag, []), cmd, project: self)
|
548
561
|
op.clear
|
549
562
|
from = :"network:#{flag}"
|
550
563
|
list_image(flag, docker_output('ps -a'), from: from) do |img|
|
@@ -561,10 +574,14 @@ module Squared
|
|
561
574
|
end
|
562
575
|
|
563
576
|
def compose?(file = dockerfile)
|
577
|
+
return file == 3 || file == 4 if file.is_a?(Numeric)
|
578
|
+
|
564
579
|
COMPOSEFILE.include?(File.basename(file))
|
565
580
|
end
|
566
581
|
|
567
582
|
def bake?(file = dockerfile)
|
583
|
+
return file == 1 || file == 2 if file.is_a?(Numeric)
|
584
|
+
|
568
585
|
BAKEFILE.include?(File.basename(file))
|
569
586
|
end
|
570
587
|
|
@@ -585,6 +602,21 @@ module Squared
|
|
585
602
|
|
586
603
|
private
|
587
604
|
|
605
|
+
def read_composefile(*keys, target: nil)
|
606
|
+
require 'yaml'
|
607
|
+
target = ENV['COMPOSE_FILE']&.split(workspace.windows? ? ';' : ':') if !target || target.empty?
|
608
|
+
Array(target || dockerfile).each do |val|
|
609
|
+
doc = YAML.load_file(path + val)
|
610
|
+
if keys.empty?
|
611
|
+
yield doc
|
612
|
+
elsif (data = doc.dig(*keys))
|
613
|
+
yield data
|
614
|
+
end
|
615
|
+
rescue StandardError => e
|
616
|
+
log.debug e
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
588
620
|
def docker_session(*cmd, opts: nil)
|
589
621
|
return session('docker', *cmd) unless opts
|
590
622
|
|
@@ -597,9 +629,9 @@ module Squared
|
|
597
629
|
session('docker', *cmd, main: false, options: false, **kwargs)
|
598
630
|
end
|
599
631
|
|
600
|
-
def append_command(flag, val, list, target: @session)
|
601
|
-
if list.delete(
|
602
|
-
list << readline('Enter command [args]', force:
|
632
|
+
def append_command(flag, val, list, target: @session, prompt: ':')
|
633
|
+
if list.delete(prompt)
|
634
|
+
list << readline('Enter command [args]', force: flag == :exec)
|
603
635
|
elsif (args = env('DOCKER_ARGS'))
|
604
636
|
list << args
|
605
637
|
end
|
@@ -616,13 +648,22 @@ module Squared
|
|
616
648
|
end
|
617
649
|
|
618
650
|
def append_file(type, target: @session)
|
619
|
-
return
|
651
|
+
return if ENV['COMPOSE_FILE'] && compose?(type)
|
620
652
|
|
653
|
+
unless @file.is_a?(Array)
|
654
|
+
case type
|
655
|
+
when 2, 4
|
656
|
+
return
|
657
|
+
when 3
|
658
|
+
return unless COMPOSEFILE.map { |val| path + val }.select(&:exist?).size > 1
|
659
|
+
end
|
660
|
+
end
|
621
661
|
files = Array(@file).map { |val| quote_option('file', path + val) }
|
622
662
|
if target.is_a?(Set)
|
623
|
-
target.
|
663
|
+
opts = target.to_a.insert(2, *files)
|
664
|
+
target.clear.merge(opts)
|
624
665
|
else
|
625
|
-
target.
|
666
|
+
target.insert(2, *files)
|
626
667
|
end
|
627
668
|
end
|
628
669
|
|
@@ -788,7 +829,7 @@ module Squared
|
|
788
829
|
bake?(val) ? 1 : 2
|
789
830
|
when '.yml', '.yaml'
|
790
831
|
if compose?(val)
|
791
|
-
path.children.
|
832
|
+
@only&.include?('compose') || path.children.none? { |file| bake?(file) } ? 3 : 1
|
792
833
|
else
|
793
834
|
4
|
794
835
|
end
|