newrelic_rpm 6.9.0.363 → 6.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (314) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  5. data/.github/actions/annotate/README.md +79 -0
  6. data/.github/actions/annotate/action.yml +6 -0
  7. data/.github/actions/annotate/dist/index.js +433 -0
  8. data/.github/actions/annotate/index.js +25 -0
  9. data/.github/actions/annotate/package-lock.json +172 -0
  10. data/.github/actions/annotate/package.json +30 -0
  11. data/.github/actions/annotate/pre-commit +5 -0
  12. data/.github/actions/build-ruby/README.md +79 -0
  13. data/.github/actions/build-ruby/action.yml +15 -0
  14. data/.github/actions/build-ruby/dist/index.js +52683 -0
  15. data/.github/actions/build-ruby/index.js +514 -0
  16. data/.github/actions/build-ruby/package-lock.json +581 -0
  17. data/.github/actions/build-ruby/package.json +32 -0
  18. data/.github/actions/build-ruby/pre-commit +5 -0
  19. data/.github/pull_request_template.md +16 -0
  20. data/.github/workflows/ci.yml +212 -0
  21. data/.github/workflows/pr_review_checklist.yml +22 -0
  22. data/.github/workflows/release.yml +78 -0
  23. data/.github/workflows/scripts/rubygems-authenticate.py +13 -0
  24. data/.github/workflows/scripts/rubygems-publish.rb +32 -0
  25. data/.github/workflows/snyk.yml +27 -0
  26. data/.github/workflows/stale.yml +21 -0
  27. data/.gitignore +6 -0
  28. data/CHANGELOG.md +254 -10
  29. data/CONTRIBUTING.md +106 -19
  30. data/Gemfile +6 -2
  31. data/LICENSE +208 -38
  32. data/README.md +81 -85
  33. data/ROADMAP.md +24 -0
  34. data/Rakefile +2 -0
  35. data/THIRD_PARTY_NOTICES.md +213 -0
  36. data/bin/nrdebug +1 -1
  37. data/init.rb +1 -1
  38. data/install.rb +1 -1
  39. data/lib/new_relic/agent.rb +14 -6
  40. data/lib/new_relic/agent/adaptive_sampler.rb +1 -1
  41. data/lib/new_relic/agent/agent.rb +15 -6
  42. data/lib/new_relic/agent/agent_logger.rb +1 -1
  43. data/lib/new_relic/agent/attribute_filter.rb +1 -1
  44. data/lib/new_relic/agent/attribute_processing.rb +1 -1
  45. data/lib/new_relic/agent/attributes.rb +3 -1
  46. data/lib/new_relic/agent/audit_logger.rb +1 -1
  47. data/lib/new_relic/agent/autostart.rb +1 -1
  48. data/lib/new_relic/agent/chained_call.rb +1 -1
  49. data/lib/new_relic/agent/commands/agent_command.rb +1 -1
  50. data/lib/new_relic/agent/commands/agent_command_router.rb +1 -1
  51. data/lib/new_relic/agent/commands/thread_profiler_session.rb +1 -1
  52. data/lib/new_relic/agent/configuration.rb +1 -1
  53. data/lib/new_relic/agent/configuration/default_source.rb +28 -1
  54. data/lib/new_relic/agent/configuration/dotted_hash.rb +1 -1
  55. data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
  56. data/lib/new_relic/agent/configuration/event_harvest_config.rb +1 -1
  57. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -1
  58. data/lib/new_relic/agent/configuration/manager.rb +1 -1
  59. data/lib/new_relic/agent/configuration/manual_source.rb +1 -1
  60. data/lib/new_relic/agent/configuration/mask_defaults.rb +1 -1
  61. data/lib/new_relic/agent/configuration/security_policy_source.rb +1 -1
  62. data/lib/new_relic/agent/configuration/server_source.rb +1 -1
  63. data/lib/new_relic/agent/configuration/yaml_source.rb +1 -1
  64. data/lib/new_relic/agent/connect/request_builder.rb +1 -1
  65. data/lib/new_relic/agent/connect/response_handler.rb +1 -1
  66. data/lib/new_relic/agent/custom_event_aggregator.rb +1 -1
  67. data/lib/new_relic/agent/database.rb +1 -1
  68. data/lib/new_relic/agent/database/explain_plan_helpers.rb +1 -1
  69. data/lib/new_relic/agent/database/obfuscation_helpers.rb +2 -2
  70. data/lib/new_relic/agent/database/obfuscator.rb +1 -1
  71. data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +1 -1
  72. data/lib/new_relic/agent/datastores.rb +1 -1
  73. data/lib/new_relic/agent/datastores/metric_helper.rb +1 -1
  74. data/lib/new_relic/agent/datastores/mongo.rb +2 -2
  75. data/lib/new_relic/agent/datastores/mongo/event_formatter.rb +1 -1
  76. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +1 -1
  77. data/lib/new_relic/agent/datastores/mongo/obfuscator.rb +1 -1
  78. data/lib/new_relic/agent/datastores/mongo/statement_formatter.rb +1 -1
  79. data/lib/new_relic/agent/datastores/redis.rb +1 -1
  80. data/lib/new_relic/agent/deprecator.rb +1 -1
  81. data/lib/new_relic/agent/distributed_tracing.rb +1 -1
  82. data/lib/new_relic/agent/distributed_tracing/cross_app_payload.rb +3 -2
  83. data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
  84. data/lib/new_relic/agent/distributed_tracing/{distributed_trace_intrinsics.rb → distributed_trace_attributes.rb} +9 -5
  85. data/lib/new_relic/agent/distributed_tracing/distributed_trace_metrics.rb +1 -1
  86. data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +3 -4
  87. data/lib/new_relic/agent/distributed_tracing/distributed_trace_transport_type.rb +1 -1
  88. data/lib/new_relic/agent/distributed_tracing/trace_context.rb +1 -1
  89. data/lib/new_relic/agent/distributed_tracing/trace_context_payload.rb +2 -2
  90. data/lib/new_relic/agent/encoding_normalizer.rb +1 -1
  91. data/lib/new_relic/agent/error_collector.rb +31 -12
  92. data/lib/new_relic/agent/error_event_aggregator.rb +5 -5
  93. data/lib/new_relic/agent/error_trace_aggregator.rb +1 -1
  94. data/lib/new_relic/agent/event_aggregator.rb +1 -1
  95. data/lib/new_relic/agent/event_buffer.rb +1 -1
  96. data/lib/new_relic/agent/event_listener.rb +1 -1
  97. data/lib/new_relic/agent/event_loop.rb +1 -1
  98. data/lib/new_relic/agent/external.rb +1 -1
  99. data/lib/new_relic/agent/guid_generator.rb +1 -1
  100. data/lib/new_relic/agent/harvester.rb +1 -1
  101. data/lib/new_relic/agent/heap.rb +1 -1
  102. data/lib/new_relic/agent/hostname.rb +8 -2
  103. data/lib/new_relic/agent/http_clients/abstract.rb +82 -0
  104. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +25 -20
  105. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +29 -14
  106. data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +18 -22
  107. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +11 -12
  108. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +17 -5
  109. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +5 -7
  110. data/lib/new_relic/agent/http_clients/uri_util.rb +12 -11
  111. data/lib/new_relic/agent/instrumentation.rb +1 -1
  112. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +5 -6
  113. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +5 -1
  114. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +12 -3
  115. data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
  116. data/lib/new_relic/agent/instrumentation/active_merchant.rb +1 -1
  117. data/lib/new_relic/agent/instrumentation/active_record.rb +85 -38
  118. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +82 -24
  119. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +1 -1
  120. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +92 -34
  121. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +8 -3
  122. data/lib/new_relic/agent/instrumentation/active_storage.rb +1 -1
  123. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +9 -5
  124. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +24 -8
  125. data/lib/new_relic/agent/instrumentation/authlogic.rb +1 -1
  126. data/lib/new_relic/agent/instrumentation/bunny.rb +114 -51
  127. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -1
  128. data/lib/new_relic/agent/instrumentation/curb.rb +92 -27
  129. data/lib/new_relic/agent/instrumentation/data_mapper.rb +4 -2
  130. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +61 -25
  131. data/lib/new_relic/agent/instrumentation/excon.rb +1 -1
  132. data/lib/new_relic/agent/instrumentation/excon/connection.rb +7 -4
  133. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +3 -2
  134. data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
  135. data/lib/new_relic/agent/instrumentation/http.rb +6 -3
  136. data/lib/new_relic/agent/instrumentation/httpclient.rb +5 -3
  137. data/lib/new_relic/agent/instrumentation/ignore_actions.rb +1 -1
  138. data/lib/new_relic/agent/instrumentation/memcache.rb +4 -2
  139. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +7 -3
  140. data/lib/new_relic/agent/instrumentation/merb/controller.rb +1 -1
  141. data/lib/new_relic/agent/instrumentation/merb/errors.rb +1 -1
  142. data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +12 -4
  143. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +9 -7
  144. data/lib/new_relic/agent/instrumentation/mongo.rb +10 -4
  145. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +36 -3
  146. data/lib/new_relic/agent/instrumentation/net.rb +59 -22
  147. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +26 -2
  148. data/lib/new_relic/agent/instrumentation/padrino.rb +40 -16
  149. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
  150. data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
  151. data/lib/new_relic/agent/instrumentation/rack.rb +36 -13
  152. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +1 -1
  153. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +1 -1
  154. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
  155. data/lib/new_relic/agent/instrumentation/rails_middleware.rb +1 -1
  156. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +1 -1
  157. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +1 -1
  158. data/lib/new_relic/agent/instrumentation/rails_notifications/action_view.rb +1 -1
  159. data/lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb +1 -1
  160. data/lib/new_relic/agent/instrumentation/rake.rb +55 -20
  161. data/lib/new_relic/agent/instrumentation/redis.rb +141 -56
  162. data/lib/new_relic/agent/instrumentation/resque.rb +1 -1
  163. data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
  164. data/lib/new_relic/agent/instrumentation/sequel_helper.rb +1 -1
  165. data/lib/new_relic/agent/instrumentation/sidekiq.rb +48 -24
  166. data/lib/new_relic/agent/instrumentation/sinatra.rb +62 -23
  167. data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +1 -1
  168. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -1
  169. data/lib/new_relic/agent/instrumentation/sunspot.rb +1 -1
  170. data/lib/new_relic/agent/instrumentation/typhoeus.rb +23 -6
  171. data/lib/new_relic/agent/internal_agent_error.rb +1 -1
  172. data/lib/new_relic/agent/javascript_instrumentor.rb +1 -1
  173. data/lib/new_relic/agent/log_once.rb +1 -1
  174. data/lib/new_relic/agent/logging.rb +2 -2
  175. data/lib/new_relic/agent/memory_logger.rb +1 -1
  176. data/lib/new_relic/agent/messaging.rb +1 -1
  177. data/lib/new_relic/agent/method_tracer.rb +16 -5
  178. data/lib/new_relic/agent/method_tracer_helpers.rb +2 -2
  179. data/lib/new_relic/agent/monitors.rb +1 -1
  180. data/lib/new_relic/agent/monitors/cross_app_monitor.rb +1 -1
  181. data/lib/new_relic/agent/monitors/distributed_tracing_monitor.rb +1 -1
  182. data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
  183. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +1 -1
  184. data/lib/new_relic/agent/new_relic_service.rb +26 -5
  185. data/lib/new_relic/agent/new_relic_service/encoders.rb +1 -1
  186. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +1 -1
  187. data/lib/new_relic/agent/new_relic_service/marshaller.rb +1 -1
  188. data/lib/new_relic/agent/new_relic_service/security_policy_settings.rb +1 -1
  189. data/lib/new_relic/agent/noticible_error.rb +22 -0
  190. data/lib/new_relic/agent/null_logger.rb +1 -1
  191. data/lib/new_relic/agent/obfuscator.rb +1 -1
  192. data/lib/new_relic/agent/parameter_filtering.rb +1 -1
  193. data/lib/new_relic/agent/payload_metric_mapping.rb +1 -1
  194. data/lib/new_relic/agent/pipe_channel_manager.rb +1 -1
  195. data/lib/new_relic/agent/pipe_service.rb +1 -1
  196. data/lib/new_relic/agent/prepend_supportability.rb +1 -1
  197. data/lib/new_relic/agent/priority_sampled_buffer.rb +8 -5
  198. data/lib/new_relic/agent/range_extensions.rb +1 -1
  199. data/lib/new_relic/agent/rules_engine.rb +1 -1
  200. data/lib/new_relic/agent/rules_engine/replacement_rule.rb +1 -1
  201. data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +1 -1
  202. data/lib/new_relic/agent/sampler.rb +1 -1
  203. data/lib/new_relic/agent/sampler_collection.rb +1 -1
  204. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
  205. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +1 -1
  206. data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
  207. data/lib/new_relic/agent/samplers/object_sampler.rb +1 -1
  208. data/lib/new_relic/agent/samplers/vm_sampler.rb +1 -1
  209. data/lib/new_relic/agent/span_event_aggregator.rb +1 -1
  210. data/lib/new_relic/agent/span_event_primitive.rb +71 -37
  211. data/lib/new_relic/agent/sql_sampler.rb +4 -4
  212. data/lib/new_relic/agent/stats.rb +1 -1
  213. data/lib/new_relic/agent/stats_engine.rb +1 -1
  214. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +1 -1
  215. data/lib/new_relic/agent/stats_engine/stats_hash.rb +1 -1
  216. data/lib/new_relic/agent/supported_versions.rb +1 -1
  217. data/lib/new_relic/agent/synthetics_event_aggregator.rb +1 -1
  218. data/lib/new_relic/agent/system_info.rb +13 -4
  219. data/lib/new_relic/agent/threading/agent_thread.rb +1 -1
  220. data/lib/new_relic/agent/threading/backtrace_node.rb +1 -1
  221. data/lib/new_relic/agent/threading/backtrace_service.rb +1 -1
  222. data/lib/new_relic/agent/threading/thread_profile.rb +1 -1
  223. data/lib/new_relic/agent/timestamp_sampled_buffer.rb +1 -1
  224. data/lib/new_relic/agent/tracer.rb +31 -16
  225. data/lib/new_relic/agent/transaction.rb +67 -46
  226. data/lib/new_relic/agent/transaction/abstract_segment.rb +29 -2
  227. data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
  228. data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
  229. data/lib/new_relic/agent/transaction/distributed_tracing.rb +2 -2
  230. data/lib/new_relic/agent/transaction/external_request_segment.rb +28 -12
  231. data/lib/new_relic/agent/transaction/message_broker_segment.rb +1 -1
  232. data/lib/new_relic/agent/transaction/request_attributes.rb +1 -1
  233. data/lib/new_relic/agent/transaction/segment.rb +23 -3
  234. data/lib/new_relic/agent/transaction/slowest_sample_buffer.rb +1 -1
  235. data/lib/new_relic/agent/transaction/synthetics_sample_buffer.rb +1 -1
  236. data/lib/new_relic/agent/transaction/trace.rb +1 -1
  237. data/lib/new_relic/agent/transaction/trace_builder.rb +1 -1
  238. data/lib/new_relic/agent/transaction/trace_context.rb +1 -1
  239. data/lib/new_relic/agent/transaction/trace_node.rb +1 -1
  240. data/lib/new_relic/agent/transaction/tracing.rb +1 -1
  241. data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +1 -1
  242. data/lib/new_relic/agent/transaction_error_primitive.rb +8 -6
  243. data/lib/new_relic/agent/transaction_event_aggregator.rb +1 -1
  244. data/lib/new_relic/agent/transaction_event_primitive.rb +3 -3
  245. data/lib/new_relic/agent/transaction_event_recorder.rb +1 -1
  246. data/lib/new_relic/agent/transaction_metrics.rb +1 -1
  247. data/lib/new_relic/agent/transaction_sampler.rb +1 -1
  248. data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
  249. data/lib/new_relic/agent/utilization/aws.rb +1 -1
  250. data/lib/new_relic/agent/utilization/azure.rb +1 -1
  251. data/lib/new_relic/agent/utilization/gcp.rb +1 -1
  252. data/lib/new_relic/agent/utilization/pcf.rb +1 -1
  253. data/lib/new_relic/agent/utilization/vendor.rb +1 -1
  254. data/lib/new_relic/agent/utilization_data.rb +1 -1
  255. data/lib/new_relic/agent/vm.rb +1 -1
  256. data/lib/new_relic/agent/vm/jruby_vm.rb +1 -1
  257. data/lib/new_relic/agent/vm/monotonic_gc_profiler.rb +1 -1
  258. data/lib/new_relic/agent/vm/mri_vm.rb +1 -1
  259. data/lib/new_relic/agent/vm/snapshot.rb +1 -1
  260. data/lib/new_relic/agent/worker_loop.rb +1 -1
  261. data/lib/new_relic/cli/command.rb +1 -1
  262. data/lib/new_relic/cli/commands/deployments.rb +1 -1
  263. data/lib/new_relic/cli/commands/install.rb +4 -3
  264. data/lib/new_relic/coerce.rb +1 -1
  265. data/lib/new_relic/collection_helper.rb +1 -1
  266. data/lib/new_relic/constants.rb +5 -1
  267. data/lib/new_relic/control.rb +1 -1
  268. data/lib/new_relic/control/class_methods.rb +1 -1
  269. data/lib/new_relic/control/frameworks.rb +1 -1
  270. data/lib/new_relic/control/frameworks/external.rb +1 -1
  271. data/lib/new_relic/control/frameworks/merb.rb +1 -1
  272. data/lib/new_relic/control/frameworks/rails.rb +1 -1
  273. data/lib/new_relic/control/frameworks/rails3.rb +1 -1
  274. data/lib/new_relic/control/frameworks/rails4.rb +1 -1
  275. data/lib/new_relic/control/frameworks/rails_notifications.rb +1 -1
  276. data/lib/new_relic/control/frameworks/ruby.rb +1 -1
  277. data/lib/new_relic/control/frameworks/sinatra.rb +1 -1
  278. data/lib/new_relic/control/instance_methods.rb +1 -1
  279. data/lib/new_relic/control/instrumentation.rb +1 -1
  280. data/lib/new_relic/control/server_methods.rb +1 -1
  281. data/lib/new_relic/delayed_job_injection.rb +1 -1
  282. data/lib/new_relic/dependency_detection.rb +1 -1
  283. data/lib/new_relic/environment_report.rb +6 -2
  284. data/lib/new_relic/helper.rb +1 -1
  285. data/lib/new_relic/language_support.rb +1 -1
  286. data/lib/new_relic/latest_changes.rb +2 -2
  287. data/lib/new_relic/local_environment.rb +1 -1
  288. data/lib/new_relic/metric_data.rb +1 -1
  289. data/lib/new_relic/metric_spec.rb +1 -1
  290. data/lib/new_relic/noticed_error.rb +29 -10
  291. data/lib/new_relic/rack.rb +1 -1
  292. data/lib/new_relic/rack/agent_hooks.rb +1 -1
  293. data/lib/new_relic/rack/agent_middleware.rb +1 -1
  294. data/lib/new_relic/rack/browser_monitoring.rb +3 -2
  295. data/lib/new_relic/recipes.rb +1 -1
  296. data/lib/new_relic/recipes/capistrano3.rb +1 -1
  297. data/lib/new_relic/recipes/capistrano_legacy.rb +1 -1
  298. data/lib/new_relic/supportability_helper.rb +1 -1
  299. data/lib/new_relic/version.rb +3 -3
  300. data/lib/newrelic_rpm.rb +1 -1
  301. data/lib/sequel/extensions/newrelic_instrumentation.rb +1 -1
  302. data/lib/sequel/plugins/newrelic_instrumentation.rb +1 -1
  303. data/lib/tasks/all.rb +1 -1
  304. data/lib/tasks/multiverse.rb +35 -1
  305. data/lib/tasks/newrelic.rb +1 -1
  306. data/lib/tasks/tests.rake +1 -1
  307. data/newrelic_rpm.gemspec +10 -9
  308. data/recipes/newrelic.rb +1 -1
  309. data/test/agent_helper.rb +237 -70
  310. metadata +42 -18
  311. data/.travis.yml +0 -210
  312. data/lib/new_relic/agent/http_clients/abstract_request.rb +0 -31
  313. data/lib/new_relic/metrics.rb +0 -13
  314. data/true +0 -0
