kettle-dev 1.1.32 → 1.1.34

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.
@@ -99,29 +99,30 @@ module Kettle
99
99
 
100
100
  # Funding org (Open Collective handle) detection.
101
101
  # Precedence:
102
- # 1) ENV["FUNDING_ORG"] when set:
103
- # - value "false" (any case) disables funding (nil)
104
- # - otherwise use the value verbatim
105
- # 2) OpenCollectiveConfig.handle(required: false)
102
+ # 1) TemplateHelpers.opencollective_disabled? - when true, funding_org is nil
103
+ # 2) ENV["FUNDING_ORG"] when set and non-empty (unless already disabled above)
104
+ # 3) OpenCollectiveConfig.handle(required: false)
106
105
  # Be lenient: allow nil when not discoverable, with a concise warning.
107
106
  begin
108
- env_funding = ENV["FUNDING_ORG"]
109
- if env_funding && !env_funding.to_s.strip.empty?
110
- funding_org = if env_funding.to_s.strip.casecmp("false").zero?
111
- nil
112
- else
113
- env_funding.to_s
114
- end
107
+ # Check if Open Collective is explicitly disabled via environment variables
108
+ if TemplateHelpers.opencollective_disabled?
109
+ funding_org = nil
115
110
  else
116
- # Preflight: if a YAML exists under the provided root, attempt to read it here so
117
- # unexpected file IO errors surface within this rescue block (see specs).
118
- oc_path = OpenCollectiveConfig.yaml_path(root)
119
- File.read(oc_path) if File.file?(oc_path)
111
+ env_funding = ENV["FUNDING_ORG"]
112
+ if env_funding && !env_funding.to_s.strip.empty?
113
+ # FUNDING_ORG is set and non-empty; use it as-is (already filtered by opencollective_disabled?)
114
+ funding_org = env_funding.to_s
115
+ else
116
+ # Preflight: if a YAML exists under the provided root, attempt to read it here so
117
+ # unexpected file IO errors surface within this rescue block (see specs).
118
+ oc_path = OpenCollectiveConfig.yaml_path(root)
119
+ File.read(oc_path) if File.file?(oc_path)
120
120
 
121
- funding_org = OpenCollectiveConfig.handle(required: false, root: root)
122
- if funding_org.to_s.strip.empty?
123
- Kernel.warn("kettle-dev: Could not determine funding org.\n - Options:\n * Set ENV['FUNDING_ORG'] to your funding handle, or 'false' to disable.\n * Or set ENV['OPENCOLLECTIVE_HANDLE'].\n * Or add .opencollective.yml with: collective: <handle> (or org: <handle>).\n * Or proceed without funding if not applicable.")
124
- funding_org = nil
121
+ funding_org = OpenCollectiveConfig.handle(required: false, root: root)
122
+ if funding_org.to_s.strip.empty?
123
+ Kernel.warn("kettle-dev: Could not determine funding org.\n - Options:\n * Set ENV['FUNDING_ORG'] to your funding handle, or 'false' to disable.\n * Or set ENV['OPENCOLLECTIVE_HANDLE'].\n * Or add .opencollective.yml with: collective: <handle> (or org: <handle>).\n * Or proceed without funding if not applicable.")
124
+ funding_org = nil
125
+ end
125
126
  end
126
127
  end
127
128
  rescue StandardError => error
@@ -104,6 +104,36 @@ module Kettle
104
104
  end
105
105
  end
106
106
 
107
+ # Push all tags to a remote.
108
+ # Notes:
109
+ # - The ruby-git gem does not provide a stable API for pushing all tags across
110
+ # versions, so we intentionally shell out to `git push --tags` for both
111
+ # backends. Tests should stub this method in higher-level code to avoid
112
+ # mutating any repositories.
113
+ #
114
+ # @param remote [String, nil] The remote name. When nil or empty, uses the
115
+ # repository's default remote (same behavior as running `git push --tags`)
116
+ # which typically uses the current branch's upstream.
117
+ # @return [Boolean] true if the system call reports success; false on failure
118
+ def push_tags(remote)
119
+ if @backend == :gem
120
+ # The ruby-git gem does not expose a dedicated API for "--tags" consistently across versions.
121
+ # Use a shell fallback even when the gem backend is active. Tests should stub this method.
122
+ if remote && !remote.to_s.empty?
123
+ system("git", "push", remote.to_s, "--tags")
124
+ else
125
+ system("git", "push", "--tags")
126
+ end
127
+ elsif remote && !remote.to_s.empty?
128
+ system("git", "push", remote.to_s, "--tags")
129
+ else
130
+ system("git", "push", "--tags")
131
+ end
132
+ rescue StandardError => e
133
+ Kettle::Dev.debug_error(e, __method__)
134
+ false
135
+ end
136
+
107
137
  # @return [String, nil] current branch name, or nil on error
