mux_tf 0.15.0 → 0.16.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.
@@ -33,7 +33,7 @@ module MuxTf
33
33
  case action
34
34
  when "create", "add"
35
35
  :green
36
- when "update", "change"
36
+ when "update", "change", "import-update"
37
37
  :yellow
38
38
  when "delete", "remove"
39
39
  :red
@@ -64,6 +64,10 @@ module MuxTf
64
64
  "±"
65
65
  when "read"
66
66
  ">"
67
+ when "import"
68
+ "→"
69
+ when "import-update"
70
+ "↗︎"
67
71
  else
68
72
  action
69
73
  end
@@ -94,7 +98,7 @@ module MuxTf
94
98
  end
95
99
  end
96
100
 
97
- def initialize(data) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
101
+ def initialize(data)
98
102
  @parts = []
99
103
 
100
104
  data["output_changes"]&.each do |output_name, v|
@@ -138,6 +142,14 @@ module MuxTf
138
142
  case v["change"]["actions"]
139
143
  when ["no-op"]
140
144
  # do nothing
145
+ if v["change"]["importing"]
146
+ parts << {
147
+ type: "resource",
148
+ action: "import",
149
+ address: v["address"],
150
+ deps: find_deps(data, v["address"])
151
+ }
152
+ end
141
153
  when ["create"]
142
154
  parts << {
143
155
  type: "resource",
@@ -146,9 +158,10 @@ module MuxTf
146
158
  deps: find_deps(data, v["address"])
147
159
  }
148
160
  when ["update"]
161
+ # ap [v["change"]["actions"], v["change"]["importing"]]
149
162
  parts << {
150
163
  type: "resource",
151
- action: "update",
164
+ action: v["change"]["importing"] ? "import-update" : "update",
152
165
  address: v["address"],
153
166
  deps: find_deps(data, v["address"])
154
167
  }
@@ -198,7 +211,7 @@ module MuxTf
198
211
  parts.select { |part| part[:type] == "output" }
199
212
  end
200
213
 
201
- def summary # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
214
+ def summary
202
215
  # resources
203
216
  resource_summary = {}
204
217
  resource_parts.each do |part|
@@ -233,11 +246,9 @@ module MuxTf
233
246
  end
234
247
 
235
248
  def flat_summary
236
- result = []
237
- resource_parts.each do |part|
238
- result << "[#{self.class.format_action(part[:action])}] #{self.class.format_address(part[:address])}"
249
+ resource_parts.map do |part|
250
+ "[#{self.class.format_action(part[:action])}] #{self.class.format_address(part[:address])}"
239
251
  end
240
- result
241
252
  end
242
253
 
243
254
  def sensitive_summary(before_value, after_value)
@@ -265,7 +276,20 @@ module MuxTf
265
276
  result
266
277
  end
267
278
 
268
- def nested_summary # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
279
+ def simple_summary(&printer)
280
+ printer = method(:puts) if printer.nil?
281
+
282
+ flat_summary.each do |line|
283
+ printer.call line
284
+ end
285
+ output_summary.each do |line|
286
+ printer.call line
287
+ end
288
+ printer.call ""
289
+ printer.call summary
290
+ end
291
+
292
+ def nested_summary
269
293
  result = []
270
294
  parts = resource_parts.deep_dup
271
295
  until parts.empty?
@@ -305,8 +329,7 @@ module MuxTf
305
329
  if result.empty?
306
330
  throw :abort, "nothing selected"
307
331
  else
308
- log "Re-running apply with the selected resources ..."
309
- MuxTf::Cli::Current.run_plan(targets: result)
332
+ result
310
333
  end
311
334
  end
312
335
 
@@ -314,22 +337,6 @@ module MuxTf
314
337
 
315
338
  attr_reader :parts
316
339
 
317
- def create_plan(filename, targets: [])
318
- log "Preparing Plan ...", depth: 1
319
- exit_code, meta = PlanFormatter.pretty_plan(filename, targets: targets)
320
- case exit_code
321
- when 0
322
- [:ok, meta]
323
- when 1
324
- [:error, meta]
325
- when 2
326
- [:changes, meta]
327
- else
328
- log pastel.yellow("terraform plan exited with an unknown exit code: #{exit_code}")
329
- [:unknown, meta]
330
- end
331
- end
332
-
333
340
  def prune_unchanged_deps(_parts)
