tpt-rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +127 -0
  3. data/Rakefile +32 -0
  4. data/app/assets/config/tpt_rails_manifest.js +1 -0
  5. data/app/assets/stylesheets/tpt/rails/application.css +15 -0
  6. data/app/controllers/tpt/rails/application_controller.rb +5 -0
  7. data/app/controllers/tpt/rails/error_tests_controller.rb +21 -0
  8. data/app/controllers/tpt/rails/health_checks_controller.rb +18 -0
  9. data/app/helpers/tpt/rails/application_helper.rb +4 -0
  10. data/app/jobs/tpt/rails/application_job.rb +4 -0
  11. data/app/mailers/tpt/rails/application_mailer.rb +6 -0
  12. data/app/models/tpt/rails/application_record.rb +5 -0
  13. data/app/views/layouts/tpt/rails/application.html.erb +15 -0
  14. data/config/routes.rb +6 -0
  15. data/lib/generators/tpt_rails/configuration/configuration_generator.rb +10 -0
  16. data/lib/generators/tpt_rails/configuration/templates/config/initializers/tpt_rails.rb +10 -0
  17. data/lib/generators/tpt_rails/continuous_integration/continuous_integration_generator.rb +17 -0
  18. data/lib/generators/tpt_rails/continuous_integration/templates/ci/Dockerfile.tt +31 -0
  19. data/lib/generators/tpt_rails/continuous_integration/templates/ci/docker-compose.yaml.tt +26 -0
  20. data/lib/generators/tpt_rails/continuous_integration/templates/ci/tasks/project.test.unit +12 -0
  21. data/lib/generators/tpt_rails/continuous_integration/templates/ci/test.Jenkinsfile.tt +40 -0
  22. data/lib/generators/tpt_rails/continuous_integration/templates/ci/test.config.xml.tt +76 -0
  23. data/lib/generators/tpt_rails/continuous_integration/templates/ci/tptcd.Jenkinsfile.tt +7 -0
  24. data/lib/generators/tpt_rails/continuous_integration/templates/ci/tptci.Jenkinsfile.tt +7 -0
  25. data/lib/generators/tpt_rails/kubernetes/kubernetes_generator.rb +156 -0
  26. data/lib/generators/tpt_rails/kubernetes/templates/Dockerfile.tt +41 -0
  27. data/lib/generators/tpt_rails/kubernetes/templates/entrypoint.sh +13 -0
  28. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/Chart.yaml.tt +16 -0
  29. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/README.md +142 -0
  30. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/requirements.yaml.tt +8 -0
  31. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/NOTES.txt.tt +8 -0
  32. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/_env.yaml +15 -0
  33. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/_helpers.tpl.tt +63 -0
  34. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/autoscaler.yaml.tt +21 -0
  35. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/deployment.yaml.tt +96 -0
  36. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/hooks/db-migrate.yaml.tt +59 -0
  37. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/service.yaml.tt +52 -0
  38. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.prod.yaml.tt +52 -0
  39. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.staging.yaml.tt +52 -0
  40. data/lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.yaml.tt +171 -0
  41. data/lib/generators/tpt_rails/postman/postman.yaml.tt +2 -0
  42. data/lib/tasks/tpt/rails_tasks.rake +23 -0
  43. data/lib/tpt/rails.rb +65 -0
  44. data/lib/tpt/rails/config.rb +77 -0
  45. data/lib/tpt/rails/engine.rb +7 -0
  46. data/lib/tpt/rails/internal.rb +3 -0
  47. data/lib/tpt/rails/internal/datadog.rb +66 -0
  48. data/lib/tpt/rails/internal/error_reporter.rb +68 -0
  49. data/lib/tpt/rails/internal/health_checks.rb +32 -0
  50. data/lib/tpt/rails/version.rb +5 -0
  51. metadata +153 -0
