kettle-dev 1.2.4 → 2.0.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +232 -3
- data/CITATION.cff +6 -6
- data/CONTRIBUTING.md +64 -46
- data/FUNDING.md +1 -1
- data/LICENSE.md +12 -0
- data/README.md +448 -457
- data/certs/pboling.pem +27 -0
- data/exe/kettle-changelog +24 -13
- data/exe/kettle-check-eof +7 -0
- data/exe/kettle-check-eof.sh +118 -0
- data/exe/kettle-dev-setup +12 -63
- data/exe/kettle-gh-release +82 -0
- data/lib/kettle/dev/changelog_cli.rb +373 -62
- data/lib/kettle/dev/ci_monitor.rb +2 -2
- data/lib/kettle/dev/dvcs_cli.rb +1 -1
- data/lib/kettle/dev/gem_spec_reader.rb +100 -10
- data/lib/kettle/dev/git_adapter.rb +37 -1
- data/lib/kettle/dev/open_collective_config.rb +15 -3
- data/lib/kettle/dev/pre_release_cli.rb +4 -4
- data/lib/kettle/dev/rakelib/reek.rake +9 -6
- data/lib/kettle/dev/rakelib/spec_test.rake +25 -25
- data/lib/kettle/dev/rakelib/yard.rake +17 -17
- data/lib/kettle/dev/readme_backers.rb +4 -4
- data/lib/kettle/dev/release_cli.rb +27 -24
- data/lib/kettle/dev/tasks/ci_task.rb +4 -4
- data/lib/kettle/dev/version.rb +2 -87
- data/lib/kettle/dev.rb +31 -17
- data/sig/kettle/dev/source_merger.rbs +40 -56
- data/sig/kettle/dev/version.rbs +8 -0
- data.tar.gz.sig +0 -0
- metadata +63 -165
- metadata.gz.sig +0 -0
- data/.aiignore.example +0 -19
- data/.devcontainer/apt-install/devcontainer-feature.json +0 -9
- data/.devcontainer/apt-install/install.sh +0 -11
- data/.devcontainer/devcontainer.json +0 -28
- data/.env.local.example +0 -31
- data/.envrc +0 -47
- data/.envrc.example +0 -51
- data/.envrc.no-osc.example +0 -51
- data/.git-hooks/commit-msg +0 -54
- data/.git-hooks/commit-subjects-goalie.txt +0 -8
- data/.git-hooks/footer-template.erb.txt +0 -16
- data/.git-hooks/prepare-commit-msg +0 -8
- data/.github/.codecov.yml.example +0 -14
- data/.github/FUNDING.yml +0 -13
- data/.github/FUNDING.yml.no-osc.example +0 -13
- data/.github/dependabot.yml +0 -13
- data/.github/workflows/ancient.yml +0 -83
- data/.github/workflows/ancient.yml.example +0 -81
- data/.github/workflows/auto-assign.yml +0 -21
- data/.github/workflows/codeql-analysis.yml +0 -70
- data/.github/workflows/coverage.yml +0 -127
- data/.github/workflows/coverage.yml.example +0 -127
- data/.github/workflows/current.yml +0 -116
- data/.github/workflows/current.yml.example +0 -115
- data/.github/workflows/dep-heads.yml +0 -117
- data/.github/workflows/dependency-review.yml +0 -20
- data/.github/workflows/discord-notifier.yml.example +0 -39
- data/.github/workflows/heads.yml +0 -117
- data/.github/workflows/heads.yml.example +0 -116
- data/.github/workflows/jruby.yml +0 -82
- data/.github/workflows/jruby.yml.example +0 -72
- data/.github/workflows/legacy.yml +0 -76
- data/.github/workflows/license-eye.yml +0 -40
- data/.github/workflows/locked_deps.yml +0 -85
- data/.github/workflows/opencollective.yml +0 -40
- data/.github/workflows/style.yml +0 -67
- data/.github/workflows/supported.yml +0 -75
- data/.github/workflows/truffle.yml +0 -99
- data/.github/workflows/unlocked_deps.yml +0 -84
- data/.github/workflows/unsupported.yml +0 -76
- data/.gitignore +0 -50
- data/.gitlab-ci.yml.example +0 -134
- data/.idea/.gitignore +0 -45
- data/.junie/guidelines-rbs.md +0 -49
- data/.junie/guidelines.md +0 -141
- data/.junie/guidelines.md.example +0 -140
- data/.licenserc.yaml +0 -7
- data/.opencollective.yml +0 -3
- data/.opencollective.yml.example +0 -3
- data/.qlty/qlty.toml +0 -79
- data/.rspec +0 -9
- data/.rubocop.yml +0 -13
- data/.rubocop_rspec.yml +0 -33
- data/.simplecov +0 -16
- data/.simplecov.example +0 -11
- data/.tool-versions +0 -1
- data/.yardignore +0 -13
- data/.yardopts +0 -14
- data/Appraisal.root.gemfile +0 -10
- data/Appraisals +0 -151
- data/Appraisals.example +0 -102
- data/CHANGELOG.md.example +0 -47
- data/CONTRIBUTING.md.example +0 -227
- data/FUNDING.md.no-osc.example +0 -63
- data/Gemfile +0 -40
- data/Gemfile.example +0 -34
- data/LICENSE.txt +0 -21
- data/README.md.example +0 -570
- data/README.md.no-osc.example +0 -536
- data/REEK +0 -0
- data/Rakefile.example +0 -68
- data/bin/setup +0 -8
- data/gemfiles/modular/coverage.gemfile +0 -6
- data/gemfiles/modular/debug.gemfile +0 -13
- data/gemfiles/modular/documentation.gemfile +0 -14
- data/gemfiles/modular/erb/r2/v3.0.gemfile +0 -1
- data/gemfiles/modular/erb/r2.3/default.gemfile +0 -6
- data/gemfiles/modular/erb/r2.6/v2.2.gemfile +0 -3
- data/gemfiles/modular/erb/r3/v5.0.gemfile +0 -1
- data/gemfiles/modular/erb/r3.1/v4.0.gemfile +0 -2
- data/gemfiles/modular/erb/vHEAD.gemfile +0 -2
- data/gemfiles/modular/injected.gemfile +0 -60
- data/gemfiles/modular/mutex_m/r2/v0.3.gemfile +0 -2
- data/gemfiles/modular/mutex_m/r2.4/v0.1.gemfile +0 -3
- data/gemfiles/modular/mutex_m/r3/v0.3.gemfile +0 -2
- data/gemfiles/modular/mutex_m/vHEAD.gemfile +0 -2
- data/gemfiles/modular/optional.gemfile +0 -8
- data/gemfiles/modular/optional.gemfile.example +0 -5
- data/gemfiles/modular/runtime_heads.gemfile +0 -10
- data/gemfiles/modular/runtime_heads.gemfile.example +0 -8
- data/gemfiles/modular/stringio/r2/v3.0.gemfile +0 -5
- data/gemfiles/modular/stringio/r2.4/v0.0.2.gemfile +0 -4
- data/gemfiles/modular/stringio/r3/v3.0.gemfile +0 -5
- data/gemfiles/modular/stringio/vHEAD.gemfile +0 -2
- data/gemfiles/modular/style.gemfile +0 -25
- data/gemfiles/modular/style.gemfile.example +0 -25
- data/gemfiles/modular/templating.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/r2/libs.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/r2.3/libs.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/r2.4/libs.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/r2.6/libs.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/r3/libs.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/r3.1/libs.gemfile +0 -3
- data/gemfiles/modular/x_std_libs/vHEAD.gemfile +0 -3
- data/gemfiles/modular/x_std_libs.gemfile +0 -2
- data/kettle-dev.gemspec.example +0 -154
- data/lib/kettle/dev/modular_gemfiles.rb +0 -119
- data/lib/kettle/dev/prism_appraisals.rb +0 -351
- data/lib/kettle/dev/prism_gemfile.rb +0 -177
- data/lib/kettle/dev/prism_gemspec.rb +0 -284
- data/lib/kettle/dev/prism_utils.rb +0 -201
- data/lib/kettle/dev/rakelib/install.rake +0 -10
- data/lib/kettle/dev/rakelib/template.rake +0 -10
- data/lib/kettle/dev/setup_cli.rb +0 -403
- data/lib/kettle/dev/source_merger.rb +0 -655
- data/lib/kettle/dev/tasks/install_task.rb +0 -553
- data/lib/kettle/dev/tasks/template_task.rb +0 -975
- data/lib/kettle/dev/template_helpers.rb +0 -685
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 423e786ae241791214751d2cd3496033ba0986b4279d738d62feda1eb197837b
|
|
4
|
+
data.tar.gz: 7c7436dcf0a65dea2d9241263bfd6d357c64a5f4a1a12432325fb5aecfe2cd38
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f7e35c2eedd5a7f4b75bd9ce4bfb0e98e269a05694875a6c53311aaab885d5a3d8839283b3ca986cd3b694f1f48b3bc3ed0dc28171decb1e5391ef61b0df0c2
|
|
7
|
+
data.tar.gz: abd66bf76d22b3d13303228bf46d22b4fbb7f69c26d0740e54ec6c693f3f31d10b34f9cc4491fb12be0e073777af8ca812d57eb740cd27af65b644bb445bba60
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -22,14 +22,237 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
22
22
|
|
|
23
23
|
### Changed
|
|
24
24
|
|
|
25
|
+
- **BREAKING**: Raised the minimum Ruby version to 2.4.0, matching
|
|
26
|
+
`kettle-test` 2.x and its runtime `turbo_tests2` dependency.
|
|
27
|
+
- `kettle-test` is now declared as a runtime dependency because the shipped rake
|
|
28
|
+
and changelog tasks invoke `bundle exec kettle-test`.
|
|
29
|
+
- Refreshed generated template output for README badge formatting and
|
|
30
|
+
Ruby 2.4-targeted RuboCop LTS style dependencies.
|
|
31
|
+
|
|
25
32
|
### Deprecated
|
|
26
33
|
|
|
27
34
|
### Removed
|
|
28
35
|
|
|
36
|
+
- Removed Ruby 2.3 and JRuby 9.1 CI workflows and appraisal gemfiles.
|
|
37
|
+
|
|
29
38
|
### Fixed
|
|
30
39
|
|
|
40
|
+
- Appraisal-based CI gemfiles now load the version-appropriate VCR/WebMock
|
|
41
|
+
recording dependencies required by the spec helper without falling back to the
|
|
42
|
+
root Gemfile.
|
|
43
|
+
- Reek, RuboCop-LTS, and coverage task specs now run in coverage CI without
|
|
44
|
+
requiring style-only dependencies.
|
|
45
|
+
- Reek rake task specs no longer change the process working directory, avoiding
|
|
46
|
+
cross-spec project root leakage under turbo workers.
|
|
47
|
+
- `rake reek:update` now raises a normal task error on unexpected reek exits
|
|
48
|
+
instead of calling `Kernel.abort`, so specs can assert the failure path without
|
|
49
|
+
poisoning the process exit status.
|
|
50
|
+
- Coverage CI thresholds now match the repository `mise.toml` thresholds instead
|
|
51
|
+
of requiring unreachable 100% line and branch coverage.
|
|
52
|
+
- Regenerated templating now keeps `kettle-test` as a runtime dependency only
|
|
53
|
+
instead of duplicating it as both runtime and development dependency.
|
|
54
|
+
- Replaced non-capturing `=~` checks with `Regexp#match?` so unlocked/style CI
|
|
55
|
+
stays clean with newer RuboCop performance cops.
|
|
56
|
+
- Cleared the remaining `rubocop_gradual` backlog and removed the lock file.
|
|
57
|
+
|
|
31
58
|
### Security
|
|
32
59
|
|
|
60
|
+
## [2.0.1] - 2026-05-25
|
|
61
|
+
|
|
62
|
+
- TAG: [v2.0.1][2.0.1t]
|
|
63
|
+
- COVERAGE: 94.88% -- 2911/3068 lines in 21 files
|
|
64
|
+
- BRANCH COVERAGE: 78.43% -- 1200/1530 branches in 21 files
|
|
65
|
+
- 76.25% documented
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- Added `kettle-changelog --update-prep` to refresh the most recent prepared
|
|
70
|
+
release section in place, including date, coverage, documentation stats, and
|
|
71
|
+
any follow-up Unreleased notes.
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- `kettle-changelog` now generates strict coverage data with
|
|
76
|
+
`bundle exec kettle-test`, preserving the faster `turbo_tests2` runner.
|
|
77
|
+
- `kettle-changelog` now treats configured coverage thresholds as a changelog
|
|
78
|
+
preparation gate by default; use `--no-coverage-threshold` or
|
|
79
|
+
`K_CHANGELOG_COVERAGE_HARD=false` to generate changelog metadata without
|
|
80
|
+
threshold enforcement.
|
|
81
|
+
- The shared `rake spec` task now delegates to `bundle exec kettle-test`, so
|
|
82
|
+
projects using kettle-dev automatically pick up kettle-test's default
|
|
83
|
+
`turbo_tests2` runner and summary output.
|
|
84
|
+
- The shared `:yard` task now installs `yard-fence` and `yard-timekeeper` integrations explicitly so documentation prep and post-processing only run during `rake yard`
|
|
85
|
+
|
|
86
|
+
- Refreshed generated kettle-jem templates, CI workflows, curated binstubs, and
|
|
87
|
+
local modular Gemfile wiring.
|
|
88
|
+
- `kettle-changelog` now auto-selects the correct no-argument action by
|
|
89
|
+
comparing `version.rb`, the latest live release, and the most recent
|
|
90
|
+
CHANGELOG.md release section before prompting for confirmation.
|
|
91
|
+
- Updated the development dependency on `kettle-test` to require 2.0.1 or newer.
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
|
|
95
|
+
- Loading YARD during unrelated rake tasks no longer triggers documentation plugin side effects that rewrite or clear `docs/`
|
|
96
|
+
|
|
97
|
+
- `rake reek:update` now resolves the Reek gem executable directly instead of
|
|
98
|
+
shelling through `bundle exec reek`, avoiding stale project binstubs, and no
|
|
99
|
+
longer fails the default task solely because Reek reported smells while
|
|
100
|
+
refreshing the `REEK` backlog file.
|
|
101
|
+
- `rake reek:update` now keeps `REEK` zero-byte when Reek reports no smells
|
|
102
|
+
instead of writing a single blank line.
|
|
103
|
+
|
|
104
|
+
## [2.0.0] - 2026-02-25
|
|
105
|
+
|
|
106
|
+
- TAG: [v2.0.0][2.0.0t]
|
|
107
|
+
- COVERAGE: 96.06% -- 2683/2793 lines in 20 files
|
|
108
|
+
- BRANCH COVERAGE: 79.16% -- 1113/1406 branches in 20 files
|
|
109
|
+
- 80.25% documented
|
|
110
|
+
|
|
111
|
+
### Added
|
|
112
|
+
|
|
113
|
+
- New `kettle-gh-release` executable for standalone GitHub release creation
|
|
114
|
+
- Extracted from `kettle-release` step 18
|
|
115
|
+
- Useful when RubyGems release succeeded but GitHub release failed
|
|
116
|
+
- Supports explicit version via `version=<VERSION>` argument
|
|
117
|
+
- Auto-detects version from `lib/**/version.rb` if not specified
|
|
118
|
+
- Requires `GITHUB_TOKEN` with `repo:public_repo` (classic) or `contents:write` scope
|
|
119
|
+
- Added `.kettle-dev.yml` configuration file for per-file merge options
|
|
120
|
+
- Hybrid format: `defaults` for shared merge options, `patterns` for glob fallbacks, `files` for per-file config
|
|
121
|
+
- Nested directory structure under `files` allows individual file configuration
|
|
122
|
+
- Supports all `Prism::Merge::SmartMerger` options: `preference`, `add_template_only_nodes`, `freeze_token`, `max_recursion_depth`
|
|
123
|
+
- Added `TemplateHelpers.kettle_config`, `.config_for`, `.find_file_config` methods
|
|
124
|
+
- Added spec coverage in `template_helpers_config_spec.rb`
|
|
125
|
+
|
|
126
|
+
### Changed
|
|
127
|
+
|
|
128
|
+
- Updated documentation on hostile takeover of RubyGems
|
|
129
|
+
- https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo
|
|
130
|
+
- **BREAKING**: Replaced `template_manifest.yml` with `.kettle-dev.yml`
|
|
131
|
+
- New hybrid format supports both glob patterns and per-file configuration
|
|
132
|
+
- `TemplateHelpers.load_manifest` now reads from `.kettle-dev.yml` patterns section
|
|
133
|
+
- `TemplateHelpers.strategy_for` checks explicit file configs before falling back to patterns
|
|
134
|
+
- **BREAKING**: Simplified `SourceMerger` to fully rely on prism-merge for AST merging
|
|
135
|
+
- Reduced from ~610 lines to ~175 lines (71% reduction)
|
|
136
|
+
- Removed custom newline normalization - prism-merge preserves original formatting
|
|
137
|
+
- Removed custom comment deduplication logic - prism-merge handles this natively
|
|
138
|
+
- All strategies (`:skip`, `:replace`, `:append`, `:merge`) now use prism-merge consistently
|
|
139
|
+
- Freeze blocks (`kettle-dev:freeze` / `kettle-dev:unfreeze`) handled by prism-merge's `freeze_token` option
|
|
140
|
+
|
|
141
|
+
### Removed
|
|
142
|
+
|
|
143
|
+
- Removed all `.example` template files from the kettle-dev root and subdirectories
|
|
144
|
+
(27 files). Template files now live exclusively in kettle-jem's `template/` directory.
|
|
145
|
+
Only `.env.local.example` is retained as a dev resource for all destination gems.
|
|
146
|
+
- Removed unused methods from `SourceMerger`:
|
|
147
|
+
- `normalize_source` - replaced by prism-merge
|
|
148
|
+
- `normalize_newlines` - prism-merge preserves original formatting
|
|
149
|
+
- `shebang?`, `magic_comment?`, `ruby_magic_comment_key?` - no longer needed
|
|
150
|
+
- Comment extraction/deduplication: `extract_magic_comments`, `extract_file_leading_comments`,
|
|
151
|
+
`create_comment_tuples`, `deduplicate_comment_sequences`, `deduplicate_sequences_pass1`,
|
|
152
|
+
`deduplicate_singles_pass2`, `extract_nodes_with_comments`, `count_blank_lines_before`,
|
|
153
|
+
`build_source_from_nodes`
|
|
154
|
+
- Unused comment restoration: `restore_custom_leading_comments`, `deduplicate_leading_comment_block`,
|
|
155
|
+
`extract_comment_lines`, `normalize_comment`, `leading_comment_block`
|
|
156
|
+
- Removed unused constants: `RUBY_MAGIC_COMMENT_KEYS`, `MAGIC_COMMENT_REGEXES`
|
|
157
|
+
|
|
158
|
+
### Fixed
|
|
159
|
+
|
|
160
|
+
- Fixed `PrismAppraisals` various comment chunk spacing
|
|
161
|
+
- extract_block_header:
|
|
162
|
+
- skips the blank spacer immediately above an `appraise` block
|
|
163
|
+
- treats any following blank line as the stop boundary once comment lines have been collected
|
|
164
|
+
- prevents preamble comments from being pulled into the first block’s header
|
|
165
|
+
- restores expected ordering:
|
|
166
|
+
- magic comments and their blank line stay at the top
|
|
167
|
+
- block headers remain adjacent to their blocks
|
|
168
|
+
- preserves blank lines between comment chunks
|
|
169
|
+
- Fixed `SourceMerger` freeze block location preservation
|
|
170
|
+
- Freeze blocks now stay in their original location in the file structure
|
|
171
|
+
- Skip normalization for files with existing freeze blocks to prevent movement
|
|
172
|
+
- Only include contiguous comments immediately before freeze markers (no arbitrary 3-line lookback)
|
|
173
|
+
- Don't add freeze reminder to files that already have freeze/unfreeze blocks
|
|
174
|
+
- Prevents unrelated comments from being incorrectly captured in freeze block ranges
|
|
175
|
+
- Added comprehensive test coverage for multiple freeze blocks at different nesting levels
|
|
176
|
+
- Fixed `TemplateTask` to not override template summary/description with empty strings from destination gemspec
|
|
177
|
+
- Only carries over summary/description when they contain actual content (non-empty)
|
|
178
|
+
- Allows token replacements to work correctly (e.g., `kettle-dev summary` → `my-gem summary`)
|
|
179
|
+
- Prevents empty destination fields from erasing meaningful template values
|
|
180
|
+
- Fixed `SourceMerger` magic comment ordering and freeze block protection
|
|
181
|
+
- Magic comments now preserve original order
|
|
182
|
+
- No blank lines inserted between consecutive magic comments
|
|
183
|
+
- Freeze reminder block properly separated from magic comments (not merged)
|
|
184
|
+
- Leverages Prism's built-in `parse_result.magic_comments` API for accurate detection
|
|
185
|
+
- Detects `kettle-dev:freeze/unfreeze` pairs using Prism, then reclassifies as file-level comments to keep blocks intact
|
|
186
|
+
- Removed obsolete `is_magic_comment?` method in favor of Prism's native detection
|
|
187
|
+
- Fixed `PrismGemspec` and `PrismGemfile` to use pure Prism AST traversal instead of regex fallbacks
|
|
188
|
+
- Removed regex-based `extract_gemspec_emoji` that parsed `spec.summary =` and `spec.description =` with regex
|
|
189
|
+
- Now traverses Prism AST to find Gem::Specification block, extracts summary/description nodes, and gets literal values
|
|
190
|
+
- Removed regex-based source line detection in `PrismGemfile.merge_gem_calls`
|
|
191
|
+
- Now uses `PrismUtils.statement_key` to find source statements via AST instead of `ln =~ /^\s*source\s+/`
|
|
192
|
+
- Aligns with project goal: move away from regex parsing toward proper AST manipulation with Prism
|
|
193
|
+
- All functionality preserved, tested, and working correctly
|
|
194
|
+
- Fixed `PrismGemspec.replace_gemspec_fields` block parameter extraction to use Prism AST
|
|
195
|
+
- **CRITICAL**: Was using regex fallback that incorrectly captured entire block body as parameter name
|
|
196
|
+
- Removed buggy regex fallback in favor of pure Prism AST traversal
|
|
197
|
+
- Now properly extracts block parameter from Prism::BlockParametersNode → Prism::ParametersNode → Prism::RequiredParameterNode
|
|
198
|
+
- Fixed `PrismGemspec.replace_gemspec_fields` insert offset calculation for emoji-containing gemspecs
|
|
199
|
+
- **CRITICAL**: Was using character length (`String#length`) instead of byte length (`String#bytesize`) to calculate insert offset
|
|
200
|
+
- When gemspecs contain multi-byte UTF-8 characters (emojis like 🍲), character length != byte length
|
|
201
|
+
- This caused fields to be inserted at wrong byte positions, resulting in truncated strings and massive corruption
|
|
202
|
+
- Changed `body_src.rstrip.length` to `body_src.rstrip.bytesize` for correct byte-offset calculations
|
|
203
|
+
- Prevents gemspec templating from producing corrupted output with truncated dependency lines
|
|
204
|
+
- Added comprehensive debug logging to trace byte offset calculations and edit operations
|
|
205
|
+
- Fixed `SourceMerger` variable assignment duplication during merge operations
|
|
206
|
+
- `node_signature` now identifies variable/constant assignments by name only, not full source
|
|
207
|
+
- Previously used full source text as signature, causing duplicates when assignment bodies differed
|
|
208
|
+
- Added specific handlers for: LocalVariableWriteNode, InstanceVariableWriteNode, ClassVariableWriteNode, ConstantWriteNode, GlobalVariableWriteNode
|
|
209
|
+
- Also added handlers for ClassNode and ModuleNode to match by name
|
|
210
|
+
- Example: `gem_version = ...` assignments with different bodies now correctly merge instead of duplicating
|
|
211
|
+
- Prevents `bin/kettle-dev-setup` from creating duplicate variable assignments in gemspecs and other files
|
|
212
|
+
- Added comprehensive specs for variable assignment deduplication and idempotency
|
|
213
|
+
- Fixed `SourceMerger` conditional block duplication during merge operations
|
|
214
|
+
- `node_signature` now identifies conditional nodes (if/unless/case) by their predicate only
|
|
215
|
+
- Previously used full source text, causing duplicate blocks when template updates conditional bodies
|
|
216
|
+
- Example: if ENV["FOO"] blocks with different bodies now correctly merge instead of duplicating
|
|
217
|
+
- Prevents `bin/kettle-dev-setup` from creating duplicate if/else blocks in gemfiles
|
|
218
|
+
- Added comprehensive specs for conditional merging behavior and idempotency
|
|
219
|
+
- Fixed `PrismGemspec.replace_gemspec_fields` to use byte-aware string operations
|
|
220
|
+
- **CRITICAL**: Was using character-based `String#[]=` with Prism's byte offsets
|
|
221
|
+
- This caused catastrophic corruption when emojis or multi-byte UTF-8 characters were present
|
|
222
|
+
- Symptoms: gemspec blocks duplicated/fragmented, statements escaped outside blocks
|
|
223
|
+
- Now uses `byteslice` and byte-aware concatenation for all edit operations
|
|
224
|
+
- Prevents gemspec templating from producing mangled output with duplicated Gem::Specification blocks
|
|
225
|
+
- Fixed `PrismGemspec.replace_gemspec_fields` to correctly handle multi-byte UTF-8 characters (e.g., emojis)
|
|
226
|
+
- Prism uses byte offsets, not character offsets, when parsing Ruby code
|
|
227
|
+
- Changed string slicing from `String#[]` to `String#byteslice` for all offset-based operations
|
|
228
|
+
- Added validation to use `String#bytesize` instead of `String#length` for offset bounds checking
|
|
229
|
+
- Prevents `TypeError: no implicit conversion of nil into String` when gemspecs contain emojis
|
|
230
|
+
- Ensures gemspec field carryover works correctly with emoji in summary/description fields
|
|
231
|
+
- Enhanced error reporting to show backtraces when debug mode is enabled
|
|
232
|
+
|
|
233
|
+
## [1.2.5] - 2025-11-28
|
|
234
|
+
|
|
235
|
+
- TAG: [v1.2.5][1.2.5t]
|
|
236
|
+
- COVERAGE: 93.53% -- 4726/5053 lines in 31 files
|
|
237
|
+
- BRANCH COVERAGE: 76.62% -- 1924/2511 branches in 31 files
|
|
238
|
+
- 69.89% documented
|
|
239
|
+
|
|
240
|
+
### Added
|
|
241
|
+
|
|
242
|
+
- Comprehensive newline normalization in templated Ruby files:
|
|
243
|
+
- Magic comments (frozen_string_literal, encoding, etc.) always followed by single blank line
|
|
244
|
+
- No more than one consecutive blank line anywhere in file
|
|
245
|
+
- Single newline at end of file (no trailing blank lines)
|
|
246
|
+
- Freeze reminder block now includes blank line before and empty comment line after for better visual separation
|
|
247
|
+
|
|
248
|
+
### Changed
|
|
249
|
+
|
|
250
|
+
- Updated `FREEZE_REMINDER` constant to include blank line before and empty comment line after
|
|
251
|
+
|
|
252
|
+
### Fixed
|
|
253
|
+
|
|
254
|
+
- Fixed `reminder_present?` to correctly detect freeze reminder when it has leading blank line
|
|
255
|
+
|
|
33
256
|
## [1.2.4] - 2025-11-28
|
|
34
257
|
|
|
35
258
|
- TAG: [v1.2.4][1.2.4t]
|
|
@@ -45,7 +268,7 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
45
268
|
- Ensures truly idempotent behavior when running templating multiple times on the same file
|
|
46
269
|
- Example: `frozen_string_literal` comments no longer multiply from 1→4→5→6 on repeated runs
|
|
47
270
|
|
|
48
|
-
## [1.2.3] - 2025-11-
|
|
271
|
+
## [1.2.3] - 2025-11-28vari
|
|
49
272
|
|
|
50
273
|
- TAG: [v1.2.3][1.2.3t]
|
|
51
274
|
- COVERAGE: 93.43% -- 4681/5010 lines in 31 files
|
|
@@ -1138,7 +1361,7 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
1138
1361
|
- <!-- RELEASE-NOTES-FOOTER-END -->
|
|
1139
1362
|
- truffle workflow: Repeat attempts for bundle install and appraisal bundle before failure
|
|
1140
1363
|
- global token replacement during kettle:dev:install
|
|
1141
|
-
-
|
|
1364
|
+
- kettle-dev => kettle-dev
|
|
1142
1365
|
- {RUBOCOP|LTS|CONSTRAINT} => dynamic
|
|
1143
1366
|
- {RUBOCOP|RUBY|GEM} => dynamic
|
|
1144
1367
|
- default to rubocop-ruby1_8 if no minimum ruby specified
|
|
@@ -1522,7 +1745,13 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
1522
1745
|
- Selecting will run the selected workflow via `act`
|
|
1523
1746
|
- This may move to its own gem in the future.
|
|
1524
1747
|
|
|
1525
|
-
[Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/
|
|
1748
|
+
[Unreleased]: https://github.com/kettle-rb/kettle-dev/compare/v2.0.1...HEAD
|
|
1749
|
+
[2.0.1]: https://github.com/kettle-rb/kettle-dev/compare/v2.0.0...v2.0.1
|
|
1750
|
+
[2.0.1t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v2.0.1
|
|
1751
|
+
[2.0.0]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.5...v2.0.0
|
|
1752
|
+
[2.0.0t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v2.0.0
|
|
1753
|
+
[1.2.5]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.4...v1.2.5
|
|
1754
|
+
[1.2.5t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.2.5
|
|
1526
1755
|
[1.2.4]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.3...v1.2.4
|
|
1527
1756
|
[1.2.4t]: https://github.com/kettle-rb/kettle-dev/releases/tag/v1.2.4
|
|
1528
1757
|
[1.2.3]: https://github.com/kettle-rb/kettle-dev/compare/v1.2.2...v1.2.3
|
data/CITATION.cff
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
cff-version: 1.2.0
|
|
2
|
-
title: kettle-dev
|
|
2
|
+
title: "kettle-dev"
|
|
3
3
|
message: >-
|
|
4
4
|
If you use this work and you want to cite it,
|
|
5
5
|
then you can use the metadata from this file.
|
|
6
6
|
type: software
|
|
7
7
|
authors:
|
|
8
|
-
- given-names: Peter
|
|
9
|
-
family-names: Boling
|
|
10
|
-
email:
|
|
11
|
-
affiliation:
|
|
8
|
+
- given-names: "Peter H."
|
|
9
|
+
family-names: "Boling"
|
|
10
|
+
email: "floss@galtzo.com"
|
|
11
|
+
affiliation: "galtzo.com"
|
|
12
12
|
orcid: 'https://orcid.org/0009-0008-8519-441X'
|
|
13
13
|
identifiers:
|
|
14
14
|
- type: url
|
|
15
15
|
value: 'https://github.com/kettle-rb/kettle-dev'
|
|
16
|
-
description: kettle-dev
|
|
16
|
+
description: "kettle-dev"
|
|
17
17
|
repository-code: 'https://github.com/kettle-rb/kettle-dev'
|
|
18
18
|
abstract: >-
|
|
19
19
|
kettle-dev
|
data/CONTRIBUTING.md
CHANGED
|
@@ -8,25 +8,34 @@ To submit a patch, please fork the project, create a patch with tests, and send
|
|
|
8
8
|
|
|
9
9
|
Remember to [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] if you make changes.
|
|
10
10
|
|
|
11
|
+
## Developer Certificate of Origin
|
|
12
|
+
|
|
13
|
+
In order to protect users of this project, we require all contributors to comply with the
|
|
14
|
+
[Developer Certificate of Origin](https://developercertificate.org/).
|
|
15
|
+
This ensures that all contributions are properly licensed and attributed.
|
|
16
|
+
|
|
11
17
|
## Help out!
|
|
12
18
|
|
|
13
|
-
Take a look at the
|
|
19
|
+
Take a look at the open issues and pull requests, or use the gem and find something to improve.
|
|
14
20
|
|
|
15
21
|
Follow these instructions:
|
|
16
22
|
|
|
17
|
-
1.
|
|
18
|
-
2.
|
|
19
|
-
3.
|
|
20
|
-
4.
|
|
21
|
-
5.
|
|
22
|
-
6.
|
|
23
|
-
7.
|
|
23
|
+
1. Join the Discord: [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite]
|
|
24
|
+
2. Fork the repository
|
|
25
|
+
3. Create your feature branch (`git checkout -b my-new-feature`)
|
|
26
|
+
4. Make some fixes.
|
|
27
|
+
5. Commit your changes (`git commit -am 'Added some feature'`)
|
|
28
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
|
29
|
+
7. Make sure to add tests for it. This is important, so it doesn't break in a future release.
|
|
30
|
+
8. Create new Pull Request.
|
|
31
|
+
9. Announce it in the channel for this org in the [Discord][✉️discord-invite]!
|
|
24
32
|
|
|
25
33
|
## Executables vs Rake tasks
|
|
26
34
|
|
|
27
|
-
Executables shipped by kettle-dev
|
|
28
|
-
|
|
35
|
+
Executables shipped by dependencies, such as kettle-dev, and stone_checksums, are available
|
|
36
|
+
after running `bin/setup`. These include:
|
|
29
37
|
|
|
38
|
+
- gem_checksums
|
|
30
39
|
- kettle-changelog
|
|
31
40
|
- kettle-commit-msg
|
|
32
41
|
- kettle-dev-setup
|
|
@@ -35,20 +44,26 @@ They will work when kettle-dev is installed globally (i.e., `gem install kettle-
|
|
|
35
44
|
- kettle-readme-backers
|
|
36
45
|
- kettle-release
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
See the full list of rake tasks in head of Rakefile
|
|
47
|
+
There are many Rake tasks available as well. You can see them by running:
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
group :development do
|
|
44
|
-
gem "kettle-dev", require: false
|
|
45
|
-
end
|
|
49
|
+
```shell
|
|
50
|
+
bin/rake -T
|
|
46
51
|
```
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
## Code quality checks
|
|
54
|
+
|
|
55
|
+
Run the Reek task when you want a smell check that fails on current findings:
|
|
56
|
+
|
|
57
|
+
```shell
|
|
58
|
+
bin/rake reek
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Refresh the checked-in `REEK` backlog through the rake task, not by redirecting
|
|
62
|
+
the raw `reek` executable output. The rake task uses the project bundle and
|
|
63
|
+
avoids stale generated binstubs shadowing the Reek gem executable:
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
bin/rake reek:update
|
|
52
67
|
```
|
|
53
68
|
|
|
54
69
|
## Environment Variables for Local Development
|
|
@@ -61,7 +76,7 @@ General/runtime
|
|
|
61
76
|
- CI: When set to true, adjusts default rake tasks toward CI behavior
|
|
62
77
|
|
|
63
78
|
Coverage (kettle-soup-cover / SimpleCov)
|
|
64
|
-
- K_SOUP_COV_DO: Enable coverage collection (default: true in .
|
|
79
|
+
- K_SOUP_COV_DO: Enable coverage collection (default: true in `mise.toml`)
|
|
65
80
|
- K_SOUP_COV_FORMATTERS: Comma-separated list of formatters (html, xml, rcov, lcov, json, tty)
|
|
66
81
|
- K_SOUP_COV_MIN_LINE: Minimum line coverage threshold (integer, e.g., 100)
|
|
67
82
|
- K_SOUP_COV_MIN_BRANCH: Minimum branch coverage threshold (integer, e.g., 100)
|
|
@@ -77,7 +92,9 @@ GitHub API and CI helpers
|
|
|
77
92
|
Releasing and signing
|
|
78
93
|
- SKIP_GEM_SIGNING: If set, skip gem signing during build/release
|
|
79
94
|
- GEM_CERT_USER: Username for selecting your public cert in `certs/<USER>.pem` (defaults to $USER)
|
|
80
|
-
- SOURCE_DATE_EPOCH: Reproducible build timestamp.
|
|
95
|
+
- SOURCE_DATE_EPOCH: Reproducible build timestamp.
|
|
96
|
+
- `kettle-release` will set this automatically for the session.
|
|
97
|
+
- Not needed on bundler >= 2.7.0, as reproducible builds have become the default.
|
|
81
98
|
|
|
82
99
|
Git hooks and commit message helpers (exe/kettle-commit-msg)
|
|
83
100
|
- GIT_HOOK_BRANCH_VALIDATE: Branch name validation mode (e.g., `jira`) or `false` to disable
|
|
@@ -85,7 +102,7 @@ Git hooks and commit message helpers (exe/kettle-commit-msg)
|
|
|
85
102
|
- GIT_HOOK_FOOTER_SENTINEL: Required when footer append is enabled — a unique first-line sentinel to prevent duplicates
|
|
86
103
|
- GIT_HOOK_FOOTER_APPEND_DEBUG: Extra debug output in the footer template (true/false)
|
|
87
104
|
|
|
88
|
-
For a quick starting point, this repository’s
|
|
105
|
+
For a quick starting point, this repository’s `mise.toml` defines the shared defaults, and `.env.local` can override them locally. Copy `.env.local.example` to `.env.local`, use `KEY=value` lines, and either activate `mise` in your shell or run commands through `mise exec -C /path/to/project -- ...`.
|
|
89
106
|
|
|
90
107
|
## Appraisals
|
|
91
108
|
|
|
@@ -104,22 +121,20 @@ bin/rake appraisal:reset
|
|
|
104
121
|
|
|
105
122
|
When adding an appraisal to CI, check the [runner tool cache][🏃♂️runner-tool-cache] to see which runner to use.
|
|
106
123
|
|
|
107
|
-
##
|
|
108
|
-
|
|
109
|
-
Take a look at the `reek` list which is the file called `REEK` and find something to improve.
|
|
124
|
+
## Run Tests
|
|
110
125
|
|
|
111
|
-
|
|
126
|
+
Run tests via `kettle-test` (provided by `kettle-test`). It runs RSpec, writes the full log to
|
|
127
|
+
`tmp/kettle-test/rspec-TIMESTAMP.log`, and prints a compact highlight block with timing, seed,
|
|
128
|
+
pass/fail count, failing example list, and SimpleCov coverage percentages.
|
|
112
129
|
|
|
113
130
|
```console
|
|
114
|
-
bundle exec
|
|
131
|
+
bundle exec kettle-test
|
|
115
132
|
```
|
|
116
133
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
To run all tests
|
|
134
|
+
For targeted runs, disable the hard coverage threshold to avoid false failures:
|
|
120
135
|
|
|
121
136
|
```console
|
|
122
|
-
bundle exec
|
|
137
|
+
K_SOUP_COV_MIN_HARD=false bundle exec kettle-test spec/path/to/spec.rb
|
|
123
138
|
```
|
|
124
139
|
|
|
125
140
|
### Spec organization (required)
|
|
@@ -148,7 +163,7 @@ For more detailed information about using RuboCop in this project, please see th
|
|
|
148
163
|
Never add `# rubocop:disable ...` / `# rubocop:enable ...` comments to code or specs (except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). Instead:
|
|
149
164
|
|
|
150
165
|
- Prefer configuration-based exclusions when a rule should not apply to certain paths or files (e.g., via `.rubocop.yml`).
|
|
151
|
-
- When a violation is temporary and you plan to fix it later, record it in `.rubocop_gradual.lock` using the gradual workflow:
|
|
166
|
+
- When a violation is temporary, and you plan to fix it later, record it in `.rubocop_gradual.lock` using the gradual workflow:
|
|
152
167
|
- `bundle exec rake rubocop_gradual:autocorrect` (preferred)
|
|
153
168
|
- `bundle exec rake rubocop_gradual:force_update` (only when you cannot fix the violations immediately)
|
|
154
169
|
|
|
@@ -183,39 +198,41 @@ NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in th
|
|
|
183
198
|
1. Update version.rb to contain the correct version-to-be-released.
|
|
184
199
|
2. Run `bundle exec kettle-changelog`.
|
|
185
200
|
3. Run `bundle exec kettle-release`.
|
|
201
|
+
4. Stay awake and monitor the release process for any errors, and answer any prompts.
|
|
186
202
|
|
|
187
203
|
#### Manual process
|
|
188
204
|
|
|
189
205
|
1. Run `bin/setup && bin/rake` as a "test, coverage, & linting" sanity check
|
|
190
206
|
2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes
|
|
191
207
|
3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock`
|
|
192
|
-
4. Run `
|
|
193
|
-
5. Run `git
|
|
208
|
+
4. Run `bin/rake yard` to regenerate the docs site using the canonical docs task
|
|
209
|
+
5. Run `git commit -am "🔖 Prepare release v<VERSION>"` to commit the changes
|
|
210
|
+
6. Run `git push` to trigger the final CI pipeline before release, and merge PRs
|
|
194
211
|
- NOTE: Remember to [check the build][🧪build].
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
7. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME`
|
|
213
|
+
8. Run `git checkout $GIT_TRUNK_BRANCH_NAME`
|
|
214
|
+
9. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure latest trunk code
|
|
215
|
+
10. Optional for older Bundler (< 2.7.0): Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use the same timestamp and generate the same checksums
|
|
199
216
|
- If your Bundler is >= 2.7.0, you can skip this; builds are reproducible by default.
|
|
200
217
|
- Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH`
|
|
201
218
|
- If the echo above has no output, then it didn't work.
|
|
202
219
|
- Note: `zsh/datetime` module is needed, if running `zsh`.
|
|
203
220
|
- In older versions of `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH`
|
|
204
|
-
|
|
205
|
-
|
|
221
|
+
11. Run `bundle exec rake build`
|
|
222
|
+
12. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr])
|
|
206
223
|
to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums`
|
|
207
224
|
[gem][💎stone_checksums].
|
|
208
225
|
- The script automatically commits but does not push the checksums
|
|
209
|
-
|
|
226
|
+
13. Sanity check the SHA256, comparing with the output from the `bin/gem_checksums` command:
|
|
210
227
|
- `sha256sum pkg/<gem name>-<version>.gem`
|
|
211
|
-
|
|
228
|
+
14. Run `bundle exec rake release` which will create a git tag for the version,
|
|
212
229
|
push git commits and tags, and push the `.gem` file to the gem host configured in the gemspec.
|
|
213
230
|
|
|
214
|
-
[📜src-gl]: https://gitlab.com/kettle-rb/kettle-dev
|
|
231
|
+
[📜src-gl]: https://gitlab.com/kettle-rb/kettle-dev
|
|
215
232
|
[📜src-cb]: https://codeberg.org/kettle-rb/kettle-dev
|
|
216
233
|
[📜src-gh]: https://github.com/kettle-rb/kettle-dev
|
|
217
234
|
[🧪build]: https://github.com/kettle-rb/kettle-dev/actions
|
|
218
|
-
[🤝conduct]: https://
|
|
235
|
+
[🤝conduct]: https://github.com/kettle-rb/kettle-dev/blob/main/CODE_OF_CONDUCT.md
|
|
219
236
|
[🖐contrib-rocks]: https://contrib.rocks
|
|
220
237
|
[🖐contributors]: https://github.com/kettle-rb/kettle-dev/graphs/contributors
|
|
221
238
|
[🚎contributors-gl]: https://gitlab.com/kettle-rb/kettle-dev/-/graphs/main
|
|
@@ -231,3 +248,4 @@ NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in th
|
|
|
231
248
|
[📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
|
|
232
249
|
[🚎appraisal2]: https://github.com/appraisal-rb/appraisal2
|
|
233
250
|
[🏃♂️runner-tool-cache]: https://github.com/ruby/ruby-builder/releases/tag/toolcache
|
|
251
|
+
[✉️discord-invite]: https://discord.gg/3qme4XHNKN
|
data/FUNDING.md
CHANGED
|
@@ -19,7 +19,7 @@ Many paths lead to being a sponsor or a backer of this project. Are you on such
|
|
|
19
19
|
[🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
|
|
20
20
|
[🖇polar]: https://polar.sh/pboling
|
|
21
21
|
[🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
|
|
22
|
-
[🖇kofi]: https://ko-fi.com/
|
|
22
|
+
[🖇kofi]: https://ko-fi.com/pboling
|
|
23
23
|
[🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
|
|
24
24
|
[🖇patreon]: https://patreon.com/galtzo
|
|
25
25
|
[🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
This project is made available under the following license.
|
|
4
|
+
Choose the option that best fits your use case:
|
|
5
|
+
|
|
6
|
+
- [AGPL-3.0-only](AGPL-3.0-only.md)
|
|
7
|
+
|
|
8
|
+
If none of the above licenses fit your use case, please [contact us](mailto:floss@galtzo.com) to discuss a custom commercial license.
|
|
9
|
+
|
|
10
|
+
## Copyright Notice
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2023, 2025-2026 Peter H. Boling
|