geordi 2.10.1 → 3.0.3
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/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +8 -2
- data/CHANGELOG.md +46 -0
- data/Gemfile +2 -5
- data/Gemfile.lock +10 -10
- data/README.md +11 -6
- data/Rakefile +6 -10
- data/{bin → exe}/b +0 -0
- data/{bin → exe}/cap-all +0 -0
- data/{bin → exe}/console-for +0 -0
- data/{bin → exe}/cuc +0 -0
- data/{bin → exe}/cuc-show +0 -0
- data/{bin → exe}/cuc-vnc-setup +0 -0
- data/{bin → exe}/deploy-to-production +0 -0
- data/{bin → exe}/dump-for +0 -0
- data/{bin → exe}/dumple +0 -0
- data/{bin → exe}/geordi +0 -0
- data/{bin → exe}/gitpt +0 -0
- data/{bin → exe}/launchy_browser +0 -0
- data/{bin → exe}/load-dump +0 -0
- data/{bin → exe}/migrate-all +0 -0
- data/{bin → exe}/rs +0 -0
- data/{bin → exe}/run_tests +0 -0
- data/{bin → exe}/shell-for +0 -0
- data/{bin → exe}/tests +0 -0
- data/geordi.gemspec +23 -20
- data/lib/geordi/COMMAND_TEMPLATE +4 -6
- data/lib/geordi/capistrano_config.rb +20 -17
- data/lib/geordi/chromedriver_updater.rb +9 -10
- data/lib/geordi/cli.rb +5 -2
- data/lib/geordi/commands/_setup_vnc.rb +23 -23
- data/lib/geordi/commands/apache_site.rb +3 -3
- data/lib/geordi/commands/bundle_install.rb +3 -3
- data/lib/geordi/commands/capistrano.rb +5 -6
- data/lib/geordi/commands/chromedriver_update.rb +0 -9
- data/lib/geordi/commands/clean.rb +5 -6
- data/lib/geordi/commands/commit.rb +0 -1
- data/lib/geordi/commands/console.rb +4 -4
- data/lib/geordi/commands/create_database_yml.rb +4 -4
- data/lib/geordi/commands/create_databases.rb +3 -3
- data/lib/geordi/commands/cucumber.rb +25 -25
- data/lib/geordi/commands/delete_dumps.rb +12 -12
- data/lib/geordi/commands/deploy.rb +27 -28
- data/lib/geordi/commands/drop_databases.rb +13 -15
- data/lib/geordi/commands/dump.rb +12 -13
- data/lib/geordi/commands/eurest.rb +2 -2
- data/lib/geordi/commands/firefox.rb +4 -4
- data/lib/geordi/commands/migrate.rb +3 -3
- data/lib/geordi/commands/png_optimize.rb +15 -14
- data/lib/geordi/commands/rake.rb +3 -3
- data/lib/geordi/commands/remove_executable_flags.rb +3 -3
- data/lib/geordi/commands/rspec.rb +11 -11
- data/lib/geordi/commands/security_update.rb +25 -25
- data/lib/geordi/commands/server.rb +6 -6
- data/lib/geordi/commands/setup.rb +8 -8
- data/lib/geordi/commands/shell.rb +3 -3
- data/lib/geordi/commands/tests.rb +1 -1
- data/lib/geordi/commands/unit.rb +3 -3
- data/lib/geordi/commands/update.rb +7 -7
- data/lib/geordi/commands/vnc.rb +1 -1
- data/lib/geordi/commands/with_rake.rb +3 -3
- data/lib/geordi/commands/yarn_install.rb +3 -3
- data/lib/geordi/cucumber.rb +35 -36
- data/lib/geordi/db_cleaner.rb +40 -41
- data/lib/geordi/dump_loader.rb +6 -5
- data/lib/geordi/firefox_for_selenium.rb +26 -29
- data/lib/geordi/gitpt.rb +14 -15
- data/lib/geordi/interaction.rb +2 -6
- data/lib/geordi/remote.rb +9 -10
- data/lib/geordi/util.rb +28 -25
- data/lib/geordi/version.rb +1 -1
- metadata +27 -39
- data/features/commit.feature +0 -17
- data/features/console.feature +0 -7
- data/features/cucumber.feature +0 -261
- data/features/deploy.feature +0 -66
- data/features/dump.feature +0 -34
- data/features/firefox.feature +0 -44
- data/features/server.feature +0 -31
- data/features/setup.feature +0 -11
- data/features/shell.feature +0 -78
- data/features/support/env.rb +0 -8
- data/features/support/step_definitions/aruba_backport_steps.rb +0 -5
- data/features/support/step_definitions/miscellaneous_steps.rb +0 -11
data/lib/geordi/dump_loader.rb
CHANGED
@@ -5,7 +5,6 @@ require 'geordi/util'
|
|
5
5
|
|
6
6
|
module Geordi
|
7
7
|
class DumpLoader
|
8
|
-
include Geordi::Interaction
|
9
8
|
|
10
9
|
def initialize(file)
|
11
10
|
@dump_file = file
|
@@ -14,7 +13,9 @@ module Geordi
|
|
14
13
|
def development_database_config
|
15
14
|
require 'yaml'
|
16
15
|
|
17
|
-
|
16
|
+
evaluated_config_file = ERB.new(File.read('config/database.yml')).result
|
17
|
+
# Allow aliases and a special set of classes like symbols and time objects
|
18
|
+
@config ||= YAML.safe_load(evaluated_config_file, [Symbol, Time], [], true)
|
18
19
|
@config['development']
|
19
20
|
end
|
20
21
|
alias_method :config, :development_database_config
|
@@ -47,16 +48,16 @@ module Geordi
|
|
47
48
|
available_dumps = Dir.glob(dumps_glob).sort
|
48
49
|
|
49
50
|
HighLine.new.choose(*available_dumps) do |menu|
|
50
|
-
menu.hidden('') { fail 'Abort.' }
|
51
|
+
menu.hidden('') { Interaction.fail 'Abort.' }
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
56
|
def load
|
56
|
-
note 'Source file: ' + dump_file
|
57
|
+
Interaction.note 'Source file: ' + dump_file
|
57
58
|
|
58
59
|
source_command = send("#{config['adapter']}_command")
|
59
|
-
Util.system! source_command, :
|
60
|
+
Util.system! source_command, fail_message: "An error occured loading #{File.basename(dump_file)}"
|
60
61
|
end
|
61
62
|
|
62
63
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'tempfile'
|
3
|
-
require File.expand_path('
|
3
|
+
require File.expand_path('interaction', __dir__)
|
4
4
|
|
5
5
|
module Geordi
|
6
6
|
module FirefoxForSelenium
|
7
|
-
extend Geordi::Interaction
|
8
7
|
|
9
8
|
FIREFOX_FOR_SELENIUM_BASE_PATH = Pathname.new('~/bin/firefoxes').expand_path
|
10
|
-
FIREFOX_FOR_SELENIUM_PROFILE_NAME = 'firefox-for-selenium'
|
9
|
+
FIREFOX_FOR_SELENIUM_PROFILE_NAME = 'firefox-for-selenium'.freeze
|
11
10
|
FIREFOX_VERSION_FILE = Pathname.new('.firefox-version')
|
12
11
|
|
13
12
|
def self.install(version)
|
@@ -17,16 +16,16 @@ module Geordi
|
|
17
16
|
def self.path_from_config
|
18
17
|
version = FIREFOX_VERSION_FILE.exist? && File.read(FIREFOX_VERSION_FILE).strip
|
19
18
|
|
20
|
-
if version
|
19
|
+
if version && (version != 'system')
|
21
20
|
unless FirefoxForSelenium.binary(version).exist?
|
22
|
-
warn "Firefox #{
|
21
|
+
Interaction.warn "Firefox #{version} not found"
|
23
22
|
|
24
|
-
note strip_heredoc(<<-INSTRUCTIONS)
|
23
|
+
Interaction.note Util.strip_heredoc(<<-INSTRUCTIONS)
|
25
24
|
Install it with
|
26
|
-
geordi firefox --setup #{
|
25
|
+
geordi firefox --setup #{version}
|
27
26
|
INSTRUCTIONS
|
28
27
|
|
29
|
-
prompt
|
28
|
+
Interaction.prompt('Run tests anyway?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
|
30
29
|
end
|
31
30
|
|
32
31
|
path(version)
|
@@ -37,7 +36,7 @@ module Geordi
|
|
37
36
|
FIREFOX_FOR_SELENIUM_BASE_PATH.join(version)
|
38
37
|
end
|
39
38
|
|
40
|
-
def self.binary(version, name =
|
39
|
+
def self.binary(version, name = 'firefox')
|
41
40
|
path(version).join(name)
|
42
41
|
end
|
43
42
|
|
@@ -46,13 +45,12 @@ module Geordi
|
|
46
45
|
|
47
46
|
if path
|
48
47
|
ENV['PATH'] = "#{path}:#{ENV['PATH']}"
|
49
|
-
note 'Firefox for Selenium set up'
|
48
|
+
Interaction.note 'Firefox for Selenium set up'
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
53
52
|
|
54
53
|
class Installer
|
55
|
-
include Geordi::Interaction
|
56
54
|
|
57
55
|
def initialize(version)
|
58
56
|
@version = version
|
@@ -72,7 +70,7 @@ module Geordi
|
|
72
70
|
private
|
73
71
|
|
74
72
|
def execute_command(cmd)
|
75
|
-
system(cmd)
|
73
|
+
system(cmd) || raise("Error while executing command: #{cmd}")
|
76
74
|
end
|
77
75
|
|
78
76
|
def run_firefox_for_selenium(args = '')
|
@@ -92,13 +90,13 @@ module Geordi
|
|
92
90
|
end
|
93
91
|
|
94
92
|
def original_binary
|
95
|
-
FirefoxForSelenium.binary(@version,
|
93
|
+
FirefoxForSelenium.binary(@version, 'firefox-original')
|
96
94
|
end
|
97
95
|
|
98
96
|
def say_hello
|
99
97
|
execute_command('clear')
|
100
98
|
|
101
|
-
puts strip_heredoc(<<-HELLO)
|
99
|
+
puts Util.strip_heredoc(<<-HELLO)
|
102
100
|
Whenever Firefox updates, Selenium breaks. This is annoying. This
|
103
101
|
script will help you create an unchanging version of Firefox for your
|
104
102
|
Selenium tests.
|
@@ -117,31 +115,31 @@ module Geordi
|
|
117
115
|
- It will live in #{path}
|
118
116
|
HELLO
|
119
117
|
|
120
|
-
prompt "Press ENTER when you're ready to begin."
|
118
|
+
Interaction.prompt "Press ENTER when you're ready to begin."
|
121
119
|
end
|
122
120
|
|
123
121
|
def check_if_run_before
|
124
122
|
if original_binary.exist?
|
125
|
-
note 'This version seems to be already installed.'
|
126
|
-
prompt 'Press ENTER to continue anyway or press CTRL+C to abort.'
|
123
|
+
Interaction.note 'This version seems to be already installed.'
|
124
|
+
Interaction.prompt 'Press ENTER to continue anyway or press CTRL+C to abort.'
|
127
125
|
end
|
128
126
|
end
|
129
127
|
|
130
128
|
def download_firefox
|
131
129
|
path.mkpath
|
132
130
|
|
133
|
-
puts strip_heredoc(<<-INSTRUCTION)
|
131
|
+
puts Util.strip_heredoc(<<-INSTRUCTION)
|
134
132
|
Please download an old version of Firefox from: #{download_url}
|
135
133
|
Unpack it with: tar xjf firefox-#{@version}.tar.bz2 -C #{path} --strip-components=1
|
136
134
|
Now #{path.join('firefox')} should be the firefox binary, not a directory.
|
137
135
|
INSTRUCTION
|
138
|
-
prompt 'Continue?'
|
136
|
+
Interaction.prompt 'Continue?'
|
139
137
|
|
140
|
-
File.file?(binary)
|
138
|
+
File.file?(binary) || raise("Could not find #{binary}")
|
141
139
|
end
|
142
140
|
|
143
141
|
def create_separate_profile
|
144
|
-
note "Creating a separate profile named '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}' so your own profile will be safe..."
|
142
|
+
Interaction.note "Creating a separate profile named '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}' so your own profile will be safe..."
|
145
143
|
# don't use the patched firefox binary for this, we don't want to give
|
146
144
|
# a -p option here
|
147
145
|
execute_command("PATH=#{path}:$PATH firefox -no-remote -CreateProfile #{FIREFOX_FOR_SELENIUM_PROFILE_NAME}")
|
@@ -149,14 +147,14 @@ module Geordi
|
|
149
147
|
end
|
150
148
|
|
151
149
|
def patch_old_firefox
|
152
|
-
note "Patching #{binary} so it uses the new profile and never re-uses windows from other Firefoxes..."
|
150
|
+
Interaction.note "Patching #{binary} so it uses the new profile and never re-uses windows from other Firefoxes..."
|
153
151
|
execute_command("mv #{binary} #{original_binary}")
|
154
152
|
execute_command("mv #{binary}-bin #{original_binary}-bin")
|
155
153
|
patched_binary = Tempfile.new('firefox')
|
156
|
-
patched_binary.write strip_heredoc(<<-PATCH)
|
154
|
+
patched_binary.write Util.strip_heredoc(<<-PATCH)
|
157
155
|
#!/usr/bin/env ruby
|
158
156
|
exec('#{original_binary}', '-no-remote', '-P', '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}', *ARGV)
|
159
|
-
|
157
|
+
PATCH
|
160
158
|
patched_binary.close
|
161
159
|
execute_command("mv #{patched_binary.path} #{binary}")
|
162
160
|
execute_command("chmod +x #{binary}")
|
@@ -164,7 +162,7 @@ module Geordi
|
|
164
162
|
end
|
165
163
|
|
166
164
|
def configure_old_firefox
|
167
|
-
puts strip_heredoc(<<-INSTRUCTION)
|
165
|
+
puts Util.strip_heredoc(<<-INSTRUCTION)
|
168
166
|
You will now have to do some manual configuration.
|
169
167
|
|
170
168
|
This script will open the patched copy of Firefox when you press ENTER.
|
@@ -178,15 +176,15 @@ module Geordi
|
|
178
176
|
Firefox profile
|
179
177
|
INSTRUCTION
|
180
178
|
|
181
|
-
prompt 'Will open the patched copy of Firefox now'
|
179
|
+
Interaction.prompt 'Will open the patched copy of Firefox now'
|
182
180
|
run_firefox_for_selenium
|
183
181
|
end
|
184
182
|
|
185
183
|
def kkthxbb
|
186
|
-
success "Congratulations, you're done!"
|
184
|
+
Interaction.success "Congratulations, you're done!"
|
187
185
|
|
188
186
|
puts
|
189
|
-
puts strip_heredoc(<<-INSTRUCTION)
|
187
|
+
puts Util.strip_heredoc(<<-INSTRUCTION)
|
190
188
|
Your patched copy of Firefox will be used when you run Cucumber using
|
191
189
|
the cucumber script that comes with the geordi gem. If you cannot use
|
192
190
|
`geordi cucumber`, but still need the test browser set up, you can use:
|
@@ -200,4 +198,3 @@ module Geordi
|
|
200
198
|
end
|
201
199
|
end
|
202
200
|
end
|
203
|
-
|
data/lib/geordi/gitpt.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
class Gitpt
|
2
|
-
include Geordi::Interaction
|
3
2
|
require 'yaml'
|
4
3
|
require 'highline'
|
5
4
|
require 'tracker_api'
|
6
5
|
|
7
|
-
SETTINGS_FILE_NAME = '.gitpt'
|
8
|
-
PROJECT_IDS_FILE_NAME = '.pt_project_id'
|
6
|
+
SETTINGS_FILE_NAME = '.gitpt'.freeze
|
7
|
+
PROJECT_IDS_FILE_NAME = '.pt_project_id'.freeze
|
9
8
|
|
10
9
|
def initialize
|
11
10
|
self.highline = HighLine.new
|
@@ -13,7 +12,7 @@ class Gitpt
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def run(git_args)
|
16
|
-
warn <<-WARNING
|
15
|
+
Geordi::Interaction.warn <<-WARNING unless Geordi::Util.staged_changes?
|
17
16
|
No staged changes. Will create an empty commit.
|
18
17
|
WARNING
|
19
18
|
|
@@ -30,16 +29,16 @@ No staged changes. Will create an empty commit.
|
|
30
29
|
def read_settings
|
31
30
|
file_path = File.join(ENV['HOME'], SETTINGS_FILE_NAME)
|
32
31
|
|
33
|
-
unless File.
|
32
|
+
unless File.exist?(file_path)
|
34
33
|
highline.say HighLine::RESET
|
35
34
|
highline.say "Welcome to #{bold 'gitpt'}.\n\n"
|
36
35
|
|
37
36
|
highline.say highlight('Your settings are missing or invalid.')
|
38
37
|
highline.say "Please configure your Pivotal Tracker access.\n\n"
|
39
|
-
token = highline.ask bold(
|
38
|
+
token = highline.ask bold('Your API key:') + ' '
|
40
39
|
highline.say "\n"
|
41
40
|
|
42
|
-
settings = { :
|
41
|
+
settings = { token: token }
|
43
42
|
File.open(file_path, 'w') do |file|
|
44
43
|
file.write settings.to_yaml
|
45
44
|
end
|
@@ -49,7 +48,7 @@ No staged changes. Will create an empty commit.
|
|
49
48
|
end
|
50
49
|
|
51
50
|
def build_client(settings)
|
52
|
-
TrackerApi::Client.new(:
|
51
|
+
TrackerApi::Client.new(token: settings.fetch(:token))
|
53
52
|
end
|
54
53
|
|
55
54
|
def load_projects
|
@@ -60,14 +59,14 @@ No staged changes. Will create an empty commit.
|
|
60
59
|
def read_project_ids
|
61
60
|
file_path = PROJECT_IDS_FILE_NAME
|
62
61
|
|
63
|
-
if File.
|
62
|
+
if File.exist?(file_path)
|
64
63
|
project_ids = File.read('.pt_project_id').split(/[\s]+/).map(&:to_i)
|
65
64
|
end
|
66
65
|
|
67
|
-
if project_ids
|
66
|
+
if project_ids && (project_ids.size > 0)
|
68
67
|
project_ids
|
69
68
|
else
|
70
|
-
warn "Sorry, I could not find a project ID in #{file_path} :("
|
69
|
+
Geordi::Interaction.warn "Sorry, I could not find a project ID in #{file_path} :("
|
71
70
|
puts
|
72
71
|
|
73
72
|
puts "Please put at least one Pivotal Tracker project id into #{file_path} in this directory."
|
@@ -79,19 +78,19 @@ No staged changes. Will create an empty commit.
|
|
79
78
|
def applicable_stories
|
80
79
|
projects = load_projects
|
81
80
|
projects.collect do |project|
|
82
|
-
project.stories(:
|
81
|
+
project.stories(filter: 'state:started,finished,rejected')
|
83
82
|
end.flatten
|
84
83
|
end
|
85
84
|
|
86
85
|
def choose_story
|
87
86
|
if Geordi::Util.testing?
|
88
|
-
return OpenStruct.new(:
|
87
|
+
return OpenStruct.new(id: 12, name: 'Test Story')
|
89
88
|
end
|
90
89
|
|
91
90
|
loading_message = 'Connecting to Pivotal Tracker ...'
|
92
91
|
print(loading_message)
|
93
92
|
stories = applicable_stories
|
94
|
-
reset_loading_message = "\r#{
|
93
|
+
reset_loading_message = "\r#{' ' * (loading_message.length + stories.length)}\r"
|
95
94
|
|
96
95
|
highline.choose do |menu|
|
97
96
|
menu.header = 'Choose a story'
|
@@ -126,7 +125,7 @@ No staged changes. Will create an empty commit.
|
|
126
125
|
|
127
126
|
def create_commit(message, *git_args)
|
128
127
|
extra = highline.ask("\nAdd an optional message").strip
|
129
|
-
message << ' - ' << extra if
|
128
|
+
message << ' - ' << extra if extra != ''
|
130
129
|
|
131
130
|
Geordi::Util.system! 'git', 'commit', '--allow-empty', '-m', message, *git_args
|
132
131
|
end
|
data/lib/geordi/interaction.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module Geordi
|
4
4
|
module Interaction
|
5
5
|
|
6
|
+
module_function
|
7
|
+
|
6
8
|
# Start your command by `announce`-ing what you're about to do
|
7
9
|
def announce(text)
|
8
10
|
message = "\n# #{text}"
|
@@ -42,12 +44,6 @@ module Geordi
|
|
42
44
|
puts "\e[32m#{message}\e[0m" # green
|
43
45
|
end
|
44
46
|
|
45
|
-
def strip_heredoc(string)
|
46
|
-
leading_whitespace = (string.match(/\A( +)[^ ]+/) || [])[1]
|
47
|
-
string.gsub! /^#{leading_whitespace}/, '' if leading_whitespace
|
48
|
-
string
|
49
|
-
end
|
50
|
-
|
51
47
|
# Returns the user's input.
|
52
48
|
# If agreement_regex is given, returns whether the input matches the regex.
|
53
49
|
def prompt(text, default = nil, agreement_regex = nil)
|
data/lib/geordi/remote.rb
CHANGED
@@ -6,9 +6,8 @@ require 'pathname'
|
|
6
6
|
|
7
7
|
module Geordi
|
8
8
|
class Remote
|
9
|
-
include Geordi::Interaction
|
10
9
|
|
11
|
-
REMOTE_DUMP_PATH = '~/dumps/dump_for_download.dump'
|
10
|
+
REMOTE_DUMP_PATH = '~/dumps/dump_for_download.dump'.freeze
|
12
11
|
|
13
12
|
def initialize(stage)
|
14
13
|
@stage = stage
|
@@ -34,8 +33,8 @@ module Geordi
|
|
34
33
|
def dump(options = {})
|
35
34
|
# Generate dump on the server
|
36
35
|
shell options.merge({
|
37
|
-
:
|
38
|
-
:
|
36
|
+
remote_command: "dumple #{@config.env} --for_download",
|
37
|
+
select_server: nil, # Dump must be generated on the primary server
|
39
38
|
})
|
40
39
|
|
41
40
|
destination_directory = File.join(@config.root, 'tmp')
|
@@ -43,17 +42,17 @@ module Geordi
|
|
43
42
|
destination_path = File.join(destination_directory, "#{@stage}.dump")
|
44
43
|
relative_destination = Pathname.new(destination_path).relative_path_from Pathname.new(@config.root)
|
45
44
|
|
46
|
-
note "Downloading remote dump to #{relative_destination} ..."
|
45
|
+
Interaction.note "Downloading remote dump to #{relative_destination} ..."
|
47
46
|
server = @config.primary_server
|
48
|
-
Util.system! "scp -C #{
|
47
|
+
Util.system! "scp -C #{@config.user(server)}@#{server}:#{REMOTE_DUMP_PATH} #{destination_path}"
|
49
48
|
|
50
|
-
success "Dumped the #{@stage} database to #{relative_destination}."
|
49
|
+
Interaction.success "Dumped the #{@stage} database to #{relative_destination}."
|
51
50
|
|
52
51
|
destination_path
|
53
52
|
end
|
54
53
|
|
55
54
|
def console(options = {})
|
56
|
-
shell(options.merge
|
55
|
+
shell(options.merge(remote_command: Util.console_command(@config.env)))
|
57
56
|
end
|
58
57
|
|
59
58
|
def shell(options = {})
|
@@ -62,8 +61,8 @@ module Geordi
|
|
62
61
|
remote_command = "cd #{@config.remote_root} && #{@config.shell}"
|
63
62
|
remote_command << " -c '#{options[:remote_command]}'" if options[:remote_command]
|
64
63
|
|
65
|
-
note 'Connecting to ' + server.to_s
|
66
|
-
Util.system! 'ssh', "#{
|
64
|
+
Interaction.note 'Connecting to ' + server.to_s
|
65
|
+
Util.system! 'ssh', "#{@config.user(server)}@#{server}", '-t', remote_command
|
67
66
|
end
|
68
67
|
|
69
68
|
end
|
data/lib/geordi/util.rb
CHANGED
@@ -4,29 +4,28 @@ require 'socket'
|
|
4
4
|
module Geordi
|
5
5
|
class Util
|
6
6
|
class << self
|
7
|
-
include Geordi::Interaction
|
8
7
|
|
9
8
|
# Geordi commands sometimes require external gems. However, we don't want
|
10
9
|
# all employed gems as runtime dependencies because that would
|
11
10
|
# unnecessarily slow down all commands.
|
12
11
|
# Thus, we have this handy method here.
|
13
|
-
def installing_missing_gems
|
12
|
+
def installing_missing_gems
|
14
13
|
yield
|
15
14
|
rescue LoadError => error
|
16
15
|
error.message =~ /-- (\S+)\Z/
|
17
|
-
|
16
|
+
Regexp.last_match(1) || raise # could not extract a gem name from the error message, re-raise the error
|
18
17
|
|
19
|
-
gem_name =
|
18
|
+
gem_name = Regexp.last_match(1).strip.split('/').first
|
20
19
|
install_command = 'gem install ' + gem_name
|
21
20
|
|
22
21
|
# install missing gem
|
23
|
-
warn 'Probably missing gem: ' + gem_name
|
24
|
-
prompt('Install it now?', 'y', /y|yes/)
|
25
|
-
system! install_command, :
|
22
|
+
Interaction.warn 'Probably missing gem: ' + gem_name
|
23
|
+
Interaction.prompt('Install it now?', 'y', /y|yes/) || Interaction.fail('Missing Gems.')
|
24
|
+
system! install_command, show_cmd: true
|
26
25
|
|
27
26
|
# retry
|
28
27
|
Gem.clear_paths
|
29
|
-
note 'Retrying ...'
|
28
|
+
Interaction.note 'Retrying ...'
|
30
29
|
require gem_name
|
31
30
|
retry
|
32
31
|
end
|
@@ -39,27 +38,27 @@ module Geordi
|
|
39
38
|
# @option fail_message: The text to print on command failure
|
40
39
|
def system!(*commands)
|
41
40
|
options = commands.last.is_a?(Hash) ? commands.pop : {}
|
42
|
-
note_cmd commands.join(' ') if options[:show_cmd]
|
41
|
+
Interaction.note_cmd commands.join(' ') if options[:show_cmd]
|
43
42
|
|
44
43
|
if options[:confirm]
|
45
|
-
prompt('Run this now?', 'n', /y|yes/) or fail('Cancelled.')
|
44
|
+
Interaction.prompt('Run this now?', 'n', /y|yes/) or Interaction.fail('Cancelled.')
|
46
45
|
end
|
47
46
|
|
48
47
|
if testing?
|
49
|
-
puts "Util.system! #{
|
48
|
+
puts "Util.system! #{commands.join ', '}"
|
50
49
|
else
|
51
50
|
# Remove Geordi's Bundler environment when running commands.
|
52
51
|
success = if !defined?(Bundler)
|
53
52
|
system(*commands)
|
54
53
|
elsif Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.1.2')
|
55
|
-
Bundler.
|
54
|
+
Bundler.with_original_env do
|
56
55
|
system(*commands)
|
57
56
|
end
|
58
57
|
else
|
59
58
|
Bundler.clean_system(*commands)
|
60
59
|
end
|
61
60
|
|
62
|
-
success
|
61
|
+
success || Interaction.fail(options[:fail_message] || 'Something went wrong.')
|
63
62
|
end
|
64
63
|
end
|
65
64
|
|
@@ -94,7 +93,7 @@ module Geordi
|
|
94
93
|
ENV['GEORDI_TESTING_STAGED_CHANGES'] == 'true'
|
95
94
|
else
|
96
95
|
statuses = `git status --porcelain`.split("\n")
|
97
|
-
statuses.any? { |l| l.start_with?
|
96
|
+
statuses.any? { |l| l.start_with? /[A-Z]/i }
|
98
97
|
end
|
99
98
|
end
|
100
99
|
|
@@ -107,7 +106,7 @@ module Geordi
|
|
107
106
|
# try to guess user's favorite cli text editor
|
108
107
|
def decide_texteditor
|
109
108
|
%w[/usr/bin/editor vi].each do |texteditor|
|
110
|
-
if cmd_exists?
|
109
|
+
if cmd_exists?(texteditor) && texteditor.start_with?('$')
|
111
110
|
return ENV[texteditor[1..-1]]
|
112
111
|
elsif cmd_exists? texteditor
|
113
112
|
return texteditor
|
@@ -116,19 +115,17 @@ module Geordi
|
|
116
115
|
end
|
117
116
|
|
118
117
|
# check if given cmd is executable. Absolute path or command in $PATH allowed.
|
119
|
-
def cmd_exists?
|
118
|
+
def cmd_exists?(cmd)
|
120
119
|
system("which #{cmd} > /dev/null")
|
121
|
-
|
120
|
+
$?.exitstatus.zero?
|
122
121
|
end
|
123
122
|
|
124
123
|
def is_port_open?(port)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
return false
|
131
|
-
end
|
124
|
+
socket = TCPSocket.new('127.0.0.1', port)
|
125
|
+
socket.close
|
126
|
+
true
|
127
|
+
rescue Errno::ECONNREFUSED
|
128
|
+
false
|
132
129
|
end
|
133
130
|
|
134
131
|
# splint lines e.g. read from a file into lines and clean those up
|
@@ -162,13 +159,19 @@ module Geordi
|
|
162
159
|
end
|
163
160
|
|
164
161
|
def file_containing?(file, regex)
|
165
|
-
File.
|
162
|
+
File.exist?(file) && File.read(file).scan(regex).any?
|
166
163
|
end
|
167
164
|
|
168
165
|
def testing?
|
169
166
|
!!ENV['GEORDI_TESTING']
|
170
167
|
end
|
171
168
|
|
169
|
+
def strip_heredoc(string)
|
170
|
+
leading_whitespace = (string.match(/\A( +)[^ ]+/) || [])[1]
|
171
|
+
string.gsub! /^#{leading_whitespace}/, '' if leading_whitespace
|
172
|
+
string
|
173
|
+
end
|
174
|
+
|
172
175
|
private
|
173
176
|
|
174
177
|
def bundle_list
|