MuranoCLI 3.0.1 → 3.0.2

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.agignore +1 -0
  3. data/.rubocop.yml +67 -5
  4. data/Gemfile +6 -3
  5. data/MuranoCLI.gemspec +14 -10
  6. data/README.markdown +299 -126
  7. data/Rakefile +6 -1
  8. data/bin/murano +2 -2
  9. data/docs/completions/murano_completion-bash +93 -0
  10. data/lib/MrMurano.rb +19 -2
  11. data/lib/MrMurano/Business.rb +22 -19
  12. data/lib/MrMurano/Config.rb +19 -9
  13. data/lib/MrMurano/Content.rb +4 -4
  14. data/lib/MrMurano/Exchange-Element.rb +99 -0
  15. data/lib/MrMurano/Exchange.rb +137 -0
  16. data/lib/MrMurano/Gateway.rb +9 -9
  17. data/lib/MrMurano/Keystore.rb +4 -2
  18. data/lib/MrMurano/ReCommander.rb +3 -5
  19. data/lib/MrMurano/Solution-ServiceConfig.rb +12 -12
  20. data/lib/MrMurano/Solution-Services.rb +15 -14
  21. data/lib/MrMurano/Solution-Users.rb +2 -2
  22. data/lib/MrMurano/Solution.rb +43 -49
  23. data/lib/MrMurano/SolutionId.rb +28 -28
  24. data/lib/MrMurano/SyncUpDown.rb +32 -22
  25. data/lib/MrMurano/Webservice-Endpoint.rb +2 -1
  26. data/lib/MrMurano/Webservice.rb +5 -5
  27. data/lib/MrMurano/commands.rb +2 -1
  28. data/lib/MrMurano/commands/business.rb +21 -19
  29. data/lib/MrMurano/commands/domain.rb +16 -2
  30. data/lib/MrMurano/commands/exchange.rb +272 -0
  31. data/lib/MrMurano/commands/globals.rb +17 -1
  32. data/lib/MrMurano/commands/init.rb +3 -3
  33. data/lib/MrMurano/commands/link.rb +16 -16
  34. data/lib/MrMurano/commands/postgresql.rb +2 -2
  35. data/lib/MrMurano/commands/show.rb +13 -7
  36. data/lib/MrMurano/commands/solution.rb +23 -17
  37. data/lib/MrMurano/commands/solution_picker.rb +49 -44
  38. data/lib/MrMurano/commands/sync.rb +2 -1
  39. data/lib/MrMurano/commands/timeseries.rb +2 -2
  40. data/lib/MrMurano/commands/tsdb.rb +2 -2
  41. data/lib/MrMurano/hash.rb +19 -7
  42. data/lib/MrMurano/http.rb +12 -2
  43. data/lib/MrMurano/orderedhash.rb +200 -0
  44. data/lib/MrMurano/spec_commander.rb +98 -0
  45. data/lib/MrMurano/verbosing.rb +2 -2
  46. data/lib/MrMurano/version.rb +2 -2
  47. data/spec/Business_spec.rb +8 -6
  48. data/spec/Solution-ServiceConfig_spec.rb +1 -1
  49. data/spec/SyncUpDown_spec.rb +6 -6
  50. data/spec/_workspace.rb +9 -4
  51. data/spec/cmd_business_spec.rb +8 -2
  52. data/spec/cmd_common.rb +266 -25
  53. data/spec/cmd_exchange_spec.rb +118 -0
  54. data/spec/cmd_help_spec.rb +54 -13
  55. data/spec/cmd_init_spec.rb +1 -12
  56. data/spec/cmd_link_spec.rb +94 -72
  57. data/spec/spec_helper.rb +11 -16
  58. metadata +23 -17
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.02 /coding: utf-8
1
+ # Last Modified: 2017.09.11 /coding: utf-8
2
2
 
3
3
  # Copyright © 2016-2017 Exosite LLC.
4
4
  # License: MIT. See LICENSE.txt.
@@ -37,6 +37,7 @@ RSpec.describe MrMurano::Business do
37
37
  pid: "ABC",
38
38
  modelId: "cde",
39
39
  label: "fts",
40
+ api_id: "XYZ",
40
41
  sid: "XYZ",
41
42
  name: "XYZ",},