108
138
  def current_branch
109
139
  if @backend == :gem
@@ -6,14 +6,14 @@ begin
6
6
 
7
7
  desc("Install Appraisal gemfiles (initial setup for projects that didn't previously use Appraisal)")
8
8
  task("appraisal:install") do
9
- bundle = Gem.bindir ? File.join(Gem.bindir, "bundle") : "bundle"
9
+ bundle = "bundle"
10
10
 
11
11
  run_in_unbundled = proc do
12
12
  env = {"BUNDLE_GEMFILE" => "Appraisal.root.gemfile"}
13
13
 
14
- # 1) bundle install --gemfile Appraisal.root.gemfile
15
- ok = system(bundle, "install", "--gemfile", "Appraisal.root.gemfile")
16
- abort("appraisal:install failed: bundle install --gemfile Appraisal.root.gemfile") unless ok
14
+ # 1) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle install
15
+ ok = system(env, bundle, "install")
16
+ abort("appraisal:install failed: BUNDLE_GEMFILE=Appraisal.root.gemfile bundle install") unless ok
17
17
 
18
18
  # 2) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal install
19
19
  ok = system(env, bundle, "exec", "appraisal", "install")
@@ -33,22 +33,22 @@ begin
33
33
 
34
34
  desc("Update Appraisal gemfiles and run RuboCop Gradual autocorrect")
35
35
  task("appraisal:update") do
36
- bundle = Gem.bindir ? File.join(Gem.bindir, "bundle") : "bundle"
36
+ bundle = "bundle"
37
37
 
38
38
  run_in_unbundled = proc do
39
39
  env = {"BUNDLE_GEMFILE" => "Appraisal.root.gemfile"}
40
40
 
41
41
  # 1) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle update --bundler
42
42
  ok = system(env, bundle, "update", "--bundler")
43
- abort("appraisal:update failed: bundle update --bundler under Appraisal.root.gemfile") unless ok
43
+ abort("appraisal:update failed: BUNDLE_GEMFILE=Appraisal.root.gemfile bundle update --bundler") unless ok
44
44
 
45
- # 2) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle (install)
46
- ok = system(env, bundle)
47
- abort("appraisal:update failed: bundler install under Appraisal.root.gemfile") unless ok
45
+ # 2) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle install
46
+ ok = system(env, bundle, "install")
47
+ abort("appraisal:update failed: BUNDLE_GEMFILE=Appraisal.root.gemfile bundle install") unless ok
48
48
 
49
49
  # 3) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update
50
50
  ok = system(env, bundle, "exec", "appraisal", "update")
51
- abort("appraisal:update failed: bundle exec appraisal update") unless ok
51
+ abort("appraisal:update failed: BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update") unless ok
52
52
 
53
53
  # 4) bundle exec rake rubocop_gradual:autocorrect
54
54
  ok = system(bundle, "exec", "rake", "rubocop_gradual:autocorrect")
@@ -22,7 +22,7 @@ namespace :bench do
22
22
  end
23
23
 
24
24
  ruby = RbConfig.ruby
25
- bundle = Gem.bindir ? File.join(Gem.bindir, "bundle") : "bundle"
25
+ bundle = "bundle"
26
26
  bench_files = Dir[File.join(__dir__, "benchmarks", "*.rb")].sort
27
27
  if bench_files.empty?
28
28
  puts "No benchmark scripts found under benchmarks/."
@@ -15,7 +15,7 @@ begin
15
15
  desc("Run reek and store the output into the REEK file")
16
16
  task("reek:update") do
17
17
  # Run via Bundler if available to ensure the right gem version is used
18
- cmd = [Gem.bindir ? File.join(Gem.bindir, "bundle") : "bundle", "exec", "reek"]
18
+ cmd = %w[bundle exec reek]
19
19
 
20
20
  output, status = Open3.capture2e(*cmd)
21
21
 
@@ -269,22 +269,25 @@ module Kettle
269
269
  # 16. generate checksums
270
270
  # Checksums are generated after release to avoid including checksums/ in gem package
271
271
  # Rationale: Running gem_checksums before release may commit checksums/ and cause Bundler's
272
- # release build to include them in the gem, altering the artifact.
272
+ # release build to include them in the gem, thus altering the artifact, and invalidating the checksums.
273
273
  if @start_step <= 16
274
- # Generate checksums for the just-built artifact, then validate
274
+ # Generate checksums for the just-built artifact, commit them, then validate
275
275
  run_cmd!("bin/gem_checksums")
276
276
  version ||= detect_version
277
277
  validate_checksums!(version, stage: "after release")
278
278
  end
279
279
 