@@ -0,0 +1,2 @@
1
+ - name: contract
2
+ collection: '?????'
@@ -0,0 +1,23 @@
1
+ namespace :tpt_rails do
2
+
3
+ desc "Gets the credentials key from Kubernetes and puts it in config/master.key"
4
+ task get_master_key: :environment do
5
+ command = <<~CMD
6
+ kubectl get secret #{Tpt::Rails.app_name}-secrets --output=json --context=kubernetes-eks-poc \
7
+ | jq --raw-output '.data."rails-master-key" | @base64d'
8
+ CMD
9
+
10
+ puts "Running command:\n#{command}"
11
+ result = `#{command}`
12
+
13
+ if $CHILD_STATUS.success?
14
+ puts 'Success'
15
+ File.open(::Rails.root.join('config/master.key'), 'w') do |file|
16
+ file.print(result.strip)
17
+ end
18
+ else
19
+ raise "Error: #{result}"
20
+ end
21
+ end
22
+
23
+ end
data/lib/tpt/rails.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'tpt/rails/engine'
2
+ require 'tpt/rails/internal'
3
+ require 'tpt/rails/config'
4
+
5
+ module Tpt::Rails
6
+ class NotConfigured < StandardError; end
7
+
8
+ class << self
9
+ # USAGE:
10
+ #
11
+ # In your app in `config/initializers/tpt_rails.rb`:
12
+ #
13
+ # Tpt::Rails.configure do |config|
14
+ # config.app_name = '…'
15
+ # config.app_env = '…'
16
+ # config.rollbar_access_token = '…'
17
+ # config.datadog_statsd_url = '…'
18
+ # config.health_check(:foo) { … }
19
+ # …
20
+ # end
21
+ #
22
+ # See Tpt::Rails::Config in `lib/tpt/rails/config.rb` for a list of all configs.
23
+ def configure
24
+ @config = Tpt::Rails::Config.new
25
+
26
+ yield @config if block_given?
27
+
28
+ @configured = true
29
+ @config.setup
30
+ end
31
+
32
+ # Whether the `Tpt::Rails.configure` block has been run yet by the host application.
33
+ def configured?
34
+ @configured
35
+ end
36
+
37
+ # Returns the app name of the application. E.g. 'earnings'.
38
+ delegate :app_name, to: :config
39
+
40
+ # Returns the app environment of the application. E.g. 'production'/'integration'/'jordan123'.
41
+ delegate :app_env, to: :config
42
+
43
+ # Access to the `Datadog::Statsd` instance for this app.
44
+ #
45
+ # Examples:
46
+ #
47
+ # Tpt::Rails.statsd.increment('foo', tags: ['a:b', 'c:d'])
48
+ # Tpt::Rails.statsd.event('Some title', 'Some text', alert_type: 'warning', tags: ['a:b'])
49
+ #
50
+ delegate :statsd, to: :config
51
+
52
+ # Report an exception via an exception-reporting tool (e.g. Busgnag/Rollbar)
53
+ #
54
+ # Example:
55
+ #
56
+ # rescue => e
57
+ # Tpt::Rails.report(e)
58
+ #
59
+ delegate :report, to: :config
60
+
61
+ def config # :nodoc:
62
+ configured? ? @config : raise(NotConfigured)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,77 @@
1
+ require 'tpt/rails/internal/datadog'
2
+ require 'tpt/rails/internal/error_reporter'
3
+ require 'tpt/rails/internal/health_checks'
4
+
5
+ class Tpt::Rails::Config
6
+ #
7
+ # You can set the following configs in your `Tpt::Rails.configure do |config|` block:
8
+ #
9
+
10
+ # E.g. production/integration/jordan123
11
+ attr_accessor :app_env
12
+ # E.g. earnings/resource-write/tpt-data
13
+ attr_accessor :app_name
14
+ # A project-specific api key from Bugsnag
15
+ attr_accessor :bugsnag_api_key
16
+ # Set this in the form of: statsd://[host]:[port]'
17
+ attr_accessor :datadog_statsd_url
18
+ # Set this in the form of: datadog://[host]:[port]'
19
+ attr_accessor :datadog_trace_url
20
+ # Set this in the form of: redis://:[password]@[hostname]:[port]/[db]
21
+ attr_accessor :redis_url
22
+ # A project-specific access token from rollbar
23
+ attr_accessor :rollbar_access_token
24
+
25
+ # Add a health check to the endpoint provided at `/internal/health-check` by
26
+ # Tpt::Rails::HealthChecksController.
27
+ #
28
+ # The block provided to this method should return a truthy/falsey value for success/failure.
29
+ #
30
+ # Example:
31
+ #
32
+ # config.health_check(:foo) { 'foo' == 'foo' }
33
+ #
34
+ def health_check(name, &block)
35
+ @health_checks.add(name, &block)
36
+ end
37
+
38
+ #
39
+ # Internal code
40
+ #
41
+
42
+ attr_reader :health_checks # :nodoc:
43
+
44
+ def initialize # :nodoc:
45
+ @health_checks = Tpt::Rails::Internal::HealthChecks.new
46
+ end
47
+
48
+ def setup # :nodoc:
49
+ if redis_url
50
+ # Ensure that redis has been added to the app's Gemfile if a `redis_url` has been set
51
+ gem 'redis', '>= 4', '< 5'
52
+ gem 'hiredis'
53
+
54
+ Redis.current = Redis.new(url: redis_url, driver: :hiredis)
55
+ end
56
+
57
+ @datadog = Tpt::Rails::Internal::Datadog.new(
58
+ statsd_url: datadog_statsd_url,
59
+ trace_url: datadog_trace_url,
60
+ )
61
+
62
+ @health_checks.setup
63
+
64
+ @error_reporter = Tpt::Rails::Internal::ErrorReporter.new(
65
+ bugsnag_api_key: bugsnag_api_key.presence,
66
+ rollbar_access_token: rollbar_access_token.presence,
67
+ )
68
+ end
69
+
70
+ def statsd # :nodoc:
71
+ @datadog.statsd
72
+ end
73
+
74
+ def report(error) # :nodoc:
75
+ @error_reporter.report(error)
76
+ end
77
+ end
@@ -0,0 +1,7 @@
1
+ module Tpt::Rails
2
+ # This turns this library into a Rails Engine.
3
+ # See https://guides.rubyonrails.org/engines.html
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Tpt::Rails
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Tpt::Rails::Internal
2
+ # Items in this namespace are only meant for direct access inside of this gem.
3
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Configures Datadog metrics and tracing, based on Tpt::Rails.config
3
+ #
4
+
5
+ require 'datadog/statsd'
6
+ require 'ddtrace'
7
+
8
+ class Tpt::Rails::Internal::Datadog # :nodoc:
9
+ DEFAULT_STATSD_PORT = 8125
10
+ DEFAULT_TRACE_PORT = 8126
11
+
12
+ attr_reader :statsd
13
+
14
+ def initialize(statsd_url: nil, trace_url: nil)
15
+ @statsd_url = statsd_url
16
+ @trace_url = trace_url
17
+
18
+ @statsd = create_statsd
19
+
20
+ if @trace_url
21
+ configure_tracing
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def create_statsd
28
+ # Fall back to a dummy client so callers don't have to worry about null checking the client
29
+ url = @statsd_url || 'statsd://localhost'
30
+ uri = URI.parse(url)
31
+
32
+ ::Datadog::Statsd.new(
33
+ uri.host,
34
+ uri.port || DEFAULT_STATSD_PORT,
35
+ {
36
+ namespace: Tpt::Rails.app_name,
37
+ tags: ["env:#{Tpt::Rails.app_env}"],
38
+ }
39
+ )
40
+ end
41
+
42
+ def configure_tracing
43
+ uri = URI.parse(@trace_url)
44
+
45
+ ::Datadog.configure do |c|
46
+ # This will activate auto-instrumentation for Rails
47
+ c.use :rails, {
48
+ analytics_enabled: true,
49
+ service_name: Tpt::Rails.app_name,
50
+ }
51
+
52
+ c.tracer(
53
+ enabled: true,
54
+ hostname: uri.host,
55
+ port: uri.port || DEFAULT_TRACE_PORT,
56
+ tags: { 'env' => Tpt::Rails.app_env },
57
+ )
58
+ end
59
+
60
+ ::Datadog::Pipeline.before_flush(
61
+ ::Datadog::Pipeline::SpanFilter.new { |span|
62
+ span.resource =~ /TptRails::HealthChecksController/
63
+ },
64
+ )
65
+ end
66
+ end
@@ -0,0 +1,68 @@
1
+ class Tpt::Rails::Internal::ErrorReporter # :nodoc:
2
+ def initialize(bugsnag_api_key: nil, rollbar_access_token: nil)
3
+ @bugsnag_api_key = bugsnag_api_key
4
+ @rollbar_access_token = rollbar_access_token
5
+
6
+ configure_bugsnag if bugsnag?
7
+ configure_rollbar if rollbar?
8
+ end
9
+
10
+ def report(error)
11
+ if bugsnag?
12
+ Bugsnag.notify(error)
13
+ end
14
+
15
+ if rollbar?
16
+ Rollbar.error(error)
17
+ end
18
+
19
+ Tpt::Rails.statsd.increment(
20
+ 'error',
21
+ tags: [
22
+ "error_class:#{error.class.name.underscore}",
23
+ 'type:reported',
24
+ ],
25
+ )
26
+
27
+ ::Rails.logger.info("Error: class=#{error.class} message=#{error.message.inspect}")
28
+
29
+ if !bugsnag? && !rollbar?
30
+ ::Rails.logger.info('Warning: No error reporter configured for Tpt::Rails. Please add one.')
31
+ ::Rails.logger.info(error.backtrace)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def bugsnag?
38
+ @bugsnag_api_key
39
+ end
40
+
41
+ def rollbar?
42
+ @rollbar_access_token
43
+ end
44
+
45
+ def configure_bugsnag
46
+ # Ensure that bugsnag has been added to the app's Gemfile
47
+ gem 'bugsnag', '>= 6.12.2', '< 7'
48
+
49
+ Bugsnag.configure do |config|
50
+ config.api_key = @bugsnag_api_key
51
+ end
52
+ end
53
+
54
+ def configure_rollbar
55
+ # Ensure that rollbar has been added to the app's Gemfile
56
+ gem 'rollbar', '>= 2.23.2', '< 3'
57
+
58
+ Rollbar.configure do |config|
59
+ config.access_token = @rollbar_access_token
60
+
61
+ if ::Rails.env.test? || ::Rails.env.development?
62
+ config.enabled = false
63
+ end
64
+
65
+ config.environment = Tpt::Rails.app_env
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,32 @@
1
+ class Tpt::Rails::Internal::HealthChecks # :nodoc:
2
+ def initialize
3
+ @checks = {}
4
+ end
5
+
6
+ def add(name, &block)
7
+ @checks[name] = block
8
+ end
9
+
10
+ def check
11
+ @checks.transform_values(&:call)
12
+ end
13
+
14
+ def setup
15
+ setup_active_record
16
+ setup_redis
17
+ end
18
+
19
+ private
20
+
21
+ def setup_active_record
22
+ if defined?(ActiveRecord::Base) && ActiveRecord::Base.configurations.any?
23
+ add(:database) { ::ApplicationRecord.connection.select_value('select 1') == 1 }
24
+ end
25
+ end
26
+
27
+ def setup_redis
28
+ if Tpt::Rails.config.redis_url.present?
29
+ add(:redis) { Redis.current.ping == 'PONG' }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ module Tpt
2
+ module Rails
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tpt-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - TpT
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.2
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.0.2.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 6.0.2
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.0.2.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: dogstatsd-ruby
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.5'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '4.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: ddtrace
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.30'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.30'
61
+ - !ruby/object:Gem::Dependency
62
+ name: sqlite3
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.4'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.4'
75
+ description:
76
+ email:
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - README.md
82
+ - Rakefile
83
+ - app/assets/config/tpt_rails_manifest.js
84
+ - app/assets/stylesheets/tpt/rails/application.css
85
+ - app/controllers/tpt/rails/application_controller.rb
86
+ - app/controllers/tpt/rails/error_tests_controller.rb
87
+ - app/controllers/tpt/rails/health_checks_controller.rb
88
+ - app/helpers/tpt/rails/application_helper.rb
89
+ - app/jobs/tpt/rails/application_job.rb
90
+ - app/mailers/tpt/rails/application_mailer.rb
91
+ - app/models/tpt/rails/application_record.rb
92
+ - app/views/layouts/tpt/rails/application.html.erb
93
+ - config/routes.rb
94
+ - lib/generators/tpt_rails/configuration/configuration_generator.rb
95
+ - lib/generators/tpt_rails/configuration/templates/config/initializers/tpt_rails.rb
96
+ - lib/generators/tpt_rails/continuous_integration/continuous_integration_generator.rb
97
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/Dockerfile.tt
98
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/docker-compose.yaml.tt
99
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/tasks/project.test.unit
100
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/test.Jenkinsfile.tt
101
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/test.config.xml.tt
102
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/tptcd.Jenkinsfile.tt
103
+ - lib/generators/tpt_rails/continuous_integration/templates/ci/tptci.Jenkinsfile.tt
104
+ - lib/generators/tpt_rails/kubernetes/kubernetes_generator.rb
105
+ - lib/generators/tpt_rails/kubernetes/templates/Dockerfile.tt
106
+ - lib/generators/tpt_rails/kubernetes/templates/entrypoint.sh
107
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/Chart.yaml.tt
108
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/README.md
109
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/requirements.yaml.tt
110
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/NOTES.txt.tt
111
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/_env.yaml
112
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/_helpers.tpl.tt
113
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/autoscaler.yaml.tt
114
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/deployment.yaml.tt
115
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/hooks/db-migrate.yaml.tt
116
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/templates/service.yaml.tt
117
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.prod.yaml.tt
118
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.staging.yaml.tt
119
+ - lib/generators/tpt_rails/kubernetes/templates/kubernetes/helm/values.yaml.tt
120
+ - lib/generators/tpt_rails/postman/postman.yaml.tt
121
+ - lib/tasks/tpt/rails_tasks.rake
122
+ - lib/tpt/rails.rb
123
+ - lib/tpt/rails/config.rb
124
+ - lib/tpt/rails/engine.rb
125
+ - lib/tpt/rails/internal.rb
126
+ - lib/tpt/rails/internal/datadog.rb
127
+ - lib/tpt/rails/internal/error_reporter.rb
128
+ - lib/tpt/rails/internal/health_checks.rb
129
+ - lib/tpt/rails/version.rb
130
+ homepage: https://github.com/TeachersPayTeachers/tpt-rails
131
+ licenses:
132
+ - None
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubygems_version: 3.0.3
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: Utils for TpT Rails apps
153
+ test_files: []