@@ -0,0 +1,514 @@
1
+ //
2
+ // NOTE: This action script is Ubuntu specific!
3
+ //
4
+
5
+ const os = require('os')
6
+ const fs = require('fs')
7
+ const path = require('path')
8
+ const crypto = require('crypto')
9
+
10
+ const core = require('@actions/core')
11
+ const exec = require('@actions/exec')
12
+ const cache = require('@actions/cache')
13
+ const io = require('@actions/io')
14
+
15
+ let aptUpdated = false; // only `sudo apt-get update` once!
16
+
17
+
18
+ // removes trailing newlines and linefeeds from the given text string
19
+ function chomp(text) {
20
+ return text.replace(/(\n|\r)+$/, '')
21
+ }
22
+
23
+ // invokes the @actions/exec exec function with listeners to capture the
24
+ // output stream as the return result.
25
+ async function execute(command) {
26
+ try {
27
+ let outputStr = ''
28
+
29
+ const options = {}
30
+ options.listeners = {
31
+ stdout: (data) => { outputStr += data.toString() },
32
+ stderr: (data) => { core.error(data.toString()) }
33
+ }
34
+
35
+ await exec.exec(command, [], options)
36
+
37
+ return chomp(outputStr);
38
+
39
+ } catch (error) {
40
+ console.error(error.toString())
41
+ }
42
+ }
43
+
44
+ // given one or more space-separated (not comma-delimited) dependency
45
+ // names, invokes the package manager to install them.
46
+ async function installDependencies(kind, dependencyList) {
47
+ if (dependencyList === '') { return }
48
+ core.startGroup(`Installing ${kind} dependencies`)
49
+
50
+ core.info(`installing ${kind} dependencies ${dependencyList}`)
51
+
52
+ // only update package list once per workflow invocation.
53
+ if (!aptUpdated) {
54
+ await exec.exec(`sudo apt-get update`)
55
+ aptUpdated = true
56
+ }
57
+ await exec.exec(`sudo apt-get install -y --no-install-recommends ${dependencyList}`)
58
+
59
+ core.endGroup()
60
+ }
61
+
62
+ // installs system dependencies needed to successfully build the ruby executables
63
+ async function installBuildDependencies() {
64
+ const dependencyList = 'libyaml-dev libgdbm-dev libreadline-dev libncurses5-dev zlib1g-dev libffi-dev'
65
+
66
+ await installDependencies('ruby-build', dependencyList);
67
+ }
68
+
69
+ // Returns if Ruby version is <= 2.3
70
+ function usesOldOpenSsl(rubyVersion) {
71
+ return rubyVersion.match(/^2\.[0123]/);
72
+ }
73
+
74
+ // ruby-build is used to compile Ruby and it's various executables
75
+ // rbenv's ruby-build doesn't fully support EOL rubies (< 2.4 at time of this writing).
76
+ // setup-ruby also doesn't correctly build the older rubies with openssl support.
77
+ // long story short, openssl library for these older ruby need to be 1.0 variant.
78
+ async function installRubyBuild(rubyVersion) {
79
+ core.startGroup(`Installing ruby-build`)
80
+
81
+ const buildDir = `${process.env.HOME}/ruby-build`
82
+ var repoPath
83
+
84
+ // Rubies 2.0 ... 2.3 (these need OpenSSL 1.0 and eregon provides it for us)
85
+ if (usesOldOpenSsl(rubyVersion)) {
86
+ core.info('cloning eregon/ruby-build')
87
+ repoPath = '--branch ruby23-openssl-linux https://github.com/eregon/ruby-build.git'
88
+
89
+ // all the other Rubies
90
+ } else {
91
+ core.info('cloning rbenv/ruby-build')
92
+ repoPath = 'https://github.com/rbenv/ruby-build.git'
93
+ }
94
+
95
+ await exec.exec(`git clone ${repoPath} ${buildDir}`)
96
+ await exec.exec(`sudo ${buildDir}/install.sh`)
97
+
98
+ core.endGroup()
99
+ }
100
+
101
+ // Add the environment variables needed to correctly build ruby and later run ruby tests.
102
+ // this function is invoked even if ruby is cached and compile step is skipped.
103
+ async function setupRubyEnvironment(rubyVersion) {
104
+
105
+ // LANG environment must be set or Ruby will default external_encoding to US-ASCII i
106
+ // instead of UTF-8 and this will fail many tests.
107
+ core.exportVariable('LANG', 'C.UTF-8')
108
+
109
+ // https://github.com/actions/virtual-environments/issues/267
110
+ core.exportVariable('CPPFLAGS', '-DENABLE_PATH_CHECK=0')
111
+
112
+ // Ensures Bundler retries failed attempts before giving up
113
+ core.exportVariable('BUNDLE_RETRY', 1)
114
+
115
+ // Number of jobs in parallel
116
+ core.exportVariable('BUNDLE_JOBS', 4)
117
+
118
+ // Where to keep the gem files
119
+ core.exportVariable('BUNDLE_PATH', gemspecFilePath(rubyVersion))
120
+
121
+ // enable-shared prevents native extension gems from breaking if they're cached
122
+ // independently of the ruby binaries
123
+ core.exportVariable('RUBY_CONFIGURE_OPTS', '--enable-shared --disable-install-doc')
124
+
125
+ // many multiverse suite tests end up in resource contention when run in parallel
126
+ core.exportVariable('SERIALIZE', 1)
127
+ }
128
+
129
+ // Sets up any options at the bundler level so that when gems that
130
+ // need specific settings are installed, their specific flags are relayed.
131
+ async function configureBundleOptions(rubyVersion) {
132
+ if (!usesOldOpenSsl(rubyVersion)) { return }
133
+
134
+ const openSslPath = rubyOpenSslPath(rubyVersion);
135
+
136
+ // https://stackoverflow.com/questions/30834421/error-when-trying-to-install-app-with-mysql2-gem
137
+ await exec.exec('bundle', [
138
+ 'config', '--global', 'build.mysql2',
139
+ `"--with-ldflags=-L${openSslPath}/lib"`,
140
+ `"--with-cppflags=-I${openSslPath}/include"`
141
+ ]);
142
+ }
143
+
144
+ // prepends the given value to the environment variable
145
+ function prependEnv(envName, envValue, divider=' ') {
146
+ let existingValue = process.env[envName];
147
+ if (existingValue) {
148
+ envValue += `${divider}${existingValue}`
149
+ }
150
+ core.exportVariable(envName, envValue);
151
+ }
152
+
153
+ // The older Rubies also need older MySQL that was built against the older OpenSSL libraries.
154
+ // Otherwise mysql adapter will segfault in Ruby because it attempts to dynamically link
155
+ // to the 1.1 series while Ruby links against the 1.0 series.
156
+ async function downgradeMySQL() {
157
+ core.startGroup(`Downgrade MySQL`)
158
+
159
+ const pkgDir = `${process.env.HOME}/packages`
160
+ const pkgOption = `--directory-prefix=${pkgDir}/`
161
+ const mirrorUrl = 'https://mirrors.mediatemple.net/debian-security/pool/updates/main/m/mysql-5.5'
162
+
163
+ // executes the following all in parallel
164
+ const promise1 = exec.exec('sudo', ['apt-get', 'remove', 'mysql-client'])
165
+ const promise2 = exec.exec('wget', [pkgOption, `${mirrorUrl}/libmysqlclient18_5.5.62-0%2Bdeb8u1_amd64.deb`])
166
+ const promise3 = exec.exec('wget', [pkgOption, `${mirrorUrl}/libmysqlclient-dev_5.5.62-0%2Bdeb8u1_amd64.deb`])
167
+
168
+ // wait for the parallel processes to finish
169
+ await Promise.all([promise1, promise2, promise3])
170
+
171
+ // executes serially
172
+ await exec.exec('sudo', ['dpkg', '-i', `${pkgDir}/libmysqlclient18_5.5.62-0+deb8u1_amd64.deb`])
173
+ await exec.exec('sudo', ['dpkg', '-i', `${pkgDir}/libmysqlclient-dev_5.5.62-0+deb8u1_amd64.deb`])
174
+
175
+ core.endGroup()
176
+ }
177
+
178
+ // mySQL (and others) must be downgraded for EOL rubies for native extension
179
+ // gems to install correctly and against the right openSSL libraries.
180
+ async function downgradeSystemPackages(rubyVersion) {
181
+ if (!usesOldOpenSsl(rubyVersion)) { return }
182
+
183
+ await downgradeMySQL();
184
+ }
185
+
186
+ // any settings needed in all Ruby environments from EOL'd rubies to current
187
+ async function setupAllRubyEnvironments() {
188
+ // core.startGroup("Setup for all Ruby Environments")
189
+
190
+ // // No-Op
191
+
192
+ // core.endGroup()
193
+ }
194
+
195
+ // any settings needed specifically for the EOL'd rubies
196
+ async function setupOldRubyEnvironments(rubyVersion) {
197
+ if (!usesOldOpenSsl(rubyVersion)) { return }
198
+
199
+ core.startGroup("Setup for EOL Ruby Environments")
200
+
201
+ const openSslPath = rubyOpenSslPath(rubyVersion);
202
+
203
+ core.exportVariable('OPENSSL_DIR', openSslPath)
204
+
205
+ prependEnv('LDFLAGS', `-L${openSslPath}/lib`)
206
+ prependEnv('CPPFLAGS', `-I${openSslPath}/include`)
207
+ prependEnv('PKG_CONFIG_PATH', `${openSslPath}/lib/pkgconfig`, ':')
208
+
209
+ openSslOption = `--with-openssl-dir=${openSslPath}`
210
+ core.exportVariable('CONFIGURE_OPTS', openSslOption)
211
+ prependEnv('RUBY_CONFIGURE_OPTS', openSslOption)
212
+
213
+ // required for some versions of nokogiri
214
+ gemInstall('pkg-config', '~> 1.1.7')
215
+
216
+ core.endGroup()
217
+ }
218
+
219
+ // setup the Ruby environment settings after Ruby has been built
220
+ // or restored from cache.
221
+ async function setupRubyEnvironmentAfterBuild(rubyVersion) {
222
+ await setupAllRubyEnvironments()
223
+ await setupOldRubyEnvironments(rubyVersion)
224
+ }
225
+
226
+ // Shows some version love!
227
+ async function showVersions() {
228
+ core.startGroup("Show Versions")
229
+
230
+ await exec.exec('ruby', ['--version'])
231
+ await exec.exec('ruby', ['-ropenssl', '-e', "puts OpenSSL::OPENSSL_LIBRARY_VERSION"])
232
+ await exec.exec('gem', ['--version'])
233
+ await exec.exec('bundle', ['--version'])
234
+ await exec.exec('openssl', ['version'])
235
+
236
+ core.endGroup()
237
+ }
238
+
239
+ // Just one place to define the ruby binaries path and that is here
240
+ // NOTE: the cache step in the workflow .yml file must match this path
241
+ function rubyPath(rubyVersion) {
242
+ return `${process.env.HOME}/.rubies/ruby-${rubyVersion}`
243
+ }
244
+
245
+ // Returns the path to openSSL that this version of Ruby was compiled with.
246
+ // NOTE: throws an error if called for Rubies that are compiled against the system OpenSSL
247
+ function rubyOpenSslPath(rubyVersion) {
248
+ if (usesOldOpenSsl(rubyVersion)) {
249
+ return `${rubyPath(rubyVersion)}/openssl`;
250
+ }
251
+ else {
252
+ throw `custom OpenSSL path not needed for this version of Ruby ${rubyVersion}`;
253
+ }
254
+ }
255
+
256
+ // This "activates" our newly built ruby so it comes first in the path
257
+ function addRubyToPath(rubyVersion) {
258
+ core.addPath(`${rubyPath(rubyVersion)}/bin`);
259
+
260
+ if (usesOldOpenSsl(rubyVersion)) {
261
+ core.addPath(`${rubyPath(rubyVersion)}/openssl/bin`);
262
+ }
263
+ }
264
+
265
+ // kicks off the ruby build process.
266
+ async function buildRuby(rubyVersion) {
267
+ core.startGroup(`Build Ruby ${rubyVersion}`)
268
+ await exec.exec(`ruby-build --verbose ${rubyVersion} ${rubyPath(rubyVersion)}`)
269
+ core.endGroup()
270
+ }
271
+
272
+ // Older rubies come with Ruby gems 2.5.x and we need 3.0.6 minimum to
273
+ // correctly install Bundler and do anything else within the multiverse test suite
274
+ async function upgradeRubyGems(rubyVersion) {
275
+ core.startGroup(`Upgrade RubyGems`)
276
+
277
+ await execute('gem --version').then(res => { gemVersionStr = res; });
278
+
279
+ core.info(`Current RubyGems is "${gemVersionStr}"`)
280
+
281
+ if (parseFloat(rubyVersion) < 2.7) {
282
+
283
+ if (parseFloat(gemVersionStr) < 3.0) {
284
+ core.info(`Ruby < 2.7, upgrading RubyGems from ${gemVersionStr}`)
285
+
286
+ await exec.exec('gem', ['update', '--system', '3.0.6', '--force']).then(res => { exitCode = res });
287
+ if (exitCode != 0) {
288
+ gemInstall('rubygems-update', '<3')
289
+ await exec.exec('update_rubygems')
290
+ };
291
+
292
+ }
293
+ else {
294
+ core.info(`Ruby < 2.7, but RubyGems already at ${gemVersionStr}`)
295
+ }
296
+ }
297
+
298
+ else {
299
+ core.info(`Ruby >= 2.7, keeping RubyGems at ${gemVersionStr}`)
300
+ }
301
+
302
+ await execute('which gem').then(res => { core.info("which gem: " + res) });
303
+ await execute('gem --version').then(res => { core.info("New RubyGems is: " + res) });
304
+
305
+ core.endGroup()
306
+ }
307
+
308
+ // utility function to standardize installing ruby gems.
309
+ async function gemInstall(name, version = undefined, binPath = undefined) {
310
+ let options = ['install', name, '--no-document']
311
+
312
+ if (version) { options.push('-v', version) }
313
+ if (binPath) { options.push('--bindir', binPath) }
314
+
315
+ await exec.exec('gem', options)
316
+ }
317
+
318
+ // install Bundler 1.17.3 (or thereabouts)
319
+ // Ruby 2.6 is first major Ruby to ship with bundle, but it also ships
320
+ // with incompatible 1.17.2 version that must be upgraded to 1.17.3
321
+ // for some test environments/suites to function correctly.
322
+ async function installBundler(rubyVersion) {
323
+ core.startGroup(`Install bundler`)
324
+
325
+ const rubyBinPath = `${rubyPath(rubyVersion)}/bin`
326
+
327
+ if (!fs.existsSync(`${rubyBinPath}/bundle`)) {
328
+ await gemInstall('bundler', '~> 1.17.3', rubyBinPath)
329
+ }
330
+ else {
331
+ await execute('bundle --version').then(res => { bundleVersionStr = res; });
332
+ if (bundleVersionStr.match(/1\.17\.2/)) {
333
+ core.info(`found bundle ${bundleVersionStr}. Upgrading to 1.17.3`)
334
+ await gemInstall('bundler', '~> 1.17.3', rubyBinPath)
335
+ }
336
+ }
337
+
338
+ core.endGroup()
339
+ }
340
+
341
+ function rubyCachePaths(rubyVersion) {
342
+ return [ `${process.env.HOME}/.rubies/ruby-${rubyVersion}` ]
343
+ }
344
+
345
+ function rubyCacheKey(rubyVersion) {
346
+ return `v8-ruby-cache-${rubyVersion}`
347
+ }
348
+
349
+ // will attempt to restore the previously built Ruby environment if one exists.
350
+ async function restoreRubyFromCache(rubyVersion) {
351
+ core.startGroup(`Restore Ruby from Cache`)
352
+
353
+ const key = rubyCacheKey(rubyVersion)
354
+ await cache.restoreCache(rubyCachePaths(rubyVersion), key, [key])
355
+
356
+ core.endGroup()
357
+ }
358
+
359
+ // Causes current Ruby environment to be archived and cached.
360
+ async function saveRubyToCache(rubyVersion) {
361
+ core.startGroup(`Save Ruby to Cache`)
362
+
363
+ const key = rubyCacheKey(rubyVersion)
364
+ await cache.saveCache(rubyCachePaths(rubyVersion), key)
365
+
366
+ core.endGroup()
367
+ }
368
+
369
+ // Ensures working, properly configured environment for running test suites.
370
+ async function postBuildSetup(rubyVersion) {
371
+ await downgradeSystemPackages(rubyVersion)
372
+ await setupRubyEnvironmentAfterBuild(rubyVersion)
373
+ await configureBundleOptions(rubyVersion)
374
+ await showVersions()
375
+ }
376
+
377
+ // Premable steps necessary for building/running the correct Ruby
378
+ async function setupEnvironment(rubyVersion, dependencyList) {
379
+ const systemDependencyList = "libcurl4-nss-dev build-essential libsasl2-dev libxslt1-dev libxml2-dev"
380
+
381
+ await installDependencies('system', systemDependencyList)
382
+ await installDependencies('workflow', dependencyList)
383
+ await setupRubyEnvironment(rubyVersion)
384
+ await addRubyToPath(rubyVersion)
385
+ }
386
+
387
+ async function setupRuby(rubyVersion){
388
+ // skip build process and just setup environment if successfully restored
389
+ if (isRubyBuilt(rubyVersion)) {
390
+ core.info("Ruby already built. Skipping the build process!")
391
+ }
392
+
393
+ // otherwise, build Ruby, cache it, then setup environment
394
+ else {
395
+ await installRubyBuild(rubyVersion)
396
+ await installBuildDependencies()
397
+ await buildRuby(rubyVersion)
398
+ await upgradeRubyGems(rubyVersion)
399
+ await installBundler(rubyVersion)
400
+
401
+ await saveRubyToCache(rubyVersion)
402
+ }
403
+
404
+ await postBuildSetup(rubyVersion)
405
+ }
406
+
407
+ // fingerprints the given filename, returning hex string representation
408
+ function fileHash(filename) {
409
+ let sum = crypto.createHash('md5')
410
+ sum.update(fs.readFileSync(filename))
411
+ return sum.digest('hex')
412
+ }
413
+
414
+ function bundleCacheKey(rubyVersion) {
415
+ const keyHash = fileHash(`${process.env.GITHUB_WORKSPACE}/newrelic_rpm.gemspec`)
416
+ return `v2-bundle-cache-${rubyVersion}-${keyHash}`
417
+ }
418
+
419
+ function gemspecFilePath(rubyVersion) {
420
+ return `${rubyPath(rubyVersion)}/.bundle-cache`
421
+ }
422
+
423
+ function bundleCachePaths(rubyVersion) {
424
+ return [ gemspecFilePath(rubyVersion) ]
425
+ }
426
+
427
+ // will attempt to restore the previously built Ruby environment if one exists.
428
+ async function restoreBundleFromCache(rubyVersion) {
429
+ core.startGroup(`Restore Bundle from Cache`)
430
+
431
+ const key = bundleCacheKey(rubyVersion)
432
+ core.info(`restore using ${key}`)
433
+ await cache.restoreCache(bundleCachePaths(rubyVersion), key, [key])
434
+
435
+ core.endGroup()
436
+ }
437
+
438
+ // Causes current Ruby environment to be archived and cached.
439
+ async function saveBundleToCache(rubyVersion) {
440
+ core.startGroup(`Save Bundle to Cache`)
441
+
442
+ const key = bundleCacheKey(rubyVersion)
443
+ await cache.saveCache(bundleCachePaths(rubyVersion), key)
444
+
445
+ core.endGroup()
446
+ }
447
+
448
+ async function setupTestEnvironment(rubyVersion) {
449
+ core.startGroup('Setup Test Environment')
450
+
451
+ const filePath = gemspecFilePath(rubyVersion)
452
+ const workspacePath = process.env.GITHUB_WORKSPACE
453
+
454
+ await restoreBundleFromCache(rubyVersion)
455
+
456
+ // restore the Gemfile.lock to working folder if cache-hit
457
+ if (fs.existsSync(`${filePath}/Gemfile.lock`)) {
458
+ await io.cp(`${filePath}/Gemfile.lock`, `${workspacePath}/Gemfile.lock`)
459
+ await exec.exec('bundle', ['install'])
460
+ }
461
+
462
+ // otherwise, bundle install and cache it
463
+ else {
464
+ await exec.exec('bundle', ['install'])
465
+ await io.cp(`${workspacePath}/Gemfile.lock`, `${filePath}/Gemfile.lock`)
466
+ try {
467
+ await saveBundleToCache(rubyVersion)
468
+ }
469
+ catch (error) {
470
+ console.log('Failed to save cache' + error.toString())
471
+ }
472
+ }
473
+
474
+ core.endGroup()
475
+ }
476
+
477
+ // Detects if we're expected to build Ruby vs. running the test suite
478
+ // This conditional controls whether we go through pain of setting up the
479
+ // environment when Ruby was previously built and cached.
480
+ function isBuildJob() {
481
+ return process.env.GITHUB_JOB.match(/build/)
482
+ }
483
+
484
+ // Returns true if Ruby was restored from cache
485
+ function isRubyBuilt(rubyVersion) {
486
+ const rubyBinPath = `${rubyPath(rubyVersion)}/bin`
487
+
488
+ return fs.existsSync(`${rubyBinPath}/ruby`)
489
+ }
490
+
491
+ // Will set up the Ruby environment so the desired Ruby binaries are used in the unit tests
492
+ // If Ruby hasn't been built and cached, yet, we also compile the Ruby binaries.
493
+ async function main() {
494
+ const dependencyList = core.getInput('dependencies')
495
+ const rubyVersion = core.getInput('ruby-version')
496
+
497
+ try {
498
+ // restores from cache if this ruby version was previously built and cached
499
+ await restoreRubyFromCache(rubyVersion)
500
+
501
+ // skip setting up environment when we're only building and Ruby's already built!
502
+ if (isRubyBuilt(rubyVersion) && isBuildJob()) { return }
503
+
504
+ await setupEnvironment(rubyVersion, dependencyList)
505
+ await setupRuby(rubyVersion)
506
+ await setupTestEnvironment(rubyVersion)
507
+ }
508
+ catch (error) {
509
+ core.setFailed(`Action failed with error ${error}`)
510
+ }
511
+
512
+ }
513
+
514
+ main()