geordi 3.0.0 → 3.2.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/CHANGELOG.md +36 -2
  4. data/Gemfile.lock +1 -1
  5. data/README.md +46 -3
  6. data/lib/geordi/COMMAND_TEMPLATE +2 -3
  7. data/lib/geordi/chromedriver_updater.rb +7 -8
  8. data/lib/geordi/cli.rb +0 -1
  9. data/lib/geordi/commands/_setup_vnc.rb +22 -22
  10. data/lib/geordi/commands/bundle_install.rb +1 -1
  11. data/lib/geordi/commands/capistrano.rb +4 -4
  12. data/lib/geordi/commands/clean.rb +6 -5
  13. data/lib/geordi/commands/commit.rb +1 -1
  14. data/lib/geordi/commands/console.rb +11 -3
  15. data/lib/geordi/commands/create_database_yml.rb +2 -2
  16. data/lib/geordi/commands/create_databases.rb +1 -1
  17. data/lib/geordi/commands/cucumber.rb +16 -9
  18. data/lib/geordi/commands/delete_dumps.rb +5 -5
  19. data/lib/geordi/commands/deploy.rb +19 -19
  20. data/lib/geordi/commands/drop_databases.rb +3 -3
  21. data/lib/geordi/commands/dump.rb +8 -9
  22. data/lib/geordi/commands/firefox.rb +2 -2
  23. data/lib/geordi/commands/migrate.rb +3 -3
  24. data/lib/geordi/commands/png_optimize.rb +5 -5
  25. data/lib/geordi/commands/rake.rb +1 -1
  26. data/lib/geordi/commands/remove_executable_flags.rb +2 -2
  27. data/lib/geordi/commands/rspec.rb +5 -5
  28. data/lib/geordi/commands/security_update.rb +76 -19
  29. data/lib/geordi/commands/server.rb +2 -2
  30. data/lib/geordi/commands/setup.rb +3 -3
  31. data/lib/geordi/commands/shell.rb +7 -3
  32. data/lib/geordi/commands/tests.rb +1 -1
  33. data/lib/geordi/commands/unit.rb +2 -2
  34. data/lib/geordi/commands/update.rb +2 -2
  35. data/lib/geordi/commands/with_rake.rb +2 -2
  36. data/lib/geordi/commands/yarn_install.rb +1 -1
  37. data/lib/geordi/cucumber.rb +18 -17
  38. data/lib/geordi/db_cleaner.rb +21 -22
  39. data/lib/geordi/dump_loader.rb +5 -4
  40. data/lib/geordi/firefox_for_selenium.rb +17 -19
  41. data/lib/geordi/gitpt.rb +10 -53
  42. data/lib/geordi/interaction.rb +2 -6
  43. data/lib/geordi/remote.rb +17 -6
  44. data/lib/geordi/settings.rb +155 -0
  45. data/lib/geordi/util.rb +14 -9
  46. data/lib/geordi/version.rb +1 -1
  47. metadata +4 -3
@@ -1,19 +1,20 @@
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'.freeze
8
- PROJECT_IDS_FILE_NAME = '.pt_project_id'.freeze
6
+ # This require-style is to prevent Ruby from loading files of a different
7
+ # version of Geordi.
8
+ require File.expand_path('settings', __dir__)
9
9
 
10
10
  def initialize
11
11
  self.highline = HighLine.new
12
- self.client = build_client(read_settings)
12
+ self.settings = Geordi::Settings.new
13
+ self.client = build_client
13
14
  end
14
15
 
15
16
  def run(git_args)
16
- warn <<-WARNING unless Geordi::Util.staged_changes?
17
+ Geordi::Interaction.warn <<-WARNING unless Geordi::Util.staged_changes?
17
18
  No staged changes. Will create an empty commit.
18
19
  WARNING
19
20
 
@@ -25,57 +26,17 @@ No staged changes. Will create an empty commit.
25
26
 
26
27
  private
27
28
 
28
- attr_accessor :highline, :client
29
+ attr_accessor :highline, :client, :settings
29
30
 