334
341
  valid_addresses = resource_parts.map { |part| part[:address] }
335
342
 
@@ -338,7 +345,7 @@ module MuxTf
338
345
  end
339
346
  end
340
347
 
341
- def find_deps(data, address) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
348
+ def find_deps(data, address)
342
349
  result = []
343
350
 
344
351
  m = address.match(/\[(.+)\]$/)
@@ -358,7 +365,7 @@ module MuxTf
358
365
  resource, parent_address = find_config(data["configuration"], "root_module", address, [])
359
366
  if resource
360
367
  deps = []
361
- resource["expressions"]&.each do |_k, v|
368
+ resource["expressions"]&.each_value do |v|
362
369
  deps << v["references"] if v.is_a?(Hash) && v["references"]
363
370
  end
364
371
  result += deps.map { |s| (parent_address + [s]).join(".") }
@@ -21,7 +21,7 @@ module MuxTf
21
21
  puts msg.join(" - ")
22
22
  end
23
23
 
24
- def update_placeholders(dst, src, placeholder) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
24
+ def update_placeholders(dst, src, placeholder)
25
25
  return unless src
26
26
 
27
27
  case src
@@ -104,7 +104,10 @@ module MuxTf
104
104
  else
105
105
  false
106
106
  end
107
- rescue Psych::SyntaxError => e
107
+ rescue Psych::DisallowedClass => e
108
+ ap e
109
+ false
110
+ rescue Psych::SyntaxError => e # rubocop:disable Lint/DuplicateBranch
108
111
  ap e
109
112
  false
110
113
  end
@@ -115,6 +118,10 @@ module MuxTf
115
118
  pastel.green(symbol)
116
119
  when "~"
117
120
  pastel.yellow(symbol)
121
+ when "-"
122
+ pastel.red(symbol)
123
+ when "?"
124
+ pastel.orange(symbol)
118
125
  else
119
126
  warning "Unknown symbol: #{symbol.inspect}"
120
127
  symbol
@@ -143,7 +150,7 @@ module MuxTf
143
150
  }.join("\n")
144
151
  end
145
152
 
146
- def in_display_representation(value) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
153
+ def in_display_representation(value)
147
154
  if valid_json?(value)
148
155
  json_body = JSON.pretty_generate(JSON.parse(value))
149
156
  wrap(json_body, prefix: "json(", suffix: ")", color: :gray)
@@ -251,12 +258,21 @@ module MuxTf
251
258
 
252
259
  def get_pretty_action_and_symbol(actions)
253
260
  case actions
261
+ when ["delete"]
262
+ pretty_action = "delete"
263
+ symbol = "-"
254
264
  when ["update"]
255
265
  pretty_action = "updated in-place"
256
266
  symbol = "~"
257
267
  when ["create"]
258
268
  pretty_action = "created"
259
269
  symbol = "+"
270
+ when %w[delete create]
271
+ pretty_action = "replaced (delete first)"
272
+ symbol = "±"
273
+ when ["read"]
274
+ pretty_action = "read"
275
+ symbol = ">"
260
276
  else
261
277
  warning "Unknown action: #{actions.inspect}"
262
278
  pretty_action = actions.inspect
@@ -286,7 +302,7 @@ module MuxTf
286
302
  # EOT
287
303
  # # (12 unchanged attributes hidden)
288
304
  # }
289
- def tf_show_json_resource(resource) # rubocop:disable Metrics/AbcSize
305
+ def tf_show_json_resource(resource)
290
306
  pretty_action, symbol = get_pretty_action_and_symbol(resource["change"]["actions"])
291
307
 
292
308
  output = []
@@ -6,7 +6,7 @@ module MuxTf
6
6
  tokenize(resource).map(&:last)
7
7
  end
8
8
 
9
- def self.tokenize(resource) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
9
+ def self.tokenize(resource)
10
10
  result = []
11
11
  n = 0
