geordi 12.5.0 → 12.6.1

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: 2e8dcb193d83d352bffb4f62670c93732de779a9471e51f942a0c20ddf19b89b
4
- data.tar.gz: 152f889f12fe2cfdeea9b1457bc1b6c9d083169d3400a1189588470fc061f4b2
3
+ metadata.gz: 212f089b529c55fd8687a9bd623984863790475c50144f4191360f841fa7357b
4
+ data.tar.gz: c33fb0561961c4d6f1c11d6a0ae966351b4528c7af62d7d22a1ebd118866e2a2
5
5
  SHA512:
6
- metadata.gz: 04732b8f09ba0f7eba641fe8fa5cbff9ea625f311ce42db3b588345a7565b4631d4e67e81420b3b4f357afc98fff3021a458cdb08a03daf15ea93110512e444d
7
- data.tar.gz: '02938cfa637e316e97b70666a7615696ccc1d881711c8823954529fc109af32ef16f98f132938ce1e04e49c0f007b1e60563e725669aff040eb504e207b7dc5f'
6
+ metadata.gz: f5940425de342af7a611912e7b17d79c922eb6933c26b43da5d6c4e880864700e7ee9b044fa4a21bf56545bebff5204f950eefcb55582d76f8017ef503c8b290
7
+ data.tar.gz: dc062018c3e10ba98b90b8bc846e8592c94c42cd669c358b5ef7abadf73371a6160949d9753f145b318296598d3575efda0660a6ffdfbeb048a84584ace3be8c
data/CHANGELOG.md CHANGED
@@ -10,6 +10,20 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
10
10
  ### Breaking changes
11
11
 
12
12
 
13
+ ## 12.6.1 2025-09-23
14
+
15
+ ### Compatible changes
16
+ * User prompts are now pink, and printed commands cyan (colors swapped).
17
+ * Restored backwards compatibility with older versions of `dumple` installed on a server.
18
+
19
+
20
+ ## 12.6.0 2025-09-22
21
+
22
+ ### Compatible changes
23
+ * `geordi dump`: Allow to forward the compression option to the underlying `dumple` command, e.g. `geordi dump --compress=zstd:3` (for PostgreSQL) or `geordi dump --compress` (for MySQL).
24
+ * `dumple`: Allow to specify a compression algorithm for PostgreSQL, e.g. `dumple --compress=zstd:3`. The already supported compression for MySQL `dumple --compress` is kept untouched.
25
+
26
+
13
27
  ## 12.5.0 2025-09-09
14
28
 
15
29
  ### Compatible changes
@@ -109,7 +123,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
109
123
  # 9.6.1 2023-09-22
110
124
 
111
125
  ### Compatible changes
112
- * `chromedriver-update` command: Retrieve chromedriver from new location
126
+ * `chromedriver-update` command: Retrieve chromedriver from new location
113
127
 
114
128
 
115
129
  # 9.6.0 2023-07-24
@@ -121,7 +135,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
121
135
  # 9.5.1 2023-04-26
122
136
 
123
137
  ### Compatible changes
124
- * `cucumber` command: Support the passing of options without "="
138
+ * `cucumber` command: Support the passing of options without "="
125
139
 
126
140
 
127
141
  # 9.5.0 2023-03-22
@@ -217,7 +231,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
217
231
  * Removed VNC test browser support for integration tests – Headless Chrome has
218
232
  matured and is almost a drop-in replacement. Also, key binding issues have
219
233
  increased with VNC and recent Linux.
220
- * Please use a headless Chrome setup <https://makandracards.com/makandra/492109-capybara-running-tests-with-headless-chrome>.
234
+ * Please use a headless Chrome setup <https://makandracards.com/makandra/492109-capybara-running-tests-with-headless-chrome>.
221
235
  * You might also want to get rid of your local VNC server `sudo apt remove tightvncserver`.
222
236
  * Removed support for serial execution of scenarios tagged with @solo. Serial
223
237
  execution is not needed with Headless Chrome, as Headless instances cannot
@@ -286,7 +300,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
286
300
  ## 4.2.0 2020-10-02
287
301
 
288
302
  ### Compatible changes
289
- * Add `auto_update_chromedriver` as global setting option to automatically update chromedriver before cucumber
303
+ * Add `auto_update_chromedriver` as global setting option to automatically update chromedriver before cucumber
290
304
  tests, if Chrome and chromedriver versions don't match.
