roo_on_rails 1.20.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +398 -282
  3. data/.circleci/config.yml.erb +63 -21
  4. data/.codecov.yml +3 -0
  5. data/Appraisals +24 -11
  6. data/CHANGELOG.md +39 -0
  7. data/README.md +20 -31
  8. data/appraise +1 -1
  9. data/exe/roo_on_rails +5 -0
  10. data/gemfiles/rails_4.gemfile +3 -1
  11. data/gemfiles/rails_5.gemfile +2 -1
  12. data/gemfiles/rails_5_1.gemfile +3 -2
  13. data/gemfiles/rails_5_2.gemfile +15 -0
  14. data/gemfiles/{rails_3.gemfile → rails_6.gemfile} +5 -4
  15. data/lib/roo_on_rails.rb +1 -4
  16. data/lib/roo_on_rails/checks/documentation/playbook_template.md +0 -4
  17. data/lib/roo_on_rails/concerns/require_api_key.rb +0 -1
  18. data/lib/roo_on_rails/config.rb +0 -8
  19. data/lib/roo_on_rails/default.env +0 -13
  20. data/lib/roo_on_rails/rack/populate_env_from_jwt.rb +25 -4
  21. data/lib/roo_on_rails/railties/database.rb +11 -10
  22. data/lib/roo_on_rails/railties/env.rb +3 -5
  23. data/lib/roo_on_rails/railties/google_oauth.rb +4 -6
  24. data/lib/roo_on_rails/railties/http.rb +34 -32
  25. data/lib/roo_on_rails/railties/roo_identity.rb +12 -8
  26. data/lib/roo_on_rails/railties/{sidekiq.rb → sidekiq_integration.rb} +18 -18
  27. data/lib/roo_on_rails/version.rb +1 -1
  28. data/roo_on_rails.gemspec +5 -6
  29. metadata +28 -57
  30. data/.travis.yml +0 -34
  31. data/README.routemaster_client.md +0 -103
  32. data/lib/roo_on_rails/railties/logging.rb +0 -25
  33. data/lib/roo_on_rails/railties/new_relic.rb +0 -32
  34. data/lib/roo_on_rails/railties/routemaster.rb +0 -42
  35. data/lib/roo_on_rails/routemaster/lifecycle_events.rb +0 -64
  36. data/lib/roo_on_rails/routemaster/publish_lifecycle_events.rb +0 -13
  37. data/lib/roo_on_rails/routemaster/publisher.rb +0 -74
  38. data/lib/roo_on_rails/routemaster/publishers.rb +0 -27
  39. data/lib/roo_on_rails/tasks/newrelic.rake +0 -25