42
43
  {bizid: "XYZxyz",
@@ -44,6 +45,7 @@ RSpec.describe MrMurano::Business do
44
45
  pid: "fgh",
45
46
  modelId: "ijk",
46
47
  label: "lua-test",
48
+ api_id: "XYZ",
47
49
  sid: "XYZ",
48
50
  name: "XYZ",},
49
51
  ]
@@ -106,14 +108,14 @@ RSpec.describe MrMurano::Business do
106
108
  {bizid: "XYZxyz",
107
109
  type: "application",
108
110
  domain: "XYZxyz.apps.exosite.io",
109
- apiId: "ACBabc",
111
+ api_id: "ACBabc",
110
112
  sid: "ACBabc",
111
113
  name: "ijk",
112
114
  },
113
115
  {bizid: "XYZxyz",
114
116
  type: "application",
115
117
  domain: "XYZxyz.apps.exosite.io",
116
- apiId: "DEFdef",
118
+ api_id: "DEFdef",
117
119
  sid: "DEFdef",
118
120
  name: "lmn",
119
121
  },
@@ -183,7 +185,7 @@ RSpec.describe MrMurano::Business do
183
185
  {bizid: "XYZxyz",
184
186
  type: "product",
185
187
  domain: "ABCabc.m2.exosite.io",
186
- apiId: "ABCabc",
188
+ api_id: "ABCabc",
187
189
  sid: "ABCabc",
188
190
  name: "XXX",
189
191
  },
@@ -192,7 +194,7 @@ RSpec.describe MrMurano::Business do
192
194
  {bizid: "XYZxyz",
193
195
  type: "application",
194
196
  domain: "XYZxyz.apps.exosite.io",
195
- apiId: "DEFdef",
197
+ api_id: "DEFdef",
196
198
  sid: "DEFdef",
197
199
  name: "XXX",
198
200
  },
@@ -222,7 +224,7 @@ RSpec.describe MrMurano::Business do
222
224
 
223
225
  sol = @biz.new_solution!("one", :product)
224
226
  expect(sol.valid?).to be true
225
- expect(sol.sid).to eq("abc123def456ghi78")
227
+ expect(sol.api_id).to eq("abc123def456ghi78")
226
228
  end
227
229
 
228
230
  # if false
@@ -18,7 +18,7 @@ RSpec.describe MrMurano::ServiceConfig do
18
18
  $cfg['product.id'] = 'XYZ'
19
19
  $cfg['application.id'] = 'XYZ'
20
20
 
21
- # ServiceConfig needs an sid, else one could instantiate
21
+ # ServiceConfig needs an api_id, else one could instantiate
22
22
  # ServiceConfigApplication or ServiceConfigProduct.
23
23
  @srv = MrMurano::ServiceConfig.new('XYZ')
24
24
  allow(@srv).to receive(:token).and_return("TTTTTTTTTT")
@@ -12,20 +12,20 @@ class TSUD
12
12
 
13
13
  def initialize
14
14
  # 2017-07-03: See MrMurano::SolutionBase.state for the list of attrs.
15
- @sid = 'XYZ'
16
- @valid_sid = true
15
+ @api_id = 'XYZ'
16
+ @valid_api_id = true
17
17
  @uriparts = []
18
18
  @solntype = 'application.id'
19
19
  @itemkey = :name
20
20
  @project_section = :routes
21
21
  end
22
22
 
23
- def sid
24
- @sid
23
+ def api_id
24
+ @api_id
25
25
  end
26
26
 
27
- def sid?
28
- @valid_sid
27
+ def api_id?
28
+ @valid_api_id
29
29
  end
30
30
 
31
31
  def fetch(id)
@@ -1,9 +1,15 @@
1
+ # Last Modified: 2017.08.29 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
1
8
  require 'fileutils'
2
9
  require 'pathname'
3
10
  require 'tmpdir'
4
11
 
5
- RSpec.shared_context "WORKSPACE" do
6
-
12
+ RSpec.shared_context 'WORKSPACE' do
7
13
  around(:example) do |ex|
8
14
  @testdir = Pathname.new(Dir.pwd).realpath
9
15
  Dir.mktmpdir do |hdir|
@@ -16,7 +22,7 @@ RSpec.shared_context "WORKSPACE" do
16
22
  @project_dir = File.join(ENV['HOME'], 'work', 'project')
17
23
  FileUtils.mkpath(@project_dir)
18
24
  Dir.chdir(@project_dir) do
19
- ex.run
25
+ ex.run
20
26
  end
21
27
  end
22
28
  ENV['HOME'] = saved_home
