rails-worktrees 0.2.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cf1debd660652a5429a2d5485e944006685268b423866a96e15af71f9cb3471
4
- data.tar.gz: 14f6a3f5efaa6b829026b3d4d085c9b55d09236cb7b610bafa8f8834a534fb5b
3
+ metadata.gz: 19ad567125176f17f962138eaf218f8e8c91a7a6585b61db0bddfa4c259f7d17
4
+ data.tar.gz: 7c29590624ed404c362deb38866f134ba9516bbd3e6f83f3b04cfb00792caeb4
5
5
  SHA512:
6
- metadata.gz: e16d066bfb55c97b959e92b4c25d1b2ac08404a728cadf077852a937a1a4c00ea17ca0c08dcfecc571654f836ba0aeccc6f81b08b6a96f7a4443093681d3b25d
7
- data.tar.gz: f7fdc3e954463fed68f62934d153fbe4b086fb86f4be97c8f8e172b54c0bcc4d402587b99c2b171cc024f7ef53be14e950da311399e49ef0a491d696ac15dc64
6
+ metadata.gz: f35103be9855cc4e262f12b4dbff0ff935cb65b67d3ae6d2ca619eb1d47bdfcf8829be5b03f2d8ff3cc587509098045d32ccea539fa48395a02c6180ca69546b
7
+ data.tar.gz: ef54f096ea64e518519b59f9f74af756bec7601ee492c0d1aec98736c485e62998cc6ec9149b251fa903f4acdb39f5e8cc36e4ed66aa650357df76090c3fd67b
@@ -1 +1 @@
1
- {".":"0.2.0"}
1
+ {".":"0.2.2"}
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.2](https://github.com/asjer/rails-worktrees/compare/v0.2.1...v0.2.2) (2026-03-30)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **yolo:** skip generating `Procfile.dev.worktree.example` in --yolo mode ([b2320be](https://github.com/asjer/rails-worktrees/commit/b2320be92c84bfdcbb4f781fb34fc079df09f0b1))
9
+
10
+ ## [0.2.1](https://github.com/asjer/rails-worktrees/compare/v0.2.0...v0.2.1) (2026-03-30)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **puma:** add missing `DEV_PORT` support to config/puma.rb ([3fd71a0](https://github.com/asjer/rails-worktrees/commit/3fd71a04d79732bed4cf626951abe06ddbc01153))
16
+
3
17
  ## [0.2.0](https://github.com/asjer/rails-worktrees/compare/v0.1.1...v0.2.0) (2026-03-30)
4
18
 
5
19
 
data/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  ```bash
14
14
  bundle add rails-worktrees
15
15
  bin/rails generate worktrees:install
16
- # or, to apply the common Procfile.dev + mise follow-ups automatically:
16
+ # or, to apply the common Procfile.dev + Puma + mise follow-ups automatically:
17
17
  bin/rails generate worktrees:install --yolo
18
18
  ```
19
19
 
@@ -21,12 +21,14 @@ The installer adds:
21
21
 
22
22
  - `bin/wt` — a thin wrapper that executes the gem-owned CLI
23
23
  - `config/initializers/rails_worktrees.rb` — optional configuration
24
- - `Procfile.dev.worktree.example` — a copy-paste helper for `${DEV_PORT:-3000}` in `Procfile.dev`
24
+ - `Procfile.dev.worktree.example` — a copy-paste helper for `${DEV_PORT:-3000}` in `Procfile.dev` on regular installs
25
25
  - a safe update to `config/database.yml` for common development/test database names
26
26
 
27
27
  With `--yolo`, the installer also:
28
28
 
29
+ - skips `Procfile.dev.worktree.example`
29
30
  - replaces the existing `web:` entry in `Procfile.dev` with the DEV_PORT-aware command when `Procfile.dev` already exists
31
+ - updates `config/puma.rb` to use `port ENV['DEV_PORT'] || ENV.fetch('PORT', 3000)` when it still uses a supported default `PORT` binding
30
32
  - updates `mise.toml` or `.mise.toml` to load `.env` from `[env]` when either file already exists
31
33
 
32
34
  ## Usage
@@ -122,17 +124,21 @@ When `bin/wt` creates a worktree it writes a worktree-local `.env` with:
122
124
 
123
125
  Existing `.env` values are never overwritten.
124
126
 
125
- By default, the installer does **not** edit your `Procfile.dev` or `mise` config. It generates `Procfile.dev.worktree.example` with a ready-to-copy line:
127
+ By default, the installer does **not** edit your `Procfile.dev`, `config/puma.rb`, or `mise` config. It generates `Procfile.dev.worktree.example` with a ready-to-copy line:
126
128
 
127
129
  ```text
128
130
  web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0.0.0.0 -p ${DEV_PORT:-3000}
129
131
  ```
130
132
 
131
- If you run `bin/rails generate worktrees:install --yolo`, the installer applies the two common follow-ups for you when the files already exist:
133
+ If you run `bin/rails generate worktrees:install --yolo`, the installer applies the three common follow-ups for you when the files already exist:
132
134
 
135
+ - skip generating `Procfile.dev.worktree.example`
133
136
  - replace the existing `web:` entry in `Procfile.dev`
137
+ - update `config/puma.rb` to `port ENV['DEV_PORT'] || ENV.fetch('PORT', 3000)` when it still uses a supported default `PORT` binding
134
138
  - add `_.file = ".env"` to the `[env]` section of `mise.toml` or `.mise.toml`
135
139
 
140
+ On a regular install, the follow-up message also suggests the same `config/puma.rb` edit when Puma still uses the default `PORT` binding.
141
+
136
142
  Use a project-local env loader like `mise` with `_.file = ".env"` to keep values scoped per-worktree.
137
143
 
138
144
  ## Development
@@ -154,7 +160,7 @@ This smoke test:
154
160
  - creates a temporary Rails app from a compatible Rails version
155
161
  - installs `rails-worktrees` from the current checkout path
156
162
  - runs `bin/rails generate worktrees:install --yolo`
157
- - verifies `bin/wt`, the generated initializer, the Procfile example, yolo updates to `Procfile.dev` and `mise.toml`, `config/database.yml` patching, and worktree `.env` bootstrapping
163
+ - verifies `bin/wt`, the generated initializer, that `--yolo` skips the Procfile example, yolo updates to `Procfile.dev`, `config/puma.rb`, and `mise.toml`, `config/database.yml` patching, and worktree `.env` bootstrapping
158
164
  - creates a temporary bare `origin` and confirms `bin/wt smoke-branch` creates a real worktree
159
165
 
160
166
  By default, the script cleans up all temp directories after the run. Set `KEEP_SMOKE_TEST_ARTIFACTS=1` to keep them around for debugging, or set `RAILS_WORKTREES_SMOKE_RAILS_VERSION` to try a different compatible Rails version.
@@ -0,0 +1,45 @@
1
+ module Rails
2
+ module Worktrees
3
+ module Generators
4
+ # Detects config/puma.rb setups that should prefer the worktree-local DEV_PORT.
5
+ module PumaFollowUp
6
+ private
7
+
8
+ def puma_follow_up_notes_text
9
+ return '' unless suggest_puma_dev_port_update?
10
+
11
+ [
12
+ '',
13
+ ' Tip:',
14
+ ' Detected config/puma.rb. To bind Puma to the worktree-local DEV_PORT,',
15
+ ' consider changing the port line to:',
16
+ " #{::Rails::Worktrees::PumaConfigUpdater::STANDARD_PORT_LINE}"
17
+ ].join("\n")
18
+ end
19
+
20
+ def suggest_puma_dev_port_update?
21
+ existing_puma_config_path && puma_update_result.status == :updated
22
+ end
23
+
24
+ def puma_update_result
25
+ return missing_puma_update_result unless existing_puma_config_path
26
+
27
+ ::Rails::Worktrees::PumaConfigUpdater.new(content: File.read(existing_puma_config_path)).call
28
+ end
29
+
30
+ def missing_puma_update_result
31
+ ::Rails::Worktrees::PumaConfigUpdater::Result.new(nil, false, :skip, [])
32
+ end
33
+
34
+ def puma_config_path
35
+ File.join(destination_root, 'config/puma.rb')
36
+ end
37
+
38
+ def existing_puma_config_path
39
+ path = puma_config_path
40
+ File.file?(path) ? path : nil
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -2,9 +2,11 @@ require 'open3'
2
2
  require 'rails/generators'
3
3
 
4
4
  require_relative '../../rails/worktrees/mise_follow_up'
5
+ require_relative '../../rails/worktrees/puma_follow_up'
5
6
  require_relative '../../../rails/worktrees/database_config_updater'
6
7
  require_relative '../../../rails/worktrees/procfile_updater'
7
8
  require_relative '../../../rails/worktrees/mise_toml_updater'
9
+ require_relative '../../../rails/worktrees/puma_config_updater'
8
10
 
9
11
  module Worktrees
10
12
  module Generators
@@ -12,6 +14,7 @@ module Worktrees
12
14
  # rubocop:disable Metrics/ClassLength
13
15
  class InstallGenerator < ::Rails::Generators::Base
14
16
  include ::Rails::Worktrees::Generators::MiseFollowUp
17
+ include ::Rails::Worktrees::Generators::PumaFollowUp
15
18
 
16
19
  namespace 'worktrees:install'
17
20
  desc 'Installs bin/wt, a Rails::Worktrees initializer, and updates config/database.yml when safe.'
@@ -19,7 +22,7 @@ module Worktrees
19
22
  class_option :conductor, type: :boolean, default: false,
20
23
  desc: 'Configure the installer for ~/Sites/conductor/workspaces'
21
24
  class_option :yolo, type: :boolean, default: false,
22
- desc: 'Apply common Procfile.dev and mise .env follow-up edits when safe'
25
+ desc: 'Apply common Procfile.dev, config/puma.rb, and mise .env follow-up edits when safe'
23
26
 
24
27
  FOLLOW_UP_TEMPLATE = <<~TEXT.freeze
25
28
  ============================================
@@ -48,6 +51,8 @@ module Worktrees
48
51
  end
49
52
 
50
53
  def create_procfile_worktree_example
54
+ return if options[:yolo]
55
+
51
56
  template('Procfile.dev.worktree.example.tt', 'Procfile.dev.worktree.example')
52
57
  end
53
58
 
@@ -55,6 +60,7 @@ module Worktrees
55
60
  return unless options[:yolo]
56
61
 
57
62
  update_procfile
63
+ update_puma_config
58
64
  update_mise_toml
59
65
  end
60
66
 
@@ -92,6 +98,10 @@ module Worktrees
92
98
  File.join(destination_root, 'Procfile.dev')
93
99
  end
94
100
 
101
+ def puma_config_path
102
+ File.join(destination_root, 'config/puma.rb')
103
+ end
104
+
95
105
  def mise_toml_paths
96
106
  [
97
107
  File.join(destination_root, 'mise.toml'),
@@ -113,12 +123,16 @@ module Worktrees
113
123
  "\n#{format(FOLLOW_UP_TEMPLATE, installed: installed_items_text, notes: follow_up_notes_text)}"
114
124
  end
115
125
 
126
+ def follow_up_notes_text
127
+ [super, puma_follow_up_notes_text].join
128
+ end
129
+
116
130
  def installed_items_text
117
131
  items = [
118
132
  ' • bin/wt',
119
- ' • config/initializers/rails_worktrees.rb',
120
- ' • Procfile.dev.worktree.example'
133
+ ' • config/initializers/rails_worktrees.rb'
121
134
  ]
135
+ items << ' • Procfile.dev.worktree.example' unless options[:yolo]
122
136
  items << database_follow_up_line if database_follow_up_line
123
137
  items.join("\n")
124
138
  end
@@ -152,6 +166,18 @@ module Worktrees
152
166
  announce_updater_result('Procfile.dev', result)
153
167
  end
154
168
 
169
+ def update_puma_config
170
+ unless File.exist?(puma_config_path)
171
+ say_status(:skip, 'config/puma.rb not found', :yellow)
172
+ say('Skipped config/puma.rb yolo update because the file does not exist yet.')
173
+ return
174
+ end
175
+
176
+ result = ::Rails::Worktrees::PumaConfigUpdater.new(content: File.read(puma_config_path)).call
177
+ File.write(puma_config_path, result.content) if result.changed?
178
+ announce_updater_result('config/puma.rb', result)
179
+ end
180
+
155
181
  def update_mise_toml
156
182
  path = first_mise_toml_path
157
183
  return announce_missing_mise_toml unless path
@@ -0,0 +1,91 @@
1
+ module Rails
2
+ module Worktrees
3
+ # Safely updates config/puma.rb to bind Puma to the worktree-local DEV_PORT.
4
+ class PumaConfigUpdater
5
+ Result = Struct.new(:content, :changed, :status, :messages) do
6
+ def changed?
7
+ changed
8
+ end
9
+ end
10
+
11
+ STANDARD_PORT_LINE = "port ENV['DEV_PORT'] || ENV.fetch('PORT', 3000)".freeze
12
+ CURRENT_PORT_PATTERN = /\A\s*port\s+ENV\.fetch\(["']PORT["'],\s*3000\)\s*(?:#.*)?\z/
13
+ LEGACY_PORT_PATTERN = /\A\s*port\s+ENV\.fetch\(["']PORT["']\)\s*\{\s*3000\s*\}\s*(?:#.*)?\z/
14
+ PORT_LINE_PATTERN = /\A\s*port\s+/
15
+ DEV_PORT_ACCESS_PATTERN = /ENV\[(["'])DEV_PORT\1\]/
16
+ DEV_PORT_FETCH_PATTERN = /ENV\.fetch\((["'])DEV_PORT\1(?:\s*,|\s*\))/
17
+
18
+ def initialize(content:)
19
+ @content = content
20
+ end
21
+
22
+ def call
23
+ lines = @content.lines(chomp: true)
24
+ return identical_result(@content) if dev_port_configured?(lines)
25
+
26
+ port_line_indexes = supported_port_line_indexes(lines)
27
+ return skip_result if port_line_indexes.empty?
28
+
29
+ updated_content = rebuild_content(
30
+ replace_port_lines(lines, port_line_indexes),
31
+ trailing_newline: @content.end_with?("\n")
32
+ )
33
+
34
+ updated_result(updated_content)
35
+ end
36
+
37
+ private
38
+
39
+ def updated_result(content)
40
+ Result.new(content, true, :updated, ['Updated config/puma.rb to prefer DEV_PORT before PORT.'])
41
+ end
42
+
43
+ def identical_result(content)
44
+ Result.new(content, false, :identical, ['config/puma.rb already uses DEV_PORT-aware port binding.'])
45
+ end
46
+
47
+ def skip_result
48
+ Result.new(
49
+ @content,
50
+ false,
51
+ :skip,
52
+ ['No supported Puma port binding found in config/puma.rb; update it manually if needed.']
53
+ )
54
+ end
55
+
56
+ def dev_port_configured?(lines)
57
+ lines.any? do |line|
58
+ line.match?(PORT_LINE_PATTERN) &&
59
+ (line.match?(DEV_PORT_ACCESS_PATTERN) || line.match?(DEV_PORT_FETCH_PATTERN))
60
+ end
61
+ end
62
+
63
+ def supported_port_line_indexes(lines)
64
+ lines.each_index.select { |index| supported_port_line?(lines[index]) }
65
+ end
66
+
67
+ def supported_port_line?(line)
68
+ line.match?(CURRENT_PORT_PATTERN) || line.match?(LEGACY_PORT_PATTERN)
69
+ end
70
+
71
+ def replace_port_lines(lines, port_line_indexes)
72
+ lines.dup.tap do |updated_lines|
73
+ port_line_indexes.each do |index|
74
+ original_line = lines[index]
75
+ indent = original_line[/\A\s*/]
76
+ trailing_comment = original_line[/(\s*#.*)\z/, 1].to_s
77
+
78
+ updated_lines[index] = "#{indent}#{STANDARD_PORT_LINE}#{trailing_comment}"
79
+ end
80
+ end
81
+ end
82
+
83
+ def rebuild_content(lines, trailing_newline:)
84
+ content = lines.join("\n")
85
+ return content if content.empty? || !trailing_newline
86
+
87
+ "#{content}\n"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,5 +1,5 @@
1
1
  module Rails
2
2
  module Worktrees
3
- VERSION = '0.2.0'.freeze
3
+ VERSION = '0.2.2'.freeze
4
4
  end
5
5
  end
@@ -8,6 +8,7 @@ require_relative 'worktrees/cli'
8
8
  require_relative 'worktrees/database_config_updater'
9
9
  require_relative 'worktrees/procfile_updater'
10
10
  require_relative 'worktrees/mise_toml_updater'
11
+ require_relative 'worktrees/puma_config_updater'
11
12
 
12
13
  module Rails
13
14
  # Rails-specific git worktree helpers and installer support.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-worktrees
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asjer Querido
@@ -46,6 +46,7 @@ files:
46
46
  - exe/wt
47
47
  - lefthook.yml
48
48
  - lib/generators/rails/worktrees/mise_follow_up.rb
49
+ - lib/generators/rails/worktrees/puma_follow_up.rb
49
50
  - lib/generators/rails/worktrees/templates/Procfile.dev.worktree.example.tt
50
51
  - lib/generators/rails/worktrees/templates/bin/wt
51
52
  - lib/generators/rails/worktrees/templates/rails_worktrees.rb.tt
@@ -64,6 +65,7 @@ files:
64
65
  - lib/rails/worktrees/mise_toml_updater.rb
65
66
  - lib/rails/worktrees/names/cities.txt
66
67
  - lib/rails/worktrees/procfile_updater.rb
68
+ - lib/rails/worktrees/puma_config_updater.rb
67
69
  - lib/rails/worktrees/railtie.rb
68
70
  - lib/rails/worktrees/version.rb
69
71
  - mise.toml