@@ -1,34 +0,0 @@
1
- sudo: required
2
- language: ruby
3
- rvm:
4
- - 2.2.7
5
- - 2.3.3
6
- - 2.4.1
7
- - ruby-head
8
- gemfile:
9
- - gemfiles/rails_3.gemfile
10
- - gemfiles/rails_4.gemfile
11
- - gemfiles/rails_5.gemfile
12
- - gemfiles/rails_5_1.gemfile
13
- install:
14
- - bundle install --jobs=3 --retry=3 --path=vendor/bundle
15
- cache:
16
- bundler: true
17
- directories:
18
- - vendor/bundle
19
- - vendor/bundle-scaffold
20
- before_script:
21
- - unset RACK_ENV
22
- - unset RAILS_ENV
23
- - mkdir -p $PWD/tmp && sudo mount -t tmpfs -o size=1024m tmpfs $PWD/tmp
24
- - gem install bundler
25
- matrix:
26
- allow_failures:
27
- - rvm: ruby-head
28
- exclude:
29
- - rvm: 2.4.1
30
- gemfile: gemfiles/rails_3.gemfile
31
- - rvm: ruby-head
32
- gemfile: gemfiles/rails_3.gemfile
33
- services:
34
- - redis-server
@@ -1,103 +0,0 @@
1
- ## Using the Routemaster Client feature
2
-
3
- [`routemaster-client`](https://github.com/deliveroo/routemaster-client) comes as a dependency of `roo_on_rails` with a basic implementation of lifecycle event publishers.
4
-
5
- This code example assumes that you are using the latest version of the [`roo_on_rails`](https://github.com/deliveroo/roo_on_rails) gem and that you have set the correct environment variables for Routemaster Client to work on your app, as explained in the main [`README.md`](https://github.com/deliveroo/roo_on_rails#routemaster-client) file.
6
-
7
- It also assumes that your app has an API for the resources you want to publish lifecycle events for, with matching routes and an `API_HOST` environment variable set.
8
-
9
- ### Setup lifecycle events for your models
10
-
11
- You can use publish events on create, update, and destroy by including the `PublishLifecycleEvents` module:
12
-
13
- ```ruby
14
- # app/models/order.rb
15
- require 'roo_on_rails/routemaster/publish_lifecycle_events'
16
-
17
- class Order < ApplicationRecord
18
- include RooOnRails::Routemaster::PublishLifecycleEvents
19
-
20
- # ...
21
- end
22
- ```
23
-
24
- If you need more control over which events are published you can use the base module `LifecycleEvents` and specify them explicitly:
25
-
26
- ```ruby
27
- # app/models/rider.rb
28
- require 'roo_on_rails/routemaster/lifecycle_events'
29
-
30
- class Rider < ApplicationRecord
31
- include RooOnRails::Routemaster::LifecycleEvents
32
-
33
- publish_lifecycle_events :create, :destroy
34
-
35
- # ...
36
- end
37
- ```
38
-
39
- ### Create publishers for lifecycle events
40
-
41
- We have now configured our models to publish lifecycle events to Routemaster, but it won't send anything until you have enabled publishing and created matching publishers. Let's start with creating an `ApplicationPublisher` that we can use as our default.
42
-
43
- ```ruby
44
- # app/publishers/application_publisher.rb
45
- require 'roo_on_rails/routemaster/publisher'
46
-
47
- class ApplicationPublisher < RooOnRails::Routemaster::Publisher
48
- include Rails.application.routes.url_helpers
49
-
50
- def url
51
- url_helper = :"api_#{model.class.name.underscore}_url"
52
- public_send(url_helper, model.id, host: ENV.fetch('API_HOST'), protocol: 'https')
53
- end
54
-
55
- # Add your method overrides here if needed
56
- end
57
- ```
58
-
59
- If different behaviour is needed for specific models then you can override the defaults in their publishers:
60
-
61
- ```ruby
62
- # app/publishers/order_publisher.rb
63
- class OrderPublisher < ApplicationPublisher
64
- def async?
65
- true
66
- end
67
- end
68
- ```
69
-
70
- and
71
-
72
- ```ruby
73
- # app/publishers/rider_publisher.rb
74
- class RiderPublisher < ApplicationPublisher
75
- def topic
76
- 'a_different_rider_topic'
77
- end
78
- end
79
- ```
80
-
81
- `#publish?`, `#topics`, `#async?`, `#data` and `#timestamp` can be overriden; see [the `Publisher` class](lib/roo_on_rails/routemaster/publisher.rb) for the default implementations.
82
-
83
- ### Register the publishers with Routemaster
84
-
85
- The final step is to tell Routemaster that these publishers exist, so that it can listen to their events. We're going to do this in an initialiser:
86
-
87
- ```ruby
88
- # config/initilizers/routemaster.rb
89
- require 'roo_on_rails/routemaster/publishers'
90
-
91
- PUBLISHERS = [
92
- OrderPublisher,
93
- RiderPublisher
94
- ].freeze
95
-
96
- RooOnRails::Routemaster::Publishers.register_default(ApplicationPublisher)
97
- PUBLISHERS.each do |publisher|
98
- model_class = publisher.to_s.gsub("Publisher", "").constantize
99
- RooOnRails::Routemaster::Publishers.register(publisher, model_class: model_class)
100
- end
101
- ```
102
-
103
- We should now be all set for our app to publish lifecycle events for all our models onto the event bus, with special behaviour for `orders` and `riders`, so that other apps can listen to them.
@@ -1,25 +0,0 @@
1
- module RooOnRails
2
- module Railties
3
- class Logging < Rails::Railtie
4
- initializer 'roo_on_rails.logging.before', before: :initialize_logger do
5
- require 'roo_on_rails/logger'
6
- Rails.logger = config.logger = RooOnRails::Logger.new
7
- # It is not possible to set log_level to an invalid value without some
8
- # deliberate gymnastics (the setter will raise an error), and Rails
9
- # defaults this to `debug`, so we don't need to guard against nil /
10
- # invalidity
11
- log_level = Rails.configuration.log_level
12
-
13
- Rails.logger.set_log_level(default: log_level)
14
- Rails.logger.debug 'initializer roo_on_rails.logging.before'
15
- end
16
-
17
- initializer 'roo_on_rails.logging.after', after: :initialize_logger do
18
- log_level = Rails.configuration.log_level
19
-
20
- Rails.logger.set_log_level(default: log_level)
21
- Rails.logger.debug 'initializer roo_on_rails.logging.after'
22
- end
23
- end
24
- end
25
- end
@@ -1,32 +0,0 @@
1
- module RooOnRails
2
- module Railties
3
- class NewRelic < Rails::Railtie
4
- initializer 'roo_on_rails.new_relic' do
5
- Rails.logger.with initializer: 'roo_on_rails.new_relic' do |log|
6
- log.debug 'loading'
7
- license_key = ENV['NEW_RELIC_LICENSE_KEY']
8
-
9
- if %w(test development).exclude?(Rails.env.to_s) && (license_key == 'override-me')
10
- abort 'Aborting: NEW_RELIC_LICENSE_KEY must be set in production environments'
11
- end
12
-
13
- abort 'Aborting: NEW_RELIC_LICENSE_KEY is required' if license_key.nil?
14
-
15
- path = %w(newrelic.yml config/newrelic.yml).map do |p|
16
- Pathname.new(p)
17
- end.find(&:exist?)
18
- if path
19
- abort "Aborting: newrelic.yml detected in '#{path.parent.realpath}', should not exist"
20
- end
21
-
22
- sync_startup = (ENV.fetch('NEW_RELIC_SYNC_STARTUP', 'YES') =~ /\A(YES|TRUE|ON|1)\Z/i)
23
-
24
- require 'newrelic_rpm'
25
- unless Rails.env.test?
26
- ::NewRelic::Control.instance.init_plugin(sync_startup: sync_startup)
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,42 +0,0 @@
1
- require 'roo_on_rails/config'
2
-
3
- module RooOnRails
4
- module Railties
5
- class Routemaster < Rails::Railtie
6
- initializer 'roo_on_rails.routemaster' do
7
- Rails.logger.with initializer: 'roo_on_rails.routemaster' do |log|
8
- next unless Config.routemaster_enabled?
9
- log.debug 'loading'
10
-
11
- abort 'Aborting: ROUTEMASTER_URL and ROUTEMASTER_UUID are required' if bus_details_missing?
12
-
13
- require 'routemaster/client'
14
-
15
- ::Routemaster::Client.configure do |config|
16
- config.url = routemaster_url
17
- config.uuid = routemaster_uuid
18
- config.verify_ssl = routemaster_verify_ssl
19
- end
20
- end
21
- end
22
-
23
- private
24
-
25
- def bus_details_missing?
26
- routemaster_url.blank? || routemaster_uuid.blank?
27
- end
28
-
29
- def routemaster_url
30
- ENV.fetch('ROUTEMASTER_URL')
31
- end
32
-
33
- def routemaster_uuid
34
- ENV.fetch('ROUTEMASTER_UUID')
35
- end
36
-
37
- def routemaster_verify_ssl
38
- ENV.fetch('ROUTEMASTER_VERIFY_SSL', 'true') != 'false'
39
- end
40
- end
41
- end
42
- end
@@ -1,64 +0,0 @@
1
- require 'active_support/concern'
2
- require 'new_relic/agent'
3
- require 'roo_on_rails/routemaster/publishers'
4
-
5
- module RooOnRails
6
- module Routemaster
7
- module LifecycleEvents
8
- extend ActiveSupport::Concern
9
-
10
- ACTIVE_RECORD_TO_ROUTEMASTER_EVENT_MAP = {
11
- create: :created,
12
- update: :updated,
13
- destroy: :deleted,
14
- noop: :noop
15
- }.freeze
16
- private_constant :ACTIVE_RECORD_TO_ROUTEMASTER_EVENT_MAP
17
-
18
- def publish_lifecycle_event(event)
19
- publish_event(event, force_publish: false)
20
- end
21
-
22
- def publish_lifecycle_event!(event)
23
- publish_event(event, force_publish: true)
24
- end
25
-
26
- private
27
-
28
- def publish_event(event, force_publish:)
29
- publishers = Routemaster::Publishers.for(self, routemaster_event_type(event))
30
- publishers.each do |publisher|
31
- begin
32
- publisher.publish!(force_publish: force_publish)
33
- rescue => e
34
- NewRelic::Agent.notice_error(e)
35
- end
36
- end
37
- end
38
-
39
- def routemaster_event_type(event)
40
- ACTIVE_RECORD_TO_ROUTEMASTER_EVENT_MAP[event].tap do |type|
41
- raise "invalid lifecycle event '#{event}'" unless type
42
- end
43
- end
44
-
45
- %i(create update destroy noop).each do |event|
46
- define_method("publish_lifecycle_event_on_#{event}") do
47
- publish_lifecycle_event(event)
48
- end
49
- end
50
-
51
- module ClassMethods
52
- def publish_lifecycle_events(*events)
53
- events = events.any? ? events : %i(create update destroy)
54
- events.each do |event|
55
- after_commit(
56
- :"publish_lifecycle_event_on_#{event}",
57
- on: event
58
- )
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
@@ -1,13 +0,0 @@
1
- require 'active_support/concern'
2
- require 'roo_on_rails/routemaster/lifecycle_events'
3
-
4
- module RooOnRails
5
- module Routemaster
6
- module PublishLifecycleEvents
7
- extend ActiveSupport::Concern
8
- include LifecycleEvents
9
-
10
- included(&:publish_lifecycle_events)
11
- end
12
- end
13
- end
@@ -1,74 +0,0 @@
1
- require 'roo_on_rails/config'
2
- require 'routemaster/client'
3
-
4
- module RooOnRails
5
- module Routemaster
6
- class Publisher
7
- attr_reader :model, :event
8
-
9
- def initialize(model, event, client: ::Routemaster::Client)
10
- @model = model
11
- @event = event
12
- @client = client
13
- end
14
-
15
- def publish?
16
- noop? || @model.new_record? || @model.previous_changes.any?
17
- end
18
-
19
- def will_publish?(force_publish: false)
20
- Config.routemaster_publishing_enabled? && (force_publish || publish?)
21
- end
22
-
23
- def publish!(force_publish: false)
24
- return unless will_publish?(force_publish: force_publish)
25
- @client.send(
26
- @event,
27
- topic,
28
- url,
29
- async: async?,
30
- data: stringify_keys(data),
31
- t: timestamp && (timestamp.to_f * 1000).to_i
32
- )
33
- end
34
-
35
- def topic
36
- @model.class.name.tableize
37
- end
38
-
39
- def url
40
- raise NotImplementedError
41
- end
42
-
43
- def async?
44
- false
45
- end
46
-
47
- def data
48
- nil
49
- end
50
-
51
- def timestamp
52
- return @model.created_at if created? && @model.respond_to?(:created_at)
53
- return @model.updated_at if (updated? || created?) && @model.respond_to?(:updated_at)
54
- nil
55
- end
56
-
57
- %i(created updated deleted noop).each do |event_type|
58
- define_method :"#{event_type}?" do
59
- @event.to_sym == event_type
60
- end
61
- end
62
-
63
- private
64
-
65
- def stringify_keys(hash)
66
- return hash if hash.nil? || hash.empty?
67
-
68
- hash.each_with_object({}) do |(k, v), h|
69
- h[k.to_s] = v.is_a?(Hash) ? stringify_keys(v) : v
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,27 +0,0 @@
1
- module RooOnRails
2
- module Routemaster
3
- module Publishers
4
- @default_publishers = []
5
- @publishers = {}
6
-
7
- def self.register_default(publisher_class)
8
- @default_publishers << publisher_class
9
- end
10
-
11
- def self.register(publisher_class, model_class:)
12
- @publishers[model_class.name] ||= Set.new
13
- @publishers[model_class.name] << publisher_class
14
- end
15
-
16
- def self.for(model, event)
17
- publisher_classes = @publishers[model.class.name] || @default_publishers
18
- publisher_classes.map { |c| c.new(model, event) }
19
- end
20
-
21
- def self.clear
22
- @default_publishers = []
23
- @publishers = {}
24
- end
25
- end
26
- end
27
- end
@@ -1,25 +0,0 @@
1
- namespace :newrelic do
2
- desc 'Notifies New Relic that a deployment has occurred'
3
- task notice_deployment: :environment do
4
- begin
5
- require 'newrelic_rpm'
6
- require 'new_relic/cli/command'
7
-
8
- appname = ENV.fetch('NEW_RELIC_APP_NAME')
9
-
10
- Rails.logger.info("Notifying New Relic of deployment to #{appname}")
11
- NewRelic::Cli::Deployments.new(
12
- environment: Rails.env.to_s,
13
- revision: ENV.fetch('SOURCE_VERSION', 'unknown'),
14
- changelog: '',
15
- description: '',
16
- appname: appname,
17
- user: '',
18
- license_key: ENV.fetch('NEW_RELIC_LICENSE_KEY')
19
- ).run
20
- rescue => e
21
- Rails.logger.error("Failed to notify New Relic (#{e.class.name}: #{e.message})")
22
- Rails.logger.info(e.backtrace.take(10).join("\n"))
23
- end
24
- end
25
- end