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 +4 -4
- data/.github/workflows/test.yml +0 -4
- data/CHANGELOG.md +30 -0
- data/Gemfile.lock +2 -2
- data/README.md +8 -25
- data/exe/dumple +79 -46
- data/geordi.gemspec +1 -0
- data/lib/geordi/chromedriver_updater.rb +26 -20
- data/lib/geordi/commands/branch.rb +3 -1
- data/lib/geordi/commands/chromedriver_update.rb +2 -2
- data/lib/geordi/commands/dump.rb +8 -7
- data/lib/geordi/gitpt.rb +4 -4
- data/lib/geordi/version.rb +1 -1
- metadata +4 -5
- data/lib/geordi/commands/docker.rb +0 -52
- data/lib/geordi/docker.rb +0 -183
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 702407b6104865ae130f2c2793aa673f3c6f847d3652689a76e6d04c59a828e6
|
4
|
+
data.tar.gz: 4718d6e956efa941c25452f382761dcb3727db98364cfd0847c4edb0b947a608
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b43e0bf03b775a47bfbfee4ebd87aaa615cdd1d13b9f85d0952fabb23f2591d3d736cb6ef852695bdec56d562cabd18e87abd37a8f204ca5ce9af74575c4b5bb
|
7
|
+
data.tar.gz: 4a8963f968e73e040a9486337881f52549563d019abf0601589cfaf64af28d950b921e990bd196d060c78212c5a1b7893d6f2d1fc3641c51697f18698406060c
|
data/.github/workflows/test.yml
CHANGED
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
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
|
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
|
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,
|
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
|
-
|
23
|
-
|
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
|
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
|
-
|
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
|
-
|
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 #{
|
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=#{
|
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
|
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
|
-
|
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 =
|
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
|
-
|
10
|
+
current_chromedriver_version = determine_chromedriver_version
|
11
11
|
|
12
|
-
|
13
|
-
|
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
|
-
|
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
|
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
|
46
|
+
chromedriver_version
|
52
47
|
end
|
53
48
|
end
|
54
49
|
|
55
|
-
|
56
|
-
|
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
|
60
|
-
|
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
|
-
|
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
|
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
|
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'
|
data/lib/geordi/commands/dump.rb
CHANGED
@@ -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,
|
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]
|
data/lib/geordi/version.rb
CHANGED
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:
|
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:
|
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
|