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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 98d683342ba1f15d5e4aa733de08516198e9190c2642c9c50b37ef6c3d0d8821
4
+ data.tar.gz: c640bd28429845a2ccb0b2ef40594f48543e073f334e2787f6f8e13e5bdd9983
5
+ SHA512:
6
+ metadata.gz: f7601dd782766cab7efbd7e96439c1b668b7b371e77c9a53e0f4d796adb2fb4bc0b63306e0af9b540cefa1c1d17600a2a9979e54697b40f7c2bfa1fcb709b347
7
+ data.tar.gz: beceb38da7ec528021393471200330c2a4c59e8759ec64a9914479dc1027521ca1c23c6582bad5fa2d404241bd6f35749dfb43cab904cc2c698fbb234d6ed65b
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # Tpt::Rails
2
+
3
+ This library helps integrate Rails projects into TpT infrastructure (e.g. Datadog, Bugsnag, etc).
4
+
5
+ ## Usage
6
+
7
+ ### Adding to your app
8
+
9
+ **NOTE: The [TpT Rails Template](https://github.com/TeachersPayTeachers/rails-template) will
10
+ automatically do the following for you.**
11
+
12
+ ```sh
13
+ bundle add tpt-rails --git 'git@github.com:TeachersPayTeachers/tpt-rails'
14
+ rails generate tpt_rails:configure
15
+ ```
16
+
17
+ ### Configuration
18
+
19
+ Running `rails generate tpt_rails:configure` will generate `config/initializers/tpt_rails.rb`. You
20
+ can configure this gem and enable optional features in that file.
21
+
22
+ See the documentation in [lib/tpt/rails.rb](lib/tpt/rails.rb).
23
+
24
+ For Kubernetes configuration:
25
+ ```sh
26
+ rails generate tpt_rails:kubernetes
27
+ ```
28
+
29
+ For CI/CD configuration:
30
+ ```sh
31
+ rails generate tpt_rails:continuous_integration
32
+ ```
33
+
34
+ ### Overview
35
+
36
+ This gem provides the following features:
37
+
38
+ - Datadog
39
+ - Instruments your app for tracing and provides `Tpt::Rails.statsd` for custom metrics
40
+ - Bugsnag/Rollbar
41
+ - Configures your app to report exceptions and provides `Tpt::Rails.report` for handled errors
42
+ - Health check endpoint
43
+ - Adds a health check at `/internal/health-check`, including built-in DB and Redis health checks
44
+ - Error test endpoint
45
+ - Adds an error test at `/internal/error-test` that reports an error and emits a metric
46
+ - Kubernetes/Helm configuration
47
+ - CI/CD configuration
48
+
49
+ See below for more details.
50
+
51
+ ### Datadog
52
+
53
+ If you configure `datadog_trace_url` then your project will be automatically instrumented.
54
+
55
+ If you configure `datadog_statsd_url` then you can also generate custom metrics:
56
+
57
+ ```ruby
58
+ Tpt::Rails.statsd.increment('foo', tags: ['a:b', 'c:d'])
59
+ ```
60
+
61
+ See the documentation in [lib/tpt/rails.rb](lib/tpt/rails.rb).
62
+
63
+ ### Error reporting (e.g. Bugsnag/Rollbar)
64
+
65
+ If you configure `rollbar_access_token` or `bugsnag_api_key` then your project will be automatically
66
+ configured to report unhandled exceptions.
67
+
68
+ To report handled exceptions:
69
+
70
+ ```ruby
71
+ rescue => e
72
+ Tpt::Rails.report(e)
73
+ ```
74
+
75
+ See the documentation in [lib/tpt/rails.rb](lib/tpt/rails.rb).
76
+
77
+ ### Health check endpoint
78
+
79
+ Tpt::Rails provides the following endpoint:
80
+
81
+ /internal/health-check
82
+
83
+ Two checks are added automatically:
84
+ - An ActiveRecord database check is performed if ActiveRecord is used in the app.
85
+ - A Redis check is performed if Redis is used in the app.
86
+
87
+ You may add more health checks as follows:
88
+ ```ruby
89
+ config.health_check(:foo) { 1 == 1 }
90
+ ```
91
+
92
+ See the documentation for `Tpt::Rails::Config#health_check` in
93
+ [lib/tpt/rails/config.rb](lib/tpt/rails/config.rb) for more details.
94
+
95
+ ### Error test endpoint
96
+
97
+ Tpt::Rails provides the following endpoint:
98
+
99
+ /internal/error-test
100
+
101
+ This endpoint reports an error via `Tpt::Rails.report` and emits a metric to Datadog.
102
+
103
+ ## Developing this Gem
104
+
105
+ ### Running tests
106
+
107
+ 1. Start `docker-compose up` (provides a real Redis instance for tests)
108
+ 2. Run `rails test`
109
+
110
+ ### Using your local version of this gem in a local app
111
+
112
+ Change your Gemfile to:
113
+
114
+ ```ruby
115
+ gem 'tpt-rails', path: '/your/local/path/to/tpt/rails'
116
+ ```
117
+
118
+ ### Publishing a new version of this gem
119
+
120
+ First ensure you have permissions to publish to rubygems.org.
121
+
122
+ Then execute:
123
+ ```sh
124
+ bundle exec gem bump --push --tag --version patch # patch/minor/major/X.X.X
125
+ bundle exec gem release
126
+ ```
127
+
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Tpt::Rails'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/tpt/rails .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ module Tpt::Rails
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ require_dependency "tpt/rails/application_controller"
2
+
3
+ class Tpt::Rails::ErrorTestsController < Tpt::Rails::ApplicationController
4
+ def index
5
+ emit_metric
6
+ report_error
7
+ render json: { message: "metric emitted and error reported" }
8
+ end
9
+
10
+ private
11
+
12
+ def emit_metric
13
+ Tpt::Rails.statsd.increment("error_test")
14
+ end
15
+
16
+ def report_error
17
+ raise "just testing"
18
+ rescue => e
19
+ Tpt::Rails.report(e)
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require_dependency "tpt/rails/application_controller"
2
+
3
+ class Tpt::Rails::HealthChecksController < ApplicationController
4
+ def index
5
+ results = Tpt::Rails.config.health_checks.check
6
+
7
+ healthy = results.values.all?
8
+ code = healthy ? 200 : 500
9
+
10
+ render(
11
+ status: code,
12
+ json: {
13
+ healthy: healthy,
14
+ checks: results,
15
+ },
16
+ )
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module Tpt::Rails
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Tpt::Rails
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Tpt::Rails
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Tpt::Rails
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Tpt rails</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "tpt/rails/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ Tpt::Rails::Engine.routes.draw do
2
+ scope 'internal' do
3
+ get 'health-check', to: 'health_checks#index'
4
+ get 'error-test', to: 'error_tests#index'
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ class Tpt::Rails::ConfigurationGenerator < ::Rails::Generators::Base
2
+ source_root File.expand_path('templates', __dir__)
3
+
4
+ desc 'Configure the app to use tpt-rails shared functionality'
5
+
6
+ def configure
7
+ route "mount Tpt::Rails::Engine => '/'"
8
+ template 'config/initializers/tpt_rails.rb'
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ Tpt::Rails.configure do |config|
2
+ config.app_name = ENV.fetch('APP_NAME')
3
+ config.app_env = ENV.fetch('APP_ENV')
4
+ if ENV['DOGSTATSD_URL'].present?
5
+ config.datadog_statsd_url = ENV.fetch('DOGSTATSD_URL')
6
+ end
7
+ if ENV['DATADOG_TRACE_URL'].present?
8
+ config.datadog_trace_url = ENV.fetch('DATADOG_TRACE_URL')
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ class Tpt::Rails::ContinuousIntegrationGenerator < ::Rails::Generators::Base
2
+ source_root File.expand_path('templates', __dir__)
3
+
4
+ def setup_continuous_integration
5
+ # TODO: should we run tpt cli to generate `test.config.xml`?
6
+ # TODO: ask nathan about the test/tptcd/tptci files
7
+ directory('ci')
8
+
9
+ say(<<~MESSAGE)
10
+ …note about running `tpt ci run protect.test.unit` to run tests
11
+
12
+ You need to ask dev tools to create a credential in jenkins. Example ticket:
13
+ https://teacherspayteachers.atlassian.net/browse/DEVT-710
14
+
15
+ MESSAGE
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ FROM teacherspayteachers/tptci as tptci
2
+ FROM ruby:<%= RUBY_VERSION %>
3
+
4
+ RUN mkdir -p /app
5
+ WORKDIR /app
6
+
7
+ RUN curl -sL https://deb.nodesource.com/setup_12.x | bash \
8
+ && apt-get update && apt-get install -y nodejs && rm -rf /var/lib/apt/lists/* \
9
+ && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
10
+ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
11
+ && apt-get update && apt-get install -y yarn && apt-get install -y netcat && rm -rf /var/lib/apt/lists/*
12
+
13
+ COPY package.json yarn.lock /app/
14
+ RUN yarn install --check-files
15
+
16
+ ENV RAILS_ENV test
17
+ ENV APP_ENV test
18
+ ENV APP_NAME <%= Tpt::Rails.app_name %>
19
+
20
+ # GITHUB_TOKEN allows accessing our private tpt-rails gem on Github
21
+ ARG GITHUB_TOKEN
22
+
23
+ COPY Gemfile /app/Gemfile
24
+ COPY Gemfile.lock /app/Gemfile.lock
25
+ # TODO: Do we need this? Can we move it into a base image?
26
+ RUN gem update bundler
27
+ RUN BUNDLE_GITHUB__COM="${GITHUB_TOKEN}:x-oauth-basic" bundle install
28
+
29
+ COPY . .
30
+
31
+ COPY --from=tptci /usr/bin/tptci /usr/bin/tptci
@@ -0,0 +1,26 @@
1
+ version: '3'
2
+ services:
3
+ db:
4
+ image: mysql:5.7
5
+ ports:
6
+ - '3306:3306'
7
+ environment:
8
+ MYSQL_ROOT_PASSWORD: ''
9
+ MYSQL_ALLOW_EMPTY_PASSWORD: '1'
10
+
11
+ tests:
12
+ build:
13
+ context: ../
14
+ dockerfile: ci/Dockerfile
15
+ args:
16
+ GITHUB_TOKEN: ${GITHUB_TOKEN}
17
+ links:
18
+ - db
19
+ depends_on:
20
+ - db
21
+ environment:
22
+ MYSQL_HOSTNAME: db
23
+ MYSQL_PORT: 3306
24
+ RAILS_LOG_TO_STDOUT: '1'
25
+ DATABASE_URL: 'mysql2://root:@db:3306/<%= Tpt::Rails.app_name %>_test'
26
+ DISABLE_SPRING: '1'
@@ -0,0 +1,12 @@
1
+ #!/bin/sh
2
+
3
+ until nc -z -v ${MYSQL_HOSTNAME} ${MYSQL_PORT}
4
+ do
5
+ echo "Waiting for database connection..."
6
+ sleep 5
7
+ done
8
+
9
+ exec bin/rails db:prepare test
10
+
11
+ # Uncomment to run system tests
12
+ # exec bin/rails test:system
@@ -0,0 +1,40 @@
1
+ @Library('tpt-pipeline-library') _
2
+
3
+ def ci = new tpt.CI(this)
4
+ ci.project = '<%= Tpt::Rails.app_name %>'
5
+
6
+ pipeline {
7
+ agent {
8
+ label 'docker-node'
9
+ }
10
+
11
+ environment {
12
+ GITHUB_TOKEN = credentials('24caddab-590e-467f-a1d2-1c0c1864d628')
13
+ }
14
+
15
+ stages {
16
+ stage('Start') {
17
+ steps {
18
+ startBuild(ci)
19
+ }
20
+ }
21
+
22
+ stage('Build') {
23
+ steps {
24
+ dockerComposeBuild(ci)
25
+ }
26
+ }
27
+
28
+ stage('Unit Test') {
29
+ steps {
30
+ dockerComposeRun(ci, "tests", './ci/tasks/project.test.unit')
31
+ }
32
+ }
33
+ }
34
+
35
+ post {
36
+ always {
37
+ finishBuild(ci, currentBuild.currentResult)
38
+ }
39
+ }
40
+ }