gempilot 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d85c949ecc31934a9f30013cf3216e6f5560f83f4847caf1ac7d54fad31556b
4
- data.tar.gz: b27b62a0b5491c32152ef170b300fe2a1bebcce9b848936d6472688bacce545f
3
+ metadata.gz: b4b895f3da5d0d8866cd13f835dd3c1ca71d8d433571c2d7531735636eeb6ad0
4
+ data.tar.gz: 878dad31a22bdecdb9ff607ebecf2330432070219edfc3e08b66a5022c205d77
5
5
  SHA512:
6
- metadata.gz: dcda741a835bb6c586adb888ec6e790edd7c7c72029034d161da046b15e187c7934fbe7bfad65481a056a981bf86bda3b4d910ea7181d67fee0968faa423a4dc
7
- data.tar.gz: 4f7ac2bad5ab9f332eec6de811d705ea825587a3d4dfbc0dae860e6bdc9520da30fe89dcca3ae3c57d094c0eab2617b535b7d7f17aa7cb9f270ea37b5dbb7f29
6
+ metadata.gz: ccfc9410fe3ccd3cc8f49e3ca34f68ef334a50183eb95d0788f09c9a5e972fcb4b1244cdfeee188b9898e25ba1c4542d6c4cf24ee24e54edebd4e8b8e907f6a1
7
+ data.tar.gz: e7deb74172aa7bcd75d84f41ad2d80022d9befcd7f1b69990c6f8b9fe6002168d8b25581242dbded279bdd601986c24552b1431573ff0ed62bec8316734e50fe
data/.rubocop.yml CHANGED
@@ -15,10 +15,11 @@ plugins:
15
15
  - rubocop-performance
16
16
  - rubocop-rake
17
17
  - rubocop-rspec
18
+ - rubocop-design
18
19
 
19
20
  AllCops:
20
21
  NewCops: enable
21
- TargetRubyVersion: 3.4
22
+ TargetRubyVersion: 4.0
22
23
  Exclude:
23
24
  - bin/*
24
25
  - vendor/**/*
@@ -279,3 +280,17 @@ RSpec/NamedSubject:
279
280
  # have_file_content matcher accepts a filename string in expect()
280
281
  RSpec/ExpectActual:
281
282
  Enabled: false
283
+
284
+ Design/PositionalArguments:
285
+ Enabled: false
286
+
287
+ Design/KeywordArguments:
288
+ Enabled: false
289
+
290
+ Design/TotalArguments:
291
+ Enabled: false
292
+
293
+ Design/AgentNounClassName:
294
+ Exclude:
295
+ - 'lib/gempilot/generator.rb'
296
+ - 'test/gempilot/cli/generator_test.rb'
data/CLAUDE.md CHANGED
@@ -20,6 +20,7 @@ A CLI tool for creating and managing Ruby gems, built on CommandKit.
20
20
  - Uses CommandKit::Inflector for name inflection
21
21
  - Generator module (`lib/gempilot/cli/generator.rb`) provides template rendering via ERB
22
22
  - GemContext module (`lib/gempilot/cli/gem_context.rb`) shared by new, destroy, release, console
23
+ - `GemConstant` value object (`lib/gempilot/gem_constant.rb`) owns constant→namespace/path resolution for `new`/`destroy`; constants are rooted at the gem module by construction
23
24
  - CommandKit::Commands::AutoLoad maps filenames in `commands/` to command names
24
25
 
25
26
  ### Testing
@@ -34,12 +35,4 @@ A CLI tool for creating and managing Ruby gems, built on CommandKit.
34
35
  - RuboCop with framework-specific plugins
35
36
  - GitHub Actions CI workflow (`.github/workflows/ci.yml`)
36
37
  - `git ls-files`-based gemspec with glob fallback for non-git repos