30
- def read_settings
31
- file_path = File.join(ENV['HOME'], SETTINGS_FILE_NAME)
32
-
33
- unless File.exist?(file_path)
34
- highline.say HighLine::RESET
35
- highline.say "Welcome to #{bold 'gitpt'}.\n\n"
36
-
37
- highline.say highlight('Your settings are missing or invalid.')
38
- highline.say "Please configure your Pivotal Tracker access.\n\n"
39
- token = highline.ask bold('Your API key:') + ' '
40
- highline.say "\n"
41
-
42
- settings = { token: token }
43
- File.open(file_path, 'w') do |file|
44
- file.write settings.to_yaml
45
- end
46
- end
47
-
48
- YAML.load_file(file_path)
49
- end
50
-
51
- def build_client(settings)
52
- TrackerApi::Client.new(token: settings.fetch(:token))
31
+ def build_client
32
+ TrackerApi::Client.new(token: settings.pivotal_tracker_api_key)
53
33
  end
54
34
 
55
35
  def load_projects
56
- project_ids = read_project_ids
36
+ project_ids = settings.pivotal_tracker_project_ids
57
37
  project_ids.collect { |project_id| client.project(project_id) }
58
38
  end
59
39
 
60
- def read_project_ids
61
- file_path = PROJECT_IDS_FILE_NAME
62
-
63
- if File.exist?(file_path)
64
- project_ids = File.read('.pt_project_id').split(/[\s]+/).map(&:to_i)
65
- end
66
-
67
- if project_ids && (project_ids.size > 0)
68
- project_ids
69
- else
70
- warn "Sorry, I could not find a project ID in #{file_path} :("
71
- puts
72
-
73
- puts "Please put at least one Pivotal Tracker project id into #{file_path} in this directory."
74
- puts 'You may add multiple IDs, separated using white space.'
75
- exit 1
76
- end
77
- end
78
-
79
40
  def applicable_stories
80
41
  projects = load_projects
81
42
  projects.collect do |project|
@@ -135,8 +96,4 @@ No staged changes. Will create an empty commit.
135
96
  HighLine::BOLD + string + HighLine::RESET
136
97
  end
137
98
 
138
- def highlight(string)
139
- bold HighLine::BLUE + string
140
- end
141
-
142
99
  end
@@ -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)
@@ -6,7 +6,6 @@ require 'pathname'
6
6
 
7
7
  module Geordi
8
8
  class Remote
9
- include Geordi::Interaction
10
9
 
11
10
  REMOTE_DUMP_PATH = '~/dumps/dump_for_download.dump'.freeze
12
11
 
@@ -35,7 +34,6 @@ module Geordi
35
34
  # Generate dump on the server
36
35
  shell options.merge({
37
36
  remote_command: "dumple #{@config.env} --for_download",
38
- select_server: nil, # Dump must be generated on the primary server
39
37
  })
40
38
 
41
39
  destination_directory = File.join(@config.root, 'tmp')
@@ -43,11 +41,11 @@ module Geordi
43
41
  destination_path = File.join(destination_directory, "#{@stage}.dump")
44
42
  relative_destination = Pathname.new(destination_path).relative_path_from Pathname.new(@config.root)
45
43
 
46
- note "Downloading remote dump to #{relative_destination} ..."
44
+ Interaction.note "Downloading remote dump to #{relative_destination} ..."
47
45
  server = @config.primary_server
48
46
  Util.system! "scp -C #{@config.user(server)}@#{server}:#{REMOTE_DUMP_PATH} #{destination_path}"
49
47
 
50
- success "Dumped the #{@stage} database to #{relative_destination}."
48
+ Interaction.success "Dumped the #{@stage} database to #{relative_destination}."
51
49
 
52
50
  destination_path
53
51
  end
@@ -57,12 +55,25 @@ module Geordi
57
55
  end
58
56
 
59
57
  def shell(options = {})
60
- server = options[:select_server] ? select_server : @config.primary_server
58
+ server_option = options[:select_server]
59
+ server_number = server_option.to_i
60
+
61
+ server = if server_option == 'select_server'
62
+ select_server
63
+ elsif server_number != 0 && server_number <= @config.servers.count
64
+ server_index = server_number - 1
65
+ @config.servers[server_index]
66
+ elsif server_option.nil?
67
+ @config.primary_server
68
+ else
69
+ Interaction.warn "Invalid server number: #{server_option}"
70
+ select_server
71
+ end
61
72
 
62
73
  remote_command = "cd #{@config.remote_root} && #{@config.shell}"
63
74
  remote_command << " -c '#{options[:remote_command]}'" if options[:remote_command]
64
75
 
65
- note 'Connecting to ' + server.to_s
76
+ Interaction.note 'Connecting to ' + server.to_s
66
77
  Util.system! 'ssh', "#{@config.user(server)}@#{server}", '-t', remote_command
