geordi 7.0.2 → 9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8c141d6bb76920354f1a772f6d7a3f88f4ee41fc11766ae40c9bc664ae3d914
4
- data.tar.gz: e1d000833fb2d445b164529da4051fc25c846b7b0a5c12a0469a3fe745e6c2da
3
+ metadata.gz: 702407b6104865ae130f2c2793aa673f3c6f847d3652689a76e6d04c59a828e6
4
+ data.tar.gz: 4718d6e956efa941c25452f382761dcb3727db98364cfd0847c4edb0b947a608
5
5
  SHA512:
6
- metadata.gz: d9f630cfa71810205a6db1b23c304c13e14b7ad3380fb71539940e1c0af6802f74b13c6461f673e3aaa456a89dfc2a3b74fda29a865c605d4c5e4ce8890c1cfb
7
- data.tar.gz: dab2ddb18a29a96872478cd896951608ffdf2baa37c604e6124522810241fb5ecee69f9c2cafdde791992914d02fa926e195556592a5e82e067f37eadd7797f3
6
+ metadata.gz: b43e0bf03b775a47bfbfee4ebd87aaa615cdd1d13b9f85d0952fabb23f2591d3d736cb6ef852695bdec56d562cabd18e87abd37a8f204ca5ce9af74575c4b5bb
7
+ data.tar.gz: 4a8963f968e73e040a9486337881f52549563d019abf0601589cfaf64af28d950b921e990bd196d060c78212c5a1b7893d6f2d1fc3641c51697f18698406060c
@@ -31,10 +31,6 @@ jobs:
31
31
  run: |
32
32
  gem install bundler:2.2.26
33
33
  bundle install --no-deployment
34
- - name: Install VNC viewer
35
- run: |
36
- sudo apt-get update
37
- sudo apt-get install -y xtightvncviewer
38
34
  - name: Run tests
39
35
  run: bundle exec rake
40
36
 
data/CHANGELOG.md CHANGED
@@ -10,16 +10,46 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
10
10
  ### Breaking changes
11
11
 
12
12
 
13
+ ## 9.2.0 2022-02-18
14
+
15
+ ### Compatible changes
16
+ * Change the update mechanism of `geordi chromedriver-update`: This command (and `geordi cucumber`/`geordi tests` if the `auto_update_chromedriver` option is active) will now always update to the latest version of chromedriver for the current chrome version.
17
+
18
+ ### Breaking changes
19
+
20
+
21
+ ## 9.1.0 2022-02-14
22
+
23
+ ### Compatible changes
24
+ * `geordi dump` and `dumple` now default to "primary" database or the first
25
+ entry in a multi-db setup
26
+ * Also added feature tests for `dumple` and structured the script
27
+
28
+
29
+ ## 9.0.0 2021-12-02
30
+
31
+ ### Breaking changes
32
+ * Remove the `geordi docker` command set.
33
+
34
+
35
+ ## 8.0.0 2021-11-08
36
+
37
+ ### Breaking changes
38
+ * `geordi branch` now checks out new branches from the current branch instead of master. To check out from master, use `geordi branch -m`.
39
+
40
+
13
41
  ## 7.0.2 2021-10-06
14
42
 
15
43
  ### Compatible changes
16
44
  * fix `YAML.safe_load` for `psych` >= 4
17
45
 
46
+
18
47
  ## 7.0.1 2021-08-13
19
48
 
20
49
  ### Compatible changes
21
50
  * Fix missing `thor` dependency
22
51
 
52
+
23
53
  ## 7.0.0 2021-08-25
24
54
 
25
55
  ### Breaking changes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- geordi (7.0.2)
4
+ geordi (9.2.0)
5
5
  thor (~> 1)
6
6
 
7
7
  GEM
@@ -165,4 +165,4 @@ DEPENDENCIES
165
165
  tracker_api
166
166
 
167
167
  BUNDLED WITH
168
- 2.2.26
168
+ 2.2.27
data/README.md CHANGED
@@ -33,6 +33,9 @@ Example: `geordi branch`
33
33
  On the first execution we ask for your Pivotal Tracker API token. It will be
34
34
  stored in `~/.config/geordi/global.yml`.
35
35
 
36
+ **Options**
37
+ - `-m, [--from-master], [--no-from-master]`: Branch from master instead of the current branch
38
+
36
39
 
37
40
  ### `geordi capistrano COMMAND`
