rails_pulse 0.4.0.pre.2 → 0.4.0.pre.4

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.
@@ -1,3 +1,3 @@
1
1
  module RailsPulse
2
- VERSION = "0.4.0.pre.2"
2
+ VERSION = "0.4.0.pre.4"
3
3
  end
data/lib/rails_pulse.rb CHANGED
@@ -5,6 +5,8 @@ require "rails_pulse/configuration"
5
5
  require "rails_pulse/paginator"
6
6
  require "rails_pulse/cleanup_service"
7
7
  require "rails_pulse/tracker"
8
+ require "rails_pulse/standalone"
9
+ require "rails_pulse/schema_check"
8
10
 
9
11
  module RailsPulse
10
12
  class << self
@@ -19,14 +19,19 @@ else
19
19
  MESSAGE
20
20
  end
21
21
 
22
+ # Root-relative links and standalone authentication — see lib/rails_pulse/standalone.rb.
23
+ RailsPulse.standalone!
24
+
22
25
  # Disable output buffering so logs appear immediately
23
26
  $stdout.sync = true
24
27
  $stderr.sync = true
25
28
 
26
29
  # Build the Rack app with session support
27
30
  require "rack/session/cookie"
31
+ require "rack/static"
28
32
  require "securerandom"
29
33
  require_relative "rails_pulse/rack_compat"
34
+ require_relative "rails_pulse/middleware/asset_server"
30
35
 
31
36
  # Simple Rack app that just serves the dashboard
32
37
  class DashboardApp
@@ -57,10 +62,38 @@ class DashboardApp
57
62
  end
58
63
  end
59
64
 
60
- # Add session middleware for the dashboard
61
- # Require SECRET_KEY_BASE for security
62
- secret_key = ENV.fetch("SECRET_KEY_BASE") do
63
- raise "SECRET_KEY_BASE environment variable must be set for standalone dashboard"
65
+ # Dashboard assets. RouteHelper#asset_path emits one of two URL shapes: the
66
+ # gem-served fallback (/rails-pulse-assets/<version>/...) or, once
67
+ # assets:precompile has run, the digested copies it installs under the host's
68
+ # public/assets. In the main app those are served by AssetServer (inserted
69
+ # into the host middleware stack by the engine) and by ActionDispatch::Static
70
+ # or the CDN. This process calls the engine directly and has neither, so both
71
+ # are served here; without them every dashboard page renders unstyled.
72
+ use RailsPulse::Middleware::AssetServer,
73
+ RailsPulse::Engine.root.join("public").to_s,
74
+ urls: [ "/rails-pulse-assets" ],
75
+ headers: RailsPulse::Engine.asset_headers
76
+
77
+ use Rack::Static,
78
+ urls: [ "/assets" ],
79
+ root: Rails.public_path.to_s,
80
+ header_rules: [ [ :all, RailsPulse::Engine.asset_headers ] ]
81
+
82
+ # Add session middleware for the dashboard. The cookie is signed with
83
+ # SECRET_KEY_BASE when set, otherwise with the host app's own secret_key_base
84
+ # (config/environment.rb is already loaded above) — hosts on encrypted
85
+ # credentials have no SECRET_KEY_BASE environment variable.
86
+ secret_key = ENV["SECRET_KEY_BASE"].to_s
87
+ if secret_key.empty?
88
+ secret_key = begin
89
+ Rails.application.secret_key_base.to_s
90
+ rescue StandardError
91
+ ""
92
+ end
93
+ end
94
+ if secret_key.empty?
95
+ raise "SECRET_KEY_BASE environment variable must be set for standalone dashboard " \
96
+ "(no Rails secret_key_base was available to fall back to)"
64
97
  end
65
98
 
66
99
  # `secure` keeps the session cookie off plain HTTP in production. Set
@@ -1,3 +1,5 @@
1
+ require "stringio"
2
+
1
3
  namespace :db do
2
4
  namespace :schema do
3
5
  desc "Load Rails Pulse schema (for separate database setup only)"
@@ -36,13 +38,25 @@ end
36
38
  # for test runs, not just for development/production db:prepare.
37
39
  # The task may be namespaced as "app:db:schema:load_rails_pulse" in engine context
38
40
  # vs "db:schema:load_rails_pulse" in a host app — try both.
41
+ #
42
+ # This fires on every single `rails test` process (once per appraisal/test_matrix
43
+ # combination, again for the migration regression process), and after the first
44
+ # run it only ever reports "tables already exist" — so its output is muted here.
45
+ # The task itself stays fully verbose when invoked directly (installs, upgrades,
46
+ # and test/lib/tasks/rails_pulse_test.rb assert on that direct-invocation output).
39
47
  Rake::Task["db:test:prepare"].enhance do
40
48
  if separate_database_setup?
41
49
  task_name = %w[db:schema:load_rails_pulse app:db:schema:load_rails_pulse]
42
50
  .find { |name| Rake::Task.task_defined?(name) }
43
51
  if task_name
44
52
  Rake::Task[task_name].reenable
45
- Rake::Task[task_name].invoke
53
+ original_stdout = $stdout
54
+ $stdout = StringIO.new
55
+ begin
56
+ Rake::Task[task_name].invoke
57
+ ensure
58
+ $stdout = original_stdout
59
+ end
46
60
  end
47
61
  end
48
62
  end if Rake::Task.task_defined?("db:test:prepare")
@@ -151,9 +165,41 @@ namespace :rails_pulse do
151
165
  revision = args[:revision]
