rails_pulse 0.1.3 ā 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/README.md +134 -16
- data/Rakefile +315 -83
- data/app/assets/images/rails_pulse/rails-pulse-logo.png +0 -0
- data/app/assets/stylesheets/rails_pulse/components/datepicker.css +191 -0
- data/app/assets/stylesheets/rails_pulse/components/switch.css +36 -0
- data/app/assets/stylesheets/rails_pulse/components/tags.css +98 -0
- data/app/assets/stylesheets/rails_pulse/components/utilities.css +26 -0
- data/app/controllers/concerns/response_range_concern.rb +15 -2
- data/app/controllers/concerns/tag_filter_concern.rb +26 -0
- data/app/controllers/concerns/time_range_concern.rb +27 -8
- data/app/controllers/rails_pulse/application_controller.rb +73 -0
- data/app/controllers/rails_pulse/queries_controller.rb +18 -21
- data/app/controllers/rails_pulse/requests_controller.rb +80 -35
- data/app/controllers/rails_pulse/routes_controller.rb +4 -2
- data/app/controllers/rails_pulse/tags_controller.rb +51 -0
- data/app/helpers/rails_pulse/application_helper.rb +2 -0
- data/app/helpers/rails_pulse/breadcrumbs_helper.rb +1 -1
- data/app/helpers/rails_pulse/chart_helper.rb +1 -1
- data/app/helpers/rails_pulse/form_helper.rb +75 -0
- data/app/helpers/rails_pulse/formatting_helper.rb +21 -2
- data/app/helpers/rails_pulse/tags_helper.rb +29 -0
- data/app/javascript/rails_pulse/application.js +6 -0
- data/app/javascript/rails_pulse/controllers/custom_range_controller.js +115 -0
- data/app/javascript/rails_pulse/controllers/datepicker_controller.js +48 -0
- data/app/javascript/rails_pulse/controllers/global_filters_controller.js +110 -0
- data/app/javascript/rails_pulse/controllers/index_controller.js +11 -3
- data/app/models/concerns/taggable.rb +61 -0
- data/app/models/rails_pulse/dashboard/tables/slow_queries.rb +1 -1
- data/app/models/rails_pulse/dashboard/tables/slow_routes.rb +1 -1
- data/app/models/rails_pulse/queries/cards/average_query_times.rb +1 -1
- data/app/models/rails_pulse/queries/cards/execution_rate.rb +56 -17
- data/app/models/rails_pulse/queries/cards/percentile_query_times.rb +1 -1
- data/app/models/rails_pulse/queries/charts/average_query_times.rb +3 -7
- data/app/models/rails_pulse/queries/tables/index.rb +10 -2
- data/app/models/rails_pulse/query.rb +2 -0
- data/app/models/rails_pulse/request.rb +10 -2
- data/app/models/rails_pulse/requests/charts/average_response_times.rb +2 -2
- data/app/models/rails_pulse/requests/tables/index.rb +77 -0
- data/app/models/rails_pulse/route.rb +2 -0
- data/app/models/rails_pulse/routes/cards/average_response_times.rb +1 -1
- data/app/models/rails_pulse/routes/cards/error_rate_per_route.rb +1 -1
- data/app/models/rails_pulse/routes/cards/percentile_response_times.rb +1 -1
- data/app/models/rails_pulse/routes/cards/request_count_totals.rb +16 -5
- data/app/models/rails_pulse/routes/tables/index.rb +14 -4
- data/app/models/rails_pulse/summary.rb +7 -7
- data/app/services/rails_pulse/analysis/query_characteristics_analyzer.rb +11 -3
- data/app/services/rails_pulse/summary_service.rb +2 -0
- data/app/views/layouts/rails_pulse/_global_filters.html.erb +84 -0
- data/app/views/layouts/rails_pulse/_menu_items.html.erb +5 -5
- data/app/views/layouts/rails_pulse/application.html.erb +8 -5
- data/app/views/rails_pulse/components/_metric_card.html.erb +2 -2
- data/app/views/rails_pulse/components/_operation_details_popover.html.erb +1 -1
- data/app/views/rails_pulse/components/_page_header.html.erb +20 -0
- data/app/views/rails_pulse/components/_sparkline_stats.html.erb +1 -1
- data/app/views/rails_pulse/dashboard/index.html.erb +1 -1
- data/app/views/rails_pulse/operations/show.html.erb +1 -1
- data/app/views/rails_pulse/queries/_analysis_results.html.erb +53 -23
- data/app/views/rails_pulse/queries/_show_table.html.erb +33 -5
- data/app/views/rails_pulse/queries/_table.html.erb +4 -6
- data/app/views/rails_pulse/queries/index.html.erb +3 -7
- data/app/views/rails_pulse/queries/show.html.erb +3 -7
- data/app/views/rails_pulse/requests/_table.html.erb +32 -19
- data/app/views/rails_pulse/requests/index.html.erb +45 -55
- data/app/views/rails_pulse/requests/show.html.erb +1 -3
- data/app/views/rails_pulse/routes/_requests_table.html.erb +41 -0
- data/app/views/rails_pulse/routes/_table.html.erb +4 -8
- data/app/views/rails_pulse/routes/index.html.erb +4 -8
- data/app/views/rails_pulse/routes/show.html.erb +6 -12
- data/app/views/rails_pulse/tags/_tag_manager.html.erb +73 -0
- data/config/initializers/rails_charts_csp_patch.rb +32 -40
- data/config/routes.rb +5 -0
- data/db/migrate/20250930105043_install_rails_pulse_tables.rb +23 -0
- data/db/rails_pulse_schema.rb +4 -1
- data/lib/generators/rails_pulse/convert_to_migrations_generator.rb +25 -9
- data/lib/generators/rails_pulse/install_generator.rb +30 -7
- data/lib/generators/rails_pulse/templates/db/rails_pulse_schema.rb +75 -2
- data/lib/generators/rails_pulse/templates/migrations/install_rails_pulse_tables.rb +3 -2
- data/lib/generators/rails_pulse/templates/rails_pulse.rb +21 -0
- data/lib/generators/rails_pulse/upgrade_generator.rb +147 -30
- data/lib/rails_pulse/configuration.rb +16 -1
- data/lib/rails_pulse/engine.rb +21 -0
- data/lib/rails_pulse/version.rb +1 -1
- data/public/rails-pulse-assets/rails-pulse-icons.js +16 -15
- data/public/rails-pulse-assets/rails-pulse-icons.js.map +1 -1
- data/public/rails-pulse-assets/rails-pulse.css +1 -1
- data/public/rails-pulse-assets/rails-pulse.css.map +1 -1
- data/public/rails-pulse-assets/rails-pulse.js +73 -69
- data/public/rails-pulse-assets/rails-pulse.js.map +4 -4
- metadata +20 -5
- data/app/views/rails_pulse/components/_breadcrumbs.html.erb +0 -12
- data/db/migrate/20241222000001_create_rails_pulse_summaries.rb +0 -54
- data/db/migrate/20250916031656_add_analysis_to_rails_pulse_queries.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8ed469f307dd71e912b46a4da0a0daa60abbdc262a8dbd12604db00a66335fe
|
|
4
|
+
data.tar.gz: 8af5a6bf946a86e1bc277c1d719100ace739bb429c07969fd1e4ec31887d6f70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eceb3af7e713b6049688e50a8fd79af7b2f09c7720158c8d15257235b0c7488ebe7c0eccfaab3cd5dfb5923f80e9a8bd8693d0a9fb2f4e021aca8846c4ac435c
|
|
7
|
+
data.tar.gz: f982a50256d99968eb68fee89e6380d3f75511e6c3e8e878ddca375919f6a68a201f9ce46c6868e2425c127ae1862ca0d1895b0e01afea89a9af6a4e85d7f0f9
|
data/README.md
CHANGED
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
- [Authentication](#authentication)
|
|
26
26
|
- [Authentication Setup](#authentication-setup)
|
|
27
27
|
- [Authentication Examples](#authentication-examples)
|
|
28
|
+
- [Tagging System](#tagging-system)
|
|
29
|
+
- [Configuring Tags](#configuring-tags)
|
|
30
|
+
- [Using Tags](#using-tags)
|
|
31
|
+
- [Filtering by Tags](#filtering-by-tags)
|
|
28
32
|
- [Data Management](#data-management)
|
|
29
33
|
- [Cleanup Strategies](#cleanup-strategies)
|
|
30
34
|
- [Cleanup Configuration](#cleanup-configuration)
|
|
@@ -58,6 +62,11 @@ Rails Pulse is a comprehensive performance monitoring and debugging gem that pro
|
|
|
58
62
|
- Smart caching with minimal performance overhead
|
|
59
63
|
- Multiple database support (SQLite, PostgreSQL, MySQL)
|
|
60
64
|
|
|
65
|
+
### Organization & Filtering
|
|
66
|
+
- Flexible tagging system for routes, requests, and queries
|
|
67
|
+
- Filter performance data by custom tags
|
|
68
|
+
- Organize monitoring data by environment, priority, or custom categories
|
|
69
|
+
|
|
61
70
|
## Screenshots
|
|
62
71
|
|
|
63
72
|
<table>
|
|
@@ -87,15 +96,22 @@ bundle install
|
|
|
87
96
|
Generate the installation files:
|
|
88
97
|
|
|
89
98
|
```bash
|
|
99
|
+
# Install with single database setup (default - recommended)
|
|
90
100
|
rails generate rails_pulse:install
|
|
91
|
-
```
|
|
92
101
|
|
|
93
|
-
|
|
102
|
+
# Or install with separate database setup
|
|
103
|
+
rails generate rails_pulse:install --database=separate
|
|
104
|
+
```
|
|
94
105
|
|
|
106
|
+
**For single database setup (default):**
|
|
95
107
|
```bash
|
|
96
|
-
rails db:
|
|
108
|
+
rails db:migrate # Creates Rails Pulse tables in your main database
|
|
97
109
|
```
|
|
98
110
|
|
|
111
|
+
**For separate database setup:**
|
|
112
|
+
1. Configure `config/database.yml` with your Rails Pulse database settings
|
|
113
|
+
2. Run: `rails db:prepare` to create and load the schema
|
|
114
|
+
|
|
99
115
|
Add the Rails Pulse route to your application:
|
|
100
116
|
|
|
101
117
|
```ruby
|
|
@@ -122,6 +138,10 @@ Rails Pulse automatically starts collecting performance data once installed. Acc
|
|
|
122
138
|
http://localhost:3000/rails_pulse
|
|
123
139
|
```
|
|
124
140
|
|
|
141
|
+
**Database Setup:**
|
|
142
|
+
- **Single Database (default)**: Rails Pulse tables are created in your main database - no additional configuration needed
|
|
143
|
+
- **Separate Database**: See the [Separate Database Support](#separate-database-support) section for setup instructions
|
|
144
|
+
|
|
125
145
|
### Basic Configuration
|
|
126
146
|
|
|
127
147
|
Customize Rails Pulse in `config/initializers/rails_pulse.rb`:
|
|
@@ -165,6 +185,9 @@ RailsPulse.configure do |config|
|
|
|
165
185
|
config.ignored_requests = [] # Array of request patterns to ignore
|
|
166
186
|
config.ignored_queries = [] # Array of query patterns to ignore
|
|
167
187
|
|
|
188
|
+
# Tagging system - define available tags for categorizing performance data
|
|
189
|
+
config.tags = ["production", "staging", "critical", "needs-optimization"]
|
|
190
|
+
|
|
168
191
|
# Data cleanup
|
|
169
192
|
config.archiving_enabled = true # Enable automatic cleanup
|
|
170
193
|
config.full_retention_period = 2.weeks # Delete records older than this
|
|
@@ -232,6 +255,72 @@ config.authentication_method = proc {
|
|
|
232
255
|
}
|
|
233
256
|
```
|
|
234
257
|
|
|
258
|
+
## Tagging System
|
|
259
|
+
|
|
260
|
+
Rails Pulse includes a flexible tagging system that allows you to categorize and organize your performance data. Tag routes, requests, and queries with custom labels to better organize and filter your monitoring data.
|
|
261
|
+
|
|
262
|
+
### Configuring Tags
|
|
263
|
+
|
|
264
|
+
Define available tags in your Rails Pulse initializer:
|
|
265
|
+
|
|
266
|
+
```ruby
|
|
267
|
+
RailsPulse.configure do |config|
|
|
268
|
+
config.tags = [
|
|
269
|
+
"production",
|
|
270
|
+
"staging",
|
|
271
|
+
"critical",
|
|
272
|
+
"needs-optimization",
|
|
273
|
+
"high-traffic",
|
|
274
|
+
"background-job"
|
|
275
|
+
]
|
|
276
|
+
end
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Using Tags
|
|
280
|
+
|
|
281
|
+
**Tag from the UI:**
|
|
282
|
+
|
|
283
|
+
1. Navigate to any route, request, or query detail page
|
|
284
|
+
2. Click the "+ tag" button next to the record
|
|
285
|
+
3. Select from your configured tags
|
|
286
|
+
4. Remove tags by clicking the Ć button on any tag badge
|
|
287
|
+
|
|
288
|
+
**Tag Programmatically:**
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
# Tag a route
|
|
292
|
+
route = RailsPulse::Route.find_by(path: "/api/users")
|
|
293
|
+
route.add_tag("critical")
|
|
294
|
+
route.add_tag("high-traffic")
|
|
295
|
+
|
|
296
|
+
# Tag a query
|
|
297
|
+
query = RailsPulse::Query.find_by(normalized_sql: "SELECT * FROM users WHERE id = ?")
|
|
298
|
+
query.add_tag("needs-optimization")
|
|
299
|
+
|
|
300
|
+
# Remove a tag
|
|
301
|
+
route.remove_tag("critical")
|
|
302
|
+
|
|
303
|
+
# Check if has tag
|
|
304
|
+
route.has_tag?("production") # => true
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Filtering by Tags
|
|
308
|
+
|
|
309
|
+
Use the global filters modal to filter performance data by tags:
|
|
310
|
+
|
|
311
|
+
1. Click the filter icon in the top navigation
|
|
312
|
+
2. Select one or more tags from the tag selector
|
|
313
|
+
3. Apply filters to see only records with those tags
|
|
314
|
+
4. Tags appear as badges in all data tables for quick visual identification
|
|
315
|
+
|
|
316
|
+
**Common Tagging Strategies:**
|
|
317
|
+
|
|
318
|
+
- **By Environment**: `production`, `staging`, `development`
|
|
319
|
+
- **By Priority**: `critical`, `high`, `medium`, `low`
|
|
320
|
+
- **By Status**: `needs-optimization`, `investigating`, `resolved`
|
|
321
|
+
- **By Type**: `api`, `background-job`, `user-facing`, `admin`
|
|
322
|
+
- **By Team**: `team-frontend`, `team-backend`, `team-data`
|
|
323
|
+
|
|
235
324
|
## Data Management
|
|
236
325
|
|
|
237
326
|
Rails Pulse provides data cleanup to prevent your monitoring database from growing indefinitely while preserving essential performance insights.
|
|
@@ -287,20 +376,36 @@ RailsPulse::CleanupJob.perform_later
|
|
|
287
376
|
|
|
288
377
|
## Separate Database Support
|
|
289
378
|
|
|
290
|
-
Rails Pulse
|
|
379
|
+
Rails Pulse offers two database setup options to fit your application's needs:
|
|
380
|
+
|
|
381
|
+
### Option 1: Single Database (Default - Recommended)
|
|
382
|
+
|
|
383
|
+
Stores Rails Pulse data in your main application database alongside your existing tables. This is the simplest setup and works great for most applications.
|
|
384
|
+
|
|
385
|
+
**Advantages:**
|
|
386
|
+
- Zero additional configuration required
|
|
387
|
+
- Simpler backup and deployment strategies
|
|
388
|
+
- Works with any database (SQLite, PostgreSQL, MySQL)
|
|
389
|
+
|
|
390
|
+
**Installation:**
|
|
391
|
+
```bash
|
|
392
|
+
rails generate rails_pulse:install
|
|
393
|
+
rails db:migrate
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Option 2: Separate Database
|
|
291
397
|
|
|
292
|
-
|
|
398
|
+
Stores Rails Pulse data in a dedicated database, completely isolated from your main application.
|
|
293
399
|
|
|
400
|
+
**Use a separate database when you want:**
|
|
294
401
|
- **Isolating monitoring data** from your main application database
|
|
295
402
|
- **Using different database engines** optimized for time-series data
|
|
296
403
|
- **Scaling monitoring independently** from your application
|
|
297
404
|
- **Simplified backup strategies** with separate retention policies
|
|
298
405
|
|
|
299
|
-
**For shared database setup (default)**, no database configuration is needed - simply run `rails db:prepare` after installation.
|
|
300
|
-
|
|
301
406
|
### Configuration
|
|
302
407
|
|
|
303
|
-
To use a separate database, configure the `connects_to` option in your Rails Pulse initializer:
|
|
408
|
+
To use a separate database, install with the `--database=separate` flag, then configure the `connects_to` option in your Rails Pulse initializer:
|
|
304
409
|
|
|
305
410
|
```ruby
|
|
306
411
|
RailsPulse.configure do |config|
|
|
@@ -356,17 +461,30 @@ production:
|
|
|
356
461
|
pool: 5
|
|
357
462
|
```
|
|
358
463
|
|
|
359
|
-
###
|
|
464
|
+
### Installation Steps
|
|
360
465
|
|
|
361
|
-
|
|
466
|
+
**For separate database setup:**
|
|
362
467
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
468
|
+
1. **Generate installation files:**
|
|
469
|
+
```bash
|
|
470
|
+
rails generate rails_pulse:install --database=separate
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
2. **Configure `config/database.yml`** (see examples above)
|
|
474
|
+
|
|
475
|
+
3. **Create and load the schema:**
|
|
476
|
+
```bash
|
|
477
|
+
rails db:prepare
|
|
478
|
+
```
|
|
479
|
+
This automatically creates the database and loads the Rails Pulse schema.
|
|
480
|
+
|
|
481
|
+
**Schema Management:**
|
|
366
482
|
|
|
367
|
-
|
|
368
|
-
-
|
|
369
|
-
-
|
|
483
|
+
The schema file `db/rails_pulse_schema.rb` serves as your single source of truth for the database structure. It:
|
|
484
|
+
- Defines all Rails Pulse tables in one place
|
|
485
|
+
- Is loaded by the installation migration
|
|
486
|
+
- Should not be deleted or modified
|
|
487
|
+
- Future updates will provide migrations in `db/rails_pulse_migrate/`
|
|
370
488
|
|
|
371
489
|
## Testing
|
|
372
490
|
|
data/Rakefile
CHANGED
|
@@ -1,109 +1,341 @@
|
|
|
1
1
|
require "bundler/setup"
|
|
2
|
+
require "bundler/gem_tasks"
|
|
2
3
|
|
|
3
4
|
# Load environment variables from .env file
|
|
4
5
|
require "dotenv/load" if File.exist?(".env")
|
|
5
6
|
|
|
6
7
|
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
|
7
8
|
load "rails/tasks/engine.rake"
|
|
8
|
-
load "rails/tasks/statistics.rake"
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
desc "Setup database for testing"
|
|
11
|
+
task :test_setup do
|
|
12
|
+
database = ENV['DB'] || 'sqlite3'
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
puts "\n" + "=" * 50
|
|
15
|
+
puts "š ļø Rails Pulse Test Setup"
|
|
16
|
+
puts "=" * 50
|
|
17
|
+
puts "Database: #{database.upcase}"
|
|
18
|
+
puts "=" * 50
|
|
19
|
+
puts
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
# Remove schema.rb to ensure clean migration
|
|
23
|
+
schema_file = "test/dummy/db/schema.rb"
|
|
24
|
+
if File.exist?(schema_file)
|
|
25
|
+
puts "š§¹ Removing existing schema.rb file..."
|
|
26
|
+
File.delete(schema_file)
|
|
27
|
+
end
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
case database.downcase
|
|
30
|
+
when 'sqlite3', 'sqlite'
|
|
31
|
+
puts "š¦ Setting up SQLite database..."
|
|
32
|
+
sh "RAILS_ENV=test bin/rails db:drop db:create db:migrate"
|
|
33
|
+
|
|
34
|
+
when 'mysql2', 'mysql'
|
|
35
|
+
puts "š¬ Setting up MySQL database..."
|
|
36
|
+
sh "DB=mysql2 RAILS_ENV=test rails db:drop db:create db:migrate"
|
|
37
|
+
|
|
38
|
+
when 'postgresql', 'postgres'
|
|
39
|
+
puts "š Setting up PostgreSQL database..."
|
|
40
|
+
sh "DB=postgresql RAILS_ENV=test rails db:drop db:create db:migrate"
|
|
41
|
+
|
|
42
|
+
else
|
|
43
|
+
puts "ā ļø Unknown database: #{database}"
|
|
44
|
+
puts "Supported databases: sqlite3, mysql2, postgresql"
|
|
45
|
+
exit 1
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
puts "\nā
Database setup complete!"
|
|
49
|
+
puts "Ready to run: rake test"
|
|
50
|
+
|
|
51
|
+
rescue => e
|
|
52
|
+
puts "\nā Database setup failed!"
|
|
53
|
+
puts "Error: #{e.message}"
|
|
54
|
+
puts "\nTroubleshooting:"
|
|
55
|
+
puts "⢠Ensure #{database} is installed and running"
|
|
56
|
+
puts "⢠Check database credentials in test/dummy/config/database.yml"
|
|
57
|
+
puts "⢠Verify RAILS_ENV=test environment is configured"
|
|
58
|
+
exit 1
|
|
22
59
|
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc "Run test suite"
|
|
63
|
+
task :test do
|
|
64
|
+
database = ENV['DB'] || 'sqlite3'
|
|
23
65
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
66
|
+
# Get Rails version from Gemfile.lock or fallback
|
|
67
|
+
rails_version = begin
|
|
68
|
+
require 'rails'
|
|
69
|
+
Rails.version
|
|
70
|
+
rescue LoadError
|
|
71
|
+
# Try to get from Gemfile.lock
|
|
72
|
+
gemfile_lock = File.read('Gemfile.lock') rescue nil
|
|
73
|
+
if gemfile_lock && gemfile_lock.match(/rails \(([^)]+)\)/)
|
|
74
|
+
$1
|
|
75
|
+
else
|
|
76
|
+
'unknown'
|
|
77
|
+
end
|
|
27
78
|
end
|
|
28
79
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
80
|
+
puts "\n" + "=" * 50
|
|
81
|
+
puts "š Rails Pulse Test Suite"
|
|
82
|
+
puts "=" * 50
|
|
83
|
+
puts "Database: #{database.upcase}"
|
|
84
|
+
puts "Rails: #{rails_version}"
|
|
85
|
+
puts "=" * 50
|
|
86
|
+
puts
|
|
87
|
+
|
|
88
|
+
sh "rails test test/controllers test/helpers test/instrumentation test/jobs test/models test/services"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
desc "Setup database for specific Rails version and database"
|
|
92
|
+
task :test_setup_for_version, [ :database, :rails_version ] do |t, args|
|
|
93
|
+
database = args[:database] || ENV['DB'] || 'sqlite3'
|
|
94
|
+
rails_version = args[:rails_version] || 'rails-8-0'
|
|
95
|
+
|
|
96
|
+
puts "\n" + "=" * 50
|
|
97
|
+
puts "š ļø Rails Pulse Test Setup"
|
|
98
|
+
puts "=" * 50
|
|
99
|
+
puts "Database: #{database.upcase}"
|
|
100
|
+
puts "Rails: #{rails_version.upcase.gsub('-', ' ')}"
|
|
101
|
+
puts "=" * 50
|
|
102
|
+
puts
|
|
103
|
+
|
|
104
|
+
begin
|
|
105
|
+
# Remove schema.rb to ensure clean migration
|
|
106
|
+
schema_file = "test/dummy/db/schema.rb"
|
|
107
|
+
if File.exist?(schema_file)
|
|
108
|
+
puts "š§¹ Removing existing schema.rb file..."
|
|
109
|
+
File.delete(schema_file)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if rails_version == "rails-8-0" && database == "sqlite3"
|
|
113
|
+
# Use current default setup
|
|
114
|
+
puts "š¦ Setting up #{database.upcase} database with Rails 8.0..."
|
|
115
|
+
sh "RAILS_ENV=test bin/rails db:drop db:create db:migrate"
|
|
116
|
+
else
|
|
117
|
+
# Use appraisal with specific database and Rails version
|
|
118
|
+
puts "š¦ Setting up #{database.upcase} database with #{rails_version.upcase.gsub('-', ' ')}..."
|
|
119
|
+
sh "DB=#{database} bundle exec appraisal #{rails_version} rails db:drop db:create db:migrate RAILS_ENV=test"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
puts "\nā
Database setup complete for #{database.upcase} + #{rails_version.upcase.gsub('-', ' ')}!"
|
|
123
|
+
|
|
124
|
+
rescue => e
|
|
125
|
+
puts "\nā Database setup failed!"
|
|
126
|
+
puts "Error: #{e.message}"
|
|
127
|
+
exit 1
|
|
32
128
|
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
desc "Test all database and Rails version combinations"
|
|
132
|
+
task :test_matrix do
|
|
133
|
+
databases = %w[sqlite3 postgresql mysql2]
|
|
134
|
+
rails_versions = %w[rails-7-2 rails-8-0]
|
|
135
|
+
|
|
136
|
+
failed_combinations = []
|
|
137
|
+
total_combinations = databases.size * rails_versions.size
|
|
138
|
+
current = 0
|
|
139
|
+
|
|
140
|
+
# Check if system tests should be included
|
|
141
|
+
include_system_tests = ENV['BROWSER'] == 'true'
|
|
142
|
+
test_paths = "test/controllers test/helpers test/instrumentation test/jobs test/models test/services"
|
|
143
|
+
test_paths += " test/system" if include_system_tests
|
|
144
|
+
|
|
145
|
+
puts "\n" + "=" * 60
|
|
146
|
+
puts "š Rails Pulse Full Test Matrix"
|
|
147
|
+
puts "=" * 60
|
|
148
|
+
puts "Testing #{total_combinations} combinations..."
|
|
149
|
+
puts "System tests: #{include_system_tests ? 'ENABLED (BROWSER=true)' : 'DISABLED (headless mode)'}"
|
|
150
|
+
puts "=" * 60
|
|
151
|
+
|
|
152
|
+
databases.each do |database|
|
|
153
|
+
rails_versions.each do |rails_version|
|
|
154
|
+
current += 1
|
|
33
155
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
gemfile = "gemfiles/#{rails_version.gsub('-', '_')}.gemfile"
|
|
50
|
-
|
|
51
|
-
# Set environment variables
|
|
52
|
-
env_vars = {
|
|
53
|
-
"DB" => database,
|
|
54
|
-
"BUNDLE_GEMFILE" => gemfile,
|
|
55
|
-
"FORCE_DB_CONFIG" => "true"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
# Add database-specific environment variables
|
|
59
|
-
case database
|
|
60
|
-
when "postgresql"
|
|
61
|
-
env_vars.merge!({
|
|
62
|
-
"POSTGRES_USERNAME" => ENV.fetch("POSTGRES_USERNAME", "postgres"),
|
|
63
|
-
"POSTGRES_PASSWORD" => ENV.fetch("POSTGRES_PASSWORD", ""),
|
|
64
|
-
"POSTGRES_HOST" => ENV.fetch("POSTGRES_HOST", "localhost"),
|
|
65
|
-
"POSTGRES_PORT" => ENV.fetch("POSTGRES_PORT", "5432")
|
|
66
|
-
})
|
|
67
|
-
when "mysql2"
|
|
68
|
-
env_vars.merge!({
|
|
69
|
-
"MYSQL_USERNAME" => ENV.fetch("MYSQL_USERNAME", "root"),
|
|
70
|
-
"MYSQL_PASSWORD" => ENV.fetch("MYSQL_PASSWORD", "password"),
|
|
71
|
-
"MYSQL_HOST" => ENV.fetch("MYSQL_HOST", "localhost"),
|
|
72
|
-
"MYSQL_PORT" => ENV.fetch("MYSQL_PORT", "3306")
|
|
73
|
-
})
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Build environment string
|
|
77
|
-
env_string = env_vars.map { |k, v| "#{k}=#{v}" }.join(" ")
|
|
78
|
-
|
|
79
|
-
# Run the test command
|
|
80
|
-
sh "#{env_string} bundle exec rails test:all"
|
|
81
|
-
|
|
82
|
-
puts "ā
PASSED: #{database} + #{rails_version}"
|
|
83
|
-
|
|
84
|
-
rescue => e
|
|
85
|
-
puts "ā FAILED: #{database} + #{rails_version}"
|
|
86
|
-
puts "Error: #{e.message}"
|
|
87
|
-
failed_combinations << "#{database} + #{rails_version}"
|
|
156
|
+
puts "\n[#{current}/#{total_combinations}] Testing: #{database.upcase} + #{rails_version.upcase.gsub('-', ' ')}"
|
|
157
|
+
puts "-" * 50
|
|
158
|
+
|
|
159
|
+
begin
|
|
160
|
+
# First setup the database for this specific combination
|
|
161
|
+
Rake::Task[:test_setup_for_version].reenable
|
|
162
|
+
Rake::Task[:test_setup_for_version].invoke(database, rails_version)
|
|
163
|
+
|
|
164
|
+
# Then run the tests
|
|
165
|
+
if rails_version == "rails-8-0" && database == "sqlite3"
|
|
166
|
+
# Current default setup
|
|
167
|
+
sh "BROWSER=#{ENV['BROWSER']} rails test #{test_paths}"
|
|
168
|
+
else
|
|
169
|
+
# Use appraisal with specific database
|
|
170
|
+
sh "DB=#{database} BROWSER=#{ENV['BROWSER']} bundle exec appraisal #{rails_version} rails test #{test_paths}"
|
|
88
171
|
end
|
|
172
|
+
|
|
173
|
+
puts "ā
PASSED: #{database} + #{rails_version}"
|
|
174
|
+
|
|
175
|
+
rescue => e
|
|
176
|
+
puts "ā FAILED: #{database} + #{rails_version}"
|
|
177
|
+
puts " Error: #{e.message}"
|
|
178
|
+
failed_combinations << "#{database} + #{rails_version}"
|
|
89
179
|
end
|
|
90
180
|
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
puts "\n" + "=" * 60
|
|
184
|
+
puts "š Test Matrix Results"
|
|
185
|
+
puts "=" * 60
|
|
186
|
+
|
|
187
|
+
if failed_combinations.empty?
|
|
188
|
+
puts "š All #{total_combinations} combinations passed!"
|
|
189
|
+
else
|
|
190
|
+
puts "ā
Passed: #{total_combinations - failed_combinations.size}/#{total_combinations}"
|
|
191
|
+
puts "ā Failed combinations:"
|
|
192
|
+
failed_combinations.each { |combo| puts " ⢠#{combo}" }
|
|
193
|
+
exit 1
|
|
194
|
+
end
|
|
195
|
+
end
|
|
91
196
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
197
|
+
desc "Pre-release testing with comprehensive checks"
|
|
198
|
+
task :test_release do
|
|
199
|
+
puts "\n" + "=" * 70
|
|
200
|
+
puts "š Rails Pulse Pre-Release Validation"
|
|
201
|
+
puts "=" * 70
|
|
202
|
+
puts
|
|
96
203
|
|
|
97
|
-
|
|
98
|
-
|
|
204
|
+
failed_tasks = []
|
|
205
|
+
current_step = 0
|
|
206
|
+
total_steps = 7
|
|
207
|
+
|
|
208
|
+
# Step 1: Git status check
|
|
209
|
+
current_step += 1
|
|
210
|
+
begin
|
|
211
|
+
puts "\n[#{current_step}/#{total_steps}] Checking git status..."
|
|
212
|
+
puts "-" * 70
|
|
213
|
+
|
|
214
|
+
git_status = `git status --porcelain`.strip
|
|
215
|
+
if !git_status.empty?
|
|
216
|
+
puts "ā Git working directory is not clean!"
|
|
217
|
+
puts "\nUncommitted changes:"
|
|
218
|
+
puts git_status
|
|
219
|
+
puts "\nPlease commit or stash your changes before running pre-release tests."
|
|
220
|
+
failed_tasks << "git_status_check"
|
|
99
221
|
else
|
|
100
|
-
puts "
|
|
101
|
-
failed_combinations.each { |combo| puts " - #{combo}" }
|
|
102
|
-
exit 1
|
|
222
|
+
puts "ā
Git working directory is clean"
|
|
103
223
|
end
|
|
224
|
+
rescue => e
|
|
225
|
+
puts "ā ļø Warning: Could not check git status (#{e.message})"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Step 2: RuboCop linting
|
|
229
|
+
current_step += 1
|
|
230
|
+
begin
|
|
231
|
+
puts "\n[#{current_step}/#{total_steps}] Running RuboCop linting..."
|
|
232
|
+
puts "-" * 70
|
|
233
|
+
sh "bundle exec rubocop"
|
|
234
|
+
puts "ā
Code style checks passed!"
|
|
235
|
+
rescue => e
|
|
236
|
+
puts "ā RuboCop linting failed!"
|
|
237
|
+
puts " Error: #{e.message}"
|
|
238
|
+
failed_tasks << "rubocop"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Step 3: Install Node dependencies
|
|
242
|
+
current_step += 1
|
|
243
|
+
begin
|
|
244
|
+
puts "\n[#{current_step}/#{total_steps}] Installing Node dependencies..."
|
|
245
|
+
puts "-" * 70
|
|
246
|
+
sh "npm install"
|
|
247
|
+
puts "ā
Node dependencies installed!"
|
|
248
|
+
rescue => e
|
|
249
|
+
puts "ā npm install failed!"
|
|
250
|
+
puts " Error: #{e.message}"
|
|
251
|
+
failed_tasks << "npm_install"
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Step 4: Build and verify assets
|
|
255
|
+
current_step += 1
|
|
256
|
+
begin
|
|
257
|
+
puts "\n[#{current_step}/#{total_steps}] Building production assets..."
|
|
258
|
+
puts "-" * 70
|
|
259
|
+
sh "npm run build"
|
|
260
|
+
|
|
261
|
+
# Verify assets were built
|
|
262
|
+
assets_dir = "public/rails-pulse-assets"
|
|
263
|
+
if Dir.exist?(assets_dir) && !Dir.empty?(assets_dir)
|
|
264
|
+
puts "ā
Assets built successfully!"
|
|
265
|
+
puts " Location: #{assets_dir}"
|
|
266
|
+
else
|
|
267
|
+
puts "ā Assets directory is missing or empty!"
|
|
268
|
+
failed_tasks << "asset_build_verification"
|
|
269
|
+
end
|
|
270
|
+
rescue => e
|
|
271
|
+
puts "ā Asset building failed!"
|
|
272
|
+
puts " Error: #{e.message}"
|
|
273
|
+
failed_tasks << "npm_build"
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Step 5: Verify gem builds
|
|
277
|
+
current_step += 1
|
|
278
|
+
begin
|
|
279
|
+
puts "\n[#{current_step}/#{total_steps}] Verifying gem builds correctly..."
|
|
280
|
+
puts "-" * 70
|
|
281
|
+
sh "gem build rails_pulse.gemspec"
|
|
282
|
+
|
|
283
|
+
# Clean up the built gem
|
|
284
|
+
built_gems = Dir.glob("rails_pulse-*.gem")
|
|
285
|
+
built_gems.each { |gem_file| File.delete(gem_file) }
|
|
286
|
+
|
|
287
|
+
puts "ā
Gem builds successfully!"
|
|
288
|
+
rescue => e
|
|
289
|
+
puts "ā Gem build failed!"
|
|
290
|
+
puts " Error: #{e.message}"
|
|
291
|
+
failed_tasks << "gem_build"
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Step 6: Run generator tests
|
|
295
|
+
current_step += 1
|
|
296
|
+
begin
|
|
297
|
+
puts "\n[#{current_step}/#{total_steps}] Running generator tests..."
|
|
298
|
+
puts "-" * 70
|
|
299
|
+
sh "./bin/test_generators"
|
|
300
|
+
puts "ā
Generator tests passed!"
|
|
301
|
+
rescue => e
|
|
302
|
+
puts "ā Generator tests failed!"
|
|
303
|
+
puts " Error: #{e.message}"
|
|
304
|
+
failed_tasks << "test_generators"
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Step 7: Run full test matrix with system tests
|
|
308
|
+
current_step += 1
|
|
309
|
+
begin
|
|
310
|
+
puts "\n[#{current_step}/#{total_steps}] Running full test matrix with system tests..."
|
|
311
|
+
puts "-" * 70
|
|
312
|
+
sh "BROWSER=true rake test_matrix"
|
|
313
|
+
puts "ā
Test matrix passed!"
|
|
314
|
+
rescue => e
|
|
315
|
+
puts "ā Test matrix failed!"
|
|
316
|
+
puts " Error: #{e.message}"
|
|
317
|
+
failed_tasks << "test_matrix"
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Print final results
|
|
321
|
+
puts "\n" + "=" * 70
|
|
322
|
+
puts "š Pre-Release Validation Results"
|
|
323
|
+
puts "=" * 70
|
|
324
|
+
|
|
325
|
+
if failed_tasks.empty?
|
|
326
|
+
puts "š All pre-release checks passed!"
|
|
327
|
+
puts "\nā
Ready for release!"
|
|
328
|
+
puts "\nNext steps:"
|
|
329
|
+
puts " 1. Update version in lib/rails_pulse/version.rb"
|
|
330
|
+
puts " 2. Update Gemfile.lock files for all Rails versions"
|
|
331
|
+
puts " 3. Follow the release process in docs/releasing.md"
|
|
332
|
+
else
|
|
333
|
+
puts "ā Failed checks (#{failed_tasks.size}/#{total_steps}):"
|
|
334
|
+
failed_tasks.each { |task| puts " ⢠#{task}" }
|
|
335
|
+
puts "\nā ļø Fix these issues before releasing."
|
|
336
|
+
exit 1
|
|
104
337
|
end
|
|
105
338
|
end
|
|
106
339
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
task test: "test:all"
|
|
340
|
+
|
|
341
|
+
task default: :test
|
|
Binary file
|