mux_tf 0.15.0 → 0.17.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.
@@ -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!(/\]$/, "") # rubocop:disable Style/SafeNavigationChainLength
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,26 +45,38 @@ 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
- def tf_init(input: nil, upgrade: nil, reconfigure: nil, color: true, &block)
66
+ def tf_init(input: nil, upgrade: nil, reconfigure: nil, color: true, json: false, &block)
33
67
  args = []
34
68
  args << "-input=#{input.inspect}" unless input.nil?
35
69
  args << "-upgrade" unless upgrade.nil?
36
70
  args << "-reconfigure" unless reconfigure.nil?
37
71
  args << "-no-color" unless color
72
+ args << "-json" if json
38
73
 
39
74
  cmd = tf_prepare_command(["init", *args], need_auth: true)
40
- stream_or_run_terraform(cmd, &block)
75
+ stream_terraform(cmd, split_streams: true, &block)
41
76
  end
42
77
 
43
- def tf_plan(out:, color: true, detailed_exitcode: nil, compact_warnings: false, input: nil, targets: [], json: false, &block) # rubocop:disable Metrics/CyclomaticComplexity
78
+ def tf_plan(out:, color: true, detailed_exitcode: nil, compact_warnings: false, input: nil, targets: [], json: false, split_streams: false,
79
+ &block)
44
80
  args = []
45
81
  args += ["-out", out]
46
82
  args << "-input=#{input.inspect}" unless input.nil?
@@ -55,7 +91,7 @@ module MuxTf
55
91
  end
56
92
 
57
93
  cmd = tf_prepare_command(["plan", *args], need_auth: true)
58
- stream_or_run_terraform(cmd, split_streams: json, &block)
94
+ stream_or_run_terraform(cmd, split_streams: json || split_streams, &block)
59
95
  end
60
96
 
61
97
  def tf_show(file, json: false, capture: false)
@@ -132,7 +168,10 @@ module MuxTf
132
168
  stderr_thread.join
133
169
  output_queue.close
134
170
  end
135
- yield(output_queue.pop) until output_queue.closed?
171
+ until output_queue.closed? && output_queue.empty?
172
+ value = output_queue.pop
173
+ yield(value) unless value.nil?
174
+ end
136
175
  wait_thr.value # Process::Status object returned.
137
176
  end
138
177
  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.17.0"
5
5
  end
@@ -3,46 +3,63 @@
3
3
  require "yaml/store"
4
4
 
5
5
  # Ruby 2.7's YAML doesn't have a :unsafe_load method .. so we skip all that
6
- if YAML.singleton_methods.include?(:unsafe_load)
7
- module YAML
8
- # Explaination from @h4xnoodle:
9
- #
10
- # Since ruby 3+ and psych 4+, the yaml loading became extra safe so the
11
- # expired_at timestamp in the yaml cache is no longer parsing for whatever reason.
12
- #
13
- # Attempts were made with
14
- #
15
- # `@store = YAML::Store.new path`
16
- # =>
17
- # `@store = YAML::Store.new(path, { aliases: true, permitted_classes: [Time] })`
18
- # to get it to work but that didn't help, so decided to just bypass the safe
19
- # loading, since the file is controlled by us for the version checking.
20
- #
21
- # This is to override the way that psych seems to be loading YAML.
22
- # Instead of using 'load' which needs work to permit the 'Time' class
23
- # (which from above I tried that and it wasn't working so I decided to just
24
- # bypass and use what it was doing before).
25
- # This brings us back to the equivalent that was working before in that unsafe
26
- # load was used before the psych upgrade.
27
- #
28
- # This change: https://my.diffend.io/gems/psych/3.3.2/4.0.0
29
- # is the changes that 'cause the problem' and so I'm 'fixing it' by using the old equivalent.
30
- #
31
- # Maybe the yaml cache needs more work to have
32
- # `YAML::Store.new(path, { aliases: true, permitted_classes: [Time] }) work.`
33
- #
34
- class << self
35
- undef load # avoid a warning about the next line redefining load
36
- alias load unsafe_load
6
+ # if YAML.singleton_methods.include?(:unsafe_load)
7
+ # module YAML
8
+ # # Explaination from @h4xnoodle:
9
+ # #
10
+ # # Since ruby 3+ and psych 4+, the yaml loading became extra safe so the
11
+ # # expired_at timestamp in the yaml cache is no longer parsing for whatever reason.
12
+ # #
13
+ # # Attempts were made with
14
+ # #
15
+ # # `@store = YAML::Store.new path`
16
+ # # =>
17
+ # # `@store = YAML::Store.new(path, { aliases: true, permitted_classes: [Time] })`
18
+ # # to get it to work but that didn't help, so decided to just bypass the safe
19
+ # # loading, since the file is controlled by us for the version checking.
20
+ # #
21
+ # # This is to override the way that psych seems to be loading YAML.
22
+ # # Instead of using 'load' which needs work to permit the 'Time' class
23
+ # # (which from above I tried that and it wasn't working so I decided to just
24
+ # # bypass and use what it was doing before).
25
+ # # This brings us back to the equivalent that was working before in that unsafe
26
+ # # load was used before the psych upgrade.
27
+ # #
28
+ # # This change: https://my.diffend.io/gems/psych/3.3.2/4.0.0
29
+ # # is the changes that 'cause the problem' and so I'm 'fixing it' by using the old equivalent.
30
+ # #
31
+ # # Maybe the yaml cache needs more work to have
32
+ # # `YAML::Store.new(path, { aliases: true, permitted_classes: [Time] }) work.`
33
+ # #
34
+ # class << self
35
+ # undef load # avoid a warning about the next line redefining load
36
+ # alias load unsafe_load
37
+ # end
38
+ # end
39
+ # end
40
+
41
+ module MuxTf
42
+ class UnsafeYamlStore < YAML::Store
43
+ def initialize(*args)
44
+ super
45
+ @opt[:permitted_classes] ||= [Symbol]
46
+ end
47
+
48
+ # basically have to override the whole load method, since it doesn't allow customization of the allowed classes ..
49
+ def load(content)
50
+ table = YAML.safe_load(content, **@opt)
51
+ if [false, nil].include?(table)
52
+ {}
53
+ else
54
+ table
55
+ end
37
56
  end