67
78
  end
68
79
 
@@ -0,0 +1,155 @@
1
+ require 'yaml'
2
+
3
+ require File.expand_path('util', __dir__)
4
+ require File.expand_path('interaction', __dir__)
5
+
6
+ module Geordi
7
+ class Settings
8
+ GLOBAL_SETTINGS_FILE_NAME = Util.testing? ? './tmp/global_settings.yml'.freeze : File.join(ENV['HOME'], '.config/geordi/global.yml').freeze
9
+ LOCAL_SETTINGS_FILE_NAME = Util.testing? ? './tmp/local_settings.yml'.freeze : './.geordi.yml'.freeze
10
+
11
+ ALLOWED_GLOBAL_SETTINGS = %w[ pivotal_tracker_api_key ].freeze
12
+ ALLOWED_LOCAL_SETTINGS = %w[ use_vnc pivotal_tracker_project_ids ].freeze
13
+
14
+ def initialize
15
+ read_settings
16
+ end
17
+
18
+ # Global settings
19
+ def pivotal_tracker_api_key
20
+ @global_settings['pivotal_tracker_api_key'] || gitpt_api_key_old || inquire_pt_api_key
21
+ end
22
+
23
+ def pivotal_tracker_api_key=(value)
24
+ @global_settings['pivotal_tracker_api_key'] = value
25
+ save_global_settings
26
+ end
27
+
28
+ # Local settings
29
+ # They should not be changed by geordi to avoid unexpected diffs, therefore
30
+ # there are no setters for these settings
31
+ def use_vnc?
32
+ @local_settings.fetch('use_vnc', true)
33
+ end
34
+
35
+ def pivotal_tracker_project_ids
36
+ project_ids = @local_settings['pivotal_tracker_project_ids'] || pt_project_ids_old
37
+
38
+ case project_ids
39
+ when Array
40
+ # nothing to do
41
+ when String
42
+ project_ids = project_ids.split(/[\s]+/).map(&:to_i)
43
+ when Integer
44
+ project_ids = [project_ids]
45
+ else
46
+ project_ids = []
47
+ end
48
+
49
+ if project_ids.empty?
50
+ puts
51
+ Geordi::Interaction.warn "Sorry, I could not find a project ID in .geordi.yml :("
52
+ puts
53
+
54
+ puts "Please put at least one Pivotal Tracker project id into the .geordi.yml file in this directory, e.g."
55
+ puts
56
+ puts "pivotal_tracker_project_ids:"
57
+ puts "- 123456"
58
+ puts
59
+ puts 'You may add multiple IDs.'
60
+ exit 1
61
+ end
62
+
63
+ project_ids
64
+ end
65
+
66
+ private
67
+
68
+ def read_settings
69
+ global_path = GLOBAL_SETTINGS_FILE_NAME
70
+ local_path = LOCAL_SETTINGS_FILE_NAME
71
+
72
+ if File.exists?(global_path)
73
+ global_settings = YAML.safe_load(File.read(global_path))
74
+ check_for_invalid_keys(global_settings, ALLOWED_GLOBAL_SETTINGS, global_path)
75
+ end
76
+
77
+ if File.exists?(local_path)
78
+ local_settings = YAML.safe_load(File.read(local_path))
79
+ check_for_invalid_keys(local_settings, ALLOWED_LOCAL_SETTINGS, local_path)
80
+ end
81
+
82
+ @global_settings = global_settings || {}
83
+ @local_settings = local_settings || {}
84
+ end
85
+
86
+ def check_for_invalid_keys(settings, allowed_keys, file)
87
+ invalid_keys = settings.keys - allowed_keys
88
+ unless invalid_keys.empty?
89
+ Geordi::Interaction.warn "Geordi detected unknown keys in #{file}.\n"
90
+
91
+ invalid_keys.sort.each do |key|
92
+ puts "* #{key}"
93
+ end
94
+
95
+ puts "\nAllowed keys are:"
96
+ allowed_keys.sort.each do |key|
97
+ puts "* #{key}"
98
+ end
99
+ puts
100
+
101
+ exit 1
102
+ end
103
+ end
104
+
105
+ def save_global_settings
106
+ global_path = GLOBAL_SETTINGS_FILE_NAME
107
+ global_directory = File.dirname(global_path)
108
+ FileUtils.mkdir_p(global_directory) unless File.directory? global_directory
109
+ File.open(global_path, 'w') do |file|
110
+ file.write @global_settings.to_yaml
111
+ end
112
+ end
113
+
114
+ # deprecated
115
+ def gitpt_api_key_old
116
+ file_path = File.join(ENV['HOME'], '.gitpt')
117
+ if File.exist?(file_path) && !Util.testing?
118
+ token = YAML.load_file(file_path).fetch :token
119
+ self.pivotal_tracker_api_key = token
120
+
121
+ Geordi::Interaction.warn "The ~/.gitpt file is deprecated."
122
+ Geordi::Interaction.note "The contained setting has been moved to ~/.config/geordi/global.yml."
123
+ Geordi::Interaction.note "If you don't need to work with an older version of geordi you can delete ~/.gitpt now."
124
+
125
+ token
126
+ end
127
+ end
128
+
129
+ def inquire_pt_api_key
130
+ Geordi::Interaction.warn 'Your settings are missing or invalid.'
131
+ Geordi::Interaction.warn "Please configure your Pivotal Tracker access."
132
+ token = Geordi::Interaction.prompt 'Your API key:'
133
+ self.pivotal_tracker_api_key = token
134
+ puts
135
+
136
+ token
137
+ end
138
+
139
+ # deprecated
140
+ def pt_project_ids_old
141
+ if File.exist?('.pt_project_id')
142
+ project_ids = File.read('.pt_project_id')
143
+ puts # Make sure to start on a new line (e.g. when invoked after a #print)
144
+ Geordi::Interaction.warn "The usage of the .pt_project_id file is deprecated."
145
+ Geordi::Interaction.note Util.strip_heredoc(<<-INSTRUCTIONS)
146
+ Please remove this file from your project and add or extend the .geordi.yml file with the following content:
147
+ pivotal_tracker_project_ids: #{project_ids}
148
+ INSTRUCTIONS
149
+
150
+ project_ids
151
+ end
152
+ end
153
+
154
+ end
155
+ end
@@ -4,7 +4,6 @@ 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
@@ -20,13 +19,13 @@ module Geordi
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/) || raise('Missing Gems.')
22
+ Interaction.warn 'Probably missing gem: ' + gem_name
23
+ Interaction.prompt('Install it now?', 'y', /y|yes/) || Interaction.fail('Missing Gems.')
25
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,10 +38,10 @@ 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/) || raise('Cancelled.')
44
+ Interaction.prompt('Run this now?', 'n', /y|yes/) or Interaction.fail('Cancelled.')
46
45
  end
