rails-profiler 0.30.9 → 0.30.10
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/CHANGELOG.md +35 -0
- data/app/controllers/profiler/api/env_vars_controller.rb +6 -0
- data/app/controllers/profiler/api/test_runner_controller.rb +3 -9
- data/lib/profiler/boot_env.rb +8 -0
- data/lib/profiler/configuration.rb +4 -1
- data/lib/profiler/env_override_store.rb +11 -0
- data/lib/profiler/mcp/server.rb +1 -1
- data/lib/profiler/mcp/tools/delete_env_var.rb +7 -0
- data/lib/profiler/mcp/tools/run_tests.rb +7 -1
- data/lib/profiler/mcp/tools/set_env_var.rb +7 -0
- data/lib/profiler/test_runner/discovery.rb +2 -2
- data/lib/profiler/test_runner/runner.rb +135 -7
- data/lib/profiler/version.rb +1 -1
- data/lib/profiler.rb +2 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9d1f1618012f3a987e45ec2f18c565acc7cda82685806ca78801e6fb892012b3
|
|
4
|
+
data.tar.gz: 0f8e433032ac46e974c6a4162afa9c44610f5fd424afdcaf7f12a601f983cfab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 30be96f28f9d20d285b9105725cb0704ed97af7ea8e34d425f7bf3fb8b4ef2f739cded05ab68b1c2931a8424058c18245e72eddb797bbee15c8d2fc1754175e7
|
|
7
|
+
data.tar.gz: 70021a953b7a36fdff2287d9e46242761e02ea114aa6ad16344860e04cb1973d6a87095d120216b4c60b48e9187130ca7a8461b0627c35a90f683931f3ac632c
|
data/CHANGELOG.md
CHANGED
|
@@ -19,6 +19,41 @@ every commit of every tag interval is accounted for one way or the other.
|
|
|
19
19
|
|
|
20
20
|
## [Unreleased]
|
|
21
21
|
|
|
22
|
+
## [0.30.10] - 2026-10-04
|
|
23
|
+
|
|
24
|
+
<!-- stamped -->
|
|
25
|
+
|
|
26
|
+
### Security
|
|
27
|
+
|
|
28
|
+
- **Test runner:** The test runner (the dashboard page and the MCP tool `run_tests`) only runs
|
|
29
|
+
the test files it discovers, `spec/**/*_spec.rb` and `test/**/*_test.rb` under the Rails root,
|
|
30
|
+
optionally with a line number (`spec/models/user_spec.rb:12`). Paths are compared after resolving
|
|
31
|
+
symbolic links. Any other path answers `422` over HTTP, or a tool error over MCP, and nothing is
|
|
32
|
+
started. The HTTP endpoint used to run any file under the Rails root, and `run_tests` any path at all.
|
|
33
|
+
- **Test runner:** A selection sent with the wrong framework (a `test/**/*_test.rb` file for
|
|
34
|
+
`rspec`, or a spec for `minitest`) now answers `422` too, and so does a path holding a null byte,
|
|
35
|
+
which used to raise an error.
|
|
36
|
+
- **Test runner:** The test process starts from the environment the shell gave Rails, copied when
|
|
37
|
+
the gem is loaded, plus the environment overrides set from the profiler, instead of the current
|
|
38
|
+
environment of the application. Overrides that make the test process, or the rbenv or asdf shim
|
|
39
|
+
that starts it, load or run other code are left out, with a warning naming them once: names
|
|
40
|
+
starting with `RUBY`, `GEM_`, `BUNDLE_`, `LD_`, `BASH_`, `RBENV_` and others, `NODE_OPTIONS`,
|
|
41
|
+
`PATH`, `SPEC_OPTS`, `PS4`, `SHELLOPTS`, any name holding a character other than a letter, a
|
|
42
|
+
digit or `_`, and the rest of the list in the README. Those keep their shell value, and so do
|
|
43
|
+
`DATABASE_URL` and `SECRET_KEY_BASE`, whose overrides were skipped but still reached the test
|
|
44
|
+
process, since an override is also written into the environment of the running application. A
|
|
45
|
+
variable deleted from the profiler is now unset in the test process, where it used to hold the
|
|
46
|
+
text `__profiler_deleted__`. Variables the application writes into `ENV` once loaded (`dotenv`
|
|
47
|
+
for instance) no longer reach the test process, which loads them itself when your test setup does.
|
|
48
|
+
The test process, which boots the same application, no longer replays the overrides on its own:
|
|
49
|
+
the runner marks it with `PROFILER_TEST_RUNNER_CHILD=1`, a name the env tools and the env vars
|
|
50
|
+
endpoint now refuse to set or delete (`422`, or a tool error over MCP).
|
|
51
|
+
- **Test runner:** Test files are found when the path of the application holds `[` or `{`.
|
|
52
|
+
- **Upgrading:** Nothing to do when you run the specs the profiler lists. To run any file under the
|
|
53
|
+
Rails root again, set `config.test_runner_allow_undiscovered_files = true`. The environment
|
|
54
|
+
overrides left out have no option, the list being a deny list that cannot be complete: set those
|
|
55
|
+
variables in the shell that starts Rails instead, the test process inherits them.
|
|
56
|
+
|
|
22
57
|
## [0.30.9] - 2026-10-04
|
|
23
58
|
|
|
24
59
|
<!-- stamped -->
|
|
@@ -17,6 +17,12 @@ module Profiler
|
|
|
17
17
|
return
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
if Profiler::EnvOverrideStore.reserved_key?(key)
|
|
21
|
+
render json: { error: "#{Profiler::EnvOverrideStore::RESERVED_KEY_ERROR}; #{key} was left unchanged" },
|
|
22
|
+
status: :unprocessable_entity
|
|
23
|
+
return
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
value = params[:value]
|
|
21
27
|
|
|
22
28
|
if Profiler::Redaction.mask?(value)
|
|
@@ -27,17 +27,11 @@ module Profiler
|
|
|
27
27
|
return render json: { error: "No files selected" }, status: :unprocessable_entity
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
#
|
|
31
|
-
root = defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
|
32
|
-
files.each do |f|
|
|
33
|
-
expanded = File.expand_path(File.join(root, f))
|
|
34
|
-
unless expanded.start_with?(root)
|
|
35
|
-
return render json: { error: "Invalid file path: #{f}" }, status: :unprocessable_entity
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
30
|
+
# Runner.start accepts only discovered test files
|
|
39
31
|
run = Profiler::TestRunner::Runner.start(files: files, framework: framework)
|
|
40
32
|
render json: run.to_h, status: :created
|
|
33
|
+
rescue Profiler::TestRunner::InvalidFileError => e
|
|
34
|
+
render json: { error: e.message }, status: :unprocessable_entity
|
|
41
35
|
end
|
|
42
36
|
|
|
43
37
|
def show
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Profiler
|
|
4
|
+
# ENV as the shell gave it to the process, captured when the gem is loaded, before
|
|
5
|
+
# EnvOverrideStore#apply! or any override set from the profiler writes into ENV. The test
|
|
6
|
+
# runner builds the environment of the processes it starts from this copy, not from ENV.
|
|
7
|
+
BOOT_ENV = ENV.to_h.freeze unless const_defined?(:BOOT_ENV)
|
|
8
|
+
end
|
|
@@ -36,7 +36,7 @@ module Profiler
|
|
|
36
36
|
:track_jobs,
|
|
37
37
|
:track_console,
|
|
38
38
|
:apply_env_overrides_when_disabled,
|
|
39
|
-
:track_tests,
|
|
39
|
+
:track_tests, :test_runner_allow_undiscovered_files,
|
|
40
40
|
:track_mailers, :capture_mail_body, :sanitize_mailer_recipients, :mailer_skip_actions,
|
|
41
41
|
:compress_bodies, :compress_body_threshold,
|
|
42
42
|
:redact_sensitive_data, :filter_parameters, :env_allowlist,
|
|
@@ -80,6 +80,9 @@ module Profiler
|
|
|
80
80
|
@track_console = true
|
|
81
81
|
@apply_env_overrides_when_disabled = false
|
|
82
82
|
@track_tests = false
|
|
83
|
+
# The test runner only runs the files listed by its discovery. true restores the
|
|
84
|
+
# previous behavior: any file under the Rails root.
|
|
85
|
+
@test_runner_allow_undiscovered_files = false
|
|
83
86
|
@track_mailers = true
|
|
84
87
|
@capture_mail_body = false
|
|
85
88
|
@sanitize_mailer_recipients = false
|
|
@@ -107,7 +107,18 @@ module Profiler
|
|
|
107
107
|
warn "[Profiler] EnvOverrideStore: failed to check overrides at boot: #{e.message}"
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
+
# Set by the test runner in the environment of the test process, to which it already gave
|
|
111
|
+
# the admitted overrides only (TestRunner::Runner.build_env).
|
|
112
|
+
TEST_RUNNER_CHILD_ENV = "PROFILER_TEST_RUNNER_CHILD"
|
|
113
|
+
RESERVED_KEY_ERROR = "#{TEST_RUNNER_CHILD_ENV} is reserved for the test runner"
|
|
114
|
+
|
|
115
|
+
# The env tools may not set or delete the test runner marker, whatever its case.
|
|
116
|
+
def self.reserved_key?(key)
|
|
117
|
+
key.to_s.upcase == TEST_RUNNER_CHILD_ENV
|
|
118
|
+
end
|
|
119
|
+
|
|
110
120
|
def apply!
|
|
121
|
+
return if ENV[TEST_RUNNER_CHILD_ENV] == "1"
|
|
111
122
|
return if blocked_reason
|
|
112
123
|
|
|
113
124
|
overrides = load_overrides
|
data/lib/profiler/mcp/server.rb
CHANGED
|
@@ -389,7 +389,7 @@ module Profiler
|
|
|
389
389
|
def define_tool(name:, description:, input_schema:, handler:)
|
|
390
390
|
::MCP::Tool.define(name: name, description: description, input_schema: input_schema) do |server_context: nil, **args|
|
|
391
391
|
result = handler.call(args.transform_keys(&:to_s))
|
|
392
|
-
::MCP::Tool::Response.new(result)
|
|
392
|
+
result.is_a?(::MCP::Tool::Response) ? result : ::MCP::Tool::Response.new(result)
|
|
393
393
|
end
|
|
394
394
|
end
|
|
395
395
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "mcp"
|
|
3
4
|
require_relative "../slave_support"
|
|
4
5
|
|
|
5
6
|
module Profiler
|
|
@@ -10,6 +11,12 @@ module Profiler
|
|
|
10
11
|
key = params["key"].to_s.strip
|
|
11
12
|
|
|
12
13
|
return [{ type: "text", text: "Error: key cannot be blank." }] if key.empty?
|
|
14
|
+
if Profiler::EnvOverrideStore.reserved_key?(key)
|
|
15
|
+
return ::MCP::Tool::Response.new(
|
|
16
|
+
[{ type: "text", text: "Error: #{Profiler::EnvOverrideStore::RESERVED_KEY_ERROR}; #{key} was left unchanged." }],
|
|
17
|
+
error: true
|
|
18
|
+
)
|
|
19
|
+
end
|
|
13
20
|
|
|
14
21
|
if (proxy = MCP::SlaveSupport.with_slave_proxy(params))
|
|
15
22
|
proxy.patch_json("/_profiler/api/env_vars", { key: key, value: "" })
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "mcp"
|
|
4
|
+
|
|
3
5
|
require_relative "../slave_support"
|
|
4
6
|
|
|
5
7
|
require_relative "../../test_runner/discovery"
|
|
@@ -41,7 +43,11 @@ module Profiler
|
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
run_started_at = Time.now
|
|
44
|
-
|
|
46
|
+
begin
|
|
47
|
+
run = Profiler::TestRunner::Runner.start(files: files, framework: framework)
|
|
48
|
+
rescue Profiler::TestRunner::InvalidFileError => e
|
|
49
|
+
return ::MCP::Tool::Response.new([{ type: "text", text: e.message }], error: true)
|
|
50
|
+
end
|
|
45
51
|
|
|
46
52
|
output_pos = 0
|
|
47
53
|
deadline = Time.now + timeout_secs
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "mcp"
|
|
3
4
|
require_relative "../slave_support"
|
|
4
5
|
require_relative "../../redaction"
|
|
5
6
|
|
|
@@ -12,6 +13,12 @@ module Profiler
|
|
|
12
13
|
value = params["value"].to_s
|
|
13
14
|
|
|
14
15
|
return [{ type: "text", text: "Error: key cannot be blank." }] if key.empty?
|
|
16
|
+
if Profiler::EnvOverrideStore.reserved_key?(key)
|
|
17
|
+
return ::MCP::Tool::Response.new(
|
|
18
|
+
[{ type: "text", text: "Error: #{Profiler::EnvOverrideStore::RESERVED_KEY_ERROR}; #{key} was left unchanged." }],
|
|
19
|
+
error: true
|
|
20
|
+
)
|
|
21
|
+
end
|
|
15
22
|
if Profiler::Redaction.mask?(value)
|
|
16
23
|
return [{ type: "text", text: "Error: #{Profiler::Redaction::MASK} is the mask the profiler shows " \
|
|
17
24
|
"in place of a hidden value, not a value; #{key} was left unchanged." }]
|
|
@@ -24,8 +24,8 @@ module Profiler
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
globs.each do |glob|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
# base: keeps glob metacharacters of the root ([, {, *) out of the pattern
|
|
28
|
+
Dir.glob(glob, base: root).each do |relative|
|
|
29
29
|
parts = relative.split("/")
|
|
30
30
|
dir = parts[0..-2].join("/")
|
|
31
31
|
result[dir] ||= []
|
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "set"
|
|
4
|
+
require_relative "../boot_env"
|
|
5
|
+
require_relative "../env_override_store"
|
|
3
6
|
require_relative "run_store"
|
|
4
7
|
require_relative "discovery"
|
|
5
8
|
|
|
6
9
|
module Profiler
|
|
7
10
|
module TestRunner
|
|
11
|
+
# Raised by Runner.start when the selection holds a file that is not a discovered test.
|
|
12
|
+
class InvalidFileError < ArgumentError; end
|
|
13
|
+
|
|
8
14
|
class Runner
|
|
15
|
+
# "spec/models/user_spec.rb:12" or ":12:30": the line selection rspec and minitest accept.
|
|
16
|
+
LINE_SUFFIX = /\A(.+?)((?::\d+)+)\z/
|
|
17
|
+
|
|
18
|
+
@warn_mutex = Mutex.new
|
|
19
|
+
@warned = {}
|
|
20
|
+
|
|
21
|
+
# Every caller (the HTTP controller, the MCP run_tests tool) goes through here, so the
|
|
22
|
+
# selection is checked once, before any run is recorded or any process is started.
|
|
9
23
|
def self.start(files:, framework:)
|
|
24
|
+
validate_files!(files, framework)
|
|
10
25
|
run = Profiler::TestRunner.run_store.create(files: files, framework: framework)
|
|
11
26
|
spawn_async(run)
|
|
12
27
|
run
|
|
@@ -26,6 +41,77 @@ module Profiler
|
|
|
26
41
|
end
|
|
27
42
|
end
|
|
28
43
|
|
|
44
|
+
# Accepts only files listed by Discovery.files for the framework, compared by their
|
|
45
|
+
# canonical path (File.realpath, symbolic links resolved), so that a test run cannot be
|
|
46
|
+
# used to execute any other Ruby file of the application.
|
|
47
|
+
def self.validate_files!(files, framework)
|
|
48
|
+
files = Array(files)
|
|
49
|
+
raise InvalidFileError, "No files selected" if files.empty?
|
|
50
|
+
|
|
51
|
+
root = project_root
|
|
52
|
+
allowed = if Profiler.configuration.test_runner_allow_undiscovered_files
|
|
53
|
+
warn_once(:undiscovered,
|
|
54
|
+
"[Profiler] config.test_runner_allow_undiscovered_files is enabled: the test runner " \
|
|
55
|
+
"runs any file under the Rails root, not only the discovered tests.")
|
|
56
|
+
nil
|
|
57
|
+
else
|
|
58
|
+
discovered_real_paths(root, framework)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
refused = files.reject do |entry|
|
|
62
|
+
next false unless entry.is_a?(String) && !entry.empty? && !entry.include?("\0")
|
|
63
|
+
|
|
64
|
+
path = entry[LINE_SUFFIX, 1] || entry
|
|
65
|
+
allowed ? allowed.include?(real_path(File.join(root, path))) : under_root?(root, File.join(root, path))
|
|
66
|
+
end
|
|
67
|
+
return if refused.empty?
|
|
68
|
+
|
|
69
|
+
message = allowed ? "Not a discovered test file" : "Not a file under the Rails root"
|
|
70
|
+
raise InvalidFileError, "#{message}: #{refused.map(&:to_s).join(", ")}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.discovered_real_paths(root, framework)
|
|
74
|
+
real_root = real_path(root)
|
|
75
|
+
Discovery.files(framework: framework).flat_map { |dir| dir[:files] }.filter_map do |file|
|
|
76
|
+
path = real_path(File.join(root, file[:path]))
|
|
77
|
+
# A discovered symbolic link whose target leaves the project is not a project test.
|
|
78
|
+
path if path && real_root && path.start_with?("#{real_root}/")
|
|
79
|
+
end.to_set
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.real_path(path)
|
|
83
|
+
File.realpath(path)
|
|
84
|
+
rescue SystemCallError, ArgumentError
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def self.under_root?(root, path)
|
|
89
|
+
expanded = File.expand_path(path)
|
|
90
|
+
expanded == root || expanded.start_with?("#{root}/")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.project_root
|
|
94
|
+
defined?(Rails) ? Rails.root.to_s : Dir.pwd
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.warn_once(key, message)
|
|
98
|
+
@warn_mutex.synchronize do
|
|
99
|
+
return if @warned[key]
|
|
100
|
+
|
|
101
|
+
@warned[key] = true
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
|
105
|
+
Rails.logger.warn(message)
|
|
106
|
+
else
|
|
107
|
+
warn(message)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.reset_warnings!
|
|
112
|
+
@warn_mutex.synchronize { @warned = {} }
|
|
113
|
+
end
|
|
114
|
+
|
|
29
115
|
private
|
|
30
116
|
|
|
31
117
|
def self.spawn_async(run)
|
|
@@ -47,7 +133,8 @@ module Profiler
|
|
|
47
133
|
|
|
48
134
|
Profiler::TestRunner.run_store.update(run.id, status: "running", started_at: Time.now)
|
|
49
135
|
|
|
50
|
-
|
|
136
|
+
# unsetenv_others: the child gets exactly env, not the ENV of this process
|
|
137
|
+
IO.popen([env, *cmd, unsetenv_others: true, err: [:child, :out]], "r") do |io|
|
|
51
138
|
Profiler::TestRunner.run_store.update(run.id, pid: io.pid)
|
|
52
139
|
|
|
53
140
|
while (chunk = io.read(256))
|
|
@@ -69,7 +156,7 @@ module Profiler
|
|
|
69
156
|
end
|
|
70
157
|
|
|
71
158
|
def self.build_command(files, framework)
|
|
72
|
-
root =
|
|
159
|
+
root = project_root
|
|
73
160
|
absolute_files = files.map { |f| File.join(root, f) }
|
|
74
161
|
|
|
75
162
|
case framework.to_sym
|
|
@@ -82,22 +169,63 @@ module Profiler
|
|
|
82
169
|
end
|
|
83
170
|
end
|
|
84
171
|
|
|
85
|
-
BLOCKED_ENV_KEYS = %w[RAILS_ENV RACK_ENV DATABASE_URL SECRET_KEY_BASE].freeze
|
|
172
|
+
BLOCKED_ENV_KEYS = %w[RAILS_ENV RACK_ENV DATABASE_URL SECRET_KEY_BASE PROFILER_TEST_RUNNER_CHILD].freeze
|
|
173
|
+
|
|
174
|
+
# Overrides of these variables make the test process, or the shell shims (rbenv, asdf) that
|
|
175
|
+
# start it, load or run code other than the selected tests. It is a deny list, so it cannot
|
|
176
|
+
# be complete; a variable needed by the tests can be set in the shell that starts Rails.
|
|
177
|
+
CODE_LOADING_ENV_KEYS = %w[
|
|
178
|
+
SPEC_OPTS TESTOPTS TEST PATH HOME XDG_CONFIG_HOME GEMRC NODE_OPTIONS NODE_PATH
|
|
179
|
+
SHELLOPTS BASHOPTS PS4 ENV CDPATH IFS
|
|
180
|
+
].freeze
|
|
181
|
+
CODE_LOADING_ENV_PREFIXES = %w[
|
|
182
|
+
RUBY GEM_ BUNDLE_ BUNDLER_ LD_ DYLD_ BASH_ RBENV_ ASDF_ RVM_ CHRUBY GIT_ BOOTSNAP_
|
|
183
|
+
PYTHON PERL5
|
|
184
|
+
].freeze
|
|
185
|
+
ENV_NAME = /\A[A-Z_][A-Z0-9_]*\z/i
|
|
186
|
+
|
|
187
|
+
def self.code_loading_env_key?(key)
|
|
188
|
+
name = key.to_s.upcase
|
|
189
|
+
return true unless ENV_NAME.match?(name)
|
|
190
|
+
|
|
191
|
+
CODE_LOADING_ENV_KEYS.include?(name) || CODE_LOADING_ENV_PREFIXES.any? { |prefix| name.start_with?(prefix) }
|
|
192
|
+
end
|
|
86
193
|
|
|
194
|
+
# Starts from the copy of ENV taken when the gem was loaded, not from ENV: the overrides are
|
|
195
|
+
# also written into ENV (by the env vars endpoint, the MCP tools and EnvOverrideStore#apply!),
|
|
196
|
+
# and one whose entry the store lost would pass unnoticed. Only the overrides read from the
|
|
197
|
+
# store and admitted are applied on top; a left-out or blocked key keeps its shell value.
|
|
87
198
|
def self.build_env
|
|
88
|
-
base =
|
|
199
|
+
base = Profiler::BOOT_ENV.dup
|
|
200
|
+
left_out = []
|
|
89
201
|
|
|
90
|
-
# Inject env var overrides configured in the profiler — skip blocked keys
|
|
91
202
|
overrides = Profiler.env_override_store.all_overrides
|
|
92
203
|
overrides.each do |key, entry|
|
|
93
|
-
|
|
204
|
+
blocked = BLOCKED_ENV_KEYS.include?(key.upcase)
|
|
205
|
+
if blocked || code_loading_env_key?(key)
|
|
206
|
+
left_out << key unless blocked
|
|
207
|
+
next
|
|
208
|
+
end
|
|
94
209
|
value = entry.is_a?(Hash) ? entry["value"] : entry
|
|
95
|
-
|
|
210
|
+
if value == EnvOverrideStore::DELETED_SENTINEL
|
|
211
|
+
base.delete(key)
|
|
212
|
+
else
|
|
213
|
+
base[key] = value
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
unless left_out.empty?
|
|
218
|
+
warn_once([:env, left_out.sort],
|
|
219
|
+
"[Profiler] Environment overrides not passed to the test runner, because they make it " \
|
|
220
|
+
"load other code: #{left_out.sort.join(", ")}.")
|
|
96
221
|
end
|
|
97
222
|
|
|
98
223
|
# Ensure test environment regardless of overrides
|
|
99
224
|
base["RAILS_ENV"] = "test"
|
|
100
225
|
base["RACK_ENV"] = "test"
|
|
226
|
+
# The test process boots the same application: its EnvOverrideStore#apply! must not
|
|
227
|
+
# replay the overrides left out above
|
|
228
|
+
base[EnvOverrideStore::TEST_RUNNER_CHILD_ENV] = "1"
|
|
101
229
|
|
|
102
230
|
base
|
|
103
231
|
end
|
data/lib/profiler/version.rb
CHANGED
data/lib/profiler.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-profiler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.30.
|
|
4
|
+
version: 0.30.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sébastien Duplessy
|
|
@@ -58,14 +58,14 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - ">="
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
61
|
+
version: '0.3'
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
68
|
+
version: '0.3'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: webmock
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -133,6 +133,7 @@ files:
|
|
|
133
133
|
- config/routes.rb
|
|
134
134
|
- exe/profiler-mcp
|
|
135
135
|
- lib/profiler.rb
|
|
136
|
+
- lib/profiler/boot_env.rb
|
|
136
137
|
- lib/profiler/cluster/master_client.rb
|
|
137
138
|
- lib/profiler/cluster/slave_proxy.rb
|
|
138
139
|
- lib/profiler/cluster/slave_registry.rb
|