38
41
  Run a capistrano command on all deploy targets.
@@ -50,10 +53,10 @@ installed Chrome.
50
53
 
51
54
  Setting `auto_update_chromedriver` to `true` in your global Geordi config file
52
55
  (`~/.config/geordi/global.yml`), will automatically update chromedriver before
53
- cucumber tests, in case Chrome and chromedriver versions don't match
56
+ cucumber tests if a newer chromedriver version is available.
54
57
 
55
58
  **Options**
56
- - `[--quiet-if-matching], [--no-quiet-if-matching]`: Suppress notification if chromedriver and chrome versions match
59
+ - `[--quiet-if-matching], [--no-quiet-if-matching]`: Suppress notification if chromedriver is already on the latest version
57
60
 
58
61
 
59
62
  ### `geordi clean`
@@ -157,28 +160,6 @@ instead of `cap deploy:migrations`. You can force using `deploy` by passing the
157
160
  - `-c, [--current-branch], [--no-current-branch]`: Set DEPLOY_BRANCH to the current branch during deploy
158
161
 
159
162
 
160
- ### `geordi docker`
161
- Manage docker containers for the current project.
162
-
163
- Manage docker containers to run your project dockerized.
164
-
165
- It expects a `docker-compose.yml` file that specifies all services, and a service
166
- named "main" that opens a shell for the project.
167
-
168
- There are three subcommands:
169
-
170
- - `geordi docker setup`
171
- Fetches all docker containers.
172
-
173
- - `geordi docker shell`
174
- Runs the docker service named 'main'.
175
- Append `--secondary` to open a second shell in an already running container.
176
-
177
- - `geordi docker vnc`
178
- Opens a VNC viewer to connect to the VNC server in the container.
179
- Append `--setup` to be guided through the setup of VNC viewer.
180
-
181
-
182
163
  ### `geordi drop-databases`
183
164
  Interactively delete local databases.
184
165
 
@@ -213,7 +194,9 @@ specified target's database and downloads it to `tmp/`.
213
194
  `geordi dump staging -l` (with a Capistrano deploy target and the `--load`
214
195
  option) sources the dump into the development database after downloading it.
215
196
 
216
- If you are using multiple databases per environment, pass the database name like this:
197
+ If you are using multiple databases per environment, Geordi defaults to the
198
+ "primary" database, or the first entry in database.yml. To dump a specific
199
+ database, pass the database name like this:
217
200
 
218
201
  geordi dump -d primary
219
202
 
data/exe/dumple CHANGED
@@ -1,28 +1,33 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'erb'
4
-
5
- fail_gently = ARGV.include?("--fail-gently")
6
- compress = ARGV.include?("--compress")
7
-
8
3
  if ARGV.include?("-i")
9
4
  puts "*******************************************************"
10
5
  puts
11
6
  system("du -sh ~/dumps")
12
7
  puts
13
8
  puts "*******************************************************"
9
+
14
10
  exit
15
11
  end
16
12
 
17
- ###
18
-
13
+ require 'erb'
19
14
  require "yaml"
20
- config_path = 'config/database.yml'
21
15
 
22
- begin
23
- # go to project root
16
+ DB_CONFIG_PATH = 'config/database.yml'
17
+ DUMPS_DIR = "#{ENV['HOME']}/dumps"
18
+
19
+ def run(*args)
20
+ if !!ENV['GEORDI_TESTING']
21
+ puts "system #{args.join(', ')}"
22
+ true # "Command succeeded"
23
+ else
24
+ system *args
25
+ end
26
+ end
27
+
28
+ def cd_to_project_root(fail_gently)
24
29
  current = Dir.pwd
25
- until (File.exists? config_path)
30
+ until File.exists?(DB_CONFIG_PATH)
26
31
  Dir.chdir '..'
27
32
  if current == Dir.pwd
28
33
  if fail_gently
@@ -38,46 +43,24 @@ begin
38
43
  sleep 5
39
44
  exit
40
45
  else
41
- raise "Call me from inside a Rails project."
46
+ raise "x Call me from inside a Rails project."
42
47
  end
43
48
  end
44
49
  current = Dir.pwd
45
50
  end
51
+ end
46
52
 