152
166
  abort "ERROR: revision is required. Usage: rake rails_pulse:record_deployment[abc1234]" if revision.blank?
153
167
 
154
- deployment = RailsPulse::Deployment.create!(revision: revision, started_at: Time.current)
168
+ attributes = { revision: revision, started_at: Time.current }
169
+ metadata = deployment_metadata_from_env
170
+ attributes[:metadata] = metadata if metadata
171
+
172
+ deployment = RailsPulse::Deployment.create!(attributes)
155
173
  puts "[RailsPulse] Deployment recorded: #{deployment.revision} at #{deployment.started_at}"
156
174
  rescue ActiveRecord::RecordInvalid => e
157
175
  abort "ERROR: #{e.message}"
158
176
  end
177
+
178
+ desc "Mark the latest deployment for a revision as finished. Usage: rake rails_pulse:finish_deployment[revision]"
179
+ task :finish_deployment, [ :revision ] => :environment do |_t, args|
180
+ revision = args[:revision]
181
+ abort "ERROR: revision is required. Usage: rake rails_pulse:finish_deployment[abc1234]" if revision.blank?
182
+
183
+ deployment = RailsPulse::Deployment.latest_for_revision(revision)
184
+ abort "ERROR: no deployment recorded for revision #{revision}" unless deployment
185
+
186
+ deployment.update!(finished_at: Time.current)
187
+ puts "[RailsPulse] Deployment finished: #{deployment.revision} at #{deployment.finished_at} (#{deployment.duration.round}s)"
188
+ rescue ActiveRecord::RecordInvalid => e
189
+ abort "ERROR: #{e.message}"
190
+ end
191
+ end
192
+
193
+ # Optional metadata for rails_pulse:record_deployment, as a JSON object:
194
+ # RAILS_PULSE_DEPLOYMENT_METADATA='{"environment":"production"}'
195
+ # Rake splits task arguments on commas, so JSON cannot be passed positionally.
196
+ def deployment_metadata_from_env
197
+ raw = ENV["RAILS_PULSE_DEPLOYMENT_METADATA"]
198
+ return nil if raw.blank?
199
+
200
+ parsed = JSON.parse(raw)
201
+ abort "ERROR: RAILS_PULSE_DEPLOYMENT_METADATA must be a JSON object" unless parsed.is_a?(Hash)
202
+ parsed.to_json
203
+ rescue JSON::ParserError => e
204
+ abort "ERROR: RAILS_PULSE_DEPLOYMENT_METADATA is not valid JSON: #{e.message}"
159
205
  end
@@ -23,6 +23,11 @@ namespace :rails_pulse do
23
23
  RailsPulse::Stats::CleanupStatsReporter.report
24
24
  end
25
25
 
26
+ desc "Reports schema, migration, route backfill and initializer state for this install; exits 1 when something needs action."
27
+ task status: :environment do
28
+ exit 1 unless RailsPulse::Tasks::StatusReporter.report
29
+ end
30
+
26
31
  desc "Migrate existing routes: backfill controller actions, normalize paths, consolidate multi-verb routes."
27
32
  task migrate_routes: :environment do
28
33
  ca_results = RailsPulse::RouteControllerActionBackfiller.call
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_pulse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre.2
4
+ version: 0.4.0.pre.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Harvey
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-09-04 00:00:00.000000000 Z
11
+ date: 2026-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -451,6 +451,7 @@ files:
451
451
  - app/views/rails_pulse/routes/index.html.erb
452
452
  - app/views/rails_pulse/routes/show.html.erb
453
453
  - app/views/rails_pulse/shared/_deployment_markers_toggle.html.erb
454
+ - app/views/rails_pulse/shared/schema_outdated.html.erb
454
455
  - app/views/rails_pulse/skeletons/_chart.html.erb
455
456
  - app/views/rails_pulse/skeletons/_metric_card.html.erb
456
457
  - app/views/rails_pulse/skeletons/_panel.html.erb
@@ -501,11 +502,14 @@ files:
501
502
  - lib/rails_pulse/paginator.rb
502
503
  - lib/rails_pulse/rack_compat.rb
503
504
  - lib/rails_pulse/route_indexes.rb
505
+ - lib/rails_pulse/schema_check.rb
506
+ - lib/rails_pulse/standalone.rb
504
507
  - lib/rails_pulse/statistics.rb
505
508
  - lib/rails_pulse/stats/cleanup_stats_reporter.rb
506
509
  - lib/rails_pulse/subscribers/exception_subscriber.rb
507
510
  - lib/rails_pulse/subscribers/operation_subscriber.rb
508
511
  - lib/rails_pulse/tasks/cleanup_task_runner.rb
512
+ - lib/rails_pulse/tasks/status_reporter.rb
509
513
  - lib/rails_pulse/tracker.rb
510
514
  - lib/rails_pulse/version.rb
511
515
  - lib/rails_pulse_server.ru
@@ -543,7 +547,7 @@ metadata:
543
547
  bug_tracker_uri: https://github.com/railspulse/rails_pulse/issues
544
548
  rubygems_mfa_required: 'true'
545
549
  post_install_message: |
546
- Rails Pulse 0.4.0.pre.2 installed.
550
+ Rails Pulse 0.4.0.pre.4 installed.
547
551
 
548
552
  UPGRADING from any 0.3.x? This release changes route identity and DROPS
549
553
  rails_pulse_routes.method. Back up your database first, then run: