appmap 0.52.0 → 0.54.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -1
  3. data/CHANGELOG.md +41 -0
  4. data/Rakefile +13 -4
  5. data/appmap.gemspec +1 -1
  6. data/exe/appmap-agent-init +19 -0
  7. data/lib/appmap.rb +31 -112
  8. data/lib/appmap/agent.rb +115 -0
  9. data/lib/appmap/class_map.rb +2 -2
  10. data/lib/appmap/config.rb +11 -3
  11. data/lib/appmap/handler/net_http.rb +3 -2
  12. data/lib/appmap/handler/rails/request_handler.rb +2 -1
  13. data/lib/appmap/handler/rails/template.rb +2 -1
  14. data/lib/appmap/hook.rb +0 -1
  15. data/lib/appmap/hook/method.rb +36 -28
  16. data/lib/appmap/metadata.rb +4 -2
  17. data/lib/appmap/minitest.rb +2 -0
  18. data/lib/appmap/railtie.rb +2 -2
  19. data/lib/appmap/rspec.rb +5 -3
  20. data/lib/appmap/service/guesser.rb +2 -9
  21. data/lib/appmap/swagger.rb +2 -0
  22. data/lib/appmap/swagger/configuration.rb +70 -0
  23. data/lib/appmap/swagger/markdown_descriptions.rb +43 -0
  24. data/lib/appmap/swagger/rake_tasks.rb +43 -0
  25. data/lib/appmap/swagger/stable.rb +37 -0
  26. data/lib/appmap/trace.rb +2 -0
  27. data/lib/appmap/util.rb +17 -1
  28. data/lib/appmap/version.rb +1 -1
  29. data/package.json +0 -1
  30. data/spec/config_spec.rb +0 -1
  31. data/spec/fixtures/hook/.gitignore +2 -0
  32. data/spec/fixtures/hook/app/controllers/api/api_keys_controller.rb +1 -0
  33. data/spec/fixtures/hook/app/controllers/organizations_controller.rb +1 -0
  34. data/spec/fixtures/hook/app/models/api_key.rb +1 -0
  35. data/spec/fixtures/hook/app/models/configuration.rb +1 -0
  36. data/spec/fixtures/hook/app/models/show.rb +1 -0
  37. data/spec/fixtures/hook/app/models/user.rb +1 -0
  38. data/spec/fixtures/hook/kwargs.rb +11 -0
  39. data/spec/fixtures/hook/revoke_api_key.appmap.json +847 -0
  40. data/spec/fixtures/hook/spec/api_spec.rb +1 -0
  41. data/spec/fixtures/hook/spec/user_spec.rb +1 -0
  42. data/spec/fixtures/hook/user_page_scenario.appmap.json +1722 -0
  43. data/spec/fixtures/rails5_users_app/config/environments/test.rb +3 -0
  44. data/spec/fixtures/rails6_users_app/Dockerfile +0 -1
  45. data/spec/fixtures/rails6_users_app/appmap.yml +3 -1
  46. data/spec/fixtures/rails6_users_app/config/environments/test.rb +3 -0
  47. data/spec/fixtures/rails6_users_app/lib/tasks/appmap.rake +13 -0
  48. data/spec/hook_spec.rb +9 -0
  49. data/spec/rails_recording_spec.rb +1 -1
  50. data/spec/record_net_http_spec.rb +1 -0
  51. data/spec/swagger/swagger_spec.rb +47 -0
  52. data/test/{agent_setup_cli_test.rb → agent_setup_init_test.rb} +4 -4
  53. data/test/gem_test.rb +1 -0
  54. metadata +39 -19
  55. data/exe/appmap-agent-setup +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91abfbaf6b18062625413f1a4ba9a465325af82734a04ab875bb8b4092f3bc34
4
- data.tar.gz: 9fb260bc1fb09cc1a6bc6771114b8306f596d1595bcaf1234dd346abe871d3b7
3
+ metadata.gz: b5368ab640de6fdf14f35502a5c756b7c6f681ee8d9a87c5fd9cd13d2b1036d9
4
+ data.tar.gz: 15806ff9cfa6256bb29c9ed2d8cb7d4ff5f62cfc3354e313e3b6f52b4cd96c12
5
5
  SHA512:
6
- metadata.gz: 4eb0fe09e7657fbb3541c17b047e2c0c24cb171201828b684353fd2de94fcca216f84b2776ce4a1f57fe1e721aaeb66c55fbea5fc627d9529f4bf687805a1079
7
- data.tar.gz: 938da5ae0d846bc3e2c7f571ef836fe35f4d0fefebe5af9f5b5846b949c87c1cc1812881a973168c014cc789a0b6bb1ee9eb556d11406e846f99fdecd0eeb04a
6
+ metadata.gz: d078fcb6e1bf1942462be38f2547b73e34c6f9a0313aabdd8919070218701937bd53bec4207c34c48c37e7b67f69500fbd6339f6fc26ad11eed86e2027ca4acf
7
+ data.tar.gz: f5493735794a3385287721a30021996bc66ac44e19bc4e2214823eb78a730f07213989c93dadf8f38f0163c6c21fc39d375511b4ccd87b33974a54e667898b22
data/.travis.yml CHANGED
@@ -1,5 +1,10 @@
1
1
  language: ruby
2
2
 
3
+ rbenv:
4
+ - 2.5
5
+ - 2.6
6
+ - 2.7
7
+
3
8
  addons:
4
9
  apt:
5
10
  packages:
@@ -38,7 +43,6 @@ jobs:
38
43
  - mkdir tmp
39
44
  - GEM_ALTERNATIVE_NAME='' bundle exec rake test
40
45
 
41
-
42
46
  before_deploy:
43
47
  - |
44
48
  nvm install --lts \
