kettle-dev 1.0.0 → 1.0.2

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.devcontainer/devcontainer.json +26 -0
  4. data/.envrc +42 -0
  5. data/.git-hooks/commit-msg +41 -0
  6. data/.git-hooks/commit-subjects-goalie.txt +8 -0
  7. data/.git-hooks/footer-template.erb.txt +16 -0
  8. data/.git-hooks/prepare-commit-msg +20 -0
  9. data/.github/FUNDING.yml +13 -0
  10. data/.github/dependabot.yml +11 -0
  11. data/.github/workflows/ancient.yml +80 -0
  12. data/.github/workflows/auto-assign.yml +21 -0
  13. data/.github/workflows/codeql-analysis.yml +70 -0
  14. data/.github/workflows/coverage.yml +130 -0
  15. data/.github/workflows/current.yml +88 -0
  16. data/.github/workflows/dependency-review.yml +20 -0
  17. data/.github/workflows/discord-notifier.yml +38 -0
  18. data/.github/workflows/heads.yml +87 -0
  19. data/.github/workflows/jruby.yml +79 -0
  20. data/.github/workflows/legacy.yml +70 -0
  21. data/.github/workflows/locked_deps.yml +88 -0
  22. data/.github/workflows/opencollective.yml +40 -0
  23. data/.github/workflows/style.yml +67 -0
  24. data/.github/workflows/supported.yml +85 -0
  25. data/.github/workflows/truffle.yml +78 -0
  26. data/.github/workflows/unlocked_deps.yml +87 -0
  27. data/.github/workflows/unsupported.yml +78 -0
  28. data/.gitignore +48 -0
  29. data/.gitlab-ci.yml +45 -0
  30. data/.junie/guidelines-rbs.md +49 -0
  31. data/.junie/guidelines.md +132 -0
  32. data/.opencollective.yml +3 -0
  33. data/.qlty/qlty.toml +79 -0
  34. data/.rspec +8 -0
  35. data/.rubocop.yml +13 -0
  36. data/.simplecov +7 -0
  37. data/.tool-versions +1 -0
  38. data/.yard_gfm_support.rb +22 -0
  39. data/.yardopts +11 -0
  40. data/Appraisal.root.gemfile +12 -0
  41. data/Appraisals +120 -0
  42. data/CHANGELOG.md +26 -5
  43. data/Gemfile +32 -0
  44. data/Rakefile +99 -0
  45. data/checksums/kettle-dev-1.0.1.gem.sha256 +1 -0
  46. data/checksums/kettle-dev-1.0.1.gem.sha512 +1 -0
  47. data/checksums/kettle-dev-1.0.2.gem.sha256 +1 -0
  48. data/checksums/kettle-dev-1.0.2.gem.sha512 +1 -0
  49. data/exe/kettle-commit-msg +185 -0
  50. data/exe/kettle-readme-backers +355 -0
  51. data/exe/kettle-release +327 -0
  52. data/gemfiles/modular/coverage.gemfile +6 -0
  53. data/gemfiles/modular/documentation.gemfile +11 -0
  54. data/gemfiles/modular/style.gemfile +16 -0
  55. data/lib/kettle/dev/rakelib/appraisal.rake +40 -0
  56. data/lib/kettle/dev/rakelib/bench.rake +58 -0
  57. data/lib/kettle/dev/rakelib/bundle_audit.rake +18 -0
  58. data/lib/kettle/dev/rakelib/ci.rake +348 -0
  59. data/lib/kettle/dev/rakelib/install.rake +304 -0
  60. data/lib/kettle/dev/rakelib/reek.rake +34 -0
  61. data/lib/kettle/dev/rakelib/require_bench.rake +7 -0
  62. data/lib/kettle/dev/rakelib/rubocop_gradual.rake +9 -0
  63. data/lib/kettle/dev/rakelib/spec_test.rake +42 -0
  64. data/lib/kettle/dev/rakelib/template.rake +413 -0
  65. data/lib/kettle/dev/rakelib/yard.rake +33 -0
  66. data/lib/kettle/dev/version.rb +1 -1
  67. data.tar.gz.sig +0 -0
  68. metadata +74 -5
  69. metadata.gz.sig +0 -0
