kettle-dev 2.4.5 → 2.5.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.
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ module Kettle
6
+ module Dev
7
+ class Error < StandardError; end unless const_defined?(:Error, false)
8
+
9
+ module ReleaseSecrets
10
+ class Provider
11
+ def gem_signing_passphrase
12
+ nil
13
+ end
14
+
15
+ def rubygems_otp
16
+ nil
17
+ end
18
+ end
19
+
20
+ class OnePassword < Provider
21
+ PROVIDER_NAMES = %w[1password onepassword op].freeze
22
+ DEFAULTS = {
23
+ "item" => "Rubygems",
24
+ "gem_signing_passphrase_field" => "GEM-SIGN-PASSPHRASE",
25
+ "rubygems_otp_field" => "one-time password"
26
+ }.freeze
27
+
28
+ def self.configured?(name)
29
+ PROVIDER_NAMES.include?(name.to_s.downcase)
30
+ end
31
+
32
+ def initialize(config)
33
+ @config = DEFAULTS.merge(config || {})
34
+ @gem_signing_passphrase = nil
35
+ @gem_signing_passphrase_loaded = false
36
+ end
37
+
38
+ def gem_signing_passphrase
39
+ return @gem_signing_passphrase if @gem_signing_passphrase_loaded
40
+
41
+ return cached_gem_signing_passphrase if cached_gem_signing_passphrase?
42
+
43
+ reference = string_config("gem_signing_passphrase_reference")
44
+ value = if reference.empty?
45
+ item_field("gem_signing_passphrase_field")
46
+ else
47
+ read_reference(reference)
48
+ end
49
+
50
+ @gem_signing_passphrase = value
51
+ @gem_signing_passphrase_loaded = true
52
+ value
53
+ end
54
+
55
+ def rubygems_otp
56
+ reference = string_config("rubygems_otp_reference")
57
+ return read_reference(reference) unless reference.empty?
58
+
59
+ item = required_config("item")
60
+ argv = ["op", "item", "get", item, "--otp"]
61
+ account = string_config("account")
62
+ argv.concat(["--account", account]) unless account.empty?
63
+ run_op(argv, purpose: "RubyGems OTP")
64
+ end
65
+
66
+ private
67
+
68
+ attr_reader :config
69
+
70
+ def cached_gem_signing_passphrase?
71
+ %w[cached family kettle-family].include?(string_config("gem_signing_passphrase_source").downcase)
72
+ end
73
+
74
+ def cached_gem_signing_passphrase
75
+ value = ENV.fetch("KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE", "").to_s
76
+ raise Kettle::Dev::Error, "cached gem signing passphrase was requested but KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE is empty" if value.empty?
77
+
78
+ value
79
+ end
80
+
81
+ def item_field(field_key)
82
+ item = required_config("item")
83
+ field = required_config(field_key)
84
+ argv = ["op", "item", "get", item, "--fields", "label=#{field}", "--reveal"]
85
+ account = string_config("account")
86
+ argv.concat(["--account", account]) unless account.empty?
87
+ run_op(argv, purpose: field_key.tr("_", " "))
88
+ end
89
+
90
+ def read_reference(reference)
91
+ argv = ["op", "read", reference]
92
+ account = string_config("account")
93
+ argv.concat(["--account", account]) unless account.empty?
94
+ run_op(argv, purpose: "secret reference")
95
+ end
96
+
97
+ def run_op(argv, purpose:)
98
+ stdout, stderr, status = Open3.capture3(*argv)
99
+ return stdout.to_s.strip if status.success? && !stdout.to_s.strip.empty?
100
+
101
+ details = stderr.to_s.strip
102
+ details = "op exited #{status.exitstatus}" if details.empty?
103
+ raise Kettle::Dev::Error, "1Password #{purpose} lookup failed: #{details}"
104
+ rescue Errno::ENOENT
105
+ raise Kettle::Dev::Error, "1Password CLI executable `op` was not found"
106
+ end
107
+
108
+ def required_config(key)
109
+ value = string_config(key)
110
+ raise Kettle::Dev::Error, "1Password release secrets require #{key}" if value.empty?
111
+
112
+ value
113
+ end
114
+
115
+ def string_config(key)
116
+ config.fetch(key, "").to_s
117
+ end
118
+ end
119
+
120
+ class Factory
121
+ ENV_KEYS = {
122
+ "account" => "KETTLE_RELEASE_1PASSWORD_ACCOUNT",
123
+ "item" => "KETTLE_RELEASE_1PASSWORD_ITEM",
124
+ "gem_signing_passphrase_field" => "KETTLE_RELEASE_1PASSWORD_GEM_SIGNING_PASSPHRASE_FIELD",
125
+ "rubygems_otp_field" => "KETTLE_RELEASE_1PASSWORD_RUBYGEMS_OTP_FIELD",
126
+ "gem_signing_passphrase_reference" => "KETTLE_RELEASE_1PASSWORD_GEM_SIGNING_PASSPHRASE_REFERENCE",
127
+ "rubygems_otp_reference" => "KETTLE_RELEASE_1PASSWORD_RUBYGEMS_OTP_REFERENCE",
128
+ "gem_signing_passphrase_source" => "KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE_SOURCE"
129
+ }.freeze
130
+
131
+ def self.build(provider_name: nil, config: nil)
132
+ configured = config || {}
133
+ name = if provider_name.to_s.empty?
134
+ configured.fetch("provider", ENV.fetch("KETTLE_RELEASE_SECRETS_PROVIDER", ""))
135
+ else
136
+ provider_name.to_s
137
+ end
138
+ return Provider.new if name.empty? || name == "interactive"
139
+ return OnePassword.new(env_config.merge(configured)) if OnePassword.configured?(name)
140
+
141
+ raise Kettle::Dev::Error, "unsupported release secrets provider #{name.inspect}"
142
+ end
143
+
144
+ def self.env_config
145
+ ENV_KEYS.each_with_object({}) do |(key, env_key), memo|
146
+ value = ENV.fetch(env_key, "").to_s
147
+ memo[key] = value unless value.empty?
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+
5
+ module Kettle
6
+ module Dev
7
+ class ResetCLI
8
+ def initialize(argv = [], root: Kettle::Dev::CIHelpers.project_root)
9
+ @argv = Array(argv).dup
10
+ @root = root
11
+ @check = false
12
+ end
13
+
14
+ def run!
15
+ args = parse!
16
+ target = args.first.to_s
17
+ raise Error, "kettle-reset requires TARGET" if target.empty?
18
+ raise Error, "unexpected argument(s): #{args.drop(1).join(" ")}" if args.length > 1
19
+
20
+ if check
21
+ validate(target)
22
+ else
23
+ paths = resetter.lockfile_paths_for(target)
24
+ unless resetter.release_lockfiles_target?(target) || paths.any? { |path| resetter.normalization_needed?(path) }
25
+ puts "#{target} is already reset."
26
+ return 0
27
+ end
28
+ resetter.reset(target)
29
+ puts "Reset #{target}."
30
+ end
31
+ 0
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :argv, :root, :check
37
+
38
+ def parse!
39
+ parser.parse!(argv)
40
+ rescue OptionParser::ParseError => error
41
+ raise Error, error.message
42
+ end
43
+
44
+ def parser
45
+ OptionParser.new do |opts|
46
+ opts.banner = "Usage: kettle-reset [--check] TARGET"
47
+ opts.separator "Targets: Gemfile.lock, Appraisal.root.gemfile.lock, release-lockfiles"
48
+ opts.on("--check", "Validate TARGET without changing it") { @check = true }
49
+ opts.on("-h", "--help", "Show this help") do
50
+ puts opts
51
+ exit(0)
52
+ end
53
+ end
54
+ end
55
+
56
+ def validate(target)
57
+ paths = resetter.lockfile_paths_for(target)
58
+ diagnostics = paths.flat_map { |path| resetter.diagnostics(path) }
59
+ raise Error, validation_message(target, diagnostics) unless diagnostics.empty?
60
+
61
+ puts "#{target} is already reset."
62
+ end
63
+
64
+ def validation_message(target, diagnostics)
65
+ <<~MSG
66
+ #{target} is not reset:
67
+ #{diagnostics.map { |diagnostic| " - #{diagnostic}" }.join("\n")}
68
+ MSG
69
+ end
70
+
71
+ def resetter
72
+ @resetter ||= Kettle::Dev::LockfileReset.new(root: root, command_runner: method(:run_cmd!))
73
+ end
74
+
75
+ def run_cmd!(command)
76
+ puts "$ #{command}"
77
+ system(command) || raise(Error, "Command failed: #{command}")
78
+ end
79
+ end
80
+ end
81
+ end
@@ -8,10 +8,10 @@ require "uri"
8
8
 
