geordi 5.2.3 → 6.0.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.
@@ -1,43 +1,41 @@
1
1
  desc 'delete-dumps [DIRECTORY]', 'Delete database dump files (*.dump)'
2
2
  long_desc <<-LONGDESC
3
- Example: `geordi delete_dumps` or `geordi delete_dumps ~/tmp/dumps`
3
+ Example: `geordi delete-dumps` or `geordi delete-dumps ~/tmp/dumps`
4
4
 
5
- Recursively search for files ending in `*.dump` and offer to delete those. When
5
+ Recursively searches for files ending in `.dump` and offers to delete them. When
6
6
  no argument is given, two default directories are searched for dump files: the
7
7
  current working directory and `~/dumps` (for dumps created with geordi).
8
8
 
9
- Geordi will ask for confirmation before actually deleting files.
9
+ Will ask for confirmation before actually deleting files.
10
10
  LONGDESC
11
11
 
12
- def delete_dumps(dump_directory = nil)
13
- deletable_dumps = []
14
- dump_directories = if dump_directory.nil?
15
- [
16
- File.join(Dir.home, 'dumps'),
17
- Dir.pwd,
18
- ]
19
- else
20
- [dump_directory]
12
+ def delete_dumps(*locations)
13
+ Interaction.announce 'Retrieving dump files'
14
+
15
+ dump_files = []
16
+ if locations.empty?
17
+ locations = [ File.join(Dir.home, 'dumps'), Dir.pwd ]
21
18
  end
22
- Interaction.announce 'Looking for *.dump in ' << dump_directories.join(',')
23
- dump_directories.each do |d|
24
- d_2 = File.expand_path(d)
25
- unless File.directory? File.realdirpath(d_2)
26
- Interaction.warn "Directory #{d_2} does not exist"
19
+ locations.map! &File.method(:expand_path)
20
+
21
+ Interaction.note "Looking in #{locations.join(', ')}"
22
+ locations.each do |dir|
23
+ directory = File.expand_path(dir)
24
+ unless File.directory? File.realdirpath(directory)
25
+ Interaction.warn "Directory #{directory} does not exist. Skipping."
27
26
  next
28
27
  end
29
- deletable_dumps.concat(Dir.glob("#{d_2}/**/*.dump"))
28
+ dump_files.concat Dir.glob("#{directory}/**/*.dump")
30
29
  end
30
+ deletable_dumps = dump_files.flatten.uniq.sort.select &File.method(:file?)
31
+
31
32
  if deletable_dumps.empty?