data/CHANGELOG.md CHANGED
@@ -12,6 +12,27 @@ and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2.
12
12
  ### Fixed
13
13
  ### Security
14
14
 
15
+ ## [1.0.2] - 2025-08-24
16
+ - TAG: [v1.0.2][1.0.2t]
17
+ - COVERAGE: 100.00% -- 98/98 lines in 7 files
18
+ - BRANCH COVERAGE: 100.00% -- 30/30 branches in 7 files
19
+ - 94.59% documented
20
+ ### Fixed
21
+ - Added files necessary for kettle:dev:template task to work
22
+ - .github/workflows/opencollective.yml working!
23
+
24
+ ## [1.0.1] - 2025-08-24
25
+ - TAG: [v1.0.1][1.0.1t]
26
+ - COVERAGE: 100.00% -- 98/98 lines in 7 files
27
+ - BRANCH COVERAGE: 100.00% -- 30/30 branches in 7 files
28
+ - 94.59% documented
29
+ ### Added
30
+ - These were documented but not yet released:
31
+ - `kettle-release` ruby script for safely, securely, releasing a gem.
32
+ - This may move to its own gem in the future.
33
+ - `kettle-readme-backers` ruby script for integrating Open Source Collective backers into a README.md file.
34
+ - This may move to its own gem in the future.
35
+
15
36
  ## [1.0.0] - 2025-08-24
16
37
  - TAG: [v1.0.0][1.0.0t]
17
38
  - COVERAGE: 100.00% -- 98/98 lines in 7 files
@@ -37,11 +58,11 @@ and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2.
37
58
  - `ci:act` rake task CLI menu / scoreboard for a project's GHA workflows
38
59
  - Selecting will run the selected workflow via `act`
39
60
  - This may move to its own gem in the future.
40
- - `kettle-release` ruby script for safely, securely, releasing a gem.
41
- - This may move to its own gem in the future.
42
- - `kettle-readme-backers` ruby script for integrating Open Source Collective backers into a README.md file.
43
- - This may move to its own gem in the future.
44
61
 
45
- [Unreleased]: https://gitlab.com/kettle-rb/kettle-dev/-/compare/v1.0.0...HEAD
62
+ [Unreleased]: https://gitlab.com/kettle-rb/kettle-dev/-/compare/v1.0.2...HEAD
63
+ [1.0.2]: https://gitlab.com/kettle-rb/kettle-dev/-/compare/v1.0.1...v1.0.2
64
+ [1.0.2t]: https://gitlab.com/kettle-rb/kettle-dev/-/tags/v1.0.2
65
+ [1.0.1]: https://gitlab.com/kettle-rb/kettle-dev/-/compare/v1.0.0...v1.0.1
66
+ [1.0.1t]: https://gitlab.com/kettle-rb/kettle-dev/-/tags/v1.0.1
46
67
  [1.0.0]: https://gitlab.com/kettle-rb/kettle-dev/-/compare/a427c302df09cfe4253a7c8d400333f9a4c1a208...v1.0.0
47
68
  [1.0.0t]: https://gitlab.com/kettle-rb/kettle-dev/-/tags/v1.0.0