38
57
  end
39
- end
40
58
 
41
- module MuxTf
42
59
  class YamlCache
43
60
  def initialize(path, default_ttl:)
44
61
  @default_ttl = default_ttl
45
- @store = YAML::Store.new path
62
+ @store = UnsafeYamlStore.new path, { aliases: true, permitted_classes: [Symbol, Time] }
46
63
  end
47
64
 
48
65
  def set(key, value, ttl: @default_ttl)
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,25 @@ 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.2.0"
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"
48
+
49
+ # stdlib suff
50
+ spec.add_dependency "benchmark"
51
+ spec.add_dependency "ostruct"
52
+ spec.add_dependency "pstore"
42
53
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mux_tf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Banasik
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-02-09 00:00:00.000000000 Z
10
+ date: 2025-05-12 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -24,6 +23,48 @@ dependencies:
24
23
  - - "<"
25
24
  - !ruby/object:Gem::Version
26
25
  version: 7.0.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: base64
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: bigdecimal
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: mutex_m
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
27
68
  - !ruby/object:Gem::Dependency
28
69
  name: awesome_print
29
70
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +141,14 @@ dependencies:
100
141
  requirements:
101
142
  - - "~>"
102
143
  - !ruby/object:Gem::Version
103
- version: 0.1.0
144
+ version: 0.2.0
104
145
  type: :runtime
105
146
  prerelease: false
106
147
  version_requirements: !ruby/object:Gem::Requirement
107
148
  requirements:
108
149
  - - "~>"
109
150
  - !ruby/object:Gem::Version
110
- version: 0.1.0
151
+ version: 0.2.0
111
152
  - !ruby/object:Gem::Dependency
112
153
  name: stateful_parser
113
154
  requirement: !ruby/object:Gem::Requirement
@@ -150,7 +191,62 @@ dependencies:
150
191
  - - ">="
151
192
  - !ruby/object:Gem::Version
152
193
  version: '0'
153
- description:
194
+ - !ruby/object:Gem::Dependency
195
+ name: zeitwerk
196
+ requirement: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: '2.6'
201
+ type: :runtime
202
+ prerelease: false
203
+ version_requirements: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '2.6'
208
+ - !ruby/object:Gem::Dependency
209
+ name: benchmark
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ type: :runtime
216
+ prerelease: false
217
+ version_requirements: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: ostruct
224
+ requirement: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ type: :runtime
230
+ prerelease: false
231
+ version_requirements: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ - !ruby/object:Gem::Dependency
237
+ name: pstore
238
+ requirement: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - ">="
241
+ - !ruby/object:Gem::Version
242
+ version: '0'
243
+ type: :runtime
244
+ prerelease: false
245
+ version_requirements: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - ">="
248
+ - !ruby/object:Gem::Version
249
+ version: '0'
154
250
  email:
155
251
  - piotr@jane.app
156
252
  executables:
@@ -167,14 +263,21 @@ files:
167
263
  - lib/mux_tf.rb
168
264
  - lib/mux_tf/cli.rb
169
265
  - lib/mux_tf/cli/current.rb
266
+ - lib/mux_tf/cli/current/plan_command.rb
170
267
  - lib/mux_tf/cli/mux.rb
171
268
  - lib/mux_tf/cli/plan_summary.rb
172
269
  - lib/mux_tf/coloring.rb
270
+ - lib/mux_tf/error_handling_methods.rb
271
+ - lib/mux_tf/formatter_common.rb
272
+ - lib/mux_tf/handlers.rb
273
+ - lib/mux_tf/handlers/plan_handler.rb
274
+ - lib/mux_tf/init_formatter.rb
173
275
  - lib/mux_tf/plan_filename_generator.rb
174
276
  - lib/mux_tf/plan_formatter.rb
175
277
  - lib/mux_tf/plan_summary_handler.rb
176
278
  - lib/mux_tf/plan_utils.rb
177
279
  - lib/mux_tf/resource_tokenizer.rb
280
+ - lib/mux_tf/stderr_line_handler.rb
178
281
  - lib/mux_tf/terraform_helpers.rb
179
282
  - lib/mux_tf/tmux.rb
180
283
  - lib/mux_tf/version.rb
@@ -188,7 +291,6 @@ metadata:
188
291
  rubygems_mfa_required: 'true'
189
292
  homepage_uri: https://github.com/piotrb/mux_tf
190
293
  source_code_uri: https://github.com/piotrb/mux_tf
191
- post_install_message:
192
294
  rdoc_options: []
193
295
  require_paths:
194
296
  - lib
@@ -203,8 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
305
  - !ruby/object:Gem::Version
204
306
  version: '0'
205
307
  requirements: []
206
- rubygems_version: 3.2.22
207
- signing_key:
308
+ rubygems_version: 3.6.2
208
309
  specification_version: 4
209
310
  summary: Terraform Multiplexing Scripts
210
311
  test_files: []