9
9
  module Kettle
10
10
  module Dev
11
- module GemCoopVersions
11
+ module RubyGemsVersions
12
12
  CACHE_BUST_TTL_SECONDS = 15 * 60
13
- ENV_REFRESH = "KETTLE_GEM_COOP_REFRESH"
14
- ENV_MARKER_PATH = "KETTLE_GEM_COOP_CACHE_BUST_PATH"
13
+ ENV_REFRESH = "KETTLE_RUBYGEMS_REFRESH"
14
+ ENV_MARKER_PATH = "KETTLE_RUBYGEMS_CACHE_BUST_PATH"
15
15
 
16
16
  class << self
17
17
  def fetch(gem_name, version_hint: nil, refresh: false)
@@ -43,7 +43,7 @@ module Kettle
43
43
  FileUtils.mkdir_p(File.dirname(path))
44
44
  File.write(path, JSON.pretty_generate(data) << "\n")
45
45
  rescue => error
46
- warn("[kettle-dev] could not update gem.coop cache-bust marker: #{error.class}: #{error.message}") if Kettle::Dev::DEBUGGING
46
+ warn("[kettle-dev] could not update RubyGems.org cache-bust marker: #{error.class}: #{error.message}") if Kettle::Dev::DEBUGGING
47
47
  end