data/CHANGELOG.md CHANGED
@@ -1,3 +1,44 @@
1
+ ## [0.54.2](https://github.com/applandinc/appmap-ruby/compare/v0.54.1...v0.54.2) (2021-06-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Require appmap/railtie if Rails is defined ([66b4cbd](https://github.com/applandinc/appmap-ruby/commit/66b4cbd4d418695b0e69150d253dfd5a6f9096cf))
7
+
8
+ ## [0.54.1](https://github.com/applandinc/appmap-ruby/compare/v0.54.0...v0.54.1) (2021-06-25)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Add missing imports and remove deprecation warnings ([f1cb087](https://github.com/applandinc/appmap-ruby/commit/f1cb087f80cad88093227ebf8b4a4cd574853667))
14
+ * Workaround Ruby bug in 2.7.3 with kwrest ([26e34ca](https://github.com/applandinc/appmap-ruby/commit/26e34ca421fdae6602b27fee5653c8fe26b3793b))
15
+
16
+ # [0.54.0](https://github.com/applandinc/appmap-ruby/compare/v0.53.0...v0.54.0) (2021-06-24)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * Handle new behavior in RSpec ExampleGroup ([176d0df](https://github.com/applandinc/appmap-ruby/commit/176d0dfca0b2e4cc5a8908fa67c01dd0c79ef175))
22
+
23
+
24
+ ### Features
25
+
26
+ * Add swagger rake task ([0aaae49](https://github.com/applandinc/appmap-ruby/commit/0aaae4973f0df530c75ed92b93f8a1940a948091))
27
+
28
+ # [0.53.0](https://github.com/applandinc/appmap-ruby/compare/v0.52.1...v0.53.0) (2021-06-23)
29
+
30
+
31
+ ### Features
32
+
33
+ * appmap-agent-setup as a separate command not using GLI library ([f0eedb7](https://github.com/applandinc/appmap-ruby/commit/f0eedb7451368ea0399872f3be680e1581ac6200))
34
+
35
+ ## [0.52.1](https://github.com/applandinc/appmap-ruby/compare/v0.52.0...v0.52.1) (2021-06-23)
36
+
37
+
38
+ ### Bug Fixes
39
+
40
+ * Better project name guesser ([d22f379](https://github.com/applandinc/appmap-ruby/commit/d22f379623bd3022ba34d7241838fe6abbbb61d6))
41
+
1
42
  # [0.52.0](https://github.com/applandinc/appmap-ruby/compare/v0.51.3...v0.52.0) (2021-06-22)
2
43
 
3
44
 
data/Rakefile CHANGED
@@ -6,8 +6,7 @@ require 'rake/testtask'
6
6
  require 'rdoc/task'
7
7
 
8
8
  require 'open3'
9
-
10
- require "rake/extensiontask"
9
+ require 'rake/extensiontask'
11
10
 
12
11
  desc 'build the native extension'
13
12
  Rake::ExtensionTask.new("appmap") do |ext|
@@ -26,7 +25,7 @@ namespace 'gem' do
26
25
  # ~/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/gem_helper.rb:39:in `install'
27
26
  def build_gem
28
27
  # Ensure that NPM packages are installed before building.
29
- sh('yarn install --prod'.shellsplit)
28
+ sh('yarn install --prod')
30
29
 
31
30
  default_build_gem
32
31
  end
@@ -34,7 +33,17 @@ namespace 'gem' do
34
33
  end
35
34
  end
36
35
 
37
- RUBY_VERSIONS=%w[2.5 2.6 2.7]
36
+ RUBY_VERSIONS=%w[2.5 2.6 2.7].select do |version|
37
+ travis_ruby_version = ENV['TRAVIS_RUBY_VERSION']
38
+ next true unless travis_ruby_version
39
+
40
+ if travis_ruby_version.index(version) == 0
41
+ warn "Testing Ruby version #{version}, since it matches TRAVIS_RUBY_VERSION=#{travis_ruby_version}"
42
+ next true
43
+ end
44
+
45
+ false
46
+ end
38
47
  FIXTURE_APPS=%w[rack_users_app rails6_users_app rails5_users_app]
39
48
 
40
49
  def run_cmd(*cmd)
data/appmap.gemspec CHANGED
@@ -33,7 +33,6 @@ Gem::Specification.new do |spec|
33
33
  spec.require_paths = ['lib']
34
34
 
35
35
  spec.add_dependency 'activesupport'
36
- spec.add_dependency 'gli'
37
36
  spec.add_dependency 'method_source'
38
37
  spec.add_dependency 'rack'
39
38
  spec.add_dependency 'reverse_markdown'
@@ -55,4 +54,5 @@ Gem::Specification.new do |spec|
55
54
  spec.add_development_dependency 'webdrivers', '~> 4.0'
56
55
  spec.add_development_dependency 'timecop'
57
56
  spec.add_development_dependency 'hashie'
57
+ spec.add_development_dependency 'webrick'
58
58
  end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+ require 'appmap'
6
+ require 'appmap/command/agent_setup/init'
7
+
8
+ @options = {:config_file => AppMap::DEFAULT_CONFIG_FILE_PATH}
9
+
10
+ OptionParser.new do |parser|
11
+ parser.banner = 'Usage: bundle exec exe/appmap-agent-init [options]'
12
+
13
+ description = "AppMap configuration file path (default: #{AppMap::DEFAULT_CONFIG_FILE_PATH})"
14
+ parser.on('-c', '--config=FILEPATH', description) do |filepath|
15
+ @options[:config_file] = filepath
16
+ end
17
+ end.parse!
18
+
19
+ AppMap::Command::AgentSetup::Init.new(@options[:config_file]).perform
data/lib/appmap.rb CHANGED
@@ -1,124 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- require 'active_support'
5
- require 'active_support/core_ext'
6
- rescue NameError
7
- warn 'active_support is not available. AppMap execution will continue optimistically without it...'
8
- end
3
+ # This is the file that's loaded when you require 'appmap'.
4
+ # If you require this file, we assume that you want to automatically activate all
5
+ # the AppMap functionality that seems suitable for your project.
6
+ # For example, if your project is a Rails project, the Railtie will be loaded.
7
+ # If your bundle includes rspec, the appmap/rspec will be loaded.
8
+ #
9
+ # If you don't want this "all-in" behavior, then you can use the 'require' option
10
+ # in your Gemfile to selectively activate just the AppMap features that you want. Then
11
+ # you can manually configure/require other features, elsewhere in your code.
12
+ # Note that you should always require 'appmap/agent' as early as possible, so that it can
13
+ # observe and hook as much code loading as possible.
14
+ #
15
+ # Modules that you can load independently include:
16
+ # - appmap/agent
17
+ # - appmap/railtie
18
+ # - appmap/rspec
19
+ # - appmap/minitest
20
+ # - appmap/swagger (Rake task)
9
21
 
10
22
  require 'appmap/version'
11
- require 'appmap/util'
12
- require 'appmap/hook'
13
- require 'appmap/config'
14
- require 'appmap/trace'
15
- require 'appmap/class_map'
16
- require 'appmap/metadata'
17
- require 'appmap/open'
18
-
19
- # load extension
20
- require 'appmap/appmap'
21
-
22
- module AppMap
23
- class << self
24
- @configuration = nil
25
- @configuration_file_path = nil
26
-
27
- # Gets the configuration. If there is no configuration, the default
28
- # configuration is initialized.
29
- def configuration
30
- @configuration ||= initialize_configuration
31
- end
32
-
33
- # Sets the configuration. This is only expected to happen once per
34
- # Ruby process.
35
- def configuration=(config)
36
- warn 'AppMap is already configured' if @configuration && config
37
-
38
- @configuration = config
39
- end
40
-
41
- def default_config_file_path
42
- ENV['APPMAP_CONFIG_FILE'] || 'appmap.yml'
43
- end
44
-
45
- # Configures AppMap for recording. Default behavior is to configure from
46
- # APPMAP_CONFIG_FILE, or 'appmap.yml'. If no config file is available, a
47
- # configuration will be automatically generated and used - and the user is prompted
48
- # to create the config file.
49
- #
50
- # This method also activates the code hooks which record function calls as trace events.
51
- # Call this function before the program code is loaded by the Ruby VM, otherwise
52
- # the load events won't be seen and the hooks won't activate.
53
- def initialize_configuration(config_file_path = default_config_file_path)
54
- Util.startup_message "Configuring AppMap from path #{config_file_path}"
55
- Config.load_from_file(config_file_path).tap do |configuration|
56
- self.configuration = configuration
57
- Hook.new(configuration).enable
58
- end
59
- end
60
-
61
- def info(msg)
62
- if defined?(::Rails) && defined?(::Rails.logger)
63
- ::Rails.logger.info msg
64
- else
65
- warn msg
66
- end
67
- end
68
-
69
- # Used to start tracing, stop tracing, and record events.
70
- def tracing
71
- @tracing ||= Trace::Tracing.new
72
- end
73
-
74
- # Records the events which occur while processing a block,
75
- # and returns an AppMap as a Hash.
76
- def record
77
- tracer = tracing.trace
78
- begin
79
- yield
80
- ensure
81
- tracing.delete(tracer)
82
- end
83
-
84
- events = [].tap do |event_list|
85
- event_list << tracer.next_event.to_h while tracer.event?
86
- end
87
- {
88
- 'version' => AppMap::APPMAP_FORMAT_VERSION,
89
- 'metadata' => detect_metadata,
90
- 'classMap' => class_map(tracer.event_methods),
91
- 'events' => events
92
- }
93
- end
94
-
95
- # Uploads an AppMap to the AppLand website and displays it.
96
- def open(appmap = nil, &block)
97
- appmap ||= AppMap.record(&block)
98
- AppMap::Open.new(appmap).perform
99
- end
100
-
101
- # Builds a class map from a config and a list of Ruby methods.
102
- def class_map(methods)
103
- ClassMap.build_from_methods(methods)
104
- end
105
-
106
- # Returns default metadata detected from the Ruby system and from the
107
- # filesystem.
108
- def detect_metadata
109
- @metadata ||= Metadata.detect.freeze
110
- @metadata.deep_dup
111
- end
112
- end
113
- end
23
+ require 'appmap/agent'
114
24
 
115
25
  lambda do
116
26
  Initializer = Struct.new(:class_name, :module_name, :gem_module_name)
117
27
 
118
28
  INITIALIZERS = {
119
- 'Rails::Railtie' => Initializer.new('AppMap::Railtie', 'appmap/railtie', 'railtie'),
29
+ # In a Rails app, Rails is always defined by the time the other gems are loaded. Therefore, we
30
+ # don't try and trap the loading of Rails itself here.
120
31
  'RSpec' => Initializer.new('AppMap::RSpec', 'appmap/rspec', 'rspec-core'),
121
- 'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest')
32
+ 'Minitest::Unit::TestCase' => Initializer.new('AppMap::Minitest', 'appmap/minitest', 'minitest'),
33
+ 'Rake' => [
34
+ Initializer.new('AppMap::Swagger', 'appmap/swagger', 'rake')
35
+ ]
122
36
  }
123
37
 
124
38
  TracePoint.new(:class) do |tp|
@@ -144,7 +58,7 @@ lambda do
144
58
  end
145
59
  end.enable
146
60
 
147
- if defined?(::Rails::Railtie)
61
+ if defined?(::Rails)
148
62
  require 'appmap/railtie'
149
63
  end
150
64
 
@@ -155,6 +69,11 @@ lambda do
155
69
  if defined?(::Minitest)
156
70
  require 'appmap/minitest'
157
71
  end
72
+
73
+ if defined?(::Rake)
74
+ require 'appmap/swagger'
75
+ end
76
+
158
77
  end.call
159
78
 
160
79
  AppMap.initialize_configuration if ENV['APPMAP'] == 'true'
@@ -0,0 +1,115 @@
1
+ require_relative 'version'
2
+ require_relative 'hook'
3
+ require_relative 'config'
4
+ require_relative 'trace'
5
+ require_relative 'class_map'
6
+ require_relative 'metadata'
7
+ require_relative 'util'
8
+ require_relative 'open'
9
+
10
+ # load extension
11
+ require_relative 'appmap'
12
+
13
+ module AppMap
14
+ class << self
15
+ @configuration = nil
16
+ @configuration_file_path = nil
17
+
18
+ # Gets the configuration. If there is no configuration, the default
19
+ # configuration is initialized.
20
+ def configuration
21
+ @configuration ||= initialize_configuration
22
+ end
23
+
24
+ # Sets the configuration. This is only expected to happen once per
25
+ # Ruby process.
26
+ def configuration=(config)
27
+ warn 'AppMap is already configured' if @configuration && config
28
+
29
+ @configuration = config
30
+ end
31
+
32
+ def default_config_file_path
33
+ ENV['APPMAP_CONFIG_FILE'] || 'appmap.yml'
34
+ end
35
+
36
+ # Configures AppMap for recording. Default behavior is to configure from
37
+ # APPMAP_CONFIG_FILE, or 'appmap.yml'. If no config file is available, a
38
+ # configuration will be automatically generated and used - and the user is prompted
39
+ # to create the config file.
40
+ #
41
+ # This method also activates the code hooks which record function calls as trace events.
42
+ # Call this function before the program code is loaded by the Ruby VM, otherwise
43
+ # the load events won't be seen and the hooks won't activate.
44
+ def initialize_configuration(config_file_path = default_config_file_path)
45
+ Util.startup_message "Configuring AppMap from path #{config_file_path}"
46
+ Config.load_from_file(config_file_path).tap do |configuration|
47
+ self.configuration = configuration
48
+ Hook.new(configuration).enable
49
+ end
50
+ end
51
+
52
+ def info(msg)
53
+ if defined?(::Rails) && defined?(::Rails.logger)
54
+ ::Rails.logger.info msg
55
+ else
56
+ warn msg
57
+ end
58
+ end
59
+
60
+ def config_message(msg)
61
+ logger = if defined?(::Rails) && ::Rails.logger
62
+ ::Rails.logger
63
+ elsif ENV['DEBUG'] == 'true'
64
+ method(:warn)
65
+ else
66
+ ->(msg) { }
67
+ end
68
+ logger.call(msg)
69
+ end
70
+
71
+ # Used to start tracing, stop tracing, and record events.
72
+ def tracing
73
+ @tracing ||= Trace::Tracing.new
74
+ end
75
+
76
+ # Records the events which occur while processing a block,
77
+ # and returns an AppMap as a Hash.
78
+ def record
79
+ tracer = tracing.trace
80
+ begin
81
+ yield
82
+ ensure
83
+ tracing.delete(tracer)
84
+ end
85
+
86
+ events = [].tap do |event_list|
87
+ event_list << tracer.next_event.to_h while tracer.event?
88
+ end
89
+ {
90
+ 'version' => AppMap::APPMAP_FORMAT_VERSION,
91
+ 'metadata' => detect_metadata,
92
+ 'classMap' => class_map(tracer.event_methods),
93
+ 'events' => events
94
+ }
95
+ end
96
+
97
+ # Uploads an AppMap to the AppLand website and displays it.
98
+ def open(appmap = nil, &block)
99
+ appmap ||= AppMap.record(&block)
100
+ AppMap::Open.new(appmap).perform
101
+ end
102
+
103
+ # Builds a class map from a config and a list of Ruby methods.
104
+ def class_map(methods)
105
+ ClassMap.build_from_methods(methods)
106
+ end
107
+
108
+ # Returns default metadata detected from the Ruby system and from the
109
+ # filesystem.
110
+ def detect_metadata
111
+ @metadata ||= Metadata.detect.freeze
112
+ Util.deep_dup(@metadata)
113
+ end
114
+ end
115
+ end
@@ -111,7 +111,7 @@ module AppMap
111
111
  end
112
112
 
113
113
  comment = method.comment
114
- function_info[:comment] = comment unless comment.blank?
114
+ function_info[:comment] = comment unless Util.blank?(comment)
115
115
 
116
116
  function_info[:labels] = parse_labels(comment) + (method.labels || [])
117
117
  object_infos << function_info
@@ -119,7 +119,7 @@ module AppMap
119
119
  parent = root
120
120
  object_infos.each do |info|
121
121
  parent = find_or_create parent.children, info do
122
- Types.const_get(info[:type].classify).new(info[:name].to_s).tap do |type|
122
+ Types.const_get(Util.classify(info[:type])).new(info[:name].to_s).tap do |type|
123
123
  info.keys.tap do |keys|
124
124
  keys.delete(:name)
125
125
  keys.delete(:type)