280
- # 17. create GitHub release (optional)
281
- if @start_step <= 17
280
+ # 17. push checksum commit (gem_checksums already commits)
281
+ push! if @start_step <= 17
282
+
283
+ # 18. create GitHub release (optional)
284
+ if @start_step <= 18
282
285
  version ||= detect_version
283
286
  maybe_create_github_release!(version)
284
287
  end
285
288
 
286
- # 18. push tags to remotes (new final step)
287
- push_tags! if @start_step <= 18
289
+ # 19. push tags to remotes (final step)
290
+ push_tags! if @start_step <= 19
288
291
 
289
292
  # Final success message
290
293
  begin
@@ -708,17 +711,20 @@ module Kettle
708
711
  # 2) Otherwise, if other remotes exist, push tags to each of them.
709
712
  # 3) If no remotes are configured, push tags using default remote.
710
713
  if has_remote?("all")
711
- run_cmd!("git push all --tags")
714
+ ok = @git.push_tags("all")
715
+ warn("Push tags to 'all' reported failure.") unless ok
712
716
  return
713
717
  end
714
718
 
715
719
  remotes = list_remotes
716
720
  remotes -= ["all"] if remotes
717
721
  if remotes.nil? || remotes.empty?
718
- run_cmd!("git push --tags")
722
+ ok = @git.push_tags(nil)
723
+ warn("Push tags (default remote) reported failure.") unless ok
719
724
  else
720
725
  remotes.each do |remote|
721
- run_cmd!("git push #{Shellwords.escape(remote)} --tags")
726
+ ok = @git.push_tags(remote)
727
+ warn("Push tags to #{remote} reported failure.") unless ok
722
728
  end
723
729
  end
724
730
  end
@@ -120,11 +120,17 @@ module Kettle
120
120
  end
121
121
 
122
122
  selected.values.each do |orig_src|
123
- src = helpers.prefer_example(orig_src)
123
+ src = helpers.prefer_example_with_osc_check(orig_src)
124
124
  # Destination path should never include the .example suffix.