37
- - Version management rake tasks in `rakelib/version.rake` (current, bump, commit, revert, release:full)
38
-
39
- ### Notes
40
- - AutoLoad uses block form in `cli.rb` with explicit `summary:` per command (lazy loading means descriptions aren't available at help time without this)
41
-
42
-
43
- ## ISSUES
44
-
45
- 1. RESOLVED — `exe/gempilot` had unconditional `ENV["BUNDLE_GEMFILE"]` and `require "bundler/setup"`, causing `Gemfile not found` after `gem install`. Removed both lines; RubyGems handles load paths for installed gems. (Ronin avoids this with a conditional `Gemfile.lock` check, but gempilot's `exe/`+`bin/` separation makes that unnecessary.)
38
+ - Version lifecycle rake tasks installed via `Gempilot::VersionTask.new` (a `Rake::TaskLib`): `version:current/bump/commit/tag/untag/reset/revert`, composite `version:release`/`version:unrelease`, and `version:github:release/unrelease/list`
data/issues.rec CHANGED
@@ -26,7 +26,7 @@ Id: F0833E66-A35C-4054-884B-F90C81F08838
26
26
  Updated: Mon, 02 Mar 2026 10:37:33 -0500
27
27
  Title: Error handling should be graceful
28
28
  Description: I did "gempilot create", and entered "A foo" as the title, and it crashed horrifically. This particular example should have validation at the minimum. Need to also use command kit's error bubbling/handling mechanism to swallow errors and print message to user. Can always use verbose or debug mode to see full trace.
29
- Status: open
29
+ Status: closed
30
30
 
31
31
  Id: 741FFD05-9BD7-44EB-BB99-E7D705F12681
32
32
  Updated: Mon, 02 Mar 2026 11:25:24 -0500
@@ -68,7 +68,7 @@ Id: 74D0FD90-0421-4452-8591-2798EE6FD23E
68
68
  Updated: Sat, 28 Mar 2026 12:59:40 -0400
69
69
  Title: Publish gem
70
70
  Description: At some point the repo should be moved to public viz, and the gem should be published.
71
- Status: open
71
+ Status: closed
72
72
 
73
73
  Id: 8C356024-3122-11F1-89F3-FE6CB9572C2F
74
74
  Updated: Mon, 06 Apr 2026 00:00:00 -0400
@@ -141,3 +141,30 @@ Description: "
141
141
  + ```
142
142
  + "
143
143
  Status: closed
144
+
145
+ Id: 1C46F71C-70E9-11F1-B65B-FE6CB9572C2E
146
+ Updated: Thu, 25 Jun 2026 18:56:32 -0400
147
+ Title: Incorrectly creates test file
148
+ Description: When doing `gempilot new Reversal::Server`, in a project called "reversal-store", I get:
149
+ +
150
+ + gempilot new class Reversal::Server
151
+ +
152
+ + Adding class Reversal::Server...
153
+ +
154
+ + create lib/reversal/server.rb
155
+ + create test/reversal/store_test.rb
156
+ +
157
+ + The test file is incorrectly named. Should be server_test.rb
158
+ Status: open
159
+
160
+ Id: F5486B48-71DB-11F1-980F-FE6CB9572C2E
161
+ Updated: Fri, 26 Jun 2026 23:54:55 -0400
162
+ Title: Rubymine <=> Minitest usage causes "no reporters allowed error"
163
+ Description: Has to do with how the ENV var RM_INFO is being interpreted
164
+ Status: open
165
+
166
+ Id: 8D847572-7273-11F1-B508-FE6CB9572C2E
167
+ Updated: Sat, 27 Jun 2026 18:00:04 -0400
168
+ Title: Gem extensions are broken
169
+ Description: when using gempilot on a gem extension, like 'foo-support', using idiomatic ruby patterns for dir structure, gempilot Project class throws an error
170
+ Status: open
@@ -27,9 +27,8 @@ module Gempilot
27
27
  end
28
28
 
29
29
  def print_console_banner
30
- puts colors.bright_white("Starting console for ") +
31
- colors.bold(colors.cyan(@gem_name)) +
32
- colors.bright_white("...")
30
+ styled_name = colors.bold(colors.cyan(@gem_name))
31
+ puts colors.bright_white("Starting console for ") + styled_name + colors.bright_white("...")
33
32
  puts
34
33
  end
35
34
  end
@@ -156,7 +156,8 @@ module Gempilot
156
156
 
157
157
  puts
158
158
  puts colors.bright_black("An executable in exe/ lets users run your gem from the command line.")
159
- options[:exe] = ask_yes_or_no(colors.green("Create an executable"), default: false)
159
+ prompt = colors.green("Create an executable")
160
+ options[:exe] = ask_yes_or_no(prompt, default: false)
160
161
  end
161
162
 
162
163
  def collect_git_options
@@ -169,7 +170,8 @@ module Gempilot
169
170
 
170
171
  puts
171
172
  puts colors.bright_black("Initialize a git repository with an initial commit.")
172
- options[:git] = ask_yes_or_no(colors.green("Initialize git repo"), default: true)
173
+ prompt = colors.green("Initialize git repo")
174
+ options[:git] = ask_yes_or_no(prompt, default: true)
173
175
  end
174
176
 
175
177
  def collect_branch
@@ -181,8 +183,9 @@ module Gempilot
181
183
  end
182
184
 
183
185
  def print_header
186
+ styled_name = colors.bold(colors.cyan(@gem_name))
184
187
  puts
185
- puts colors.bright_white("Creating gem '") + colors.bold(colors.cyan(@gem_name)) + colors.bright_white("'...")
188
+ puts colors.bright_white("Creating gem '") + styled_name + colors.bright_white("'...")
186
189
  puts
187
190
  end
188
191
 
@@ -27,7 +27,7 @@ module Gempilot
27
27
  def run(type = nil, path = nil)
28
28
  type ||= prompt_for_type
29
29
  detect_gem_context
30
- path ||= prompt_for_path
30
+ path ||= prompt_for_path(type)
31
31
  dispatch_destroy(type, path)
32
32
  end
33
33
 
@@ -38,16 +38,14 @@ module Gempilot
38
38
  ask_multiple_choice(colors.green("Type"), %w[class module command])
39
39
  end
40
40
 
41
- def prompt_for_path
42
- puts
43
- puts colors.bright_black("Fully-qualified constant name (e.g., #{@gem_module}::Services::Authentication).")
44
- ask(colors.green("Constant"), required: true)
41
+ def prompt_for_path(type)
42
+ ask(colors.green(type), required: true)
45
43
  end
46
44
 
47
45
  def dispatch_destroy(type, path)
48
46
  case type
49
- when "class" then destroy_class(path)
50
- when "module" then destroy_module(path)
47
+ when "class" then destroy_class(gem_constant(path))
48
+ when "module" then destroy_module(gem_constant(path))
51
49
  when "command" then destroy_command(path)
52
50
  else
53
51
  puts colors.red("Unknown type '#{type}'. Use class, module, or command.")
@@ -56,25 +54,14 @@ module Gempilot
56
54
  end
57
55
 
58
56
  def destroy_class(constant)
59
- namespaces, _class_name, segments = parse_constant(constant)
60
- validate_gem_root!(namespaces.first)
61
-
62
- lib_path = "#{File.join("lib", *segments)}.rb"
63
- test_path = test_path_for(segments)
57
+ lib_path = constant.lib_path
58
+ test_path = constant.test_path(@test_framework)
64
59
 
65
60
  remove_file(lib_path)
66
61
  remove_file(test_path)
67
62
  cleanup_empty_dirs(lib_path, test_path)
68
63
  end
69
64
 
70
- def test_path_for(segments)
71
- if @test_framework == :rspec
72
- "#{File.join("spec", @require_path, *segments[1..])}_spec.rb"
73
- else
74
- "#{File.join("test", @require_path, *segments[1..])}_test.rb"
75
- end
76
- end
77
-
78
65
  def cleanup_empty_dirs(lib_path, test_path)
79
66
  remove_empty_parents(File.dirname(lib_path), File.join("lib", @require_path))
80
67
  test_root = @test_framework == :rspec ? File.join("spec", @require_path) : File.join("test", @require_path)
@@ -82,10 +69,8 @@ module Gempilot
82
69
  end
83
70
 
84
71
  def destroy_module(constant)
85
- namespaces, _mod_name, segments = parse_constant(constant)
86
- validate_gem_root!(namespaces.first)
72
+ lib_path = constant.lib_path
87
73
 
88
- lib_path = "#{File.join("lib", *segments)}.rb"
89
74
  remove_file(lib_path)
90
75
  remove_empty_parents(File.dirname(lib_path), File.join("lib", @require_path))
91
76
  end
@@ -29,7 +29,7 @@ module Gempilot
29
29
  def run(type = nil, path = nil)
30
30
  type ||= prompt_for_type
31
31
  detect_gem_context
32
- path ||= prompt_for_path
32
+ path ||= prompt_for_path(type)
33
33
  dispatch_add(type, path)
34
34
  end
35
35
 
@@ -40,16 +40,14 @@ module Gempilot
40
40
  ask_multiple_choice(colors.green("Type"), %w[class module command])
41
41
  end
42
42
 
43
- def prompt_for_path
44
- puts
45
- puts colors.bright_black("Fully-qualified constant name (e.g., #{@gem_module}::Services::Authentication).")
46
- ask(colors.green("Constant"), required: true)
43
+ def prompt_for_path(type)
44
+ ask(colors.green(type), required: true)
47
45
  end
48
46
 
49
47
  def dispatch_add(type, path)
50
48
  case type
51
- when "class" then add_class(path)
52
- when "module" then add_module(path)
49
+ when "class" then add_class(gem_constant(path))
50
+ when "module" then add_module(gem_constant(path))
53
51
  when "command" then add_command(path)
54
52
  else
55
53
  puts colors.red("Unknown type '#{type}'. Use class, module, or command.")
@@ -79,38 +77,29 @@ module Gempilot
79
77
  end
80
78
 
81
79
  def print_adding_banner(kind, label)
80
+ styled_label = colors.bold(colors.cyan(label))
82
81
  puts
83
- puts colors.bright_white("Adding #{kind} ") +
84
- colors.bold(colors.cyan(label)) +
85
- colors.bright_white("...")
82
+ puts colors.bright_white("Adding #{kind} ") + styled_label + colors.bright_white("...")
86
83
  puts
87
84
  end
88
85
 
89
- def prepare_constant(constant)
90
- namespaces, name, segments = parse_constant(constant)
91
- validate_gem_root!(namespaces.first)
92
- file_path = "#{File.join("lib", *segments)}.rb"
93
- ensure_directory(File.dirname(file_path))
94
- [namespaces, name, segments, file_path]
95
- end
96
-
97
86
  def ensure_directory(dir)
98
87
  mkdir(dir) unless File.directory?(dir)
99
88
  end
100
89
 
101
90
  def add_class(constant)
102
- namespaces, class_name, segments, file_path = prepare_constant(constant)
103
- print_adding_banner("class", "#{namespaces.join("::")}::#{class_name}")
104
- source = build_nested_source(namespaces, "class", class_name)
105
- create_file(file_path, source)
106
- add_test_file(namespaces, class_name, segments)
91
+ print_adding_banner("class", constant.qualified)
92
+ ensure_directory(File.dirname(constant.lib_path))
93
+ source = build_nested_source(constant.namespaces, "class", constant.name)
94
+ create_file(constant.lib_path, source)
95
+ add_test_file(constant)
107
96
  end
108
97
 
109
98
  def add_module(constant)
110
- namespaces, mod_name, _segments, file_path = prepare_constant(constant)
111
- print_adding_banner("module", "#{namespaces.join("::")}::#{mod_name}")
112
- source = build_nested_source(namespaces, "module", mod_name)
113
- create_file(file_path, source)
99
+ print_adding_banner("module", constant.qualified)
100
+ ensure_directory(File.dirname(constant.lib_path))
101
+ source = build_nested_source(constant.namespaces, "module", constant.name)
102
+ create_file(constant.lib_path, source)
114
103
  end
115
104
 
116
105
  def add_command(name)
@@ -179,14 +168,6 @@ module Gempilot
179
168
  create_file(test_path, content)
180
169
  end
181
170
 
182
- def class_test_path(segments)
183
- if @test_framework == :rspec
184
- "#{File.join("spec", @require_path, *segments[1..])}_spec.rb"
185
- else
186
- "#{File.join("test", @require_path, *segments[1..])}_test.rb"
187
- end
188
- end
189
-
190
171
  def rspec_class_content(namespaces, class_name)
191
172
  <<~RUBY
192
173
  require "spec_helper"
@@ -211,13 +192,13 @@ module Gempilot
211
192
  RUBY
212
193
  end
213
194
 
214
- def add_test_file(namespaces, class_name, segments)
215
- test_path = class_test_path(segments)
195
+ def add_test_file(constant)
196
+ test_path = constant.test_path(@test_framework)
216
197
  ensure_directory(File.dirname(test_path))
217
198
  content = if @test_framework == :rspec
218
- rspec_class_content(namespaces, class_name)
199
+ rspec_class_content(constant.namespaces, constant.name)
219
200
  else
220
- minitest_class_content(namespaces, class_name)
201
+ minitest_class_content(constant.namespaces, constant.name)
221
202
  end
222
203
  create_file(test_path, content)
223
204
  end
@@ -18,9 +18,8 @@ module Gempilot
18
18
  private
19
19
 
20
20
  def print_release_banner
21
- puts colors.bright_white("Releasing ") +
22
- colors.bold(colors.cyan(@gem_name)) +
23
- colors.bright_white("...")
21
+ styled_name = colors.bold(colors.cyan(@gem_name))
22
+ puts colors.bright_white("Releasing ") + styled_name + colors.bright_white("...")
24
23
  puts
25
24
  end
26
25
 
@@ -17,23 +17,19 @@ module Gempilot
17
17
  @gem_name = File.basename(gemspec, ".gemspec")
18
18
  @require_path = @gem_name.tr("-", "/")
19
19
  @gem_module = @require_path.camelize
20
- @test_framework = File.directory?("spec") ? :rspec : :minitest
20
+ @test_framework = detect_test_framework
21
21
  end
22
22
 
23
- def parse_constant(constant)
24
- parts = constant.split("::")
25
- namespaces = parts[0...-1]
26
- name = parts.last
27
- segments = parts.map(&:underscore)
28
- [namespaces, name, segments]
29
- end
23
+ # Detect rspec by its canonical config files rather than the mere
24
+ # presence of a spec/ directory, which a minitest project may also have.
25
+ def detect_test_framework
26
+ return :rspec if File.exist?(".rspec") || File.exist?(File.join("spec", "spec_helper.rb"))
30
27
 
31
- def validate_gem_root!(root)
32
- expected = @gem_module.split("::").first
33
- return if root == expected
28
+ :minitest
29
+ end
34
30
 
35
- puts colors.red("Expected constant to start with #{expected}, got #{root}")
36
- exit 1
31
+ def gem_constant(input)
32
+ GemConstant.new(input: input, gem_module: @gem_module, require_path: @require_path)
37
33
  end
38
34
  end
39
35
  end
@@ -37,8 +37,9 @@ module Gempilot
37
37
  end
38
38
 
39
39
  def print_action(command, dest, source: nil)
40
+ styled_command = colors.bold(colors.green(command))
40
41
  line = +""
41
- line << "\t" << colors.bold(colors.green(command))
42
+ line << "\t" << styled_command
42
43
  line << "\t" << colors.green(source) if source
43
44
  line << "\t" << colors.green(dest) if dest
44
45
 
@@ -0,0 +1,61 @@
1
+ module Gempilot
2
+ ## A class or module constant resolved within a gem's namespace.
3
+ ##
4
+ ## Wraps raw user input (a bare suffix like +Services::Auth+ or a
5
+ ## fully-qualified +MyGem::Services::Auth+) together with the gem's module
6
+ ## and require path, and derives the qualified constant, file paths, and
7
+ ## namespace pieces from a single parse.
8
+ ##
9
+ ## Every constant is rooted at the gem's module: bare input is prefixed with
10
+ ## it, while input already starting with the gem's root segment is left as
11
+ ## is. Rooting is matched on the first segment only, so an extension gem
12
+ ## whose module is +My::Gem+ accepts any +My::...+ constant.
13
+ GemConstant = Data.define(:input, :gem_module, :require_path) do
14
+ using String::Inflectable
15
+
16
+ ## The fully-qualified constant, rooted at the gem module.
17
+ def qualified
18
+ input.start_with?("#{root_segment}::") ? input : "#{gem_module}::#{input}"
19
+ end
20
+
21
+ ## Namespace segments preceding the final constant name.
22
+ def namespaces
23
+ parts[0...-1]
24
+ end
25
+
26
+ ## The final class or module name.
27
+ def name
28
+ parts.last
29
+ end
30
+
31
+ ## Path to the constant's source file, e.g. +lib/my_gem/services/auth.rb+.
32
+ def lib_path
33
+ "#{File.join("lib", *path_segments)}.rb"
34
+ end
35
+
36
+ ## Path to the constant's test file for +framework+ (+:rspec+ or
37
+ ## +:minitest+); correct for multi-segment (hyphenated) gem modules.
38
+ def test_path(framework)
39
+ rest = path_segments.drop(require_path.split("/").length)
40
+ if framework == :rspec
41
+ "#{File.join("spec", require_path, *rest)}_spec.rb"
42
+ else
43
+ "#{File.join("test", require_path, *rest)}_test.rb"
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def root_segment
50
+ gem_module.split("::").first
51
+ end
52
+
53
+ def parts
54
+ qualified.split("::")
55
+ end
56
+
57
+ def path_segments
58
+ parts.map(&:underscore)
59
+ end
60
+ end
61
+ end
@@ -1,8 +1,9 @@
1
- require "pathname"
2
1
  require "warning"
3
2
 
4
3
  module Gempilot
5
4
  ## Introspects a gem project to discover its name, module, and version.
5
+ ## Works for both regular gems (+lib/my_gem.rb+) and extension gems whose
6
+ ## entry point nests deeper (+lib/my_gem/extension.rb+ for +my_gem-extension+).
6
7
  class Project
7
8
  class ProjectIntrospectionError < StandardError; end
8
9
 
@@ -29,11 +30,11 @@ module Gempilot
29
30
  end
30
31
 
31
32
  def name
32
- lib_project.basename.to_s
33
+ project_segments.join("-")
33
34
  end
34
35
 
35
36
  def klass
36
- Object.const_get(name.camelize)
37
+ Object.const_get(project_segments.map(&:camelize).join("::"))
37
38
  end
38
39
 
39
40
  def version
@@ -67,6 +68,10 @@ module Gempilot
67
68
 
68
69
  private
69
70
 
71
+ def project_segments
72
+ lib_project.relative_path_from(lib).each_filename.to_a
73
+ end
74
+
70
75
  def with_version_file
71
76
  version.path.open(File::RDWR, 0o644) do |f|
72
77
  f.flock File::LOCK_EX
@@ -76,8 +81,7 @@ module Gempilot
76
81
  end
77
82
 
78
83
  def fetch_lib_project
79
- files = lib.glob("*.rb")
80
- dirs = files.map { it.sub_ext("") }.select(&:directory?)
84
+ dirs = shallowest_entry_dirs
81
85
  case dirs.count
82
86
  in 0 then raise ProjectIntrospectionError, "Could not identify project dir"
83
87
  in (2..)
@@ -87,6 +91,22 @@ module Gempilot
87
91
  end
88
92
  end
89
93
 
94
+ def shallowest_entry_dirs
95
+ entry_dirs.group_by { depth_below_lib(it) }
96
+ .min_by(&:first)
97
+ &.last || []
98
+ end
99
+
100
+ def entry_dirs
101
+ lib.glob("**/*.rb")
102
+ .map { it.sub_ext("") }
103
+ .select(&:directory?)
104
+ end
105
+
106
+ def depth_below_lib(path)
107
+ path.relative_path_from(lib).each_filename.count
108
+ end
109
+
90
110
  def fetch_version
91
111
  Warning.ignore(REDEFINITION_WARNING)
92
112
  Warning.ignore(REINITIALIZATION_WARNING)
@@ -1,3 +1,3 @@
1
1
  module Gempilot
2
- VERSION = "0.2.1".freeze
2
+ VERSION = "0.2.3".freeze
3
3
  end
@@ -5,6 +5,10 @@ module Gempilot
5
5
  class VersionTag
6
6
  include StrictShell
7
7
 
8
+ ## Commit-message prefix written for a version bump; the guard below
9
+ ## matches on it, so the two must stay in sync.
10
+ BUMP_MESSAGE_PREFIX = "Bump version to ".freeze
11
+
8
12
  attr_reader :version
9
13
 
10
14
  def initialize(version)
@@ -16,7 +20,7 @@ module Gempilot
16
20
  raise "Cannot proceed, staging area must be clean" unless status.success?
17
21
 
18
22
  sh "git", "add", version.path.to_s
19
- sh "git", "commit", "-m", "Bump version to #{version.value}"
23
+ sh "git", "commit", "-m", "#{BUMP_MESSAGE_PREFIX}#{version.value}"
20
24
  end
21
25
 
22
26
  def tag
@@ -47,7 +51,7 @@ module Gempilot
47
51
  raise "Failed to read last commit message" unless status.success?
48
52
 
49
53
  message.strip!
50
- abort "Last commit does not appear to be a version bump." unless message.start_with?("Bump version to ")
54
+ raise "Last commit does not appear to be a version bump." unless message.start_with?(BUMP_MESSAGE_PREFIX)
51
55
  end
52
56
  end
53
57
  end
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gempilot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Gillis
@@ -106,15 +106,6 @@ files:
106
106
  - data/templates/gem/test/zeitwerk_test.rb.erb
107
107
  - data/templates/new/.keep
108
108
  - data/templates/new/command.rb.erb
109
- - docs/command_kit_comparison.md
110
- - docs/command_kit_reference.md
111
- - docs/plans/2026-02-18-gempilot-add-command.md
112
- - docs/superpowers/plans/2026-04-01-rubocop-new-config.md
113
- - docs/superpowers/plans/2026-04-06-dogfood-inflectable.md
114
- - docs/superpowers/plans/2026-04-06-inflection-tests-and-erb-rename.md
115
- - docs/superpowers/plans/2026-04-06-integrate-version-tools.md
116
- - docs/superpowers/plans/2026-04-06-new-readme.md
117
- - docs/version-management-redesign.md
118
109
  - exe/gempilot
119
110
  - issues.rec
120
111
  - lib/core_ext/string/inflection_methods.rb
@@ -131,6 +122,7 @@ files:
131
122
  - lib/gempilot/cli/gem_builder.rb
132
123
  - lib/gempilot/cli/gem_context.rb
133
124
  - lib/gempilot/cli/generator.rb
125
+ - lib/gempilot/gem_constant.rb
134
126
  - lib/gempilot/github_release.rb
135
127
  - lib/gempilot/project.rb
136
128
  - lib/gempilot/project/version.rb
@@ -138,7 +130,7 @@ files:
138
130
  - lib/gempilot/version.rb
139
131
  - lib/gempilot/version_tag.rb
140
132
  - lib/gempilot/version_task.rb
141
- - notes.md
133
+ - vendor/vendored.gemv
142
134
  homepage: https://github.com/gillisd/gempilot
143
135
  licenses:
144
136
  - MIT
@@ -152,14 +144,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
144
  requirements:
153
145
  - - ">="
154
146
  - !ruby/object:Gem::Version
155
- version: '3.4'
147
+ version: '4.0'
156
148
  required_rubygems_version: !ruby/object:Gem::Requirement
157
149
  requirements:
158
150
  - - ">="
159
151
  - !ruby/object:Gem::Version
160
152
  version: '0'
161
153
  requirements: []
162
- rubygems_version: 4.0.13
154
+ rubygems_version: 4.0.15
163
155
  specification_version: 4
164
156
  summary: A toolkit for creating, managing, and releasing your own rubygems
165
157
  test_files: []