47
- config = YAML::load(ERB.new(File.read(config_path)).result)
48
- environment, database = ARGV.reject{ |arg| arg[0].chr == '-' }
49
- environment ||= 'production'
50
- config = config[environment] or raise "No #{environment} database found.\nUsage: dumple ENVIRONMENT [DATABASE]"
51
-
52
- if database
53
- config = config[database] or raise %(Unknown #{environment} database "#{database}")
54
- end
55
-
56
- dump_dir = "#{ENV['HOME']}/dumps"
57
- unless File.directory?(dump_dir)
58
- Dir.mkdir(dump_dir)
59
- system("chmod 700 #{dump_dir}")
60
- end
61
-
62
- if ARGV.find{ |arg| arg == '--for_download'}
63
- dump_path = "#{dump_dir}/dump_for_download.dump"
64
- else
65
- dump_path = "#{dump_dir}/#{config['database']}_#{Time.now.strftime("%Y%m%d_%H%M%S")}.dump"
66
- end
67
-
68
- given_database = database ? %(#{database} ) : ""
69
- puts "> Dumping #{given_database}database for \"#{environment}\" environment ..."
70
-
53
+ def dump_command(dump_file, config)
71
54
  host = config['host']
72
55
  port = config['port']
73
56
 
74
- dump_command = case config['adapter']
57
+ case config['adapter']
75
58
  when /mysql/
76
59
  command = "mysqldump"
77
60
  command << " -u\"#{config['username']}\""
78
61
  command << " -p\"#{config['password']}\""
79
62
  command << " #{config['database']}"
80
- command << " -r #{dump_path}"
63
+ command << " -r #{dump_file}"
81
64
  # Using a transaction to allow concurrent request while creating a dump.
82
65
  # This works only reliable for InnoDB tables.
83
66
  # More details: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_single-transaction
@@ -96,25 +79,75 @@ begin
96
79
  command << " pg_dump #{config['database']}"
97
80
  command << " --clean"
98
81
  command << " --format=custom"
99
- command << " --file=#{dump_path}"
82
+ command << " --file=#{dump_file}"
100
83
  command << " --username=\"#{config['username']}\""
101
84
  command << " --host=#{host}" if host
102
85
  command << " --port=#{port}" if port
103
86
  command
104
87
  else
105
- raise "Adapter \"#{config['adapter']}\" is not supported"
88
+ raise %(x Adapter "#{config['adapter']}" is not supported.)
89
+ end
90
+ end
91
+
92
+ def find_database_config(config_path, environment, database)
93
+ environment ||= 'production'
94
+ database_yml = ERB.new(File.read(config_path)).result
95
+ config = YAML::load(database_yml)
96
+ config = config[environment] or raise "x No #{environment} database found.\nUsage: dumple ENVIRONMENT [DATABASE]"
97
+
98
+ if config.values[0].is_a? Hash # Multi-db setup
99
+ if database # Explicitly requested
100
+ config = config[database] or raise %(x Unknown #{environment} database "#{database}".)
101
+ elsif config.key? 'primary'
102
+ puts '> Multiple databases detected. Defaulting to primary database.'
103
+ config = config['primary']
104
+ else
105
+ puts "> Multiple databases detected. Defaulting to first entry (#{config.keys[0]})."
106
+ config = config.values[0]
107
+ end
108
+ else # Single-db setup
109
+ if database
110
+ raise %(x Could not select "#{database}" database in a single-db environment.)
111
+ end
106
112
  end
107
- success = system(dump_command)
108
- success or raise "Creating the dump failed"
109
113
 
110
- system "chmod 600 #{dump_path}"
114
+ config
115
+ end
116
+
117
+ def prepare_dump_path(config)
118
+ unless File.directory?(DUMPS_DIR)
119
+ Dir.mkdir(DUMPS_DIR)
120
+ run "chmod 700 #{DUMPS_DIR}"
121
+ end
122
+
123
+ if ARGV.include? '--for_download'
124
+ "#{DUMPS_DIR}/dump_for_download.dump"
125
+ else
126
+ "#{DUMPS_DIR}/#{config['database']}_#{Time.now.strftime("%Y%m%d_%H%M%S")}.dump"
127
+ end
128
+ end
129
+
130
+ begin
131
+ fail_gently = ARGV.include?("--fail-gently")
132
+ compress = ARGV.include?("--compress")
133
+ environment, database = ARGV.reject { |arg| arg[0].chr == '-' }
134
+
135
+ cd_to_project_root(fail_gently)
136
+ config = find_database_config(DB_CONFIG_PATH, environment, database)
137
+ dump_path = prepare_dump_path(config)
138
+
139
+ # Dump!
140
+ given_database = database ? %(#{database} ) : ""
141
+ command = dump_command(dump_path, config)
142
+ puts "> Dumping #{given_database}database for \"#{environment}\" environment ..."
143
+ run command or raise "x Creating the dump failed."
144
+ run "chmod 600 #{dump_path}"
111
145
 
112
146
  if compress
113
147
  puts "> Compressing the dump ..."
114
-
115
148
  # gzip compresses in place
116
- compress_success = system("gzip #{dump_path}")
117
- compress_success or raise "Compressing the dump failed"
149
+ compress_success = run "gzip #{dump_path}"
150
+ compress_success or raise "x Compressing the dump failed."
118
151
  dump_path << ".gz"
119
152
  end
120
153
 
data/geordi.gemspec CHANGED
@@ -13,6 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.description = spec.summary
14
14
  spec.homepage = 'https://makandra.com'
15
15
  spec.license = 'MIT'
16
+ spec.metadata = { 'rubygems_mfa_required' => 'true' }
16
17
 
17
18
  # Specify which files should be added to the gem when it is released.
18
19
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -7,18 +7,13 @@ module Geordi
7
7
 
8
8
  def run(options)
9
9
  chrome_version = determine_chrome_version
10
- chromedriver_version = determine_chromedriver_version
10
+ current_chromedriver_version = determine_chromedriver_version
11
11
 
12
- if skip_update?(chrome_version, chromedriver_version)
13
- Interaction.success "No update required: both Chrome and chromedriver are on v#{chrome_version}!" unless options[:quiet_if_matching]
12
+ latest_chromedriver_version = latest_version(chrome_version)
13
+ if current_chromedriver_version == latest_chromedriver_version
14
+ Interaction.success "No update required: Chromedriver is already on the latest version v#{latest_chromedriver_version}!" unless options[:quiet_if_matching]
14
15
  else
15
- chromedriver_zip = download_chromedriver(chrome_version)
16
- unzip(chromedriver_zip, File.expand_path('~/bin'))
17
-
18
- chromedriver_zip.unlink
19
-
20
- # We need to determine the version again, as it could be nil in case no chromedriver was installed before
21
- Interaction.success "Chromedriver updated to v#{determine_chromedriver_version}."
16
+ update_chromedriver(latest_chromedriver_version)
22
17
  end
23
18
  end
24
19
 
@@ -27,13 +22,13 @@ module Geordi
27
22
  def determine_chrome_version
28
23
  stdout_str, _error_str, status = Open3.capture3('google-chrome', '--version')
29
24
  chrome_version = unless stdout_str.nil?
30
- stdout_str[/\AGoogle Chrome (\d+)/, 1]
25
+ stdout_str[/\AGoogle Chrome ([\d.]+)/, 1]
31
26
  end
32
27
 
33
28
  if !status.success? || chrome_version.nil?
34
29
  Interaction.fail('Could not determine the version of Google Chrome.')
35
30
  else
36
- chrome_version.to_i
31
+ chrome_version
37
32
  end
38
33
  end
39
34
 
@@ -42,23 +37,32 @@ module Geordi
42
37
 
43
38
  stdout_str, _error_str, status = Open3.capture3('chromedriver', '-v')
44
39
  chromedriver_version = unless stdout_str.nil?
45
- stdout_str[/\AChromeDriver (\d+)/, 1]
40
+ stdout_str[/\AChromeDriver ([\d.]+)/, 1]
46
41
  end
47
42
 
48
43
  if !status.success? || chromedriver_version.nil?
49
44
  Interaction.fail('Could not determine the version of chromedriver.')
50
45
  else
51
- chromedriver_version.to_i
46
+ chromedriver_version
52
47
  end
53
48
  end
54
49
 
55
- def skip_update?(chrome_version, chromedriver_version)
56
- chrome_version == chromedriver_version
50
+ # Check https://groups.google.com/a/chromium.org/g/chromium-discuss/c/4BB4jmsRyv8/m/TY3FXS4HBgAJ
51
+ # for information how chrome version numbers work
52
+ def major_version(full_version)
53
+ full_version.match(/^(\d+\.\d+\.\d+)\.\d+$/)[1]
57
54
  end
58
55
 
59
- def download_chromedriver(chrome_version)
60
- latest_version = latest_version(chrome_version)
56
+ def update_chromedriver(latest_chromedriver_version)
57
+ chromedriver_zip = download_chromedriver(latest_chromedriver_version)
58
+
59
+ unzip(chromedriver_zip, File.expand_path('~/bin'))
61
60
 
61
+ # We need to determine the version again, as it could be nil in case no chromedriver was installed before
62
+ Interaction.success "Chromedriver updated to v#{determine_chromedriver_version}."
63
+ end
64
+
65
+ def download_chromedriver(latest_version)
62
66
  uri = URI("https://chromedriver.storage.googleapis.com/#{latest_version}/chromedriver_linux64.zip")
63
67
  response = Net::HTTP.get_response(uri)
64
68
 
@@ -73,11 +77,13 @@ module Geordi
73
77
  end
74
78
 
75
79
  def latest_version(chrome_version)
76
- uri = URI("https://chromedriver.storage.googleapis.com/LATEST_RELEASE_#{chrome_version}")
80
+ return @latest_version if @latest_version
81
+
82
+ uri = URI("https://chromedriver.storage.googleapis.com/LATEST_RELEASE_#{major_version(chrome_version)}")
77
83
  response = Net::HTTP.get_response(uri)
78
84
 
79
85
  if response.is_a?(Net::HTTPSuccess)
80
- response.body.to_s
86
+ @latest_version = response.body.to_s
81
87
  else
82
88
  Interaction.fail("Could not download the chromedriver v#{chrome_version}.")
83
89
  end
@@ -6,7 +6,9 @@ On the first execution we ask for your Pivotal Tracker API token. It will be
6
6
  stored in `~/.config/geordi/global.yml`.
7
7
  LONGDESC
8
8
 
9
+ option :from_master, aliases: '-m', type: :boolean, desc: 'Branch from master instead of the current branch'
10
+
9
11
  def branch
10
12
  require 'geordi/gitpt'
11
- Gitpt.new.run_branch
13
+ Gitpt.new.run_branch(from_master: options.from_master)
12
14
  end
@@ -7,11 +7,11 @@ installed Chrome.
7
7
 
8
8
  Setting `auto_update_chromedriver` to `true` in your global Geordi config file
9
9
  (`~/.config/geordi/global.yml`), will automatically update chromedriver before
10
- cucumber tests, in case Chrome and chromedriver versions don't match
10
+ cucumber tests if a newer chromedriver version is available.
11
11
  LONGDESC
12
12
 
13
13
  option :quiet_if_matching, type: :boolean, default: false,
14
- desc: 'Suppress notification if chromedriver and chrome versions match'
14
+ desc: 'Suppress notification if chromedriver is already on the latest version'
15
15
 
16
16
  def chromedriver_update
17
17
  require 'geordi/chromedriver_updater'
@@ -11,7 +11,9 @@ specified target's database and downloads it to `tmp/`.
11
11
  `geordi dump staging -l` (with a Capistrano deploy target and the `--load`
12
12
  option) sources the dump into the development database after downloading it.
13
13
 
14
- If you are using multiple databases per environment, pass the database name like this:
14
+ If you are using multiple databases per environment, Geordi defaults to the
15
+ "primary" database, or the first entry in database.yml. To dump a specific
16
+ database, pass the database name like this:
15
17
 
16
18
  geordi dump -d primary
17
19
 
@@ -26,9 +28,8 @@ def dump(target = nil, *_args)
26
28
  require 'geordi/remote'
27
29
  database = options[:database] ? "#{options[:database]} " : ''
28
30
 
29
- if target.nil?
30
- if options.load
31
- # validate load option
31
+ if target.nil? # Local …
32
+ if options.load # … dump loading
32
33
  Interaction.fail 'Missing a dump file.' if options.load == 'load'
33
34
  File.exist?(options.load) || raise('Could not find the given dump file: ' + options.load)
34
35
 
@@ -39,19 +40,19 @@ def dump(target = nil, *_args)
39
40
 
40
41
  Interaction.success "Your #{loader.config['database']} database has now the data of #{options.load}."
41
42
 
42
- else
43
+ else # … dump creation
43
44
  Interaction.announce 'Dumping the development database'
44
45
  Util.run!("dumple development #{database}")
45
46
  Interaction.success "Successfully dumped the #{database}development database."
46
47
  end
47
48
 
48
- else
49
+ else # Remote dumping …
49
50
  database_label = options[:database] ? " (#{database}database)" : ""
50
51
 
51
52
  Interaction.announce "Dumping the database of #{target}#{database_label}"
52
53
  dump_path = Geordi::Remote.new(target).dump(options)
53
54
 
54
- if options.load
55
+ if options.load # … and dump loading
55
56
  loader = DumpLoader.new(dump_path)
56
57
 
57
58
  Interaction.announce "Sourcing dump into the #{loader.config['database']} db"
data/lib/geordi/gitpt.rb CHANGED
@@ -26,7 +26,7 @@ module Geordi
26
26
  end
27
27
  end
28
28
 
29
- def run_branch
29
+ def run_branch(from_master: false)
30
30
  story = choose_story || Interaction.fail('No story selected.')
31
31
 
32
32
  normalized_story_name = normalize_string(story.name)
@@ -50,7 +50,7 @@ module Geordi
50
50
  if branch_name.present?
51
51
  checkout_branch branch_name, new_branch: false
52
52
  else
53
- checkout_branch new_branch_name, new_branch: true
53
+ checkout_branch new_branch_name, new_branch: true, from_master: from_master
54
54
  end
55
55
  end
56
56
 
@@ -139,9 +139,9 @@ module Geordi
139
139
  HighLine::BOLD + string + HighLine::RESET
140
140
  end
141
141
 
142
- def checkout_branch(name, new_branch: false)
142
+ def checkout_branch(name, new_branch: false, from_master: false)
143
143
  if new_branch
144
- Util.run! ['git', 'checkout', 'master']
144
+ Util.run! ['git', 'checkout', 'master'] if from_master
145
145
  Util.run! ['git', 'checkout', '-b', name]
146
146
  else
147
147
  Util.run! ['git', 'checkout', name]
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '7.0.2'.freeze
2
+ VERSION = '9.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: 7.0.2
4
+ version: 9.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: 2021-10-06 00:00:00.000000000 Z
11
+ date: 2022-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -67,7 +67,6 @@ files:
67
67
  - lib/geordi/commands/cucumber.rb
68
68
  - lib/geordi/commands/delete_dumps.rb
69
69
  - lib/geordi/commands/deploy.rb
70
- - lib/geordi/commands/docker.rb
71
70
  - lib/geordi/commands/drop_databases.rb
72
71
  - lib/geordi/commands/dump.rb
73
72
  - lib/geordi/commands/migrate.rb
@@ -87,7 +86,6 @@ files:
87
86
  - lib/geordi/commands/yarn_install.rb
88
87
  - lib/geordi/cucumber.rb
89
88
  - lib/geordi/db_cleaner.rb
90
- - lib/geordi/docker.rb
91
89
  - lib/geordi/dump_loader.rb
92
90
  - lib/geordi/gitpt.rb
93
91
  - lib/geordi/interaction.rb
@@ -98,7 +96,8 @@ files:
98
96
  homepage: https://makandra.com
99
97
  licenses:
100
98
  - MIT
101
- metadata: {}
99
+ metadata:
100
+ rubygems_mfa_required: 'true'
102
101
  post_install_message: 'Support for sequential running of integration tests tagged
103
102
  with @solo has been dropped.
104
103
 
@@ -1,52 +0,0 @@
1
- class DockerCLI < Thor
2
- desc 'setup', 'Setup docker and fetch required docker-container for the current project'
3
- def setup
4
- docker.setup
5
- end
6
-
7
- desc 'shell', 'Open a shell in the main docker container for the current project'
8
- option :secondary, default: false, type: :boolean
9
- map 'shell' => '_shell'
10
- def _shell
11
- docker.shell(:secondary => options[:secondary])
12
- end
13
-
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'
16
- def vnc
17
- if options.setup
18
- docker.setup_vnc
19
- else
20
- docker.vnc
21
- end
22
- end
23
-
24
- private
25
-
26
- def docker
27
- require 'geordi/docker'
28
- Geordi::Docker.new
29
- end
30
- end
31
-
32
- desc 'docker', 'Manage docker containers for the current project'
33
- long_desc <<-LONGDESC
34
- Manage docker containers to run your project dockerized.
35
-
36
- It expects a `docker-compose.yml` file that specifies all services, and a service
37
- named "main" that opens a shell for the project.
38
-
39
- There are three subcommands:
40
-
41
- - `geordi docker setup`
42
- Fetches all docker containers.
43
-
44
- - `geordi docker shell`
45
- Runs the docker service named 'main'.
46
- Append `--secondary` to open a second shell in an already running container.
47
-
48
- - `geordi docker vnc`
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.
51
- LONGDESC
52
- subcommand 'docker', DockerCLI
data/lib/geordi/docker.rb DELETED
@@ -1,183 +0,0 @@
1
- require 'geordi/interaction'
2
- require 'geordi/cucumber'
3
- require 'yaml'
4
- require 'open3'
5
-
6
- module Geordi
7
- class Docker
8
- DOCKER_COMPOSE_FILE = 'docker-compose.yml'.freeze
9
-
10
- include Interaction
11
-
12
- def setup
13
- check_installation_and_config
14
- announce('Fetching containers...')
15
- if execute(:system, 'docker-compose', 'pull')
16
- success('Fetch successful.')
17
- else
18
- fail('Fetch failed.')
19
- end
20
- end
21
-
22
- def shell(options = {})
23
- check_installation_and_config
24
- if options[:secondary]
25
- attach_to_running_shell
26
- else
27
- run_shell
28
- end
29
- end
30
-
31
- def vnc
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 <<~TEXT
54
- Done. You can view the VNC window with `geordi docker vnc`.
55
- TEXT
56
-
57
- Interaction.success 'Happy cuking!'
58
- end
59
-
60
- private
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
-
80
- def attach_to_running_shell
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")
87
- if (main_container_line = running_containers.grep(/_main_run/).first)
88
- container_name = main_container_line.split(' ').first
89
- execute(:exec, 'docker', 'exec', '-it', container_name, 'bash')
90
- else
91
- fail('Could not find a running shell. Start without --secondary first.')
92
- end
93
- end
94
-
95
- def run_shell
96
- command = [:system, 'docker-compose', 'run', '--service-ports']
97
- command += ssh_agent_forward
98
- command += ['main']
99
- execute(*command)
100
- execute(:system, 'docker-compose', 'stop')
101
- end
102
-
103
- def execute(kind, *args)
104
- if ENV['GEORDI_TESTING']
105
- puts "Stubbed run #{args.join(' ')}"
106
- if kind == :` || kind == :capture
107
- mock_parse(*args)
108
- else
109
- mock_run(*args)
110
- end
111
- else
112
- if kind == :capture
113
- Open3.capture2(*args)
114
- else
115
- send(kind, *args)
116
- end
117
- end
118
- end
119
-
120
- def mock_run(*args)
121
- # exists just to be stubbed in tests
122
- true
123
- end
124
-
125
- def mock_parse(*args)
126
- # exists just to be stubbed in tests
127
- 'command output'
128
- end
129
-
130
- def check_installation_and_config
131
- unless command_exists?('docker')
132
- fail('You need to install docker first with `sudo apt install docker`. After installation please log out and back in to your system once.')
133
- end
134
-
135
- unless command_exists?('docker-compose')
136
- fail('You need to install docker-compose first with `sudo apt install docker-compose`.')
137
- end
138
-
139
- unless docker_compose_config && (services = docker_compose_config['services']) && services.key?('main')
140
- fail('Your project does not seem to be properly set up. Expected to find a docker-compose.yml which defines a service named "main".')
141
- end
142
- end
143
-
144
- def command_exists?(command)
145
- execute(:system, "which #{command} > /dev/null")
146
- end
147
-
148
- def docker_compose_config
149
- @docker_compose_config ||= if File.exists?(DOCKER_COMPOSE_FILE)
150
- if YAML.respond_to?(:safe_load)
151
- YAML.safe_load(File.read(DOCKER_COMPOSE_FILE))
152
- else
153
- YAML.load(File.read(DOCKER_COMPOSE_FILE))
154
- end
155
- end
156
- rescue
157
- false
158
- end
159
-
160
- def ssh_agent_forward
161
- if (auth_sock = ENV['SSH_AUTH_SOCK'])
162
- dirname = File.dirname(auth_sock)
163
- ['-v', "#{dirname}:#{dirname}", '-e', "SSH_AUTH_SOCK=#{auth_sock}"]
164
- else
165
- []
166
- end
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
-
182
- end
183
- end