geordi 7.0.2 → 9.2.0

Sign up to get free protection for your applications and to get access to all the features.
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