@@ -24,4 +30,3 @@ RSpec.shared_context "WORKSPACE" do
24
30
  end
25
31
  end
26
32
 
27
- # vim: set ai et sw=2 ts=2 :
@@ -1,4 +1,4 @@
1
- # Last Modified: 2017.08.17 /coding: utf-8
1
+ # Last Modified: 2017.08.31 /coding: utf-8
2
2
  # frozen_string_literal: probably not yet
3
3
 
4
4
  # Copyright © 2016-2017 Exosite LLC.
@@ -13,6 +13,12 @@ require 'cmd_common'
13
13
  RSpec.describe 'murano business', :cmd, :needs_password do
14
14
  include_context "CI_CMD"
15
15
 
16
+ context "without project" do
17
+ it "help" do
18
+ cmd_verify_help('business')
19
+ end
20
+ end
21
+
16
22
  context "list" do
17
23
  it "as table" do
18
24
  out, err, status = Open3.capture3(capcmd('murano', 'business', 'list'))
@@ -28,7 +34,7 @@ RSpec.describe 'murano business', :cmd, :needs_password do
28
34
  it "as json" do
29
35
  out, err, status = Open3.capture3(capcmd('murano', 'business', 'list', '-c', 'outformat=json'))
30
36
  expect(err).to eq("")
31
- expect{JSON.parse(out)}.to_not raise_error
37
+ expect{ JSON.parse(out) }.to_not raise_error
32
38
  expect(status.exitstatus).to eq(0)
33
39
  end
34
40
 
@@ -1,17 +1,68 @@
1
+ # Last Modified: 2017.08.31 /coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright © 2016-2017 Exosite LLC.
5
+ # License: MIT. See LICENSE.txt.
6
+ # vim:tw=0:ts=2:sw=2:et:ai
7
+
8
+ require 'highline'
9
+ # Set HighLine's $terminal global.
10
+ require 'highline/import'
1
11
  require 'pathname'
2
12
  require 'shellwords'
3
13
  require 'timeout'
4
14
  require 'tmpdir'
15
+ require 'webmock/rspec'
16
+
5
17
  require 'MrMurano/Config'
6
18
 
