tpt-rails 1.0.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.
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: []