32
- Interaction.success 'No dumps to delete' if deletable_dumps.empty?
33
- exit 0
34
- end
35
- deletable_dumps.uniq!.sort!
36
- Interaction.note 'The following dumps can be deleted:'
37
- puts
38
- puts deletable_dumps
39
- Interaction.prompt('Delete those dumps', 'n', /y|yes/) || raise('Cancelled.')
40
- deletable_dumps.each do |dump|
41
- File.delete dump unless File.directory? dump
33
+ Interaction.warn 'No dump files found.'
34
+ else
35
+ puts deletable_dumps
36
+ Interaction.prompt('Delete these files?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
37
+
38
+ deletable_dumps.each &File.method(:delete)
39
+ Interaction.success 'Done.'
42
40
  end
43
41
  end
@@ -12,8 +12,13 @@ class DockerCLI < Thor
12
12
  end
13
13
 
14
14
  desc 'vnc', 'Open a vnc viewer connecting to the docker container'
15
+ option :setup, default: false, type: :boolean, desc: 'Guide through the setup of VNC'
15
16
  def vnc
16
- docker.vnc
17
+ if options.setup
18
+ docker.setup_vnc
19
+ else
20
+ docker.vnc
21
+ end
17
22
  end
18
23
 
19
24
  private
@@ -42,5 +47,6 @@ There are three subcommands:
42
47
 
43
48
  - `geordi docker vnc`
44
49
  Opens a VNC viewer to connect to the VNC server in the container.
50
+ Append `--setup` to be guided through the setup of VNC viewer.
45
51
  LONGDESC
46
52
  subcommand 'docker', DockerCLI
@@ -47,6 +47,4 @@ def drop_databases
47
47
  cleaner = DBCleaner.new(extra_flags)
48
48
  cleaner.clean_mysql unless options.postgres_only
49
49
  cleaner.clean_postgres unless options.mysql_only
50
-
51
- Interaction.success 'Done.'
52
50
  end
@@ -57,6 +57,9 @@ def dump(target = nil, *_args)
57
57
  Interaction.announce "Sourcing dump into the #{loader.config['database']} db"
58
58
  loader.load
59
59
 
60
+ Util.run! "rm #{dump_path}"
61
+ Interaction.note "Dump file removed"
62
+
60
63
  Interaction.success "Your #{loader.config['database']} database has now the data of #{target}#{database_label}."
61
64
  end
62
65
  end
@@ -10,5 +10,6 @@ def remove_executable_flags
10
10
  Interaction.note pattern
11
11
  `find . -name "#{pattern}" -exec chmod -x {} ';'`
12
12
  end
13
- puts 'Done.'
13
+
14
+ Interaction.success 'Done.'
14
15
  end
@@ -2,7 +2,10 @@ desc 'rspec [FILES]', 'Run RSpec'
2
2
  long_desc <<-LONGDESC
3
3
  Example: `geordi rspec spec/models/user_spec.rb:13`
4
4
 
5
- Runs RSpec with RSpec 1/2 support, parallel_tests detection and `bundle exec`.
5
+ Runs RSpec with version 1/2 support, parallel_tests detection and `bundle exec`.
6
+
7
+ In order to limit processes in a parallel run, you can set an environment
8
+ variable like this: `PARALLEL_TEST_PROCESSORS=6 geordi rspec`
6
9
  LONGDESC
7
10
 
8
11
  def rspec(*files)
@@ -4,67 +4,23 @@ require 'tempfile'
4
4
  # This require-style is to prevent Ruby from loading files of a different
5
5
  # version of Geordi.
6
6
  require File.expand_path('interaction', __dir__)
7
- require File.expand_path('firefox_for_selenium', __dir__)
8
7
  require File.expand_path('settings', __dir__)
9
8
 
10
9
  module Geordi
11
10
  class Cucumber
12
11
 
13
- VNC_DISPLAY = ':17'.freeze
14
- VNC_PASSWORD_FILE = File.expand_path('~/.vnc/passwd').freeze # default for "vncpasswd"
15
- VNC_SERVER_DEFAULT_OPTIONS = "-localhost -nolisten tcp -geometry 1280x1024 -rfbauth #{VNC_PASSWORD_FILE}".freeze
16
- VNC_SERVER_COMMAND = "vncserver #{VNC_DISPLAY} #{ENV.fetch('GEORDI_VNC_OPTIONS', VNC_SERVER_DEFAULT_OPTIONS)}".freeze
17
- VNC_VIEWER_COMMAND = "vncviewer -passwd #{VNC_PASSWORD_FILE}".freeze
18
- VNC_ENV_VARIABLES = %w[DISPLAY BROWSER LAUNCHY_BROWSER].freeze
19
-
20
12
  def run(files, cucumber_options, options = {})
21
13
  self.argv = files + cucumber_options.map { |option| option.split('=') }.flatten
22
14
  self.settings = Geordi::Settings.new
23
15
 
24
16
  consolidate_rerun_txt_files
25
17
  show_features_to_run
26
- setup_vnc if settings.use_vnc?
27
18
 
28
19
  command = use_parallel_tests?(options) ? parallel_execution_command : serial_execution_command
29
20
  Interaction.note_cmd(command) if options[:verbose]
30
21
 
31
22
  puts # Make newline
32
- system command # Util.run! would reset the Firefox PATH
33
- end
34
-
35
- def launch_vnc_viewer(source = VNC_DISPLAY)
36
- fork do
37
- error = capture_stderr do
38
- system("#{VNC_VIEWER_COMMAND} #{source}")
39
- end
40
- unless $?.success?
41
- if $?.exitstatus == 127
42
- Interaction.fail 'VNC viewer not found. Install it with `geordi vnc --setup`.'
43
- else
44
- Interaction.note 'VNC viewer could not be opened:'
45
- puts error
46
- puts
47
- end
48
- end
49
- end
50
- end
51
-
52
- def restore_env
53
- VNC_ENV_VARIABLES.each do |variable|
54
- ENV[variable] = ENV["OUTER_#{variable}"]
55
- end
56
- end
57
-
58
- def setup_vnc
59
- if try_and_start_vnc
60
- VNC_ENV_VARIABLES.each do |variable|
61
- ENV["OUTER_#{variable}"] = ENV[variable] if ENV[variable]
62
- end
63
- ENV['BROWSER'] = ENV['LAUNCHY_BROWSER'] = File.expand_path('../../exe/launchy_browser', __dir__)
64
- ENV['DISPLAY'] = VNC_DISPLAY
65
-
66
- Interaction.note 'Run `geordi vnc` to view the Selenium test browsers'
67
- end
23
+ system command
68
24
  end
69
25
 
70
26
  private
@@ -76,7 +32,7 @@ module Geordi
76
32
  unless argv.include?('--format') || argv.include?('-f')
77
33
  format_args = spinner_available? ? ['--format', 'CucumberSpinner::CuriousProgressBarFormatter'] : ['--format', 'progress']
78
34
  end
79
- [use_firefox_for_selenium, Util.binstub_or_fallback('cucumber'), format_args, escape_shell_args(argv)].flatten.compact.join(' ')
35
+ [ Util.binstub_or_fallback('cucumber'), format_args, escape_shell_args(argv)].flatten.compact.join(' ')
80
36
  end
81
37
 
82
38
  def parallel_execution_command
@@ -88,28 +44,12 @@ module Geordi
88
44
  features = find_all_features_recursively('features') if features.empty?
89
45
 
90
46
  [
91
- use_firefox_for_selenium,
92
47
  'bundle exec parallel_test -t ' + type_arg,
93
- %(-o '#{command_line_options.join(' ')} --tags "#{not_tag('@solo')}"'),
48
+ %(-o '#{command_line_options.join(' ')}'),
94
49
  "-- #{features.join(' ')}",
95
50
  ].compact.join(' ')
96
51
  end
97
52
 
98
- def not_tag(name)
99
- if Util.gem_major_version('cucumber') < 3
100
- "~#{name}"
101
- else
102
- "not #{name}"
103
- end
104
- end
105
-
106
- def use_firefox_for_selenium
107
- path = Geordi::FirefoxForSelenium.path_from_config
108
- if path
109
- "PATH=#{path}:$PATH"
110
- end
111
- end
112
-
113
53
  def escape_shell_args(*args)
114
54
  args.flatten.collect do |arg|
115
55
  arg.gsub(/([\\ "])/) { |_match| "\\#{Regexp.last_match(1)}" }
@@ -117,9 +57,7 @@ module Geordi
117
57
  end
118
58
 
119
59
  def show_features_to_run
120
- if command_line_options.include? '@solo'
121
- Interaction.note 'All features tagged with @solo'
122
- elsif command_line_options.include? 'rerun'
60
+ if command_line_options.include? 'rerun'
123
61
  Interaction.note 'Rerunning failed scenarios'
124
62
  elsif features_to_run.empty?
125
63
  Interaction.note 'All features in features/'
@@ -210,39 +148,5 @@ module Geordi
210
148
  features_to_run.none? { |f| f.include? ':' }
211
149
  end
212
150
 
213
- def try_and_start_vnc
214
- # check if vnc is already running
215
- # return true if vnc_server_running?
216
- error = capture_stderr do
217
- system(VNC_SERVER_COMMAND)
218
- end
219
- case $?.exitstatus
220
- when 0,
221
- 98 # was already running after all
222
- true
223
- when 127 # not installed
224
- Interaction.warn 'Could not launch VNC server. Install it with `geordi vnc --setup`.'
225
- false
226
- else
227
- Interaction.warn 'Starting VNC failed:'
228
- puts error
229
- puts
230
- false
231
- end
232
- end
233
-
234
- def capture_stderr
235
- old_stderr = $stderr.dup
236
- io = Tempfile.new('cuc')
237
- $stderr.reopen(io)
238
- yield
239
- io.rewind
240
- io.read
241
- ensure
242
- io.close
243
- io.unlink
244
- $stderr.reopen(old_stderr)
245
- end
246
-
247
151
  end
248
152
  end
@@ -180,7 +180,7 @@ HEREDOC
180
180
  if @mysql_command.include? '-p'
181
181
  puts "Please enter your MySQL/MariaDB account 'root' for: DROP DATABASE #{db}"
182
182
  else
183
- Interaction.note "Dropping MySQL/MariaDB database #{db}"
183
+ puts "Dropping MySQL/MariaDB database #{db}"
184
184
  end
185
185
  `#{@mysql_command} -e 'DROP DATABASE \`#{db}\`;'`
186
186
  end
@@ -206,7 +206,7 @@ HEREDOC
206
206
  until %w[y n].include? proceed
207
207
  deletable_dbs = filter_whitelisted(dbtype, database_list)
208
208
  if deletable_dbs.empty?
209
- Interaction.note "No #{dbtype} databases found that were not whitelisted"
209
+ Interaction.note "No #{dbtype} databases found that were not whitelisted."
210
210
  if Interaction.prompt('Edit the whitelist? [y]es or [n]o') == 'y'
211
211
  proceed = 'e'
212
212
  else
@@ -214,11 +214,11 @@ HEREDOC
214
214
  end
215
215
  end
216
216
  if proceed.empty?
217
- Interaction.note "The following #{dbtype} databases are not whitelisted and could be deleted:"
217
+ Interaction.note "The following #{dbtype} databases are not whitelisted and can be deleted:"
218
218
  deletable_dbs.sort.each do |db|
219
219
  puts db
220
220
  end
221
- Interaction.note "Those #{dbtype} databases are not whitelisted and could be deleted."
221
+ Interaction.note "These #{dbtype} databases are not whitelisted and can be deleted."
222
222
  proceed = Interaction.prompt('Proceed? [y]es, [n]o or [e]dit whitelist')
223
223
  end
224
224
  case proceed
@@ -226,7 +226,7 @@ HEREDOC
226
226
  proceed = '' # reset user selection
227
227
  edit_whitelist dbtype
228
228
  when 'n'
229
- Interaction.success 'Not deleting anything'
229
+ Interaction.success 'Nothing deleted.'
230
230
  return []
231
231
  when 'y'
232
232
  return deletable_dbs
data/lib/geordi/docker.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'geordi/interaction'
2
2
  require 'geordi/cucumber'
3
3
  require 'yaml'
4
+ require 'open3'
4
5
 
5
6
  module Geordi
6
7
  class Docker
@@ -28,13 +29,61 @@ module Geordi
28
29
  end
29
30
 
30
31
  def vnc
31
- Cucumber.new.launch_vnc_viewer('::5967')
32
+ check_installation_and_config
33
+ launch_vnc_viewer('::5967')
34
+ end
35
+
36
+ def setup_vnc
37
+ `clear`
38
+ Interaction.note 'This script will help you install a VNC viewer.'
39
+ Interaction.note 'Please open a second shell to execute instructions.'
40
+ Interaction.prompt 'Continue ...'
41
+
42
+ Interaction.announce 'Setup VNC viewer'
43
+ vnc_viewer_installed = system('which vncviewer > /dev/null 2>&1')
44
+ if vnc_viewer_installed
45
+ Interaction.success 'It appears you already have a VNC viewer installed. Good job!'
46
+ else
47
+ puts 'Please run:'
48
+ Interaction.note_cmd 'sudo apt-get install xtightvncviewer'
49
+ Interaction.prompt 'Continue ...'
50
+ end
51
+
52
+ puts
53
+ puts Util.strip_heredoc <<-TEXT
54
+ Done. You can view the VNC window with `geordi docker vnc`.
55
+ TEXT
56
+
57
+ Interaction.success 'Happy cuking!'
32
58
  end
33
59
 
34
60
  private
35
61
 
62
+ def launch_vnc_viewer(source)
63
+ fail('VNC viewer not found. Install it with `geordi docker vnc --setup`.') unless command_exists?('vncviewer')
64
+
65
+ fork do
66
+ error = capture_stderr do
67
+ system("vncviewer #{source}")
68
+ end
69
+ unless $?.success?
70
+ if $?.exitstatus == 127
71
+ fail('VNC viewer not found. Install it with `geordi docker vnc --setup`.')
72
+ else
73
+ fail("VNC viewer could not be opened: #{error}")
74
+ end
75
+ end
76
+ end
77
+ exit 0
78
+ end
79
+
36
80
  def attach_to_running_shell
37
- running_containers = execute(:`, 'docker-compose ps').split("\n")
81
+ # The command line output of docker-compose ps changes depending on the container name length, this is
82
+ # caused by the varying terminal length and results in the longer outputs, e.g the container name and id
83
+ # to be cut after x characters and the rest being placed in the line below.
84
+
85
+ stdout_str, _error_str = execute(:capture, {'COLUMNS' => '400'}, 'docker-compose ps')
86
+ running_containers = stdout_str.split("\n")
38
87
  if (main_container_line = running_containers.grep(/_main_run/).first)
39
88
  container_name = main_container_line.split(' ').first
40
89
  execute(:exec, 'docker', 'exec', '-it', container_name, 'bash')
@@ -54,13 +103,17 @@ module Geordi
54
103
  def execute(kind, *args)
55
104
  if ENV['GEORDI_TESTING']
56
105
  puts "Stubbed run #{args.join(' ')}"
57
- if kind == :`
106
+ if kind == :` || kind == :capture
58
107
  mock_parse(*args)
59
108
  else
60
109
  mock_run(*args)
61
110
  end
62
111
  else
63
- send(kind, *args)
112
+ if kind == :capture
113
+ Open3.capture2(*args)
114
+ else
115
+ send(kind, *args)
116
+ end
64
117
  end
65
118
  end
66
119
 
@@ -112,5 +165,19 @@ module Geordi
112
165
  []
113
166
  end
114
167
  end
168
+
169
+ def capture_stderr
170
+ old_stderr = $stderr.dup
171
+ io = Tempfile.new('cuc')
172
+ $stderr.reopen(io)
173
+ yield
174
+ io.rewind
175
+ io.read
176
+ ensure
177
+ io.close
178
+ io.unlink
179
+ $stderr.reopen(old_stderr)
180
+ end
181
+
115
182
  end
116
183
  end
@@ -57,7 +57,7 @@ module Geordi
57
57
  Interaction.note 'Source file: ' + dump_file
58
58
 
59
59
  source_command = send("#{config['adapter']}_command")
60
- Util.run! source_command, fail_message: "An error occured loading #{File.basename(dump_file)}"
60
+ Util.run! source_command, fail_message: "An error occurred loading #{File.basename(dump_file)}"
61
61
  end
62
62
 
63
63
  end