12
12
  pn = 0
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "English"
4
+ module MuxTf
5
+ class StderrLineHandler
6
+ include PiotrbCliUtils::Util
7
+ include Coloring
8
+
9
+ include ErrorHandlingMethods
10
+
11
+ attr_reader :meta
12
+
13
+ def initialize(operation: nil)
14
+ @operation = operation
15
+ @held_messages = []
16
+ @parser = StatefulParser.new(normalizer: pastel.method(:strip))
17
+ @meta = {}
18
+ setup_error_handling(@parser, from_states: [:none])
19
+ end
20
+
21
+ def transform_paths!(hash, key)
22
+ return unless hash[key]
23
+
24
+ if key == "prefix"
25
+ hash[key].strip!
26
+ hash[key].gsub!(/^\[/, "")
27
+ hash[key].gsub!(/\]$/, "")
28
+ end
29
+
30
+ hash[key].gsub!("#{Dir.getwd}/", "")
31
+ hash[key].gsub!(Dir.getwd, "")
32
+
33
+ hash[key].gsub!($LAST_MATCH_INFO[1], "<cache>/") if hash[key].match(%r{(\.terragrunt-cache/[^/]+/[^/]+/)})
34
+
35
+ hash
36
+ end
37
+
38
+ def handle(raw_line)
39
+ return if raw_line.strip.empty?
40
+
41
+ if raw_line =~ /Error when retrieving token from sso: Token has expired and refresh failed/
42
+ log "#{pastel.red('error')}: SSO Session expired.", depth: 2
43
+ return
44
+ end
45
+
46
+ # [✘] error when retrieving credentials from custom process. please login using 'granted sso login --sso-start-url https://janeapp.awsapps.com/start --sso-region us-east-1'
47
+ if raw_line =~ /error when retrieving credentials from custom process. please login using '([^']+)'/
48
+ unless @sso_expired
49
+ @sso_expired = true
50
+ log "#{pastel.red('error')}: SSO Session expired.", depth: 2
51
+ log "#{pastel.red('error')}: Run: #{$LAST_MATCH_INFO[1]}", depth: 2
52
+ end
53
+ return
54
+ end
55
+
56
+ if raw_line.strip[0] == "{" && raw_line.strip[-1] == "}"
57
+ begin
58
+ # assuming that stderr is JSON and TG logs
59
+ parsed_line = JSON.parse(raw_line)
60
+ transform_paths!(parsed_line, "msg")
61
+ transform_paths!(parsed_line, "prefix")
62
+ parsed_line["msg"].gsub!("#{Dir.getwd}/", "")
63
+ parsed_line["prefix"]&.strip!&.gsub!(/^\[/, "")&.gsub!(/\]$/, "")
64
+ parsed_line["prefix"]&.gsub!(Dir.getwd, "")
65
+ if @operation == :plan
66
+ handle_plan_json(parsed_line)
67
+ else
68
+ log format_tg_log_line(parsed_line), depth: 2
69
+ end
70
+ rescue JSON::ParserError => e
71
+ log "#{pastel.red('error')}: failed to parse JSON: #{e.message}", depth: 2
72
+ log raw_line.rstrip, depth: 2
73
+ end
74
+ else
75
+ @parser.parse(raw_line.rstrip) do |state, line|
76
+ # log raw_line.rstrip, depth: 2
77
+ log_unhandled_line(state, line, reason: "unexpected state in StderrLineHandler") unless handle_error_states(@meta, state, line)
78
+ end
79
+ end
80
+ end
81
+
82
+ def handle_plan_json(parsed_line)
83
+ if parsed_line["msg"] =~ /terraform invocation failed in/
84
+ @held_messages << format_tg_log_line(parsed_line)
85
+ elsif parsed_line["msg"] =~ /1 error occurred/ && parsed_line["msg"] =~ /exit status 2\n/
86
+ # 2 = Succeeded with non-empty diff (changes present)
87
+ # clear the held messages and swallow up this message too
88
+ @held_messages = []
89
+ else
90
+ # flush
91
+ log format_tg_log_line(parsed_line), depth: 2
92
+ end
93
+ end
94
+
95
+ def flush
96
+ @held_messages.each do |msg|
97
+ log msg, depth: 2
98
+ end
99
+ @held_messages = []
100
+ end
101
+
102
+ def do_print_errors
103
+ print_errors(@meta) if @meta[:errors] && !@meta[:errors].empty?
104
+ end
105
+
106
+ def merge_meta_into(other_meta)
107
+ [:errors, :warnings].each do |type|
108
+ if @meta[type]
109
+ other_meta[type] ||= []
110
+ other_meta[type] += @meta[type]
111
+ end
112
+ end
113
+
114
+ extra_keys = @meta.keys - [:errors, :warnings]
115
+ return unless extra_keys.any?
116
+
117
+ log "Unhandled keys in stderr_handler.meta: #{extra_keys.inspect}"
118
+ log @meta.inspect
119
+ end
120
+
121
+ private
122
+
123
+ def format_tg_log_line(line_data)
124
+ # {
125
+ # "level"=>"error",
126
+ # "msg"=>"terraform invocation failed in /Users/piotr/Work/janepods/accounts/eks-dev/unstable-1/kluster/.terragrunt-cache/Gqer3b7TGI4swB-Nw7Pe5DUIrus/JkQqfrQedXyGMwcl4yYfGocMcvk/modules/kluster",
127
+ # "prefix"=>"[/Users/piotr/Work/janepods/accounts/eks-dev/unstable-1/kluster] ",
128
+ # "time"=>"2024-02-28T16:14:28-08:00"
129
+ # }
130
+
131
+ msg = ""
132
+ msg += case line_data["level"]
133
+ when "info"
134
+ pastel.cyan(line_data["level"])
135
+ when "error"
136
+ pastel.red(line_data["level"])
137
+ else
138
+ pastel.orange(line_data["level"])
139
+ end
140
+ msg += ": #{line_data['msg']}"
141
+ msg += " [#{line_data['prefix']}]" if line_data["prefix"] && !line_data["prefix"].empty?
142
+ msg
143
+ end
144
+ end
145
+ end
@@ -11,6 +11,30 @@ module MuxTf
11
11
  run_terraform(tf_prepare_command(["force-unlock", "-force", id], need_auth: true))