48
48
 
49
49
  def marker_path
@@ -52,13 +52,13 @@ module Kettle
52
52
 
53
53
  state_home = ENV["XDG_STATE_HOME"]
54
54
  state_home = File.join(Dir.home, ".local", "state") if state_home.to_s.empty?
55
- File.join(state_home, "kettle-dev", "gem-coop-cache-bust.json")
55
+ File.join(state_home, "kettle-dev", "rubygems-cache-bust.json")
56
56
  end
57
57
 
58
58
  private
59
59
 
60
60
  def versions_uri(gem_name, cache_bust:)
61
- uri = URI("https://gem.coop/api/v1/versions/#{gem_name}.json")
61
+ uri = URI("https://rubygems.org/api/v1/versions/#{gem_name}.json")
62
62
  uri.query = "_kettle_cache_bust=#{Time.now.to_i}" if cache_bust
63
63
  uri
64
64
  end
@@ -2,9 +2,12 @@
2
2
 
3
3
  module Kettle
4
4
  module Dev
5
+ # Version namespace for this gem.
5
6
  module Version
6
- VERSION = "2.4.5"
7
+ # Current gem version.
8
+ VERSION = "2.5.0"
7
9
  end
10
+ # Current gem version exposed at the traditional constant location.
8
11
  VERSION = Version::VERSION # Traditional Constant Location
9
12
  end
10
13
  end
data/lib/kettle/dev.rb CHANGED
@@ -34,15 +34,19 @@ module Kettle
34
34
  autoload :CommitMsg, "kettle/dev/commit_msg"
35
35
  autoload :DvcsCLI, "kettle/dev/dvcs_cli"
36
36
  autoload :ExitAdapter, "kettle/dev/exit_adapter"
