appmap 0.59.2 → 0.62.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 +4 -4
- data/.travis.yml +6 -16
- data/ARCHITECTURE.md +68 -0
- data/CHANGELOG.md +37 -0
- data/exe/appmap-agent-validate +19 -0
- data/exe/appmap-index +7 -0
- data/lib/appmap.rb +2 -0
- data/lib/appmap/agent.rb +0 -11
- data/lib/appmap/command/agent_setup/status.rb +1 -1
- data/lib/appmap/command/agent_setup/validate.rb +24 -0
- data/lib/appmap/command/index.rb +25 -0
- data/lib/appmap/command/inspect.rb +0 -1
- data/lib/appmap/config.rb +8 -1
- data/lib/appmap/depends.rb +2 -0
- data/lib/appmap/depends/api.rb +84 -0
- data/lib/appmap/depends/configuration.rb +59 -0
- data/lib/appmap/depends/node_cli.rb +44 -0
- data/lib/appmap/depends/rake_tasks.rb +58 -0
- data/lib/appmap/depends/test_file_inspector.rb +89 -0
- data/lib/appmap/depends/test_runner.rb +106 -0
- data/lib/appmap/depends/util.rb +34 -0
- data/lib/appmap/service/config_analyzer.rb +7 -8
- data/lib/appmap/service/integration_test_path_finder.rb +29 -25
- data/lib/appmap/service/test_command_provider.rb +5 -7
- data/lib/appmap/service/validator/config_validator.rb +89 -0
- data/lib/appmap/service/validator/violation.rb +50 -0
- data/lib/appmap/version.rb +4 -1
- data/package.json +1 -1
- data/spec/depends/api_spec.rb +184 -0
- data/spec/depends/spec_helper.rb +27 -0
- data/spec/fixtures/config/invalid_config.yml +2 -2
- data/spec/fixtures/config/invalid_yaml_config.yml +3 -0
- data/spec/fixtures/depends/.gitignore +2 -0
- data/spec/fixtures/depends/app/controllers/api/api_keys_controller.rb +2 -0
- data/spec/fixtures/depends/app/controllers/organizations_controller.rb +2 -0
- data/spec/fixtures/depends/app/models/api_key.rb +2 -0
- data/spec/fixtures/depends/app/models/configuration.rb +2 -0
- data/spec/fixtures/depends/app/models/show.rb +2 -0
- data/spec/fixtures/depends/app/models/user.rb +2 -0
- data/spec/fixtures/depends/revoke_api_key.appmap.json +901 -0
- data/spec/fixtures/depends/spec/actual_rspec_test.rb +7 -0
- data/spec/fixtures/depends/spec/api_spec.rb +2 -0
- data/spec/fixtures/depends/spec/user_spec.rb +2 -0
- data/spec/fixtures/depends/test/actual_minitest_test.rb +5 -0
- data/spec/fixtures/depends/user_page_scenario.appmap.json +1776 -0
- data/spec/fixtures/rails5_users_app/create_app +3 -3
- data/spec/fixtures/rails6_users_app/create_app +3 -3
- data/spec/fixtures/rails6_users_app/lib/tasks/appmap.rake +11 -1
- data/spec/service/config_analyzer_spec.rb +4 -4
- data/spec/service/integration_test_path_finder_spec.rb +24 -0
- data/spec/service/validator/violation_spec.rb +68 -0
- data/test/agent_setup_status_test.rb +8 -5
- data/test/agent_setup_validate_test.rb +75 -0
- data/test/test_helper.rb +3 -0
- data/yarn.lock +23 -9
- metadata +38 -2
@@ -16,9 +16,7 @@ module AppMap
|
|
16
16
|
command: {
|
17
17
|
program: 'bundle',
|
18
18
|
args: %w[exec rspec] + integration_test_paths[:rspec].map { |path| "./#{path}" },
|
19
|
-
environment: {
|
20
|
-
APPMAP: 'true'
|
21
|
-
}
|
19
|
+
environment: { APPMAP: 'true', DISABLE_SPRING: 'true' }
|
22
20
|
}
|
23
21
|
}
|
24
22
|
end
|
@@ -32,7 +30,7 @@ module AppMap
|
|
32
30
|
command: {
|
33
31
|
program: 'bundle',
|
34
32
|
args: %w[exec cucumber],
|
35
|
-
environment: { APPMAP: 'true' }
|
33
|
+
environment: { APPMAP: 'true', DISABLE_SPRING: 'true' }
|
36
34
|
}
|
37
35
|
}
|
38
36
|
end
|
@@ -50,7 +48,7 @@ module AppMap
|
|
50
48
|
command: {
|
51
49
|
program: 'bundle',
|
52
50
|
args: %w[exec rails test] + integration_test_paths[:minitest].map { |path| "./#{path}" },
|
53
|
-
environment: { APPMAP: 'true' }
|
51
|
+
environment: { APPMAP: 'true', DISABLE_SPRING: 'true' }
|
54
52
|
}
|
55
53
|
}
|
56
54
|
]
|
@@ -61,7 +59,7 @@ module AppMap
|
|
61
59
|
command: {
|
62
60
|
program: 'bundle',
|
63
61
|
args: ['exec', 'ruby', "./#{path}"],
|
64
|
-
environment: { APPMAP: 'true' }
|
62
|
+
environment: { APPMAP: 'true', DISABLE_SPRING: 'true' }
|
65
63
|
}
|
66
64
|
}
|
67
65
|
end
|
@@ -69,7 +67,7 @@ module AppMap
|
|
69
67
|
end
|
70
68
|
|
71
69
|
def integration_test_paths
|
72
|
-
@paths ||= Service::IntegrationTestPathFinder.find
|
70
|
+
@paths ||= Service::IntegrationTestPathFinder.new.find
|
73
71
|
end
|
74
72
|
end
|
75
73
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'appmap/service/validator/violation'
|
4
|
+
|
5
|
+
module AppMap
|
6
|
+
module Service
|
7
|
+
module Validator
|
8
|
+
class ConfigValidator
|
9
|
+
attr_reader :violations
|
10
|
+
|
11
|
+
def initialize(config_file)
|
12
|
+
@config_file = config_file
|
13
|
+
@violations = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def config
|
17
|
+
parse_config
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
validate_ruby_version
|
22
|
+
validate_rails_presence
|
23
|
+
validate_config_presence
|
24
|
+
parse_config
|
25
|
+
validate_config_load
|
26
|
+
@violations.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def present?
|
32
|
+
File.exist?(@config_file)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_config
|
36
|
+
return unless present?
|
37
|
+
|
38
|
+
@config_data ||= YAML.load_file(@config_file)
|
39
|
+
rescue Psych::SyntaxError => e
|
40
|
+
@violations << Violation.error(
|
41
|
+
filename: @config_file,
|
42
|
+
message: 'AppMap configuration is not valid YAML',
|
43
|
+
detailed_message: e.message
|
44
|
+
)
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_config_load
|
49
|
+
return unless @config_data
|
50
|
+
|
51
|
+
AppMap::Config.load(@config_data)
|
52
|
+
rescue StandardError => e
|
53
|
+
@violations << Violation.error(
|
54
|
+
filename: @config_file,
|
55
|
+
message: 'AppMap configuration could not be loaded',
|
56
|
+
detailed_message: e.message
|
57
|
+
)
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_config_presence
|
62
|
+
unless present?
|
63
|
+
@violations << Violation.error(
|
64
|
+
filename: @config_file,
|
65
|
+
message: 'AppMap configuration file does not exist'
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate_rails_presence
|
71
|
+
unless Gem.loaded_specs.has_key?('rails')
|
72
|
+
@violations << Violation.error(
|
73
|
+
message: 'AppMap auto-configuration is currently not available for non Rails projects'
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_ruby_version
|
79
|
+
unless RUBY_VERSION =~ AppMap::SUPPORTED_RUBY_VERSIONS_REGEX
|
80
|
+
@violations << Violation.error(
|
81
|
+
message: "AppMap does not support Ruby #{RUBY_VERSION}. " \
|
82
|
+
"Supported versions are: #{AppMap::SUPPORTED_RUBY_VERSIONS.join(', ')}."
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AppMap
|
4
|
+
module Service
|
5
|
+
module Validator
|
6
|
+
class Violation
|
7
|
+
attr_reader :level, :setting, :filename, :message, :detailed_message, :help_urls
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def error(message:, setting: nil, filename: nil, detailed_message: nil, help_urls: nil)
|
11
|
+
self.new(
|
12
|
+
level: :error,
|
13
|
+
message: message,
|
14
|
+
setting: setting,
|
15
|
+
filename: filename,
|
16
|
+
detailed_message: detailed_message,
|
17
|
+
help_urls: help_urls
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def warning(message:, setting: nil, filename: nil, detailed_message: nil, help_urls: nil)
|
22
|
+
self.new(
|
23
|
+
level: :warning,
|
24
|
+
message: message,
|
25
|
+
setting: setting,
|
26
|
+
filename: filename,
|
27
|
+
detailed_message: detailed_message,
|
28
|
+
help_urls: help_urls
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(level:, message:, setting:, filename:, detailed_message:, help_urls:)
|
34
|
+
@level = level
|
35
|
+
@setting = setting
|
36
|
+
@filename = filename
|
37
|
+
@message = message
|
38
|
+
@detailed_message = detailed_message
|
39
|
+
@help_urls = help_urls
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_h
|
43
|
+
instance_variables.each_with_object({}) do |var, hash|
|
44
|
+
hash[var.to_s.delete("@")] = self.instance_variable_get(var)
|
45
|
+
end.compact
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/appmap/version.rb
CHANGED
@@ -3,10 +3,13 @@
|
|
3
3
|
module AppMap
|
4
4
|
URL = 'https://github.com/applandinc/appmap-ruby'
|
5
5
|
|
6
|
-
VERSION = '0.
|
6
|
+
VERSION = '0.62.0'
|
7
7
|
|
8
8
|
APPMAP_FORMAT_VERSION = '1.5.1'
|
9
9
|
|
10
|
+
SUPPORTED_RUBY_VERSIONS_REGEX = /^2\.[567]\./.freeze
|
11
|
+
SUPPORTED_RUBY_VERSIONS = %w[2.5 2.6 2.7].freeze
|
12
|
+
|
10
13
|
DEFAULT_APPMAP_DIR = 'tmp/appmap'.freeze
|
11
14
|
DEFAULT_CONFIG_FILE_PATH = 'appmap.yml'.freeze
|
12
15
|
end
|
data/package.json
CHANGED
@@ -0,0 +1,184 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
require 'appmap/depends/api'
|
3
|
+
|
4
|
+
module AppMap
|
5
|
+
module Depends
|
6
|
+
module APISpec
|
7
|
+
class << self
|
8
|
+
def minitest_environment_method
|
9
|
+
AppMap::Depends.test_env
|
10
|
+
end
|
11
|
+
|
12
|
+
def rspec_environment_method
|
13
|
+
AppMap::Depends.test_env
|
14
|
+
end
|
15
|
+
|
16
|
+
def minitest_test_command(test_files)
|
17
|
+
"time bundle exec ruby -rminitest -Itest #{test_files}"
|
18
|
+
end
|
19
|
+
|
20
|
+
alias minitest_test_command_method minitest_test_command
|
21
|
+
|
22
|
+
def rspec_test_command_method(test_files)
|
23
|
+
"time bundle exec rspec #{test_files}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def rspec_select_tests_method(test_files)
|
27
|
+
AppMap::Depends.select_rspec_tests(test_files)
|
28
|
+
end
|
29
|
+
|
30
|
+
def minitest_select_tests_method(test_files)
|
31
|
+
AppMap::Depends.select_minitest_tests(test_files)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'Depends API' do
|
39
|
+
let(:api) { AppMap::Depends::API.new(ENV['DEBUG'] == 'true') }
|
40
|
+
let(:fixture_dir) { DEPENDS_TEST_DIR }
|
41
|
+
|
42
|
+
describe '.modified' do
|
43
|
+
it 'is empty by default' do
|
44
|
+
test_list = api.modified(appmap_dir: DEPENDS_TEST_DIR, base_dir: DEPENDS_BASE_DIR)
|
45
|
+
expect(test_list).to be_empty
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'detects modification of a dependent file' do
|
49
|
+
FileUtils.touch 'spec/fixtures/depends/app/models/user.rb'
|
50
|
+
test_list = api.modified(appmap_dir: DEPENDS_TEST_DIR, base_dir: DEPENDS_BASE_DIR)
|
51
|
+
expect(test_list.to_a).to eq(%w[spec/fixtures/depends/spec/user_spec.rb])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.inspect_test_files' do
|
56
|
+
it 'reports metadata, added, removed, changed, failed' do
|
57
|
+
test_report = api.inspect_test_files(appmap_dir: DEPENDS_TEST_DIR, test_file_patterns: %w[spec/fixtures/depends/spec/*_spec.rb])
|
58
|
+
expect(test_report.metadata_files).to eq(%w[spec/fixtures/depends/user_page_scenario/metadata.json spec/fixtures/depends/revoke_api_key/metadata.json])
|
59
|
+
expect(test_report.added).to be_empty
|
60
|
+
expect(test_report.removed).to be_empty
|
61
|
+
expect(test_report.changed).to be_empty
|
62
|
+
expect(test_report.failed.to_a).to eq(%w[spec/fixtures/depends/spec/user_spec.rb])
|
63
|
+
end
|
64
|
+
it 'detects an added test' do
|
65
|
+
FileUtils.touch 'spec/tmp/new_spec.rb'
|
66
|
+
test_report = api.inspect_test_files(appmap_dir: DEPENDS_TEST_DIR, test_file_patterns: %w[spec/fixtures/depends/spec/*_spec.rb spec/tmp/*_spec.rb])
|
67
|
+
expect(test_report.added.to_a).to eq(%w[spec/tmp/new_spec.rb])
|
68
|
+
end
|
69
|
+
it 'detects a removed test' do
|
70
|
+
FileUtils.mv 'spec/fixtures/depends/spec/user_spec.rb', 'spec/tmp/'
|
71
|
+
begin
|
72
|
+
test_report = api.inspect_test_files(appmap_dir: DEPENDS_TEST_DIR, test_file_patterns: %w[spec/fixtures/depends/spec/*_spec.rb spec/tmp/*_spec.rb])
|
73
|
+
expect(test_report.removed.to_a).to eq(%w[spec/fixtures/depends/spec/user_spec.rb])
|
74
|
+
ensure
|
75
|
+
FileUtils.mv 'spec/tmp/user_spec.rb', 'spec/fixtures/depends/spec/'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
it 'detects a changed test' do
|
79
|
+
FileUtils.touch 'spec/fixtures/depends/spec/user_spec.rb'
|
80
|
+
test_report = api.inspect_test_files(appmap_dir: DEPENDS_TEST_DIR, test_file_patterns: %w[spec/fixtures/depends/spec/*_spec.rb])
|
81
|
+
expect(test_report.changed.to_a).to eq(%w[spec/fixtures/depends/spec/user_spec.rb])
|
82
|
+
end
|
83
|
+
it 'removes AppMaps whose source file has been removed' do
|
84
|
+
appmap = JSON.parse(File.read('spec/fixtures/depends/revoke_api_key.appmap.json'))
|
85
|
+
appmap['metadata']['source_location'] = 'spec/tmp/new_spec.rb'
|
86
|
+
new_spec_file = 'spec/fixtures/depends/revoke_api_key_2.appmap.json'
|
87
|
+
File.write new_spec_file, JSON.pretty_generate(appmap)
|
88
|
+
|
89
|
+
begin
|
90
|
+
update_appmap_index
|
91
|
+
test_report = api.inspect_test_files(appmap_dir: DEPENDS_TEST_DIR, test_file_patterns: %w[spec/fixtures/depends/spec/*_spec.rb])
|
92
|
+
expect(test_report.removed.to_a).to eq(%w[spec/tmp/new_spec.rb])
|
93
|
+
|
94
|
+
test_report.clean_appmaps
|
95
|
+
|
96
|
+
expect(File.exists?(new_spec_file)).to be_falsey
|
97
|
+
ensure
|
98
|
+
FileUtils.rm_f new_spec_file if File.exists?(new_spec_file)
|
99
|
+
FileUtils.rm_rf new_spec_file.split('.')[0]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '.run_tests' do
|
105
|
+
def run_tests
|
106
|
+
Dir.chdir 'spec/fixtures/depends' do
|
107
|
+
api.run_tests([ 'spec/actual_rspec_test.rb', 'test/actual_minitest_test.rb' ], appmap_dir: Pathname.new(DEPENDS_TEST_DIR).expand_path.to_s)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'smoke test' do
|
112
|
+
around do |test|
|
113
|
+
@minitest_test_command_method = AppMap.configuration.depends_config.minitest_test_command_method
|
114
|
+
AppMap.configuration.depends_config.minitest_test_command_method = 'AppMap::Depends::APISpec.minitest_test_command'
|
115
|
+
|
116
|
+
test.call
|
117
|
+
ensure
|
118
|
+
AppMap.configuration.depends_config.minitest_test_command_method = @minitest_test_command
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'passes a smoke test' do
|
122
|
+
run_tests
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'configuration settings' do
|
127
|
+
it 'can all be modified' do
|
128
|
+
defaults = {}
|
129
|
+
|
130
|
+
%i[rspec minitest].each do |framework|
|
131
|
+
%i[environment_method select_tests_method test_command_method].each do |setting|
|
132
|
+
full_setting = [ framework, setting ].join('_').to_sym
|
133
|
+
defaults[full_setting] = AppMap.configuration.depends_config.send(full_setting)
|
134
|
+
AppMap.configuration.depends_config.send("#{full_setting}=", "AppMap::Depends::APISpec.#{full_setting}")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
run_tests
|
139
|
+
ensure
|
140
|
+
defaults.keys.each do |setting|
|
141
|
+
AppMap.configuration.depends_config.send("#{setting}=", defaults[setting])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '.remove_out_of_date_appmaps' do
|
148
|
+
it 'is a nop in normal circumstances' do
|
149
|
+
since = Time.now
|
150
|
+
removed = api.remove_out_of_date_appmaps(since, appmap_dir: DEPENDS_TEST_DIR, base_dir: DEPENDS_BASE_DIR)
|
151
|
+
expect(removed).to be_empty
|
152
|
+
end
|
153
|
+
|
154
|
+
it "removes an out-of-date AppMap that hasn't been brought up to date" do
|
155
|
+
# This AppMap will be modified before the 'since' time
|
156
|
+
appmap_path = "spec/fixtures/depends/user_page_scenario.appmap.json"
|
157
|
+
appmap = File.read(appmap_path)
|
158
|
+
|
159
|
+
sleep 0.01
|
160
|
+
since = Time.now
|
161
|
+
sleep 0.01
|
162
|
+
|
163
|
+
# Touch the rest of the AppMaps so that they are modified after +since+
|
164
|
+
Dir.glob('spec/fixtures/depends/*.appmap.json').each do |path|
|
165
|
+
next if path == appmap_path
|
166
|
+
FileUtils.touch path
|
167
|
+
end
|
168
|
+
|
169
|
+
sleep 0.01
|
170
|
+
# Make the AppMaps out of date
|
171
|
+
FileUtils.touch 'spec/fixtures/depends/app/models/user.rb'
|
172
|
+
sleep 0.01
|
173
|
+
|
174
|
+
begin
|
175
|
+
# At this point, we would run tests to bring the AppMaps up to date
|
176
|
+
# Then once the tests have finished, remove any AppMaps that weren't refreshed
|
177
|
+
removed = api.remove_out_of_date_appmaps(since, appmap_dir: DEPENDS_TEST_DIR, base_dir: DEPENDS_BASE_DIR)
|
178
|
+
expect(removed).to eq([ appmap_path.split('.')[0] ])
|
179
|
+
ensure
|
180
|
+
File.write(appmap_path, appmap)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
DEPENDS_TEST_DIR = 'spec/fixtures/depends'
|
4
|
+
DEPENDS_BASE_DIR = DEPENDS_TEST_DIR
|
5
|
+
|
6
|
+
def update_appmap_index
|
7
|
+
cmd = [
|
8
|
+
'./exe/appmap-index',
|
9
|
+
'--appmap-dir',
|
10
|
+
DEPENDS_TEST_DIR
|
11
|
+
]
|
12
|
+
if ENV['DEBUG'] == 'true'
|
13
|
+
cmd << '--verbose'
|
14
|
+
end
|
15
|
+
|
16
|
+
system cmd.join(' ') or raise "Failed to update AppMap index in #{DEPENDS_TEST_DIR}"
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |rspec|
|
20
|
+
rspec.before do
|
21
|
+
Dir.glob("#{DEPENDS_TEST_DIR}/*.appmap.json").each { |fname| FileUtils.touch fname }
|
22
|
+
update_appmap_index
|
23
|
+
|
24
|
+
FileUtils.rm_rf 'spec/tmp'
|
25
|
+
FileUtils.mkdir_p 'spec/tmp'
|
26
|
+
end
|
27
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
name:
|
2
|
-
packages:
|
1
|
+
name: name
|
2
|
+
packages: [1,2,3]
|