12
12
  end
13
13
 
14
+ def tf_stream_helper(cmd, operation:, echo_stdout: false, &block)
15
+ # stdout = ""
16
+
17
+ stderr_handler = StderrLineHandler.new(operation: operation)
18
+
19
+ result_struct = stream_terraform(cmd, split_streams: true) { |(stream, raw_line)|
20
+ case stream
21
+ when :command
22
+ log "Running command: #{raw_line.strip} ...", depth: 2
23
+ when :stdout
24
+ # stdout += raw_line
25
+ print raw_line if echo_stdout
26
+ block&.call(:stdout, raw_line)
27
+ when :stderr
28
+ stderr_handler.handle(raw_line)
29
+ end
30
+ }
31
+
32
+ stderr_handler.flush
33
+ stderr_handler.do_print_errors
34
+
35
+ result_struct
36
+ end
37
+
14
38
  def tf_apply(filename: nil, targets: [])
15
39
  args = []
16
40
  args << filename if filename
@@ -21,12 +45,22 @@ module MuxTf
21
45
  end
22
46
 
23
47
  cmd = tf_prepare_command(["apply", *args], need_auth: true)
24
- run_terraform(cmd)
48
+
49
+ tf_stream_helper(cmd, operation: :apply, echo_stdout: true)
25
50
  end
26
51
 
27
52
  def tf_validate
28
53
  cmd = tf_prepare_command(["validate", "-json"], need_auth: true)
29
- capture_terraform(cmd, json: true)
54
+
55
+ stdout = ""
56
+
57
+ tf_stream_helper(cmd, operation: :validate) do |stream, raw_line|
58
+ stdout += raw_line if stream == :stdout
59
+ end
60
+
61
+ throw :abort, false if stdout.strip.empty?
62
+
63
+ JSON.parse(stdout)
30
64
  end
31
65
 
32
66
  def tf_init(input: nil, upgrade: nil, reconfigure: nil, color: true, &block)
@@ -37,10 +71,11 @@ module MuxTf
37
71
  args << "-no-color" unless color
38
72
 
39
73
  cmd = tf_prepare_command(["init", *args], need_auth: true)
40
- stream_or_run_terraform(cmd, &block)
74
+ stream_terraform(cmd, split_streams: true, &block)
41
75
  end
42
76
 
43
- def tf_plan(out:, color: true, detailed_exitcode: nil, compact_warnings: false, input: nil, targets: [], json: false, &block) # rubocop:disable Metrics/CyclomaticComplexity
77
+ def tf_plan(out:, color: true, detailed_exitcode: nil, compact_warnings: false, input: nil, targets: [], json: false, split_streams: false,
78
+ &block)
44
79
  args = []
45
80
  args += ["-out", out]
46
81
  args << "-input=#{input.inspect}" unless input.nil?
@@ -55,7 +90,7 @@ module MuxTf
55
90
  end
56
91
 
57
92
  cmd = tf_prepare_command(["plan", *args], need_auth: true)
58
- stream_or_run_terraform(cmd, split_streams: json, &block)
93
+ stream_or_run_terraform(cmd, split_streams: json || split_streams, &block)
59
94
  end
60
95
 
61
96
  def tf_show(file, json: false, capture: false)
@@ -132,7 +167,10 @@ module MuxTf
132
167
  stderr_thread.join
133
168
  output_queue.close
134
169
  end
135
- yield(output_queue.pop) until output_queue.closed?
170
+ until output_queue.closed? && output_queue.empty?
171
+ value = output_queue.pop
172
+ yield(value) unless value.nil?
173
+ end
136
174
  wait_thr.value # Process::Status object returned.
137
175
  end
138
176
  end
data/lib/mux_tf/tmux.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "shellwords"
4
+ require "open3"
4
5
 
5
6
  module MuxTf
6
7
  module Tmux
@@ -23,6 +24,13 @@ module MuxTf
23
24
  panes.find { |pane| pane[:name] == name }
24
25
  end
25
26
 
27
+ def list_panes
28
+ `tmux list-panes -F "\#{pane_id},\#{pane_index},\#{pane_title}"`.strip.split("\n").map do |row|
29
+ x = row.split(",")
30
+ { id: x[0], index: x[1], name: x[2] }
31
+ end
32
+ end
33
+
26
34
  def list_windows
27
35
  `tmux list-windows -F "\#{window_id},\#{window_index},\#{window_name}"`.strip.split("\n").map do |row|
28
36
  x = row.split(",")
@@ -30,8 +38,15 @@ module MuxTf
30
38
  end
31
39
  end
32
40
 
33
- def new_session(name)
34
- tmux %(new-session -s #{name.inspect} -d)
41
+ def new_session(name, cwd: nil, cmd: nil)
42
+ parts = [
43
+ "new-session",
44
+ "-s #{name.inspect}",
45
+ "-d",
46
+ cwd ? "-c #{cwd}" : nil,
47
+ cmd&.inspect
48
+ ].compact
49
+ tmux parts.join(" ")
35
50
  end
36
51
 
37
52
  def select_pane(name)
@@ -50,8 +65,23 @@ module MuxTf
50
65
  tmux "select-layout tiled"
51
66
  end
52
67
 
53
- def attach(name, cc: false)
54
- tmux %(#{(cc && '-CC') || ''} attach -t #{name.inspect}), raise_on_error: false
68
+ def attach_control(name, on_line:, on_spawn:)
69
+ parts = [
70
+ "-C",
71
+ "attach",
72
+ "-t #{name.inspect}"
73
+ ].compact
74
+ tmux parts.join(" "), raise_on_error: false, mode: :popen, on_line: on_line, on_spawn: on_spawn
75
+ end
76
+
77
+ def attach(name, cc: false, control: false)
78
+ parts = [
79
+ cc ? "-CC" : nil,
80
+ control ? "-C" : nil,
81
+ "attach",
82
+ "-t #{name.inspect}"
83
+ ].compact
84
+ tmux parts.join(" "), raise_on_error: false
55
85
  end
56
86
 
57
87
  def kill_pane(pane_id)
@@ -75,7 +105,7 @@ module MuxTf
75
105
 
76
106
  parts = [
77
107
  "split-window",
78
- cwd && "-c #{cwd}",
108
+ cwd ? "-c #{cwd}" : nil,
79
109
  mode_part,
80
110
  "-t #{target_pane.inspect}",
81
111
  cmd&.inspect
@@ -89,7 +119,7 @@ module MuxTf
89
119
  @tmux_bin ||= `which tmux`.strip
90
120
  end
91
121
 
92
- def tmux(cmd, raise_on_error: true, mode: :system)
122
+ def tmux(cmd, raise_on_error: true, mode: :system, on_line: nil, on_spawn: nil)
93
123
  case mode
94
124
  when :system
95
125
  # puts " => tmux #{cmd}"
@@ -102,6 +132,25 @@ module MuxTf
102
132
  true
103
133
  when :exec
104
134
  exec tmux_bin, *Shellwords.shellwords(cmd)
135
+ when :popen
136
+ Open3.popen3(tmux_bin, *Shellwords.shellwords(cmd)) do |stdin, stdout, stderr, wait_thr|
137
+ on_spawn&.call(stdin, wait_thr)
138
+ Thread.new do
139
+ until stdout.closed? || stdout.eof?
140
+ line = stdout.gets
141
+ on_line&.call(:stdout, line)
142
+ end
143
+ end
144
+ Thread.new do
145
+ until stderr.closed? || stderr.eof?
146
+ line = stderr.gets
147
+ on_line&.call(:stderr, line)
148
+ end
149
+ end
150
+ # pid = wait_thr.pid
151
+ exit_status = wait_thr.value
152
+ fail_with("`tmux #{cmd}' failed with code: #{exit_status}") if raise_on_error && exit_status != 0
153
+ end
105
154
  end
106
155
  end
107
156
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MuxTf
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end
@@ -25,6 +25,6 @@ module MuxTf
25
25
  @cache ||= YamlCache.new(File.expand_path("~/.mux_tf.yaml"), default_ttl: 1.hour)
26
26
  end
27
27
 
28
- module_function :has_updates?, :latest_gem_version, :current_gem_version, :cache
28
+ module_function :has_updates?, :latest_gem_version, :current_gem_version, :cache # rubocop:disable Style/AccessModifierDeclarations
29
29
  end
30
30
  end
data/lib/mux_tf.rb CHANGED
@@ -26,19 +26,13 @@ require "diff/lcs"
26
26
  require "diff/lcs/string"
27
27
  require "diff/lcs/hunk"
28
28
 
29
- require_relative "mux_tf/version"
30
- require_relative "mux_tf/coloring"
31
- require_relative "mux_tf/plan_filename_generator"
32
- require_relative "mux_tf/resource_tokenizer"
33
- require_relative "mux_tf/cli"
34
- require_relative "mux_tf/tmux"
35
- require_relative "mux_tf/terraform_helpers"
36
- require_relative "mux_tf/plan_formatter"
37
- require_relative "mux_tf/version_check"
38
- require_relative "mux_tf/yaml_cache"
39
- require_relative "mux_tf/plan_summary_handler"
40
- require_relative "mux_tf/plan_utils"
29
+ require "zeitwerk"
30
+ loader = Zeitwerk::Loader.for_gem
31
+ loader.ignore("#{__dir__}/deps.rb")
32
+ loader.setup
41
33
 
42
34
  module MuxTf
43
35
  ROOT = File.expand_path(File.join(__dir__, ".."))
44
36
  end
37
+
38
+ loader.eager_load
data/mux_tf.gemspec CHANGED
@@ -29,14 +29,20 @@ Gem::Specification.new do |spec|
29
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
31
 
32
+ # below activesupport are deps which cause warnings in ruby 3.3
32
33
  spec.add_dependency "activesupport", "< 7.0.0"
34
+ spec.add_dependency "base64"
35
+ spec.add_dependency "bigdecimal"
36
+ spec.add_dependency "mutex_m"
37
+
33
38
  spec.add_dependency "awesome_print"
34
39
  spec.add_dependency "diff-lcs"
35
40
  spec.add_dependency "dotenv"
36
41
  spec.add_dependency "hashdiff"
37
42
  spec.add_dependency "pastel"
38
- spec.add_dependency "piotrb_cli_utils", "~> 0.1.0"
43
+ spec.add_dependency "piotrb_cli_utils", "~> 0.1.1"
39
44
  spec.add_dependency "stateful_parser", "~> 0.1.1"
40
45
  spec.add_dependency "tty-prompt"
41
46
  spec.add_dependency "tty-table"
47
+ spec.add_dependency "zeitwerk", "~> 2.6"
42
48
  end