125
125
  rel = orig_src.sub(/^#{Regexp.escape(gem_checkout_root)}\/?/, "").sub(/\.example\z/, "")
126
126
  dest = File.join(project_root, rel)
127
127
 
128
+ # Skip opencollective-specific files when Open Collective is disabled
129
+ if helpers.skip_for_disabled_opencollective?(rel)
130
+ puts "Skipping #{rel} (Open Collective disabled)"
131
+ next
132
+ end
133
+
128
134
  # Optional file: .github/workflows/discord-notifier.yml should NOT be copied by default.
129
135
  # Only copy when --include matches it.
130
136
  if rel == ".github/workflows/discord-notifier.yml"
@@ -422,7 +428,13 @@ module Kettle
422
428
  end
423
429
 
424
430
  files_to_copy.each do |rel|
425
- src = helpers.prefer_example(File.join(gem_checkout_root, rel))
431
+ # Skip opencollective-specific files when Open Collective is disabled
432
+ if helpers.skip_for_disabled_opencollective?(rel)
433
+ puts "Skipping #{rel} (Open Collective disabled)"
434
+ next
435
+ end
436
+
437
+ src = helpers.prefer_example_with_osc_check(File.join(gem_checkout_root, rel))
426
438
  dest = File.join(project_root, rel)
427
439
  next unless File.exist?(src)
428
440
 
@@ -76,6 +76,51 @@ module Kettle
76
76
  File.exist?(example) ? example : src_path
77
77
  end
78
78
 
79
+ # Check if Open Collective is disabled via environment variable.
80
+ # Returns true when OPENCOLLECTIVE_HANDLE or FUNDING_ORG is explicitly set to a falsey value.
81
+ # @return [Boolean]
82
+ def opencollective_disabled?
83
+ oc_handle = ENV["OPENCOLLECTIVE_HANDLE"]
84
+ funding_org = ENV["FUNDING_ORG"]
85
+
86
+ # Check if either variable is explicitly set to false
87
+ [oc_handle, funding_org].any? do |val|
88
+ val && val.to_s.strip.match(Kettle::Dev::ENV_FALSE_RE)
89
+ end
90
+ end
91
+
92
+ # Prefer a .no-osc.example variant when Open Collective is disabled.
93
+ # Otherwise, falls back to prefer_example behavior.
94
+ # For a given source path, this will return:
95
+ # - "path.no-osc.example" if opencollective_disabled? and it exists
96
+ # - Otherwise delegates to prefer_example
97
+ # @param src_path [String]
98
+ # @return [String]
99
+ def prefer_example_with_osc_check(src_path)
100
+ if opencollective_disabled?
101
+ # Try .no-osc.example first
102
+ base = src_path.sub(/\.example\z/, "")
103
+ no_osc = base + ".no-osc.example"
104
+ return no_osc if File.exist?(no_osc)
105
+ end
106
+ prefer_example(src_path)
107
+ end
108
+
109
+ # Check if a file should be skipped when Open Collective is disabled.
110
+ # Returns true for opencollective-specific files when opencollective_disabled? is true.
111
+ # @param relative_path [String] relative path from gem checkout root
112
+ # @return [Boolean]
113
+ def skip_for_disabled_opencollective?(relative_path)
114
+ return false unless opencollective_disabled?
115
+
116
+ opencollective_files = [
117
+ ".opencollective.yml",
118
+ ".github/workflows/opencollective.yml",
119
+ ]
120
+
121
+ opencollective_files.include?(relative_path)
122
+ end
123
+
79
124
  # Record a template action for a destination path
80
125
  # @param dest_path [String]
81
126
  # @param action [Symbol] one of :create, :replace, :skip, :dir_create, :dir_replace
@@ -6,7 +6,7 @@ module Kettle
6
6
  module Version
7
7
  # The gem version.
8
8
  # @return [String]
9
- VERSION = "1.1.32"
9
+ VERSION = "1.1.34"
10
10
 
11
11
  module_function
12
12
 
data/lib/kettle/dev.rb CHANGED
@@ -62,6 +62,11 @@ module Kettle
62
62
  # Accepts 1, true, y, yes (any case).
63
63
  # @return [Regexp]
64
64
  ENV_TRUE_RE = /\A(1|true|y|yes)\z/i
65
+
66
+ # A case-insensitive regular expression that matches common falsy ENV values.
67
+ # Accepts false, n, no, 0 (any case).
68
+ # @return [Regexp]
69
+ ENV_FALSE_RE = /\A(false|n|no|0)\z/i
65
70
  # Absolute path to the root of the kettle-dev gem (repository root when working from source)
66
71
  # @return [String]
67
72
  GEM_ROOT = File.expand_path("../..", __dir__)
data/sig/kettle/dev.rbs CHANGED
@@ -12,6 +12,7 @@ module Kettle
12
12
  REQUIRE_BENCH: bool
13
13
  RUNNING_AS: String
14
14
  ENV_TRUE_RE: Regexp
15
+ ENV_FALSE_RE: Regexp
15
16
  GEM_ROOT: String
16
17
 
17
18
  # Singleton methods
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: 1.1.32
4
+ version: 1.1.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -222,8 +222,10 @@ files:
222
222
  - "./.simplecov.example"
223
223
  - "./Appraisals.example"
224
224
  - "./CHANGELOG.md.example"
225
+ - "./FUNDING.md.no-osc.example"
225
226
  - "./Gemfile.example"
226
227
  - "./README.md.example"
228
+ - "./README.md.no-osc.example"
227
229
  - "./Rakefile.example"
228
230
  - "./kettle-dev.gemspec.example"
229
231
  - ".aiignore.example"
@@ -237,6 +239,7 @@ files:
237
239
  - ".git-hooks/prepare-commit-msg.example"
238
240
  - ".github/.codecov.yml.example"
239
241
  - ".github/FUNDING.yml"
242
+ - ".github/FUNDING.yml.no-osc.example"
240
243
  - ".github/dependabot.yml"
241
244
  - ".github/workflows/ancient.yml"
242
245
  - ".github/workflows/ancient.yml.example"
@@ -288,11 +291,13 @@ files:
288
291
  - CODE_OF_CONDUCT.md
289
292
  - CONTRIBUTING.md
290
293
  - FUNDING.md
294
+ - FUNDING.md.no-osc.example
291
295
  - Gemfile
292
296
  - Gemfile.example
293
297
  - LICENSE.txt
294
298
  - README.md
295
299
  - README.md.example
300
+ - README.md.no-osc.example
296
301
  - REEK
297
302
  - RUBOCOP.md
298
303
  - Rakefile.example
@@ -404,10 +409,10 @@ licenses:
404
409
  - MIT
405
410
  metadata:
406
411
  homepage_uri: https://kettle-dev.galtzo.com/
407
- source_code_uri: https://github.com/kettle-rb/kettle-dev/tree/v1.1.32
408
- changelog_uri: https://github.com/kettle-rb/kettle-dev/blob/v1.1.32/CHANGELOG.md
412
+ source_code_uri: https://github.com/kettle-rb/kettle-dev/tree/v1.1.34
413
+ changelog_uri: https://github.com/kettle-rb/kettle-dev/blob/v1.1.34/CHANGELOG.md
409
414
  bug_tracker_uri: https://github.com/kettle-rb/kettle-dev/issues
410
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/1.1.32
415
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/1.1.34
411
416
  funding_uri: https://github.com/sponsors/pboling
412
417
  wiki_uri: https://github.com/kettle-rb/kettle-dev/wiki
413
418
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
Binary file