37
- autoload :GemCoopVersions, "kettle/dev/gem_coop_versions"
37
+ autoload :RubyGemsVersions, "kettle/dev/ruby_gems_versions"
38
38
  autoload :GemSpecReader, "kettle/dev/gem_spec_reader"
39
39
  autoload :GitAdapter, "kettle/dev/git_adapter"
40
40
  autoload :GitCommitFooter, "kettle/dev/git_commit_footer"
41
41
  autoload :GhaShaPinsCLI, "kettle/dev/gha_sha_pins_cli"
42
42
  autoload :InputAdapter, "kettle/dev/input_adapter"
43
+ autoload :InteractiveReleaseCommand, "kettle/dev/interactive_release_command"
44
+ autoload :LockfileReset, "kettle/dev/lockfile_reset"
43
45
  autoload :ReadmeBackers, "kettle/dev/readme_backers"
44
46
  autoload :OpenCollectiveConfig, "kettle/dev/open_collective_config"
45
47
  autoload :ReleaseCLI, "kettle/dev/release_cli"
48
+ autoload :ReleaseSecrets, "kettle/dev/release_secrets"
49
+ autoload :ResetCLI, "kettle/dev/reset_cli"
46
50
  autoload :PreReleaseCLI, "kettle/dev/pre_release_cli"
47
51
  autoload :Version, "kettle/dev/version"
48
52
  autoload :VersionBump, "kettle/dev/version_bump"
@@ -181,6 +185,10 @@ module Kettle
181
185
  defaults.include?(task_name.to_s)
182
186
  end
183
187
 
188
+ def skip_test_tasks?
189
+ ENV_TRUE_RE.match?(ENV.fetch("KETTLE_DEV_SKIP_TESTS", ""))
190
+ end
191
+
184
192
  private
185
193
 
186
194
  ### LINTING TASKS
@@ -204,6 +212,8 @@ module Kettle
204
212
  # Set up kettle-soup-cover
205
213
  # @return [void]
206
214
  def coverage_tasks
215
+ return if skip_test_tasks?
216
+
207
217
  # Lazy loaded because it won't be installed for Ruby < 2.7
208
218
  require "kettle-soup-cover"
209
219
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kettle-dev
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.5
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -207,6 +207,26 @@ dependencies:
207
207
  - - ">="
208
208
  - !ruby/object:Gem::Version
209
209
  version: 1.0.4
210
+ - !ruby/object:Gem::Dependency
211
+ name: anonymous_loader
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - "~>"
215
+ - !ruby/object:Gem::Version
216
+ version: '0.1'
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ version: 0.1.3
220
+ type: :development
221
+ prerelease: false
222
+ version_requirements: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - "~>"
225
+ - !ruby/object:Gem::Version
226
+ version: '0.1'
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: 0.1.3
210
230
  - !ruby/object:Gem::Dependency
211
231
  name: appraisal2
212
232
  requirement: !ruby/object:Gem::Requirement
@@ -236,7 +256,7 @@ dependencies:
236
256
  version: '3.2'
237
257
  - - ">="
238
258
  - !ruby/object:Gem::Version
239
- version: 3.2.1
259
+ version: 3.2.3
240
260
  type: :development
241
261
  prerelease: false
242
262
  version_requirements: !ruby/object:Gem::Requirement
@@ -246,7 +266,7 @@ dependencies:
246
266
  version: '3.2'
247
267
  - - ">="
248
268
  - !ruby/object:Gem::Version
249
- version: 3.2.1
269
+ version: 3.2.3
250
270
  - !ruby/object:Gem::Dependency
251
271
  name: stone_checksums
252
272
  requirement: !ruby/object:Gem::Requirement
@@ -256,7 +276,7 @@ dependencies:
256
276
  version: '1.0'
257
277
  - - ">="
258
278
  - !ruby/object:Gem::Version
259
- version: 1.0.6
279
+ version: 1.0.7
260
280
  type: :development
261
281
  prerelease: false
262
282
  version_requirements: !ruby/object:Gem::Requirement