7
- RSpec.shared_context "CI_CMD" do
19
+ # Prevent Commander from registering its at_exit hook.
20
+ # - Also print warning if spec exits, which rspec doesn't see as wrong.
21
+ # - Note that this comes before importing Commander.
22
+ $exited_abnormally = false
23
+ at_exit do
24
+ if $exited_abnormally
25
+ STDERR.puts('¡!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
26
+ STDERR.puts('¡Unexpected spec exit killed rspec!')
27
+ STDERR.puts('¡!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
28
+ end
29
+ end
30
+ alias original_at_exit at_exit
31
+ def at_exit(*args, &block)
32
+ #original_at_exit *args, &block
33
+ # pass!
34
+ end
35
+
36
+ require 'MrMurano/spec_commander.rb'
37
+
38
+ module Commander
39
+ class Command
40
+ attr_writer :when_called
41
+ #def when_called=(args)
42
+ # @when_called = args
43
+ #end
44
+
45
+ def peek_when_called
46
+ @when_called
47
+ end
48
+ end
49
+
50
+ class Runner
51
+ def force_args(args)
52
+ @args = args
53
+ end
54
+ end
55
+ end
56
+
57
+ RSpec.shared_context 'CI_CMD' do
58
+ # capcmd makes an Open3-ready `murano` command from a list of args.
8
59
  def capcmd(*args)
9
- args = [args] unless args.kind_of? Array
60
+ args = [args] unless args.is_a? Array
10
61
  args.flatten!
11
62
  testdir = File.realpath(@testdir.to_s)
12
- if ENV['CI_MR_EXE'].nil? then
63
+ if ENV['CI_MR_EXE'].nil?
13
64
  args[0] = File.join(testdir, 'bin', args[0])
14
- args.unshift("ruby", "-I#{File.join(testdir, 'lib')}")
65
+ args.unshift('ruby', "-I#{File.join(testdir, 'lib')}")
15
66
  else
16
67
  args[0] = File.join(testdir, (args[0] + '.exe'))
17
68
  end
@@ -20,13 +71,13 @@ RSpec.shared_context "CI_CMD" do
20
71
  # The spinner output would make it hard to write expects().
21
72
  args.push '--no-progress'
22
73
 
23
- if Gem.win_platform? then
74
+ if Gem.win_platform?
24
75
  cmd = args.map do |i|
25
76
  case i
26
77
  when /[ ]/
27
- %{"#{i}"}
78
+ %("#{i}")
28
79
  when /[\*#]/
29
- i.gsub(/([\*#])/,'^\1')
80
+ i.gsub(/([\*#])/, '^\1')
30
81
  else
31
82
  i
32
83
  end
@@ -38,17 +89,9 @@ RSpec.shared_context "CI_CMD" do
38
89
  cmd
39
90
  end
40
91
 
41
- def rname(name)
42
- #"#{name}-#{Random.new.rand.hash.abs.to_s(16)}"
43
- # MUR-2454: Product name may only contain letters and numbers.
44
- #"#{name}#{Random.new.rand.hash.abs.to_s(16)}"
45
- # MUR-XXXX: Product name must be lowercase.
46
- # 2017-06-01: From [cr]: "I'll be having bizapi convert to lower case
47
- # in the short term, and pegasus is updating to allow upper case."
48
- # LATER: Remove .downcase once PAAS fixed.
49
- "#{name.downcase}#{Random.new.rand.hash.abs.to_s(16)}"
50
- end
92
+ # *** Utility fcns: symlinks.
51
93
 
94
+ # Makes a symlink to the /tmp project dir.
52
95
  def mk_symlink
53
96
  # Make it easy to debug tests, e.g., add breakpoint before capcmd('murano', ...)
54
97
  # run test, then open another terminal window and `cd /tmp/murcli-test`.
@@ -56,8 +99,8 @@ RSpec.shared_context "CI_CMD" do
56
99
  # Since this is for DEVs only, we can hack around this.
57
100
  tmpdir = Dir.tmpdir()
58
101
  return unless tmpdir == '/tmp'
59
- @dev_symlink = File.join(tmpdir, "murcli-test")
60
- FileUtils.rm(@dev_symlink, :force => true)
102
+ @dev_symlink = File.join(tmpdir, 'murcli-test')
103
+ FileUtils.rm(@dev_symlink, force: true)
61
104
  begin
62
105
  FileUtils.ln_s(Dir.pwd, @dev_symlink)
63
106
  rescue NotImplementedError => err
@@ -65,22 +108,220 @@ RSpec.shared_context "CI_CMD" do
65
108
  require 'rbconfig'
66
109
  # Check the platform, e.g., "linux-gnu", or other.
67
110
  is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
68
- $stderr.puts(
69
- "Unexpected: ln_s failed on non-Windows machine / host_os: #{RbConfig::CONFIG['host_os']} / err: #{err}"
70
- ) unless is_windows
111
+ unless is_windows
112
+ $stderr.puts(
113
+ 'Unexpected: ln_s failed on non-Windows machine / ' \
114
+ "host_os: #{RbConfig::CONFIG['host_os']} / err: #{err}"
115
+ )
116
+ end
71
117
  end
72
118
  end
73
119
 
120
+ # Removes the /tmp project directory symlink.
74
121
  def rm_symlink
75
- FileUtils.rm(@dev_symlink, :force => true) if defined?(@dev_symlink)
122
+ FileUtils.rm(@dev_symlink, force: true) if defined?(@dev_symlink)
123
+ end
124
+
125
+ # *** Utility fcns: Murano Solutions management: create/delete/expunge.
126
+
127
+ def murano_solutions_expunge_yes
128
+ out, err, status = Open3.capture3(
129
+ capcmd('murano', 'solutions', 'expunge', '-y')
130
+ )
131
+ expect(out).to \
132
+ eq('').or \
133
+ eq("No solutions found\n").or \
134
+ match(/^Deleted [\d]+ solutions/)
135
+ expect(strip_color(err)).to eq('').or eq("No solutions found\n")
136
+ expect(status.exitstatus).to eq(0).or eq(1)
76
137
  end
77
138
 
139
+ def project_up(skip_link: false)
140
+ # Preemptive clean up!
141
+ murano_solutions_expunge_yes if defined?(PRE_EXPUNGE) && PRE_EXPUNGE
142
+
143
+ @proj_name_prod = rname('MurCLITestProd')
144
+ out, err, status = Open3.capture3(
145
+ capcmd('murano', 'product', 'create', @proj_name_prod, '--save')
146
+ )
147
+ expect(err).to eq('')
148
+ expect(out.chomp).to match(/^[a-zA-Z0-9]+$/)
149
+ expect(status.exitstatus).to eq(0)
150
+
151
+ @proj_name_appy = rname('MurCLITestAppy')
152
+ out, err, status = Open3.capture3(
153
+ capcmd('murano', 'application', 'create', @proj_name_appy, '--save')
154
+ )
155
+ expect(err).to eq('')
156
+ soln_id = out
157
+ expect(soln_id.chomp).to match(/^[a-zA-Z0-9]+$/)
158
+ expect(status.exitstatus).to eq(0)
159
+
160
+ project_up_link unless skip_link
161
+ end
162
+
163
+ def project_up_link
164
+ out, err, status = Open3.capture3(capcmd('murano', 'assign', 'set'))
165
+ #expect(out).to a_string_starting_with("Linked product #{@proj_name_prod}")
166
+ olines = out.lines
167
+ expect(olines[0].encode!('UTF-8', 'UTF-8')).to eq(
168
+ "Linked ‘#{@proj_name_prod}’ to ‘#{@proj_name_appy}’\n"
169
+ )
170
+ expect(olines[1]).to eq("Created default event handler\n")
171
+ expect(err).to eq('')
172
+ expect(status.exitstatus).to eq(0)
173
+ end
174
+
175
+ def project_down
176
+ return if defined?(PRE_EXPUNGE) && PRE_EXPUNGE
177
+
178
+ out, err, status = Open3.capture3(
179
+ capcmd('murano', 'solution', 'delete', @proj_name_appy, '-y')
180
+ )
181
+ expect(out).to eq('')
182
+ expect(err).to eq('')
183
+ expect(status.exitstatus).to eq(0)
184
+
185
+ out, err, status = Open3.capture3(
186
+ capcmd('murano', 'solution', 'delete', @proj_name_prod, '-y')
187
+ )
188
+ expect(out).to eq('')
189
+ expect(err).to eq('')
190
+ expect(status.exitstatus).to eq(0)
191
+ end
192
+
193
+ # Utility fcns: Strings.
194
+
195
+ # rname makes a random Murano-acceptable Solution name.
196
+ def rname(name)
197
+ #"#{name}-#{Random.new.rand.hash.abs.to_s(16)}"
198
+ # MUR-2454: Product name may only contain letters and numbers.
199
+ #"#{name}#{Random.new.rand.hash.abs.to_s(16)}"
200
+ # MUR-XXXX: Product name must be lowercase.
201
+ # 2017-06-01: From [cr]: "I'll be having bizapi convert to lower case
202
+ # in the short term, and pegasus is updating to allow upper case."
203
+ # LATER: Remove .downcase once PAAS fixed.
204
+ "#{name.downcase}#{Random.new.rand.hash.abs.to_s(16)}"
205
+ end
206
+
207
+ def strip_color(str)
208
+ str.gsub(/\e\[(\d+)m/, '')
209
+ end
210
+
211
+ # *** rb-commander goodies
212
+
213
+ def murano_command_run(cmd, *args)
214
+ murano_command_runner(cmd, *args)
215
+ end
216
+
217
+ def murano_command_exits(cmd, *args)
218
+ murano_command_runner(cmd, *args, wont_run: true)
219
+ end
220
+
221
+ def murano_command_wont_parse(cmd, *args)
222
+ murano_command_runner(cmd, *args, wont_parse: true)
223
+ end
224
+
225
+ def murano_command_runner(cmd, *args, wont_run: false, wont_parse: false)
226
+ # This is a functional test, so tell WebMock to back off.
227
+ # FIXME: Remember the setting and re-enable.
228
+ WebMock.allow_net_connect!
229
+
230
+ wasout = $stdout
231
+ waserr = $stderr
232
+ wasterm = $terminal
233
+ tmpout = StringIO.new
234
+ tmperr = StringIO.new
235
+
236
+ # Commander's `say` calls HighLine's $terminal.say, so redirect that, too.
237
+ hline = HighLine.new($stdin, tmpout)
238
+ $terminal = hline
239
+ # DEVs: If you set a byebug break after this point, the byebug will
240
+ # show when the code breaks, but you'll see no echo or output. So
241
+ # comment this code out if you're debugging.
242
+ $stdout = tmpout
243
+ $stderr = tmperr
244
+
245
+ # When Commander is loaded, it sets an at_exit hook, which we monkey
246
+ # patch in ReCommander. Since Config.validate_cmd is called before
247
+ # at_exit, it uses runner.command_exit to tell ReCommander's at_exit
248
+ # monkey patch not to call Commander.run!. Via rspec, we don't use the
249
+ # at_exit hook, or ReCommander.
250
+ $cfg = MrMurano::Config.new(::Commander::Runner.instance)
251
+ $cfg.load
252
+ $cfg.validate_cmd(cmd)
253
+ $cfg['tool.no-progress'] = true
254
+ runner = ::Commander::Runner.instance
255
+ unless defined?(runner.command_exit) && runner.command_exit
256
+ # Commander's at_exit hook calls runner.run! which runs the command
257
+ # that was determined with Commander was loaded. I [lb] tried a few
258
+ # different ways to reset Runner.instance, but nothing worked; our
259
+ # best bet is to just call the command directly.
260
+ the_cmd = command(cmd.to_sym)
261
+ when_called = the_cmd.peek_when_called.dup
262
+
263
+ runner.force_args(args.dup)
264
+ $exited_abnormally = true
265
+ #runner.parse_global_options
266
+ if wont_parse
267
+ expect { runner.old_parse_global_options }.to raise_error(SystemExit)
268
+ else
269
+ runner.old_parse_global_options
270
+ runner.remove_global_options runner.options, args
271
+ if wont_run
272
+ expect { the_cmd.run(*args) }.to raise_error(SystemExit)
273
+ else
274
+ the_cmd.run(*args)
275
+ end
276
+ end
277
+ $exited_abnormally = false
278
+
279
+ # Reset proxy_options otherwise Commander::Command.call
280
+ # uses them the next time this command is called.
281
+ the_cmd.proxy_options = []
282
+ the_cmd.when_called = when_called
283
+ end
284
+ runner.command_exit = nil
285
+
286
+ # Ruby provides std i/o constants, so we could do this:
287
+ # $stdout, $stderr = STDOUT, STDERR
288
+ $stdout = wasout
289
+ $stderr = waserr
290
+ $terminal = wasterm
291
+ [strip_color(tmpout.string), strip_color(tmperr.string)]
292
+ end
293
+
294
+ def cmd_verify_help(cmd_name)
295
+ stdout, stderr = murano_command_run(cmd_name)
296
+ expect(stdout).to start_with(
297
+ " NAME:\n\n murano #{cmd_name}\n\n DESCRIPTION:\n\n "
298
+ )
299
+ expect(stderr).to eq('')
300
+ end
301
+
302
+ # *** before() and around()
303
+
304
+ # Before: Load Config.
78
305
  before(:example) do
79
306
  $cfg = MrMurano::Config.new
80
307
  $cfg.load
81
308
  end
82
309
 
310
+ # Around: Make project dir under /tmp.
83
311
  around(:example) do |ex|
312
+ # Load the byebug library now, before changing directories.
313
+ # This sets Setting[:histfile]. Within byebug, try `show histfile`.
314
+ # Make sure this is set now, otherwise, byebug crashes, e.g.,
315
+ # <Errno::ENOENT: No such file or directory @ rb_sysopen -
316
+ # /tmp/d20170830-10087-h7tq6a/project/.byebug_history>
317
+ # This happens if the first call to byebug is after the chdir.
318
+ # Byebug creates the histfile in the tmp dir. So the next time
319
+ # the method containing `byebug` is called, it's from within a
320
+ # different tmp dir, and the old tmp dir has been removed. So
321
+ # byebug crashes trying to access the old, missing histfile.
322
+ require 'byebug/settings/histfile'
323
+ _ignored = ::Byebug::HistfileSetting::DEFAULT
324
+
84
325
  @testdir = Pathname.new(Dir.pwd).realpath
85
326
  Dir.mktmpdir do |hdir|
86
327
  ENV['HOME'] = hdir
@@ -90,7 +331,8 @@ RSpec.shared_context "CI_CMD" do
90
331
  Dir.mkdir(@tmpdir)
91
332
  Dir.chdir(@tmpdir) do
92
333
  mk_symlink
93
- Timeout::timeout(300) do
334
+ # Timeout after 300 secs/5 mins.
335
+ Timeout.timeout(300) do
94
336
  ex.run
95
337
  end
96
338
  rm_symlink
@@ -100,4 +342,3 @@ RSpec.shared_context "CI_CMD" do
100
342
  end
101
343
  end
102
344
 
103
- # vim: set ai et sw=2 ts=2 :