291
305
  * Dump command: Add support for multiple databases (#103 by @kajatiger)
292
306
  * Add Ruby 2.7 to list of supported Ruby versions
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- geordi (12.5.0)
4
+ geordi (12.6.1)
5
5
  highline
6
6
  thor (~> 1)
7
7
 
data/README.md CHANGED
@@ -65,8 +65,8 @@ Example: `geordi chromedriver_update`
65
65
  This command will find and install the matching chromedriver for the currently
66
66
  installed Chrome.
67
67
 
68
- Setting `auto_update_chromedriver` to `true` in your global Geordi config file
69
- (`~/.config/geordi/global.yml`), will automatically update chromedriver before
68
+ Setting `auto_update_chromedriver` to `true` in your global Geordi config file
69
+ (`~/.config/geordi/global.yml`), will automatically update chromedriver before
70
70
  cucumber tests if a newer chromedriver version is available.
71
71
 
72
72
 
@@ -98,8 +98,8 @@ servers. When passed a number, directly connects to the selected server.
98
98
  IRB flags can be given as `irb_flags: '...'` in the global or local Geordi config file
99
99
  (`~/.config/geordi/global.yml` / `./.geordi.yml`). If you define irb_flags in both files, the local config file will be
100
100
  used. For IRB >=1.2 in combination with Ruby <3 geordi automatically sets the `--nomultiline` flag, to prevent slow
101
- pasting. You can override this behavior by setting `--multiline` in the global config file or by defining `irb_flags`
102
- in the local config file. The latter will always turn off the automatic behavior, even if you don't set any values for
101
+ pasting. You can override this behavior by setting `--multiline` in the global config file or by defining `irb_flags`
102
+ in the local config file. The latter will always turn off the automatic behavior, even if you don't set any values for
103
103
  the irb_flags key.
104
104
 
105
105
  **Options**
@@ -170,11 +170,9 @@ Finds available Capistrano stages by their prefix, e.g. `geordi deploy p` will
170
170
  deploy production, `geordi deploy mak` will deploy a `makandra` stage if there
171
171
  is a file config/deploy/makandra.rb.
172
172
 
173
- If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state. Disable with "skip".
173
+ If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state. Disable this with "skip".
174
174
 
175
- When your project is running Capistrano 3, deployment will use `cap deploy`
176
- instead of `cap deploy:migrations`. You can force using `deploy` by passing the
177
- -M option: `geordi deploy -M staging`.
175
+ If your project is running Capistrano 2, Geordi will use `cap deploy:migrations` by default. Skip migrations by passing the -M option: `geordi deploy -M staging`.
178
176
 
179
177
  **Options**
180
178
  - `-M, --no-migrations`: Run cap deploy instead of cap deploy:migrations
@@ -191,8 +189,8 @@ and offer to delete them. Excluded are databases that are whitelisted. This come
191
189
  in handy when you're keeping your currently active projects in the whitelist files
192
190
  and perform regular housekeeping with Geordi.
193
191
 
194
- Per default, Geordi will try to connect to the databases as a local user without
195
- password authorization.
192
+ Per default, Geordi will try to connect to the databases as a local user without
193
+ password authorization.
196
194
 
197
195
  Geordi will ask for confirmation before actually dropping databases and will
198
196
  offer to edit the whitelist instead.
@@ -234,6 +232,7 @@ not match, please issue separate commands for dumping (`dump -d`) and sourcing
234
232
  **Options**
235
233
  - `-l, --load=[DUMP_FILE]`: Load a dump
236
234
  - `-d, --database=NAME`: Target database, if there are multiple databases
235
+ - `-c, --compress=[ALGORITHM]`: Compress the dump file (default for PSQL)
237
236
 
238
237
 
239
238
  ### `geordi help [COMMAND]`
@@ -341,7 +340,7 @@ Run all employed tests.
341
340
  When running `geordi tests` without any arguments, all unit tests, rspec specs
342
341
  and cucumber features will be run.
343
342
 
344
- When passing file paths or directories as arguments, Geordi will forward them to `rspec` and `cucumber`.
343
+ When passing file paths or directories as arguments, Geordi will forward them to `rspec` and `cucumber`.
345
344
  All rspec specs and cucumber features matching the given paths will be run.
346
345
 
347
346
 
@@ -389,7 +388,9 @@ Stores a timestamped database dump for the given Rails environment in `~/dumps`:
389
388
 
390
389
  **Options**
391
390
  - `-i`: Print disk usage of `~/dumps`
392
- - `--compress`: After dumping, run gzip to compress the dump in place
391
+ - `--fail-gently`: On error, do not crash but print a warning and exit(0)
392
+ - `--for-download`: Dump to `~/dumps/dump_for_download.dump`
393
+ - `--compress`: Compress the dump (default for PostgreSQL) and optionally set the compression algorithm (only available for PostgreSQL)
393
394
 
394
395
 
395
396
  Contributing
data/Rakefile CHANGED
@@ -18,9 +18,9 @@ task :rspec do
18
18
  end
19
19
 
20
20
  task :check do
21
- Geordi::Interaction.prompt('Are all specs & features green?', 'y', /y|yes/) || Geordi::Interaction.fail('Please run all tests with `rake`.')
22
- Geordi::Interaction.prompt('Have you updated the README?', 'y', /y|yes/) || Geordi::Interaction.fail('Please update the README with `rake readme`.')
23
- Geordi::Interaction.prompt('Have you updated the CHANGELOG', 'y', /y|yes/) || Geordi::Interaction.fail('Please update the CHANGELOG with the latest changes.')
21
+ Geordi::Interaction.confirm_or_cancel('Are all specs & features green?', 'Please run all tests with `rake`.', default: 'n')
22
+ Geordi::Interaction.confirm_or_cancel('Have you updated the README?', 'Please update the README with `rake readme`.', default: 'n')
23
+ Geordi::Interaction.confirm_or_cancel('Have you updated the CHANGELOG?', 'Please update the CHANGELOG with the latest changes.', default: 'n')
24
24
  end
25
25
 
26
26
  task :readme do
data/exe/dumple CHANGED
@@ -50,7 +50,7 @@ def cd_to_project_root(fail_gently)
50
50
  end
51
51
  end
52
52
 
53
- def dump_command(dump_file, config)
53
+ def dump_command(dump_file, config, compress)
54
54
  host = config['host']
55
55
  port = config['port']
56
56
 
@@ -79,6 +79,7 @@ def dump_command(dump_file, config)
79
79
  command << " pg_dump #{config['database']}"
80
80
  command << " --clean"
81
81
  command << " --format=custom"
82
+ command << " --compress=#{compress}" if compress.is_a?(String)
82
83
  command << " --file=#{dump_file}"
83
84
  command << " --username=\"#{config['username']}\""
84
85
  command << " --host=#{host}" if host
@@ -124,7 +125,7 @@ def prepare_dump_path(config)
124
125
  run "chmod 700 #{DUMPS_DIR}"
125
126
  end
126
127
 
127
- if ARGV.include? '--for_download'
128
+ if ARGV.include?('--for_download') || ARGV.include?('--for-download')
128
129
  "#{DUMPS_DIR}/dump_for_download.dump"
129
130
  else
130
131
  "#{DUMPS_DIR}/#{config['database']}_#{Time.now.strftime("%Y%m%d_%H%M%S")}.dump"
@@ -133,8 +134,14 @@ end
133
134
 
134
135
  begin
135
136
  fail_gently = ARGV.include?("--fail-gently")
136
- compress = ARGV.include?("--compress")
137
- environment, database = ARGV.reject { |arg| arg[0].chr == '-' }
137
+ compress = ARGV.find do |argument|
138
+ if argument == '--compress'
139
+ break true
140
+ elsif argument.start_with?('--compress=')
141
+ break argument.split('=').last
142
+ end
143
+ end
144
+ environment, database = ARGV.reject { |argument| argument.start_with?('-') }
138
145
 
139
146
  cd_to_project_root(fail_gently)
140
147
  config = find_database_config(DB_CONFIG_PATH, environment, database)
@@ -142,12 +149,17 @@ begin
142
149
 
143
150
  # Dump!
144
151
  given_database = database ? %(#{database} ) : ""
145
- command = dump_command(dump_path, config)
152
+ command = dump_command(dump_path, config, compress)
146
153
  puts "> Dumping #{given_database}database for \"#{environment}\" environment ..."
147
154
  run command or raise "x Creating the dump failed."
148
155
  run "chmod 600 #{dump_path}"
149
156
 
150
- if compress
157
+ if config['adapter'] == 'mysql' && compress.is_a?(String)
158
+ puts "> Cannot compress a MySQL dump with #{compress}, falling back to gzip."
159
+ end
160
+
161
+ # For PostgreSQL, #dump_command will do the compression. MySQL needs manual compression.
162
+ if config['adapter'] == 'mysql' && compress
151
163
  puts "> Compressing the dump ..."
152
164
  # gzip compresses in place
153
165
  compress_success = run "gzip #{dump_path}"
@@ -8,7 +8,7 @@ def capistrano(*args)
8
8
 
9
9
  Interaction.note 'Found the following deploy targets:'
10
10
  puts targets
11
- Interaction.prompt('Continue?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
11
+ Interaction.confirm_or_cancel(default: 'n')
12
12
 
13
13
  targets << nil if targets.empty? # default target
14
14
  targets.each do |stage|
@@ -5,8 +5,8 @@ Example: `geordi chromedriver_update`
5
5
  This command will find and install the matching chromedriver for the currently
6
6
  installed Chrome.
7
7
 
8
- Setting `auto_update_chromedriver` to `true` in your global Geordi config file
9
- (`~/.config/geordi/global.yml`), will automatically update chromedriver before
8
+ Setting `auto_update_chromedriver` to `true` in your global Geordi config file
9
+ (`~/.config/geordi/global.yml`), will automatically update chromedriver before
10
10
  cucumber tests if a newer chromedriver version is available.
11
11
  LONGDESC
12
12
 
@@ -10,8 +10,8 @@ servers. When passed a number, directly connects to the selected server.
10
10
  IRB flags can be given as `irb_flags: '...'` in the global or local Geordi config file
11
11
  (`~/.config/geordi/global.yml` / `./.geordi.yml`). If you define irb_flags in both files, the local config file will be
12
12
  used. For IRB >=1.2 in combination with Ruby <3 geordi automatically sets the `--nomultiline` flag, to prevent slow
13
- pasting. You can override this behavior by setting `--multiline` in the global config file or by defining `irb_flags`
14
- in the local config file. The latter will always turn off the automatic behavior, even if you don't set any values for
13
+ pasting. You can override this behavior by setting `--multiline` in the global config file or by defining `irb_flags`
14
+ in the local config file. The latter will always turn off the automatic behavior, even if you don't set any values for
15
15
  the irb_flags key.
16
16
 
17
17
  LONGDESC
@@ -33,7 +33,7 @@ def delete_dumps(*locations)
33
33
  Interaction.warn 'No dump files found.'
34
34
  else
35
35
  puts deletable_dumps
36
- Interaction.prompt('Delete these files?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
36
+ Interaction.confirm_or_cancel('Delete these files?', default: 'n')
37
37
 
38
38
  deletable_dumps.each &File.method(:delete)
39
39
  Interaction.success 'Done.'
@@ -28,11 +28,9 @@ Finds available Capistrano stages by their prefix, e.g. `geordi deploy p` will
28
28
  deploy production, `geordi deploy mak` will deploy a `makandra` stage if there
29
29
  is a file config/deploy/makandra.rb.
30
30
 
31
- If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state. Disable with "skip".
31
+ If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state. Disable this with "skip".
32
32
 
33
- When your project is running Capistrano 3, deployment will use `cap deploy`
34
- instead of `cap deploy:migrations`. You can force using `deploy` by passing the
35
- -M option: `geordi deploy -M staging`.
33
+ If your project is running Capistrano 2, Geordi will use `cap deploy:migrations` by default. Skip migrations by passing the -M option: `geordi deploy -M staging`.
36
34
  LONGDESC
37
35
 
38
36
  option :no_migrations, aliases: '-M', type: :boolean,
@@ -55,7 +53,7 @@ def deploy(target_stage = nil)
55
53
  target_stage || Interaction.warn('Given deployment stage not found')
56
54
  end
57
55
 
58
- # Ask for required information
56
+ # Retrieve required information ##############################################
59
57
  target_stage ||= Interaction.prompt 'Deployment stage:', branch_stage_map.fetch(Git.current_branch, 'staging')
60
58
  capistrano_config = CapistranoConfig.new(target_stage)
61
59
 
@@ -82,46 +80,50 @@ def deploy(target_stage = nil)
82
80
  config_state = 'skip' if config_state.empty?
83
81
  target_state = Interaction.prompt("Move deployed Linear issues to state:", config_state)
84
82
  target_state = '' if target_state.empty? || target_state == 'skip'
85
- settings.persist_linear_state_after_deploy(target_stage, target_state)
86
83
  end
87
84
 
88
85
  merge_needed = (source_branch != target_branch)
89
86
  push_needed = merge_needed || `git cherry -v | wc -l`.strip.to_i > 0
87
+ linear_issue_ids = []
88
+ if push_needed
89
+ commit_messages = Git.commits_between(source_branch, target_branch)
90
+ linear_issue_ids = LinearClient.extract_issue_ids(commit_messages)
91
+ end
92
+ move_issues = !linear_issue_ids.empty? && target_state && !target_state.empty?
90
93
 
91
- Interaction.announce "Checking whether your #{source_branch} branch is ready" ############
94
+ # Checks #####################################################################
95
+ Interaction.note "Checking whether your #{source_branch} branch is ready"
92
96
  Util.run!("git checkout #{source_branch}")
93
97
  if (`git status -s | wc -l`.strip != '0') && !Util.testing?
94
98
  Interaction.warn "Your #{source_branch} branch holds uncommitted changes."
95
99
  Interaction.prompt('Continue anyway?', 'n', /y|yes/) || raise('Cancelled.')
96
100
  else
97
- Interaction.note 'All good.'
101
+ puts 'All good.'
98
102
  end
99
103
 
100
104
  if merge_needed
101
- Interaction.announce "Checking what's in your #{target_branch} branch right now" #######
105
+ Interaction.note "Checking what's in your #{target_branch} branch right now"
102
106
  Util.run!("git checkout #{target_branch} && git pull")
103
107
  end
104
108
 
105
- Interaction.announce 'You are about to:' #################################################
109
+ # Confirm ####################################################################
110
+ Interaction.announce 'Planned actions'
106
111
  Interaction.note "Merge branch #{source_branch} into #{target_branch}" if merge_needed
107
- linear_issue_ids = []
108
112
  if push_needed
109
113
  Interaction.note 'Push these commits:'
110
114
  Util.run!("git --no-pager log origin/#{target_branch}..#{source_branch} --oneline")
111
-
112
- commit_messages = Git.commits_between(source_branch, target_branch)
113
- linear_issue_ids = linear_client.extract_issue_ids(commit_messages)
114
115
  end
115
116
  Interaction.note "Deploy to #{target_stage}"
116
117
  Interaction.note "From current branch #{source_branch}" if options.current_branch
117
118
 
118
- if !linear_issue_ids.empty? && target_state && !target_state.empty?
119
+ if move_issues
119
120
  relevant_commits = linear_client.filter_by_issue_ids(commit_messages, linear_issue_ids)
120
121
  Interaction.note("Move these Linear issues to state \"#{target_state}\":")
121
122
  puts relevant_commits.join("\n")
122
123
  end
123
124
 
124
- if Interaction.prompt('Go ahead with the deployment?', 'n', /y|yes/)
125
+ # Execute ####################################################################
126
+ if Interaction.prompt('Execute this now?', 'y', /y|yes/)
125
127
  puts
126
128
  git_call = []
127
129
  git_call << "git merge #{source_branch}" if merge_needed
@@ -140,11 +142,12 @@ def deploy(target_stage = nil)
140
142
 
141
143
  Util.run!(capistrano_call, show_cmd: true)
142
144
 
143
- if !linear_issue_ids.empty? && target_state && !target_state.empty?
145
+ if move_issues
144
146
  linear_client.move_issues_to_state(linear_issue_ids, target_state)
147
+ settings.persist_linear_state_after_deploy(target_stage, target_state)
145
148
  end
146
149
 
147
- Interaction.success 'Deployment complete.'
150
+ Interaction.success "Successfully deployed to #{target_stage}."
148
151
 
149
152
  Hint.did_you_know [
150
153
  :capistrano,
@@ -152,6 +155,6 @@ def deploy(target_stage = nil)
152
155
  ]
153
156
  else
154
157
  Util.run!("git checkout #{source_branch}")
155
- Interaction.fail 'Deployment cancelled.'
158
+ Interaction.fail 'Cancelled.'
156
159
  end
157
160
  end
@@ -7,8 +7,8 @@ and offer to delete them. Excluded are databases that are whitelisted. This come
7
7
  in handy when you're keeping your currently active projects in the whitelist files
8
8
  and perform regular housekeeping with Geordi.
9
9
 
10
- Per default, Geordi will try to connect to the databases as a local user without
11
- password authorization.
10
+ Per default, Geordi will try to connect to the databases as a local user without
11
+ password authorization.
12
12
 
13
13
  Geordi will ask for confirmation before actually dropping databases and will
14
14
  offer to edit the whitelist instead.
@@ -26,11 +26,11 @@ DESC
26
26
 
27
27
  option :load, aliases: '-l', type: :string, desc: 'Load a dump', banner: '[DUMP_FILE]'
28
28
  option :database, aliases: '-d', type: :string, desc: 'Target database, if there are multiple databases', banner: 'NAME'
29
+ option :compress, aliases: '-c', type: :string, desc: 'Compress the dump file (default for PSQL)', banner: '[ALGORITHM]'
29
30
 
30
31
  def dump(target = nil, *_args)
31
32
  require 'geordi/dump_loader'
32
33
  require 'geordi/remote'
33
- database = options[:database] ? "#{options[:database]} " : ''
34
34
 
35
35
  if target.nil? # Local …
36
36
  if options.load # … dump loading
@@ -46,14 +46,17 @@ def dump(target = nil, *_args)
46
46
 
47
47
  else # … dump creation
48
48
  Interaction.announce 'Dumping the development database'
49
- Util.run!("dumple development #{database}")
49
+ Util.run!(Util.dumple_command('development', options))
50
+
51
+ database = "#{options[:database]} " if options[:database]
50
52
  Interaction.success "Successfully dumped the #{database}development database."
51
53
  end
52
54
 
53
55
  else # Remote dumping …
54
- database_label = options[:database] ? " (#{database}database)" : ""
56
+ database_label = target.dup
57
+ database_label << " (#{options[:database]} database)" if options[:database]
55
58
 
56
- Interaction.announce "Dumping the database of #{target}#{database_label}"
59
+ Interaction.announce "Dumping the database of #{database_label}"
57
60
  dump_path = Geordi::Remote.new(target).dump(options)
58
61
 
59
62
  if options.load # … and dump loading
@@ -65,7 +68,7 @@ def dump(target = nil, *_args)
65
68
  Util.run! "rm #{dump_path}"
66
69
  Interaction.note "Dump file removed"
67
70
 
68
- Interaction.success "Your #{loader.config['database']} database has now the data of #{target}#{database_label}."
71
+ Interaction.success "Your #{loader.config['database']} database has now the data of #{database_label}."
69
72
  end
70
73
  end
71
74
 
@@ -18,7 +18,7 @@ def security_update(step = 'prepare')
18
18
  Interaction.announce 'Preparing for security update'
19
19
  Interaction.warn 'Please read https://makandracards.com/makandra/1587 before applying security updates!'
20
20
  Interaction.note 'About to checkout production and pull.'
21
- Interaction.prompt('Continue?', 'y', /y|yes/) || Interaction.fail('Cancelled.')
21
+ Interaction.confirm_or_cancel
22
22
 
23
23
  Util.run!('git checkout production', show_cmd: true)
24
24
  Util.run!('git pull', show_cmd: true)
@@ -42,7 +42,7 @@ def security_update(step = 'prepare')
42
42
  Interaction.prompt('Have you successfully run all tests?', 'n', /y|yes/) || Interaction.fail('Please run tests first.')
43
43
 
44
44
  Interaction.note "About to: push production, checkout & pull #{master}, merge production, push #{master}."
45
- Interaction.prompt('Continue?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
45
+ Interaction.confirm_or_cancel
46
46
 
47
47
  Util.run!('git push', show_cmd: true)
48
48
  Util.run!("git checkout #{master}", show_cmd: true)
@@ -58,12 +58,12 @@ def security_update(step = 'prepare')
58
58
 
59
59
  if all_deploy_targets.include?('staging')
60
60
  Interaction.note 'There is a staging environment.'
61
- Interaction.prompt('Deploy staging now?', 'y', /y|yes/) || Interaction.fail('Cancelled.')
61
+ Interaction.confirm_or_cancel('Deploy staging now?')
62
62
 
63
63
  Interaction.announce 'Deploy staging'
64
64
  Util.run! "bundle exec cap staging #{deploy}", show_cmd: true
65
65
 
66
- Interaction.prompt('Is the deployment log okay and the application is still running on staging?', 'y', /y|yes/) || Interaction.fail('Please fix the deployment issues on staging before you continue.')
66
+ Interaction.confirm_or_cancel('Is the deployment log okay and is the application still running on staging?', 'Please fix the deployment issues on staging before you continue.', default: 'n')
67
67
  else
68
68
  Interaction.note 'There is no staging environment.'
69
69
  end
@@ -77,14 +77,14 @@ def security_update(step = 'prepare')
77
77
  Interaction.note 'Found the following other stages:'
78
78
  puts deploy_targets_without_staging
79
79
  puts
80
- Interaction.prompt('Deploy other stages now?', 'y', /y|yes/) || Interaction.fail('Cancelled.')
80
+ Interaction.confirm_or_cancel('Deploy other stages now?')
81
81
 
82
82
  deploy_targets_without_staging.each do |target|
83
83
  Interaction.announce "Deploy #{target}"
84
84
  Util.run!("bundle exec cap #{target} #{deploy}", show_cmd: true)
85
85
  end
86
86
 
87
- Interaction.prompt('Is the application still running on all other stages and the logs are okay?', 'y', /y|yes/) || Interaction.fail('Please fix the application immediately!')
87
+ Interaction.confirm_or_cancel('Are *all* the deployment logs okay and is the application still running on *all* other stages?', 'Please fix the application immediately!', default: 'n')
88
88
  end
89
89
 
90
90
  Interaction.success 'Successfully pushed and deployed security update'
@@ -3,7 +3,7 @@ long_desc <<-LONGDESC
3
3
  When running `geordi tests` without any arguments, all unit tests, rspec specs
4
4
  and cucumber features will be run.
5
5
 
6
- When passing file paths or directories as arguments, Geordi will forward them to `rspec` and `cucumber`.
6
+ When passing file paths or directories as arguments, Geordi will forward them to `rspec` and `cucumber`.
7
7
  All rspec specs and cucumber features matching the given paths will be run.
8
8
  LONGDESC
9
9
 
@@ -230,8 +230,8 @@ module Geordi
230
230
  until %w[y n].include? proceed
231
231
  deletable_dbs = filter_allowlisted(dbtype, database_list)
232
232
  if deletable_dbs.empty?
233
- Interaction.note "No #{dbtype} databases found that were not allowlisted."
234
- if Interaction.prompt('Edit the allowlist? [y]es or [n]o') == 'y'
233
+ Interaction.note "No deletable #{dbtype} databases found."
234
+ if Interaction.prompt('Edit the allowlist?', 'y', /y|yes/)
235
235
  proceed = 'e'
236
236
  else
237
237
  return []
@@ -245,6 +245,7 @@ module Geordi
245
245
  Interaction.note "These #{dbtype} databases are not allowlisted and can be deleted."
246
246
  proceed = Interaction.prompt('Proceed? [y]es, [n]o or [e]dit allowlist')
247
247
  end
248
+
248
249
  case proceed
249
250
  when 'e'
250
251
  proceed = '' # reset user selection
@@ -28,7 +28,7 @@ module Geordi
28
28
  # Also see Util.run!
29
29
  def note_cmd(text)
30
30
  message = "> #{text}"
31
- puts "\e[35m#{message}\e[0m" # pink
31
+ puts "\e[36m#{message}\e[0m" # cyan
32
32
  end
33
33
 
34
34
  # Exit execution with status code 1 and give a short note what happened,
@@ -52,7 +52,7 @@ module Geordi
52
52
  message = "#{text} "
53
53
  message << "[#{default}] " if default
54
54
 
55
- print "\e[36m#{message}\e[0m" # cyan
55
+ print "\e[35m#{message}\e[0m" # pink
56
56
  input = $stdin.gets.strip
57
57
  input = default if input.empty? && default
58
58
 
@@ -61,5 +61,9 @@ module Geordi
61
61
  fail 'Cancelled.'
62
62
  end
63
63
 
64
+ def confirm_or_cancel(message = 'Continue?', cancel_message = 'Cancelled.', default: 'y')
65
+ prompt(message, default, /y|yes/) or fail(cancel_message)
66
+ end
67
+
64
68
  end
65
69
  end
@@ -11,6 +11,20 @@ module Geordi
11
11
 
12
12
  API_ENDPOINT = 'https://api.linear.app/graphql'.freeze
13
13
 
14
+ def self.extract_issue_ids(strings)
15
+ found_ids = []
16
+
17
+ regex = /^\[[A-Z]+\d*-\d+\]/
18
+
19
+ strings&.each do |string|
20
+ string&.scan(regex) do |match|
21
+ found_ids << match
22
+ end
23
+ end
24
+
25
+ found_ids.map { |id| id.delete('[]') } # [W-365] => W-365
26
+ end
27
+
14
28
  def initialize
15
29
  self.highline = HighLine.new
16
30
  self.settings = Settings.new
@@ -87,20 +101,6 @@ module Geordi
87
101
  end
88
102
  end
89
103
 
90
- def extract_issue_ids(commit_messages)
91
- found_ids = []
92
-
93
- regex = /^\[[A-Z]+\d*-\d+\]/
94
-
95
- commit_messages&.each do |line|
96
- line&.scan(regex) do |match|
97
- found_ids << match
98
- end
99
- end
100
-
101
- found_ids.map { |id| id.delete('[]') } # [W-365] => W-365
102
- end
103
-
104
104
  def filter_by_issue_ids(list_of_strings, issue_ids)
105
105
  list_of_strings.select do |message|
106
106
  issue_ids.any? { |id| message.start_with?("[#{id}]") }
data/lib/geordi/remote.rb CHANGED
@@ -33,11 +33,9 @@ module Geordi
33
33
  end
34
34
 
35
35
  def dump(options = {})
36
- database = options[:database] ? " #{options[:database]}" : ''
37
36
  # Generate dump on the server
38
- shell options.merge({
39
- remote_command: "dumple #{@config.env}#{database} --for_download",
40
- })
37
+ dumple = Util.dumple_command(@config.env, options.merge(for_download: true))
38
+ shell(options.merge(remote_command: dumple))
41
39
 
42
40
  destination_directory = File.join(@config.root, 'tmp')
43
41
  FileUtils.mkdir_p destination_directory
@@ -48,6 +46,7 @@ module Geordi
48
46
  server = @config.primary_server
49
47
  Util.run!("scp -C #{@config.user(server)}@#{server}:#{REMOTE_DUMP_PATH} #{destination_path}")
50
48
 
49
+ database = " #{options[:database]}" if options[:database]
51
50
  Interaction.success "Dumped the#{database} #{@stage} database to #{relative_destination}."
52
51
 
53
52
  destination_path
data/lib/geordi/util.rb CHANGED
@@ -21,7 +21,7 @@ module Geordi
21
21
 
22
22
  # install missing gem
23
23
  Interaction.warn 'Probably missing gem: ' + gem_name
24
- Interaction.prompt('Install it now?', 'y', /y|yes/) || Interaction.fail('Missing Gems.')
24
+ Interaction.confirm_or_cancel('Install it now?', 'Missing Gems.')
25
25
  Util.run!(install_command, show_cmd: true)
26
26
 
27
27
  # retry
@@ -50,13 +50,12 @@ module Geordi
50
50
  show_command = [command]
51
51
  end
52
52
 
53
- if show_cmd
54
- # Join with spaces for better readability and copy-pasting
53
+ if show_cmd || confirm
55
54
  Interaction.note_cmd show_command.join(' ')
56
55
  end
57
56
 
58
57
  if confirm
59
- Interaction.prompt('Run this now?', 'n', /y|yes/) or Interaction.fail('Cancelled.')
58
+ Interaction.confirm_or_cancel('Run this now?')
60
59
  end
61
60
 
62
61
  if testing?
@@ -119,6 +118,21 @@ module Geordi
119
118
  end
120
119
  end
121
120
 
121
+ def dumple_command(environment, options)
122
+ compress = if options[:compress] == 'compress'
123
+ '--compress'
124
+ elsif options[:compress]
125
+ "--compress=#{options[:compress]}"
126
+ end
127
+
128
+ cmd = ['dumple']
129
+ cmd << environment
130
+ cmd << options[:database]
131
+ cmd << compress
132
+ cmd << '--for_download' if options[:for_download]
133
+
134
+ cmd.compact.join(' ')
135
+ end
122
136
 
123
137
  def deploy_targets
124
138
  Dir['config/deploy/*'].map do |f|
@@ -205,6 +219,7 @@ module Geordi
205
219
  def rspec_path?(path)
206
220
  %r{(^|\/)spec|_spec\.rb($|:)}.match?(path)
207
221
  end
222
+
208
223
  end
209
224
  end
210
225
  end
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '12.5.0'.freeze
2
+ VERSION = '12.6.1'.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: 12.5.0
4
+ version: 12.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-22 00:00:00.000000000 Z
11
+ date: 2025-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -124,7 +124,7 @@ metadata:
124
124
  bug_tracker_uri: https://github.com/makandra/geordi/issues
125
125
  changelog_uri: https://github.com/makandra/geordi/blob/master/CHANGELOG.md
126
126
  rubygems_mfa_required: 'true'
127
- post_install_message:
127
+ post_install_message:
128
128
  rdoc_options: []
129
129
  require_paths:
130
130
  - lib
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
140
  version: '0'
141
141
  requirements: []
142
142
  rubygems_version: 3.1.6
143
- signing_key:
143
+ signing_key:
144
144
  specification_version: 4
145
145
  summary: Collection of command line tools we use in our daily work with Ruby, Rails
146
146
  and Linux at makandra.