rails_agent_server 0.1.0 → 0.2.0

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: 67c2f8f4c1a4d5f62de047f40c1bf076549b7f303b1dad62b8459919cd73ed87
4
- data.tar.gz: 4ae4c453471fb620d461742684b379fc0ba4e28d62b77d662f704bc039b10a54
3
+ metadata.gz: 11eb2a0d810274304d6e7131cdcddfd1c3f5b4a1473eed28c0fd27b36d664237
4
+ data.tar.gz: e029aa9ba2ee8b4c36c56e0ef2bca85d59b99597aad5333dc2f4c9accbc99e99
5
5
  SHA512:
6
- metadata.gz: 414387d2240dd9736ae51d8149949e0adb72d75eac81b39dcd50da9cbf03ff29424cbc281d4477fe10ab211541e45b6d7e48b5d512d3ce20389f50508e768f45
7
- data.tar.gz: 325d73826e71519c811aac9b91206d1f1f702006d578ddc40618abac28d18ca7411da1dc5db54d8bc13bba68036f0bc2ad96491bf9bb3f0c621122ddef29f33a
6
+ metadata.gz: 45ce707f90465a9be908e2fede50fd55a89ec92b2ad9f92f04766d7e23f6d18725b2ba7db9f021126869116383dec56f8ac91f922cf84d7d480c35924e5d72c1
7
+ data.tar.gz: f5e672ba4329e07f4eaac6e6338e78dd8a386c127706f2236f3ce4568458b85a1bda06f56a57d7cfe8bd09334f5f3145e94e10f83c8e802f557560cca6c8bda2
data/README.md CHANGED
@@ -6,7 +6,7 @@ A persistent Rails server for AI agents that avoids boot overhead for repeated q
6
6
 
7
7
  When using AI coding assistants or automation tools with Rails applications, the agent often needs to run many small queries via `bin/rails runner` to understand the runtime behaviour or state. Using `bin/rails runner` for each query means booting Rails every time, which can typically take 5-10 seconds per query.
8
8
 
9
- Rails Agent Server starts a persistent background server that keeps Rails loaded in memory. The first request takes the normal Rails boot time, but subsequent requests are instant.
9
+ Rails Agent Server starts a persistent background server that keeps Rails loaded in memory. The first request takes the normal Rails boot time, but subsequent requests are almost instant.
10
10
 
11
11
  ### Why Not `bin/rails console`?
12
12
 
@@ -43,7 +43,19 @@ Rails Agent Server is a lightweight alternative that lets AI agents treat your R
43
43
 
44
44
  ## Installation
45
45
 
46
- Add this line to your application's Gemfile:
46
+ ### Option 1: Global Installation (Recommended for AI Agents)
47
+
48
+ Install the gem globally so it works with any Rails app without modifying Gemfiles:
49
+
50
+ ```bash
51
+ gem install rails_agent_server
52
+ ```
53
+
54
+ This allows AI agents to use the tool on any Rails project immediately.
55
+
56
+ ### Option 2: Add to Gemfile
57
+
58
+ Alternatively, add it to your application's Gemfile:
47
59
 
48
60
  ```ruby
49
61
  gem 'rails_agent_server', group: :development
@@ -55,12 +67,6 @@ And then execute:
55
67
  bundle install
56
68
  ```
57
69
 
58
- Or install it yourself as:
59
-
60
- ```bash
61
- gem install rails_agent_server
62
- ```
63
-
64
70
  ## Agent Setup
65
71
 
66
72
  Add this section to your project's `CLAUDE.md` or equivalent:
@@ -73,13 +79,15 @@ This project uses `rails_agent_server` for fast Rails runner access without boot
73
79
  When you need to query the database or run Rails code:
74
80
  - Use `rails_agent_server 'YourCode.here'` instead of `bin/rails runner`
75
81
  - First request auto-starts a persistent server (takes ~5 seconds)
76
- - Subsequent requests are instant (no Rails boot time)
82
+ - Subsequent requests are almost instant (no Rails boot time)
77
83
  - Server stays running in background until you run `rails_agent_server stop`
78
84
 
79
85
  Examples:
80
- rails_agent_server 'User.count'
81
- rails_agent_server 'Post.where(published: true).count'
82
- rails_agent_server 'User.find_by(email: "test@example.com")&.name'
86
+ rails_agent_server 'puts User.count'
87
+ rails_agent_server 'puts Post.where(published: true).count'
88
+ rails_agent_server 'puts User.find_by(email: "test@example.com")&.name'
89
+
90
+ Note: Use `bundle exec rails_agent_server` if the gem is in your Gemfile, or just `rails_agent_server` if installed globally.
83
91
  ```
84
92
 
85
93
  ## Usage
@@ -90,7 +98,7 @@ These commands are designed to be used by AI agents (like Claude Code) or automa
90
98
 
91
99
  ```bash
92
100
  # Run a Ruby expression (auto-starts server if needed)
93
- rails_agent_server 'User.count'
101
+ rails_agent_server 'puts User.count'
94
102
 
95
103
  # Run code that prints output
96
104
  rails_agent_server 'puts User.pluck(:email).join(", ")'
@@ -100,27 +108,24 @@ rails_agent_server /path/to/script.rb
100
108
 
101
109
  # Server management
102
110
  rails_agent_server status # Check if server is running
103
- rails_agent_server start # Manually start the server
104
111
  rails_agent_server stop # Stop the background server
105
112
  rails_agent_server restart # Restart the background server
106
- rails_agent_server help # Show help
107
113
  ```
108
114
 
109
115
  ### Examples
110
116
 
111
117
  ```bash
112
118
  # Database queries
113
- rails_agent_server 'User.count'
114
- rails_agent_server 'Post.where(published: true).pluck(:title)'
115
- rails_agent_server 'User.find_by(email: "test@example.com")&.name'
119
+ rails_agent_server 'puts User.count'
120
+ rails_agent_server 'puts Post.where(published: true).pluck(:title)'
121
+ rails_agent_server 'puts User.find_by(email: "test@example.com")&.name'
116
122
 
117
123
  # Inspect schema
118
- rails_agent_server 'ActiveRecord::Base.connection.tables'
119
- rails_agent_server 'User.column_names'
124
+ rails_agent_server 'puts ActiveRecord::Base.connection.tables'
125
+ rails_agent_server 'puts User.column_names'
120
126
 
121
127
  # Complex operations