data/Gemfile ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+ git_source(:gitlab) { |repo_name| "https://gitlab.com/#{repo_name}" }
7
+
8
+ #### IMPORTANT #######################################################
9
+ # Gemfile is for local development ONLY; Gemfile is NOT loaded in CI #
10
+ ####################################################### IMPORTANT ####
11
+
12
+ # Include dependencies from <gem name>.gemspec
13
+ gemspec
14
+
15
+ platform :mri do
16
+ # Debugging - Ensure ENV["DEBUG"] == "true" to use debuggers within spec suite
17
+ # Use binding.break, binding.b, or debugger in code
18
+ gem "debug", ">= 1.0.0" # ruby >= 2.7
19
+ gem "gem_bench", "~> 2.0", ">= 2.0.5"
20
+
21
+ # Dev Console - Binding.pry - Irb replacement
22
+ gem "pry", "~> 0.14" # ruby >= 2.0
23
+ end
24
+
25
+ # Code Coverage
26
+ eval_gemfile "gemfiles/modular/coverage.gemfile"
27
+
28
+ # Linting
29
+ eval_gemfile "gemfiles/modular/style.gemfile"
30
+
31
+ # Documentation
32
+ eval_gemfile "gemfiles/modular/documentation.gemfile"
data/Rakefile ADDED
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Galtzo FLOSS Rakefile v1.0.11 - 2025-08-19
4
+ # Ruby 2.3 (Safe Navigation) or higher required
5
+ #
6
+ # CHANGELOG
7
+ # v1.0.0 - initial release w/ support for rspec, minitest, rubocop, reek, yard, and stone_checksums
8
+ # v1.0.1 - fix test / spec tasks running 2x
9
+ # v1.0.2 - fix duplicate task warning from RuboCop
10
+ # v1.0.3 - add bench tasks to run mini benchmarks (add scripts to /benchmarks)
11
+ # v1.0.4 - add support for floss_funding:install
12
+ # v1.0.5 - add support for halting in Rake tasks with binding.b (from debug gem)
13
+ # v1.0.6 - add RBS files and checksums to YARD-generated docs site
14
+ # v1.0.7 - works with vanilla ruby, non-gem, bundler-managed, projects
15
+ # v1.0.8 - improved Dir globs, add back and document rbconfig dependency
16
+ # v1.0.9 - add appraisal:update task to update Appraisal gemfiles and autocorrect with RuboCop Gradual
17
+ # v1.0.10 - add ci:act to run GHA workflows locally, and get status of remote workflows
18
+ # v1.0.11 - ci:act workflows are populated entirely dynamically, based on existing files
19
+ #
20
+ # MIT License (see License.txt)
21
+ #
22
+ # Copyright (c) 2025 Peter H. Boling (galtzo.com)
23
+ #
24
+ # Expected to work in any project that uses Bundler.
25
+ #
26
+ # Sets up tasks for appraisal, floss_funding, rspec, minitest, rubocop, reek, yard, and stone_checksums.
27
+ #
28
+ # rake appraisal:update # Update Appraisal gemfiles and run RuboCop Gradual autocorrect
29
+ # rake bench # Run all benchmarks (alias for bench:run)
30
+ # rake bench:list # List available benchmark scripts
31
+ # rake bench:run # Run all benchmark scripts (skips on CI)
32
+ # rake build # Build gitmoji-regex-1.0.2.gem into the pkg directory
33
+ # rake build:checksum # Generate SHA512 checksum of gitmoji-regex-1.0.2.gem into the checksums directory
34
+ # rake build:generate_checksums # Generate both SHA256 & SHA512 checksums into the checksums directory, and git...
35
+ # rake bundle:audit:check # Checks the Gemfile.lock for insecure dependencies
36
+ # rake bundle:audit:update # Updates the bundler-audit vulnerability database
37
+ # rake ci:act[opt] # Run 'act' with a selected workflow
38
+ # rake clean # Remove any temporary products
39
+ # rake clobber # Remove any generated files
40
+ # rake coverage # Run specs w/ coverage and open results in browser
41
+ # rake floss_funding:install # (stub) floss_funding is unavailable
42
+ # rake install # Build and install gitmoji-regex-1.0.2.gem into system gems
43
+ # rake install:local # Build and install gitmoji-regex-1.0.2.gem into system gems without network ac...
44
+ # rake reek # Check for code smells
45
+ # rake reek:update # Run reek and store the output into the REEK file
46
+ # rake release[remote] # Create tag v1.0.2 and build and push gitmoji-regex-1.0.2.gem to rubygems.org
47
+ # rake rubocop # alias rubocop task to rubocop_gradual
48
+ # rake rubocop_gradual # Run RuboCop Gradual
49
+ # rake rubocop_gradual:autocorrect # Run RuboCop Gradual with autocorrect (only when it's safe)
50
+ # rake rubocop_gradual:autocorrect_all # Run RuboCop Gradual with autocorrect (safe and unsafe)
51
+ # rake rubocop_gradual:check # Run RuboCop Gradual to check the lock file
52
+ # rake rubocop_gradual:force_update # Run RuboCop Gradual to force update the lock file
53
+ # rake spec # Run RSpec code examples
54
+ # rake test # Run tests
55
+ # rake yard # Generate YARD Documentation
56
+
57
+ # External gems
58
+ require "bundler/gem_tasks" if !Dir[File.join(__dir__, "*.gemspec")].empty?
59
+
60
+ # Detect if the invoked task is spec/test to avoid eagerly requiring the library,
61
+ # which would load code before SimpleCov can start (when running `rake spec`).
62
+ invoked_tasks = Rake.application.top_level_tasks
63
+ running_specs = invoked_tasks.any? { |t| t == "spec" || t == "test" || t == "coverage" }
64
+
65
+ if running_specs
66
+ # Define minimal rspec tasks locally to keep coverage accurate
67
+ begin
68
+ require "rspec/core/rake_task"
69
+ desc("Run RSpec code examples")
70
+ RSpec::Core::RakeTask.new(:spec)
71
+ desc("Run tests")
72
+ task(test: :spec)
73
+ rescue LoadError
74
+ # If rspec isn't available, let it fail when the task is invoked
75
+ end
76
+ else
77
+ require "kettle/dev"
78
+
79
+ # Define a base default task early so other files can enhance it.
80
+ desc "Default tasks aggregator"
81
+ task :default do
82
+ puts "Default task complete."
83
+ end
84
+
85
+ Kettle::Dev.install_tasks
86
+
87
+ ### RELEASE TASKS
88
+ # Setup stone_checksums
89
+ begin
90
+ require "stone_checksums"
91
+
92
+ GemChecksums.install_tasks
93
+ rescue LoadError
94
+ desc("(stub) build:generate_checksums is unavailable")
95
+ task("build:generate_checksums") do
96
+ warn("NOTE: stone_checksums isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
97
+ end
98
+ end
99
+ end
@@ -0,0 +1 @@
1
+ 5b92c8a76f54954791e4154bb22594dbc9dd4f0e06d9d4c5db15a32aa2718ede
@@ -0,0 +1 @@
1
+ 5cac18505a8f780d3897f1d900a662c896537056441b1a8178531355a4b10198bee0bdc62216ab2036b640adada34911bc30b813f715a14a464d797718d7a065
@@ -0,0 +1 @@
1
+ 2338f9fc4e14a03c39c6509d11fdcfad85faaa7615d855703cb511bc9f95351c
@@ -0,0 +1 @@
1
+ ccc6a5c3cd36a8c40d78458166adfbd7ad452b62055579ee4333089a56313170bf97d0aca1f8c3d4f15287bb3d396cfbfcce2174665feb7a77f0b6b03ac8096c
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set syntax=ruby
3
+
4
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5
+
6
+ require "rubygems"
7
+ require "bundler/setup"
8
+
9
+ # Standard library
10
+ require "erb"
11
+
12
+ # ENV variable control (set in .envrc, or .env.local)
13
+ # BRANCH_RULE_TYPE = jira, or another type of branch rule validation, or false to disable
14
+ # FOOTER_APPEND = true/false append commit message footer
15
+ BRANCH_RULES = {
16
+ "jira" => /^(?<story_type>(hotfix)|(bug)|(feature)|(candy))\/(?<story_id>\d{8,})-.+\Z/,
17
+ }
18
+ BRANCH_RULE_TYPE = (validate = ENV.fetch("GIT_HOOK_BRANCH_VALIDATE", "false")) && !validate.casecmp?("false") && validate
19
+
20
+ # Called the "JIRA pattern", because of traditional use with JIRA.
21
+ if (branch_rule = BRANCH_RULES[BRANCH_RULE_TYPE])
22
+ # branches should be named like:
23
+ # <story_type>/<story_id>-explosion-in-the-fudge-factory-spec-suite-fix
24
+ # where story type is one of "hotfix", "bug", "feature", "candy"
25
+ #
26
+ branch = %x(git branch 2> /dev/null | grep -e ^* | awk '{print $2}')
27
+ match_data = branch.match(branch_rule)
28
+ # NOTE: `match` will return nil if match fails, otherwise an instance of MatchData.
29
+ # If not nil then we are assured matches for both regex capture groups
30
+ # match_data_or_nil[:story_type] will be one of "hotfix", "bug", "feature", "candy"
31
+ # match_data_or_nil[:story_id] will be a numeric string
32
+
33
+ if !match_data.nil?
34
+ commit_msg = File.read(ARGV[0])
35
+ unless commit_msg.include?(match_data[:story_id])
36
+ commit_msg = <<~EOS
37
+ #{commit_msg.strip}
38
+ [#{match_data[:story_type]}][#{match_data[:story_id]}]
39
+ EOS
40
+ File.open(ARGV[0], "w") do |file|
41
+ file.print(commit_msg)
42
+ end
43
+ end
44
+ end
45
+ else
46
+ # puts "No branch rule configured (set GIT_HOOK_BRANCH_VALIDATE=jira to enforce rules for jira style branch names)"
47
+ end
48
+
49
+ class GitCommitFooter
50
+ # Prefer project-local .git-hooks (repo root), then fallback to global ~/.git-hooks
51
+ NAME_ASSIGNMENT_REGEX = /\bname\s*=\s*(["'])([^"']+)\1/.freeze
52
+ FOOTER_APPEND = ENV.fetch("GIT_HOOK_FOOTER_APPEND", "false").casecmp("true").zero?
53
+ SENTINEL = ENV["GIT_HOOK_FOOTER_SENTINEL"] # No default to avoid accidental duplicate commit of a footer via ammended commits
54
+ raise "Set GIT_HOOK_FOOTER_SENTINEL=<footer sentinel> in .env.local (e.g., '⚡️ A message from a fellow meat-based-AI ⚡️')" if FOOTER_APPEND && SENTINEL.nil? || SENTINEL.empty?
55
+
56
+ class << self
57
+ def git_toplevel
58
+ toplevel = nil
59
+ begin
60
+ # 'git rev-parse --show-toplevel' returns the repo root when run anywhere inside the repo
61
+ out = %x(git rev-parse --show-toplevel 2>/dev/null)
62
+ toplevel = out.strip unless out.nil? || out.empty?
63
+ rescue StandardError
64
+ # ignore
65
+ end
66
+ toplevel
67
+ end
68
+
69
+ def local_hooks_dir
70
+ top = git_toplevel
71
+ return unless top && !top.empty?
72
+ File.join(top, ".git-hooks")
73
+ end
74
+
75
+ def global_hooks_dir
76
+ File.join(ENV["HOME"], ".git-hooks")
77
+ end
78
+
79
+ def hooks_path_for(filename)
80
+ local_dir = local_hooks_dir
81
+ if local_dir
82
+ local_path = File.join(local_dir, filename)
83
+ return local_path if File.file?(local_path)
84
+ end
85
+ File.join(global_hooks_dir, filename)
86
+ end
87
+
88
+ def commit_goalie_path
89
+ hooks_path_for("commit-subjects-goalie.txt")
90
+ end
91
+
92
+ # Determine whether the commit subject allows footer append, based on optional goalie file
93
+ # ~/.git-hooks/commit-subjects-goalie.txt
94
+ # - If present, only allow appending when the first line of the commit message starts with one of the non-commented prefixes
95
+ # - If absent, disallow footer
96
+ def goalie_allows_footer?(subject_line)
97
+ goalie_path = commit_goalie_path
98
+ return false unless File.file?(goalie_path)
99
+
100
+ prefixes = File.read(goalie_path).lines.map { |l| l.strip }.reject { |l| l.empty? || l.start_with?("#") }
101
+ # If the file exists but has no usable lines, treat as deny-all per goalie intent
102
+ return false if prefixes.empty?
103
+
104
+ subj = subject_line.to_s.strip
105
+ prefixes.any? { |prefix| subj.start_with?(prefix) }
106
+ end
107
+
108
+ def render(*argv)
109
+ commit_msg = File.read(argv[0])
110
+ subject_line = commit_msg.lines.first.to_s
111
+ if GitCommitFooter::FOOTER_APPEND && goalie_allows_footer?(subject_line)
112
+ if commit_msg.include?(GitCommitFooter::SENTINEL)
113
+ # This is a commit message that has already been appended
114
+ # This will happen if the commit message is edited and re-committed
115
+ # puts "FOOTER_APPEND is true, skipping footer append"
116
+ exit(0)
117
+ else
118
+ footer_binding = GitCommitFooter.new
119
+ # Append footer to the commit message
120
+ File.open(argv[0], "w") do |file|
121
+ file.print(commit_msg)
122
+ file.print("\n")
123
+ file.print(footer_binding.render)
124
+ end
125
+ end
126
+ else
127
+ # Skipping footer append (either FOOTER_APPEND is false, or goalie did not allow it)
128
+ end
129
+ end
130
+ end
131
+
132
+ def initialize
133
+ @pwd = Dir.pwd
134
+ @gemspecs = Dir["*.gemspec"]
135
+ @spec = @gemspecs.first
136
+ @gemspec_path = File.expand_path(@spec, @pwd)
137
+ @gem_name = parse_gemspec_name || derive_gem_name
138
+ end
139
+
140
+ # Render ERB with binding variables
141
+ def render
142
+ ERB.new(template).result(binding)
143
+ end
144
+
145
+ private
146
+
147
+ # Lightweight parse for gem name to avoid full Gem::Specification load
148
+ def parse_gemspec_name
149
+ begin
150
+ content = File.read(@gemspec_path)
151
+ # Look for name assignment patterns like:
152
+ # spec.name = "my_gem" OR Gem::Specification.new do |spec|; spec.name = 'my_gem'
153
+ @name_index = content =~ NAME_ASSIGNMENT_REGEX
154
+ if @name_index
155
+ return $2
156
+ end
157
+ rescue StandardError
158
+ # fall through
159
+ end
160
+ nil
161
+ end
162
+
163
+ # No-parse derivation of gem name, when parsing gemspec fails
164
+ def derive_gem_name
165
+ File.basename(@gemspec_path, ".*") if @gemspec_path
166
+ end
167
+
168
+ # Example
169
+ #
170
+ # ⚡️ A message from a fellow meat-based-AI ⚡️
171
+ # I ❤️ working on <%= @gem_name %>.
172
+ #
173
+ # The first line is the footer sentinel (which does appear in the commit).
174
+ # The second line, and any additional, is the main body of the footer.
175
+ #
176
+ # The sentinel must be set in an ENV variable (e.g., in your .env.local file):
177
+ #
178
+ # export GIT_HOOK_FOOTER_SENTINEL="⚡️ A message from a fellow meat-based-AI ⚡️"
179
+ #
180
+ def template
181
+ File.read(self.class.hooks_path_for("footer-template.erb.txt"))
182
+ end
183
+ end
184
+
185
+ GitCommitFooter.render(*ARGV)