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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +14 -0
- data/README.md +11 -5
- data/lib/generators/rails/worktrees/puma_follow_up.rb +45 -0
- data/lib/generators/worktrees/install/install_generator.rb +29 -3
- data/lib/rails/worktrees/puma_config_updater.rb +91 -0
- data/lib/rails/worktrees/version.rb +1 -1
- data/lib/rails/worktrees.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 19ad567125176f17f962138eaf218f8e8c91a7a6585b61db0bddfa4c259f7d17
|
|
4
|
+
data.tar.gz: 7c29590624ed404c362deb38866f134ba9516bbd3e6f83f3b04cfb00792caeb4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f35103be9855cc4e262f12b4dbff0ff935cb65b67d3ae6d2ca619eb1d47bdfcf8829be5b03f2d8ff3cc587509098045d32ccea539fa48395a02c6180ca69546b
|
|
7
|
+
data.tar.gz: ef54f096ea64e518519b59f9f74af756bec7601ee492c0d1aec98736c485e62998cc6ec9149b251fa903f4acdb39f5e8cc36e4ed66aa650357df76090c3fd67b
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{".":"0.2.
|
|
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
|
|
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
|
data/lib/rails/worktrees.rb
CHANGED
|
@@ -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.
|
|
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
|