122
- rails_agent_server 'User.group(:status).count'
123
- rails_agent_server 'Rails.cache.clear; "Cache cleared"'
128
+ rails_agent_server 'Rails.cache.clear; puts "Cache cleared"'
124
129
  ```
125
130
 
126
131
  ## How It Works
@@ -156,7 +161,7 @@ If not in a Rails directory, files are created in `/tmp/`.
156
161
  ## Performance
157
162
 
158
163
  - **First request**: ~5-10 seconds (Rails boot time)
159
- - **Subsequent requests**: ~50-200ms (no boot overhead)
164
+ - **Subsequent requests**: Almost instant (no boot overhead)
160
165
  - **Memory**: One Rails process running in background (~200-500MB depending on your app)
161
166
 
162
167
  ## When to Restart
@@ -183,10 +188,14 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
183
188
 
184
189
  To install this gem onto your local machine, run `bundle exec rake install`.
185
190
 
191
+ ### Testing
192
+
193
+ The test suite includes unit tests (fast, run in CI) and integration tests (slower, require process forking). By default, `rake test` runs only unit tests. See [TESTING.md](TESTING.md) for details on running integration tests locally.
194
+
186
195
  ## Contributing
187
196
 
188
197
  Bug reports and pull requests are welcome on GitHub at https://github.com/andyw8/rails_agent_server.
189
198
 
190
199
  ## License
191
200
 
192
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
201
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -3,7 +3,9 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "minitest/test_task"
5
5
 
6
- Minitest::TestTask.create
6
+ Minitest::TestTask.create do |t|
7
+ t.test_globs = ["test/test_rails_agent_server.rb", "test/test_cli.rb"]
8
+ end
7
9
 
8
10
  require "standard/rake"
9
11
 
data/TESTING.md ADDED
@@ -0,0 +1,162 @@
1
+ # Testing
2
+
3
+ This document explains the test structure and how to run tests for the rails_agent_server gem.
4
+
5
+ ## Test Structure
6
+
7
+ The test suite is organized into three categories:
8
+
9
+ ### Unit Tests (Always Run)
10
+
11
+ - **`test/test_rails_agent_server.rb`** - Tests for the `Server` class
12
+ - Path resolution and defaults
13
+ - Server status checking
14
+ - Response formatting
15
+ - File cleanup
16
+ - No actual process forking or Rails loading
17
+
18
+ - **`test/test_cli.rb`** - Tests for the `CLI` class
19
+ - Command parsing and help text
20
+ - Error handling
21
+ - Mocked server interactions
22
+ - No actual server startup
23
+
24
+ ### Integration Tests (Manual Only)
25
+
26
+ - **`test/test_integration.rb`** - Tests with actual server process
27
+ - Forks background server process
28
+ - Tests real socket communication
29
+ - Tests code execution and error handling
30
+ - Requires ability to fork and manage processes
31
+
32
+ - **`test/test_dummy_integration.rb`** - Tests with dummy Rails app
33
+ - Uses `test/dummy` Rails application
34
+ - Tests full Rails environment loading
35
+ - Tests database operations and persistence
36
+ - Most realistic but slowest tests
37
+
38
+ ## Running Tests
39
+
40
+ ### Quick Test (Default)
41
+
42
+ Run the unit tests that are stable in all environments:
43
+
44
+ ```bash
45
+ bundle exec rake test
46
+ ```
47
+
48
+ This runs only the unit tests (`test_rails_agent_server.rb` and `test_cli.rb`).
49
+
50
+ ### Run Linter
51
+
52
+ ```bash
53
+ bundle exec rake standard
54
+ ```
55
+
56
+ ### Run Both Tests and Linter
57
+
58
+ ```bash
59
+ bundle exec rake
60
+ ```
61
+
62
+ ### Run Integration Tests (Local Only)
63
+
64
+ These tests fork processes and require a real Rails environment:
65
+
66
+ ```bash
67
+ # Run basic integration tests
68
+ bundle exec ruby -Ilib:test test/test_integration.rb
69
+
70
+ # Run Rails dummy app integration tests
71
+ cd test/dummy
72
+ bundle exec ruby -I../../lib:../../test ../../test/test_dummy_integration.rb
73
+ ```
74
+
75
+ **Note:** Integration tests are skipped in CI because they were flaky during initial setup. The flakiness stems from:
76
+ - **Timing sensitivity** - Tests poll for file existence with short timeouts that can fail on slow CI runners
77
+ - **Process forking** - Background processes via `fork` and `spawn` can behave differently in GitHub Actions
78
+ - **Rails boot time** - Full Rails environment loading is slow and can exceed polling timeouts
79
+ - **Maintenance cost** - Debugging flaky CI tests outweighed the additional confidence they provide
80
+
81
+ These tests *could* be enabled in CI with improvements like:
82
+ - Longer timeouts and wait times when `ENV['CI']` is set
83
+ - More robust waiting logic (e.g., exponential backoff)
84
+ - Retry mechanisms for transient failures
85
+ - Dedicated CI job with allowed failures
86
+
87
+ ## CI Configuration
88
+
89
+ The CI workflow (`.github/workflows/main.yml`) runs:
90
+
91
+ 1. `bundle exec rake test` - Unit tests only
92
+ 2. `bundle exec rake standard` - Code linting
93
+
94
+ The Rakefile explicitly sets `test_globs` to only include unit tests. This is a pragmatic choice:
95
+ - Unit tests provide good coverage of core logic
96
+ - They run in ~10ms vs seconds for integration tests
97
+ - They're deterministic and never flaky
98
+ - Integration tests can be run manually before releases
99
+
100
+ ## Test Philosophy
101
+
102
+ - **Unit tests** should be fast, deterministic, and run everywhere (local, CI, different OS)
103
+ - **Integration tests** verify real-world behavior but trade speed and reliability for realism
104
+ - All tests use standard Minitest without extra dependencies
105
+ - CI runs unit tests; integration tests are for local verification and releases
106
+
107
+ ## Troubleshooting
108
+
109
+ ### Tests hang or timeout
110
+
111
+ This usually means an integration test is running when it shouldn't be. Check:
112
+
113
+ 1. Is `ENV['CI']` set? Integration tests skip when this is set.
114
+ 2. Are you running the right test file? Use `bundle exec rake test` for safety.
115
+ 3. Is there a stale server process? Run `ps aux | grep rails_agent_server` and kill if needed.
116
+
117
+ ### Integration tests fail locally
118
+
119
+ Integration tests require:
120
+ - Ability to fork processes (won't work on Windows)
121
+ - Write access to temp directories
122
+ - No firewall blocking Unix sockets
123
+ - A working Rails environment for dummy app tests
124
+
125
+ Common failure modes:
126
+ - **Timeout waiting for socket** - Server took too long to start, increase wait time
127
+ - **Address already in use** - Previous test didn't clean up, check for stale processes
128
+ - **Rails not found** - Dummy app needs `bundle install` in `test/dummy`
129
+
130
+ If they consistently fail, focus on unit tests which provide 80%+ coverage of core functionality.
131
+
132
+ ## Adding New Tests
133
+
134
+ - **Add unit tests** for new functionality in the Server or CLI classes
135
+ - **Keep mocks simple** - avoid calling test assertions inside mocked methods (they can cause hangs)
136
+ - **Integration tests are optional** - they verify real behavior but aren't required for CI
137
+ - **Consider CI-friendliness** - if adding integration tests, make timeouts configurable for CI environments
138
+
139
+ ## Re-enabling Integration Tests in CI (Future Work)
140
+
141
+ If you want to run integration tests in CI:
142
+
143
+ 1. **Make timeouts CI-aware**:
144
+ ```ruby
145
+ wait_iterations = ENV['CI'] ? 100 : 30 # 10s vs 3s
146
+ ```
147
+
148
+ 2. **Add retry logic**:
149
+ ```ruby
150
+ Minitest::Retry.use!(retry_count: 3, exceptions_to_retry: [Minitest::Assertion])
151
+ ```
152
+
153
+ 3. **Create separate CI job**:
154
+ ```yaml
155
+ integration-tests:
156
+ runs-on: ubuntu-latest
157
+ continue-on-error: true # Don't block merges on flaky tests
158
+ ```
159
+
160
+ 4. **Use Docker for consistency**:
161
+ - Eliminates environment differences
162
+ - Predictable performance characteristics
@@ -19,10 +19,7 @@ module RailsAgentServer
19
19
  server.restart
20
20
  when "status"
21
21
  server.status
22
- when "start"
23
- server.start
24
- puts "Rails agent server started"
25
- when "--help", "-h", "help", nil
22
+ when "--help", "-h", nil
26
23
  print_help
27
24
  else
28
25
  execute_code
@@ -39,7 +36,7 @@ module RailsAgentServer
39
36
  end
40
37
 
41
38
  if code.empty?
42
- $stderr.puts "Error: No code provided"
39
+ warn "Error: No code provided"
43
40
  print_help
44
41
  exit 1
45
42
  end
@@ -47,10 +44,10 @@ module RailsAgentServer
47
44
  begin
48
45
  puts server.execute(code)
49
46
  rescue Errno::ENOENT
50
- $stderr.puts "Error: Could not connect to Rails agent server"
47
+ warn "Error: Could not connect to Rails agent server"
51
48
  exit 1
52
49
  rescue => e
53
- $stderr.puts "Error: #{e.message}"
50
+ warn "Error: #{e.message}"
54
51
  exit 1
55
52
  end
56
53
  end
@@ -60,20 +57,18 @@ module RailsAgentServer
60
57
  Rails Agent Server - A persistent Rails server for AI agents
61
58
 
62
59
  Usage:
63
- rails_agent_server 'User.count' # Run a Ruby expression
60
+ rails_agent_server 'puts User.count' # Run a Ruby expression
64
61
  rails_agent_server /path/to/script.rb # Run a script file
65
- rails_agent_server start # Start the server
66
62
  rails_agent_server stop # Stop the server
67
63
  rails_agent_server restart # Restart the server
68
64
  rails_agent_server status # Check server status
69
- rails_agent_server help # Show this help
70
65
 
71
66
  The server auto-starts on first use if not already running.
72
67
 
73
68
  Examples:
74
- rails_agent_server 'User.count'
69
+ rails_agent_server 'puts User.count'
75
70
  rails_agent_server 'puts User.pluck(:email).join(", ")'
76
- rails_agent_server 'ActiveRecord::Base.connection.tables'
71
+ rails_agent_server 'puts ActiveRecord::Base.connection.tables'
77
72
  rails_agent_server script.rb
78
73
 
79
74
  For Claude Code or AI agents, add this to your CLAUDE.md:
@@ -89,9 +84,9 @@ module RailsAgentServer
89
84
  - Server stays running in background until you run `rails_agent_server stop`
90
85
 
91
86
  Examples:
92
- rails_agent_server 'User.count'
93
- rails_agent_server 'Post.where(published: true).count'
94
- rails_agent_server 'User.find_by(email: "test@example.com")&.name'
87
+ rails_agent_server 'puts User.count'
88
+ rails_agent_server 'puts Post.where(published: true).count'
89
+ rails_agent_server 'puts User.find_by(email: "test@example.com")&.name'
95
90
  HELP
96
91
  end
97
92
  end
@@ -19,14 +19,17 @@ module RailsAgentServer
19
19
 
20
20
  puts "Starting Rails agent server (this will take a few seconds)..."
21
21
 
22
+ # Build load path argument to ensure spawned process uses same gem version
23
+ load_path_args = $LOAD_PATH.map { |path| ["-I", path] }.flatten
24
+
22
25
  pid = spawn(
23
- RbConfig.ruby, "-r", "rails_agent_server/server",
26
+ RbConfig.ruby, *load_path_args, "-r", "rails_agent_server/server",
24
27
  "-e", "RailsAgentServer::Server.new(socket_path: '#{socket_path}', pid_path: '#{pid_path}', log_path: '#{log_path}').run",
25
28
  out: log_path, err: log_path
26
29
  )
27
30
  Process.detach(pid)
28
31
 
29
- wait_for_server
32
+ wait_for_server(pid)
30
33
  end
31
34
 
32
35
  def stop
@@ -90,8 +93,8 @@ module RailsAgentServer
90
93
  handle_client(client)
91
94
  end
92
95
  rescue => e
93
- $stderr.puts "Server error: #{e.class}: #{e.message}"
94
- $stderr.puts e.backtrace.join("\n")
96
+ warn "Server error: #{e.class}: #{e.message}"
97
+ warn e.backtrace.join("\n")
95
98
  cleanup_files
96
99
  raise
97
100
  end
@@ -133,9 +136,23 @@ module RailsAgentServer
133
136
  end
134
137
  end
135
138
 
136
- def wait_for_server(timeout: 30)
139
+ def wait_for_server(pid, timeout: 30)
137
140
  (timeout * 2).times do
138
141
  return if File.exist?(socket_path)
142
+
143
+ # Check if process is still alive
144
+ begin
145
+ Process.kill(0, pid)
146
+ rescue Errno::ESRCH
147
+ # Process died - show error from log
148
+ if File.exist?(log_path)
149
+ error_msg = File.read(log_path).strip
150
+ abort "Rails agent server failed to start: #{error_msg}"
151
+ else
152
+ abort "Rails agent server failed to start (no log file found)"
153
+ end
154
+ end
155
+
139
156
  sleep 0.5
140
157
  end
141
158
 
@@ -217,8 +234,6 @@ module RailsAgentServer
217
234
 
218
235
  if error
219
236
  response << error
220
- elsif printed_output.empty?
221
- response << result.inspect
222
237
  end
223
238
 
224
239
  response
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAgentServer
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_agent_server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Waite
@@ -11,7 +11,7 @@ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: Rails Agent Server provides a persistent background server for running
13
13
  Rails code without the overhead of booting Rails for each request. Perfect for AI
14
- agents and automation tools that need fast Rails console access.
14
+ agents that need fast Rails console access.
15
15
  email:
16
16
  - andyw8@users.noreply.github.com
17
17
  executables:
@@ -22,6 +22,7 @@ files:
22
22
  - LICENSE.txt
23
23
  - README.md
24
24
  - Rakefile
25
+ - TESTING.md
25
26
  - exe/rails_agent_server
26
27
  - lib/rails_agent_server.rb
27
28
  - lib/rails_agent_server/cli.rb