47
46
 
48
47
  if testing?
@@ -59,7 +58,7 @@ module Geordi
59
58
  Bundler.clean_system(*commands)
60
59
  end
61
60
 
62
- success || raise(options[:fail_message] || 'Something went wrong.')
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? /[A-Z]/i }
96
+ statuses.any? { |l| /^[A-Z]/i =~ l }
98
97
  end
99
98
  end
100
99
 
@@ -118,7 +117,7 @@ module Geordi
118
117
  # check if given cmd is executable. Absolute path or command in $PATH allowed.
119
118
  def cmd_exists?(cmd)
120
119
  system("which #{cmd} > /dev/null")
121
- $CHILD_STATUS.exitstatus.zero?
120
+ $?.exitstatus.zero?
122
121
  end
123
122
 
124
123
  def is_port_open?(port)
@@ -167,6 +166,12 @@ module Geordi
167
166
  !!ENV['GEORDI_TESTING']
168
167
  end
169
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
+
170
175
  private
171
176
 
172
177
  def bundle_list
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '3.0.0'.freeze
2
+ VERSION = '3.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geordi
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-04 00:00:00.000000000 Z
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -123,6 +123,7 @@ files:
123
123
  - lib/geordi/gitpt.rb
124
124
  - lib/geordi/interaction.rb
125
125
  - lib/geordi/remote.rb
126
+ - lib/geordi/settings.rb
126
127
  - lib/geordi/util.rb
127
128
  - lib/geordi/version.rb
128
129
  homepage: http://makandra.com
@@ -144,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
145
  - !ruby/object:Gem::Version
145
146
  version: '0'
146
147
  requirements: []
147
- rubygems_version: 3.0.8
148
+ rubygems_version: 3.0.3
148
149
  signing_key:
149
150
  specification_version: 4
150
151
  summary: Collection of command line tools we use in our daily work with Ruby, Rails