@@ -266,7 +286,7 @@ dependencies:
266
286
  version: '1.0'
267
287
  - - ">="
268
288
  - !ruby/object:Gem::Version
269
- version: 1.0.6
289
+ version: 1.0.7
270
290
  - !ruby/object:Gem::Dependency
271
291
  name: gitmoji-regex
272
292
  requirement: !ruby/object:Gem::Requirement
@@ -276,7 +296,7 @@ dependencies:
276
296
  version: '2.0'
277
297
  - - ">="
278
298
  - !ruby/object:Gem::Version
279
- version: 2.0.5
299
+ version: 2.0.6
280
300
  type: :development
281
301
  prerelease: false
282
302
  version_requirements: !ruby/object:Gem::Requirement
@@ -286,7 +306,7 @@ dependencies:
286
306
  version: '2.0'
287
307
  - - ">="
288
308
  - !ruby/object:Gem::Version
289
- version: 2.0.5
309
+ version: 2.0.6
290
310
  description: "\U0001F372 Kettle::Dev is a meta tool from kettle-dev to streamline
291
311
  development and testing. Acts as a shim dependency, pulling in many other dependencies,
292
312
  to give you OOTB productivity with a RubyGem, or Ruby app project. Configures a
@@ -307,6 +327,7 @@ executables:
307
327
  - kettle-pre-release
308
328
  - kettle-readme-backers
309
329
  - kettle-release
330
+ - kettle-reset
310
331
  extensions: []
311
332
  extra_rdoc_files: []
312
333
  files:
@@ -325,6 +346,7 @@ files:
325
346
  - exe/kettle-pre-release
326
347
  - exe/kettle-readme-backers
327
348
  - exe/kettle-release
349
+ - exe/kettle-reset
328
350
  - lib/kettle-dev.rb
329
351
  - lib/kettle/dev.rb
330
352
  - lib/kettle/dev/bump_cli.rb
@@ -337,12 +359,13 @@ files:
337
359
  - lib/kettle/dev/dvcs_cli.rb
338
360
  - lib/kettle/dev/executable_version.rb
339
361
  - lib/kettle/dev/exit_adapter.rb
340
- - lib/kettle/dev/gem_coop_versions.rb
341
362
  - lib/kettle/dev/gem_spec_reader.rb
342
363
  - lib/kettle/dev/gha_sha_pins_cli.rb
343
364
  - lib/kettle/dev/git_adapter.rb
344
365
  - lib/kettle/dev/git_commit_footer.rb
345
366
  - lib/kettle/dev/input_adapter.rb
367
+ - lib/kettle/dev/interactive_release_command.rb
368
+ - lib/kettle/dev/lockfile_reset.rb
346
369
  - lib/kettle/dev/open_collective_config.rb
347
370
  - lib/kettle/dev/pre_release_cli.rb
348
371
  - lib/kettle/dev/rakelib/appraisal.rake
@@ -356,6 +379,9 @@ files:
356
379
  - lib/kettle/dev/rakelib/yard.rake
357
380
  - lib/kettle/dev/readme_backers.rb
358
381
  - lib/kettle/dev/release_cli.rb
382
+ - lib/kettle/dev/release_secrets.rb
383
+ - lib/kettle/dev/reset_cli.rb
384
+ - lib/kettle/dev/ruby_gems_versions.rb
359
385
  - lib/kettle/dev/tasks.rb
360
386
  - lib/kettle/dev/tasks/ci_task.rb
361
387
  - lib/kettle/dev/version.rb
@@ -369,10 +395,10 @@ licenses:
369
395
  - AGPL-3.0-only
370
396
  metadata:
371
397
  homepage_uri: https://kettle-dev.galtzo.com
372
- source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.4.5
373
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.4.5/CHANGELOG.md
398
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.5.0
399
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.5.0/CHANGELOG.md
374
400
  bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
375
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.4.5
401
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.5.0
376
402
  funding_uri: https://github.com/sponsors/pboling
377
403
  wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
378
404
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
Binary file