rails_template_18f 0.1.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -1
- data/README.md +16 -19
- data/exe/rails_template_18f +60 -0
- data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +135 -0
- data/lib/generators/rails_template18f/active_storage/templates/app/jobs/file_scan_job.rb +33 -0
- data/lib/generators/rails_template18f/active_storage/templates/app/models/file_upload.rb +25 -0
- data/lib/generators/rails_template18f/active_storage/templates/doc/adr/clamav.md.tt +30 -0
- data/lib/generators/rails_template18f/active_storage/templates/spec/jobs/file_scan_job_spec.rb +35 -0
- data/lib/generators/rails_template18f/active_storage/templates/spec/models/file_upload_spec.rb +38 -0
- data/lib/generators/rails_template18f/circleci/circleci_generator.rb +26 -10
- data/lib/generators/rails_template18f/cloud_gov_config/cloud_gov_config_generator.rb +28 -0
- data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +15 -0
- data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +44 -0
- data/lib/generators/rails_template18f/dap/dap_generator.rb +72 -0
- data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +27 -11
- data/lib/generators/rails_template18f/i18n/i18n_generator.rb +107 -0
- data/{templates → lib/generators/rails_template18f/i18n/templates}/config/locales/en.yml.tt +3 -3
- data/{templates → lib/generators/rails_template18f/i18n/templates}/config/locales/es.yml +3 -3
- data/{templates → lib/generators/rails_template18f/i18n/templates}/config/locales/fr.yml +3 -6
- data/{templates → lib/generators/rails_template18f/i18n/templates}/config/locales/zh.yml +0 -0
- data/lib/generators/rails_template18f/i18n_js/i18n_js_generator.rb +60 -0
- data/lib/generators/rails_template18f/i18n_js/templates/lib/tasks/i18n.rake +9 -0
- data/lib/generators/rails_template18f/newrelic/newrelic_generator.rb +79 -0
- data/{templates/config/newrelic.yml → lib/generators/rails_template18f/newrelic/templates/config/newrelic.yml.tt} +7 -7
- data/lib/generators/rails_template18f/sidekiq/sidekiq_generator.rb +70 -0
- data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +14 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/README.md.tt +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/bootstrap/import.sh +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/bootstrap/main.tf.tt +3 -3
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/bootstrap/providers.tf +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/bootstrap/run.sh.tt +1 -1
- data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/teardown_creds.sh.tt +5 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/bootstrap/variables.tf +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/create_space_deployer.sh +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/destroy_space_deployer.sh +0 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/production/main.tf.tt +82 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/production/providers.tf.tt +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/production/variables.tf +0 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/shared/clamav/main.tf.tt +50 -0
- data/{templates/terraform/shared/database → lib/generators/rails_template18f/terraform/templates/terraform/shared/clamav}/providers.tf +0 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/shared/clamav/variables.tf +47 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/shared/database/main.tf.tt +0 -0
- data/{templates/terraform/shared/domain → lib/generators/rails_template18f/terraform/templates/terraform/shared/database}/providers.tf +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/shared/database/variables.tf +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/shared/domain/main.tf.tt +1 -1
- data/{templates/terraform/shared/s3 → lib/generators/rails_template18f/terraform/templates/terraform/shared/domain}/providers.tf +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/shared/domain/variables.tf +0 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/shared/redis/main.tf.tt +23 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/shared/redis/providers.tf +16 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/shared/redis/variables.tf +42 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/shared/s3/main.tf +0 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/shared/s3/providers.tf +16 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/shared/s3/variables.tf +0 -0
- data/lib/generators/rails_template18f/terraform/templates/terraform/staging/main.tf.tt +62 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/staging/providers.tf.tt +0 -0
- data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/staging/variables.tf +0 -0
- data/lib/generators/rails_template18f/terraform/terraform_generator.rb +84 -0
- data/lib/rails_template18f/app_updater.rb +19 -0
- data/lib/rails_template18f/generators/base.rb +53 -0
- data/lib/rails_template18f/generators/cloud_gov_options.rb +53 -0
- data/lib/rails_template18f/generators/pipeline_options.rb +18 -0
- data/lib/rails_template18f/generators.rb +11 -0
- data/lib/rails_template18f/version.rb +1 -1
- data/lib/rails_template_18f.rb +1 -4
- data/rails-template-18f.gemspec +1 -0
- data/template.rb +84 -148
- data/templates/README.md.tt +7 -44
- data/templates/config/deployment/staging.yml +1 -1
- data/templates/config/environments/ci.rb +0 -1
- data/templates/doc/compliance/apps/application.boundary.md.tt +4 -31
- data/templates/githooks/{pre-commit.tt → pre-commit} +0 -15
- data/templates/manifest.yml.tt +1 -2
- metadata +77 -34
- data/lib/rails_template18f/terraform_options.rb +0 -68
- data/templates/terraform/bootstrap/teardown_creds.sh.tt +0 -5
- data/templates/terraform/production/main.tf.tt +0 -50
- data/templates/terraform/staging/main.tf.tt +0 -30
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails_helper"
|
4
|
+
|
5
|
+
RSpec.describe CloudGovConfig, type: :model do
|
6
|
+
subject { described_class }
|
7
|
+
|
8
|
+
describe ".dig" do
|
9
|
+
context "VCAP_SERVICES is blank" do
|
10
|
+
it "returns nil" do
|
11
|
+
expect(subject.dig(:s3, :credentials, :bucket)).to be_nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "VCAP_SERVICES is set" do
|
16
|
+
let(:bucket_name) { "bucket-name" }
|
17
|
+
let(:vcap) {
|
18
|
+
{
|
19
|
+
s3: [
|
20
|
+
{
|
21
|
+
credentials: {
|
22
|
+
bucket: bucket_name
|
23
|
+
}
|
24
|
+
}
|
25
|
+
]
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
around do |example|
|
30
|
+
ClimateControl.modify VCAP_SERVICES: vcap.to_json do
|
31
|
+
example.run
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can find a path" do
|
36
|
+
expect(subject.dig(:s3, :credentials, :bucket)).to eq bucket_name
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns nil for a missing path" do
|
40
|
+
expect(subject.dig(:s3, :credentials, :other)).to be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module RailsTemplate18f
|
6
|
+
module Generators
|
7
|
+
class DapGenerator < ::Rails::Generators::Base
|
8
|
+
include Base
|
9
|
+
|
10
|
+
class_option :agency_code, default: "GSA", desc: "Agency code to track DAP metrics"
|
11
|
+
|
12
|
+
desc <<~DESC
|
13
|
+
Description:
|
14
|
+
Install JS snippet for Digital Analytics Program (DAP)
|
15
|
+
DESC
|
16
|
+
|
17
|
+
def update_content_security_policy
|
18
|
+
csp_file = "config/initializers/content_security_policy.rb"
|
19
|
+
gsub_file csp_file, /(policy.img_src .*)$/, '\1, "https://www.google-analytics.com"'
|
20
|
+
gsub_file csp_file, /(policy.script_src .*)$/, '\1, "https://dap.digitalgov.gov", "https://www.google-analytics.com"'
|
21
|
+
if file_content(csp_file).match?(/policy.connect_src/)
|
22
|
+
gsub_file csp_file, /(policy.connect_src .*)$/, '\1, "https://dap.digitalgov.gov", "https://www.google-analytics.com"'
|
23
|
+
else
|
24
|
+
gsub_file csp_file, /((#?)(\s+)policy.script_src .*)$/, "\\1\n\\2\\3policy.connect_src :self, \"https://dap.digitalgov.gov\", \"https://www.google-analytics.com\""
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def install_js_snippet
|
29
|
+
insert_into_file "app/views/layouts/application.html.erb", <<EODAP, before: /^\s+<\/head>/
|
30
|
+
|
31
|
+
<% if Rails.env.production? %>
|
32
|
+
<!-- We participate in the US government's analytics program. See the data at analytics.usa.gov. -->
|
33
|
+
<%= javascript_include_tag "https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js?agency=#{options[:agency_code]}", async: true, id:"_fed_an_ua_tag" %>
|
34
|
+
<% end %>
|
35
|
+
EODAP
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_readme
|
39
|
+
insertion_regex = /^## Documentation$/
|
40
|
+
if file_content("README.md").match?(insertion_regex)
|
41
|
+
insert_into_file "README.md", readme, before: insertion_regex
|
42
|
+
else
|
43
|
+
append_to_file "README.md", readme
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def update_boundary_diagram
|
48
|
+
boundary_filename = "doc/compliance/apps/application.boundary.md"
|
49
|
+
insert_into_file boundary_filename, <<EOB, after: "Boundary(gsa_saas, \"GSA-authorized SaaS\") {\n"
|
50
|
+
System_Ext(dap, "DAP", "Analytics collection")
|
51
|
+
EOB
|
52
|
+
insert_into_file boundary_filename, <<~EOB, before: "@enduml"
|
53
|
+
Rel(browser, dap, "reports usage", "https (443)")
|
54
|
+
Rel(developer, dap, "View traffic statistics", "https GET (443)")
|
55
|
+
EOB
|
56
|
+
end
|
57
|
+
|
58
|
+
no_tasks do
|
59
|
+
def readme
|
60
|
+
<<~EOM
|
61
|
+
## Analytics
|
62
|
+
|
63
|
+
Digital Analytics Program (DAP) code has been included for the Production environment, associated with #{options[:agency_code]}.
|
64
|
+
|
65
|
+
If #{app_name.titleize} is for another agency, update the agency line in `app/views/layouts/application.html.erb`
|
66
|
+
|
67
|
+
EOM
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rails/generators"
|
4
|
+
|
3
5
|
module RailsTemplate18f
|
4
6
|
module Generators
|
5
7
|
class GithubActionsGenerator < ::Rails::Generators::Base
|
6
|
-
include
|
7
|
-
include
|
8
|
+
include Base
|
9
|
+
include PipelineOptions
|
8
10
|
|
9
11
|
class_option :node_version, desc: "Node version to test against in actions"
|
10
12
|
|
@@ -13,10 +15,6 @@ module RailsTemplate18f
|
|
13
15
|
Install Github Actions workflow files
|
14
16
|
DESC
|
15
17
|
|
16
|
-
def self.source_root
|
17
|
-
@source_root ||= File.expand_path("templates", __dir__)
|
18
|
-
end
|
19
|
-
|
20
18
|
def install_actions
|
21
19
|
directory "github", ".github"
|
22
20
|
if !terraform?
|
@@ -26,10 +24,28 @@ module RailsTemplate18f
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def update_readme
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
if file_content("README.md").match?(/^## CI\/CD$/)
|
28
|
+
insert_into_file "README.md", readme_cicd, after: "## CI/CD\n"
|
29
|
+
insert_into_file "README.md", readme_staging_deploy, after: "#### Staging\n"
|
30
|
+
insert_into_file "README.md", readme_prod_deploy, after: "#### Production\n"
|
31
|
+
insert_into_file "README.md", readme_credentials, after: "#### Credentials and other Secrets\n"
|
32
|
+
else
|
33
|
+
append_to_file "README.md", <<~EOM
|
34
|
+
## CI/CD
|
35
|
+
#{readme_cicd}
|
36
|
+
|
37
|
+
### Deployment
|
38
|
+
|
39
|
+
#### Staging
|
40
|
+
#{readme_staging_deploy}
|
41
|
+
|
42
|
+
#### Production
|
43
|
+
#{readme_prod_deploy}
|
44
|
+
|
45
|
+
#### Credentials and other Secrets
|
46
|
+
#{readme_credentials}
|
47
|
+
EOM
|
48
|
+
end
|
33
49
|
end
|
34
50
|
|
35
51
|
def update_boundary_diagram
|
@@ -48,7 +64,7 @@ EOB
|
|
48
64
|
readme_filename = "terraform/README.md"
|
49
65
|
insert_into_file readme_filename, " |- .force-action-apply\n", after: " |- secrets.auto.tfvars\n"
|
50
66
|
insert_into_file readme_filename, <<~EOM, after: /- `secrets.auto.tfvars`.*$/
|
51
|
-
- `.force-action-apply` is a file that can be updated to force GitHub Actions to run `terraform apply` during the deploy phase
|
67
|
+
\n- `.force-action-apply` is a file that can be updated to force GitHub Actions to run `terraform apply` during the deploy phase
|
52
68
|
EOM
|
53
69
|
end
|
54
70
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
require "bundler"
|
5
|
+
|
6
|
+
module RailsTemplate18f
|
7
|
+
module Generators
|
8
|
+
class I18nGenerator < ::Rails::Generators::Base
|
9
|
+
include Base
|
10
|
+
|
11
|
+
class_option :languages, default: "es,fr,zh", desc: "Comma separated list of supported language short codes"
|
12
|
+
|
13
|
+
desc <<~DESC
|
14
|
+
Description:
|
15
|
+
Install translation framework and configuration for given languages.
|
16
|
+
Always installs configuration for English
|
17
|
+
DESC
|
18
|
+
|
19
|
+
def install_helper_gem_and_tasks
|
20
|
+
return if file_content("Gemfile").match?(/gem "i18n-tasks"/)
|
21
|
+
gem_group :development, :test do
|
22
|
+
gem "i18n-tasks", "~> 0.9"
|
23
|
+
end
|
24
|
+
Bundler.with_original_env do
|
25
|
+
in_root do
|
26
|
+
run "bundle install"
|
27
|
+
run "cp $(i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/"
|
28
|
+
run "cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
insert_into_file "config/i18n-tasks.yml", "\n#{indent("- app/assets/builds", 4)}", after: "exclude:"
|
32
|
+
uncomment_lines "config/i18n-tasks.yml", "ignore_missing:"
|
33
|
+
insert_into_file "config/i18n-tasks.yml", indent(<<~EOM), after: "ignore_missing:\n"
|
34
|
+
- 'shared.languages.*'
|
35
|
+
- 'shared.header.{title,close,demo_banner,menu}'
|
36
|
+
EOM
|
37
|
+
end
|
38
|
+
|
39
|
+
def install_translations
|
40
|
+
inside "config/locales" do
|
41
|
+
template "en.yml"
|
42
|
+
languages.each do |lang|
|
43
|
+
copy_file "#{lang}.yml"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def configure_i18n
|
49
|
+
application "config.i18n.fallbacks = [:en]"
|
50
|
+
available_regex = /^(\s*config.i18n.available_locales).*$/
|
51
|
+
if file_content("config/application.rb").match?(available_regex)
|
52
|
+
gsub_file "config/application.rb", available_regex, "\\1 = #{supported_languages}"
|
53
|
+
else
|
54
|
+
application "config.i18n.available_locales = #{supported_languages}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def install_nav_helper
|
59
|
+
inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", indent(<<~'EOH')
|
60
|
+
def format_active_locale(locale_string)
|
61
|
+
link_classes = "usa-nav__link"
|
62
|
+
if locale_string.to_sym == I18n.locale
|
63
|
+
link_classes = "#{link_classes} usa-current"
|
64
|
+
end
|
65
|
+
link_to t("shared.languages.#{locale_string}"), root_path(locale: locale_string), class: link_classes
|
66
|
+
end
|
67
|
+
EOH
|
68
|
+
end
|
69
|
+
|
70
|
+
def install_around_action
|
71
|
+
return if languages.empty?
|
72
|
+
inject_into_class "app/controllers/application_controller.rb", "ApplicationController", indent(<<~EOM)
|
73
|
+
around_action :switch_locale
|
74
|
+
|
75
|
+
def switch_locale(&action)
|
76
|
+
locale = params[:locale] || I18n.default_locale
|
77
|
+
I18n.with_locale(locale, &action)
|
78
|
+
end
|
79
|
+
EOM
|
80
|
+
end
|
81
|
+
|
82
|
+
def install_route
|
83
|
+
return if languages.empty?
|
84
|
+
return if file_content("config/routes.rb").match?(/scope "\(:locale\)"/)
|
85
|
+
regex = /(^.+\.routes\.draw do\s*$)\n(.*)^end$/m
|
86
|
+
gsub_file "config/routes.rb", regex, <<~'EOR'
|
87
|
+
\1
|
88
|
+
scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
|
89
|
+
# Your application routes go here
|
90
|
+
\2
|
91
|
+
end
|
92
|
+
end
|
93
|
+
EOR
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def supported_languages
|
99
|
+
@supported_languages ||= [:en, *languages]
|
100
|
+
end
|
101
|
+
|
102
|
+
def languages
|
103
|
+
@languages ||= options[:languages].split(",").map(&:to_sym)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -12,11 +12,11 @@ en:
|
|
12
12
|
secure_heading: Secure .gov websites use HTTPS
|
13
13
|
us_flag: U.S. Flag
|
14
14
|
header:
|
15
|
-
title: <%= app_name.titleize %>
|
16
|
-
menu: Menu
|
17
15
|
close: Close
|
18
|
-
primary: Primary navigation
|
19
16
|
demo_banner: TEST SITE - Do not use real personal information (demo purposes only) - TEST SITE
|
17
|
+
menu: Menu
|
18
|
+
primary: Primary navigation
|
19
|
+
title: <%= app_name.titleize %>
|
20
20
|
languages:
|
21
21
|
en: English
|
22
22
|
es: Español
|
@@ -12,8 +12,8 @@ es:
|
|
12
12
|
secure_heading: Los sitios web seguros .gov usan HTTPS
|
13
13
|
us_flag: Bandera de Estados Unidos
|
14
14
|
header:
|
15
|
-
menu: Menú
|
16
15
|
close: Cerrar
|
17
|
-
primary: Navegacion primaria
|
18
16
|
demo_banner: SITIO DE PRUEBA - No utilice información personal real (sólo para propósitos de demostración) - SITIO DE PRUEBA
|
19
|
-
|
17
|
+
menu: Menú
|
18
|
+
primary: Navegacion primaria
|
19
|
+
skip_link: Salte al contenido principal
|
@@ -8,15 +8,12 @@ fr:
|
|
8
8
|
lock: Verrou
|
9
9
|
locked_padlock: Verrou fermé
|
10
10
|
official_site: Un site web officiel du gouvernement des États-Unis
|
11
|
-
secure_description_html: Un <strong>verrou</strong> (%{lock_icon}) ou
|
12
|
-
<strong>https://</strong> signifie que vous êtes connecté en toute
|
13
|
-
sécurité au site Web .gov. Partagez des informations sensibles
|
14
|
-
uniquement sur des sites Web officiels et sécurisés.
|
11
|
+
secure_description_html: Un <strong>verrou</strong> (%{lock_icon}) ou <strong>https://</strong> signifie que vous êtes connecté en toute sécurité au site Web .gov. Partagez des informations sensibles uniquement sur des sites Web officiels et sécurisés.
|
15
12
|
secure_heading: Les sites Web sécurisés .gov utilisent HTTPS
|
16
13
|
us_flag: Drapeau américain
|
17
14
|
header:
|
18
|
-
menu: Menu
|
19
15
|
close: Fermer
|
20
|
-
primary: Navigation primaire
|
21
16
|
demo_banner: SITE DE TEST - N’utilisez pas de véritables données personnelles (il s’agit d’une démonstration seulement) - SITE DE TEST
|
17
|
+
menu: Menu
|
18
|
+
primary: Navigation primaire
|
22
19
|
skip_link: Passer au contenu principal
|
File without changes
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
require "bundler"
|
5
|
+
|
6
|
+
module RailsTemplate18f
|
7
|
+
module Generators
|
8
|
+
class I18nJsGenerator < ::Rails::Generators::Base
|
9
|
+
include Base
|
10
|
+
|
11
|
+
desc <<~DESC
|
12
|
+
Description:
|
13
|
+
Install and configure i18n-js gem to provide translations to JS code.
|
14
|
+
|
15
|
+
By default, will only export translations with keys that match `*.js.*`
|
16
|
+
DESC
|
17
|
+
|
18
|
+
def install_gem_and_tasks
|
19
|
+
return if file_content("Gemfile").match?(/gem "i18n-js"/)
|
20
|
+
gem "i18n-js", "~> 3.9"
|
21
|
+
Bundler.with_original_env do
|
22
|
+
in_root do
|
23
|
+
run "bundle install"
|
24
|
+
run "yarn add i18n-js"
|
25
|
+
generate "i18n:js:config"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
append_to_file "config/i18n-js.yml", <<~EOYAML
|
29
|
+
# remove `only` to include all translations
|
30
|
+
translations:
|
31
|
+
- file: "app/assets/builds/translations.js"
|
32
|
+
only: "*.js.*"
|
33
|
+
EOYAML
|
34
|
+
end
|
35
|
+
|
36
|
+
def configure_asset_pipeline
|
37
|
+
copy_file "lib/tasks/i18n.rake"
|
38
|
+
environment "config.middleware.use I18n::JS::Middleware", env: :development
|
39
|
+
insert_into_file "app/views/layouts/application.html.erb", indent(<<~EOHTML, 4), after: /<%= stylesheet_link_tag "application".*$\n/
|
40
|
+
<%= javascript_include_tag "i18n", "data-turbo-track": "reload" %>
|
41
|
+
<%= javascript_include_tag "translations", "data-turbo-track": "reload" %>
|
42
|
+
EOHTML
|
43
|
+
append_to_file "app/assets/config/manifest.js", <<~EOJS
|
44
|
+
//= link i18n.js
|
45
|
+
//= link translations.js
|
46
|
+
EOJS
|
47
|
+
end
|
48
|
+
|
49
|
+
def ignore_generated_file
|
50
|
+
unless skip_git?
|
51
|
+
append_to_file ".gitignore", <<~EOM
|
52
|
+
|
53
|
+
# Generated by i18n-js
|
54
|
+
/public/javascripts/i18n.js
|
55
|
+
EOM
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# export translations as part of asset precompile
|
2
|
+
|
3
|
+
Rake::Task["assets:precompile"].enhance(["i18n:js:export"])
|
4
|
+
|
5
|
+
if Rake::Task.task_defined?("test:prepare")
|
6
|
+
Rake::Task["test:prepare"].enhance(["i18n:js:export"])
|
7
|
+
elsif Rake::Task.task_defined?("db:test:prepare")
|
8
|
+
Rake::Task["db:test:prepare"].enhance(["i18n:js:export"])
|
9
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module RailsTemplate18f
|
6
|
+
module Generators
|
7
|
+
class NewrelicGenerator < ::Rails::Generators::Base
|
8
|
+
include Base
|
9
|
+
|
10
|
+
desc <<~DESC
|
11
|
+
Description:
|
12
|
+
Install NewRelic config for FedRAMP collection
|
13
|
+
DESC
|
14
|
+
|
15
|
+
def update_content_security_policy
|
16
|
+
csp_file = "config/initializers/content_security_policy.rb"
|
17
|
+
gsub_file csp_file, /(policy.script_src .*)$/, '\1, "https://js-agent.newrelic.com", "https://*.nr-data.net"'
|
18
|
+
if file_content(csp_file).match?(/policy.connect_src/)
|
19
|
+
gsub_file csp_file, /(policy.connect_src .*)$/, '\1, "https://*.nr-data.net"'
|
20
|
+
else
|
21
|
+
gsub_file csp_file, /((#?)(\s+)policy.script_src .*)$/, "\\1\n\\2\\3policy.connect_src :self, \"https://*.nr-data.net\""
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def install_gem
|
26
|
+
gem "newrelic_rpm", "~> 8.4"
|
27
|
+
end
|
28
|
+
|
29
|
+
def install_config
|
30
|
+
template "config/newrelic.yml"
|
31
|
+
end
|
32
|
+
|
33
|
+
def update_cloud_gov_manifest
|
34
|
+
insert_into_file "manifest.yml", " NEW_RELIC_LOG: stdout\n", before: /^\s+processes:/
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_readme
|
38
|
+
insertion_regex = /^## Documentation$/
|
39
|
+
if file_content("README.md").match?(insertion_regex)
|
40
|
+
insert_into_file "README.md", readme, before: insertion_regex
|
41
|
+
else
|
42
|
+
append_to_file "README.md", readme
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_boundary_diagram
|
47
|
+
boundary_filename = "doc/compliance/apps/application.boundary.md"
|
48
|
+
insert_into_file boundary_filename, <<EOB, after: "Boundary(gsa_saas, \"GSA-authorized SaaS\") {\n"
|
49
|
+
System_Ext(newrelic, "New Relic", "Monitoring SaaS")
|
50
|
+
EOB
|
51
|
+
insert_into_file boundary_filename, <<~EOB, before: "@enduml"
|
52
|
+
Rel(app, newrelic, "reports telemetry (ruby agent)", "tcp (443)")
|
53
|
+
Rel(browser, newrelic, "reports ux metrics (javascript agent)", "https (443)")
|
54
|
+
Rel(developer, newrelic, "Manage performance", "https (443)")
|
55
|
+
EOB
|
56
|
+
end
|
57
|
+
|
58
|
+
no_tasks do
|
59
|
+
def readme
|
60
|
+
<<~EOM
|
61
|
+
## Monitoring with New Relic
|
62
|
+
|
63
|
+
The [New Relic Ruby agent](https://docs.newrelic.com/docs/apm/agents/ruby-agent/getting-started/introduction-new-relic-ruby) has been installed for monitoring this application.
|
64
|
+
|
65
|
+
The config lives at `config/newrelic.yml`, and points to a [FEDRAMP version of the New Relic service as its host](https://docs.newrelic.com/docs/security/security-privacy/compliance/fedramp-compliant-endpoints/). To access the metrics dashboard, you will need to be connected to VPN.
|
66
|
+
|
67
|
+
### Getting started
|
68
|
+
|
69
|
+
To get started sending metrics via New Relic APM:
|
70
|
+
1. Add your New Relic license key to the Rails credentials with key `new_relic_key`.
|
71
|
+
1. Optionally, update `app_name` entries in `config/newrelic.yml` with what is registered for your application in New Relic
|
72
|
+
1. Comment out the `agent_enabled: false` line in `config/newrelic.yml`
|
73
|
+
1. Add the [Javascript snippet provided by New Relic](https://docs.newrelic.com/docs/browser/browser-monitoring/installation/install-browser-monitoring-agent) into `application.html.erb`. It is recommended to vary this based on environment (i.e. include one snippet for staging and another for production).
|
74
|
+
EOM
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -10,14 +10,14 @@
|
|
10
10
|
|
11
11
|
common: &default_settings
|
12
12
|
# Required license key associated with your New Relic account.
|
13
|
-
license_key:
|
13
|
+
license_key: <%%= Rails.application.credentials.new_relic_key %>
|
14
14
|
# FEDRAMP-specific New Relic host
|
15
15
|
# https://docs.newrelic.com/docs/security/security-privacy/compliance/fedramp-compliant-endpoints/
|
16
16
|
host: 'gov-collector.newrelic.com'
|
17
17
|
|
18
18
|
# Your application name. Renaming here affects where data displays in New
|
19
19
|
# Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications
|
20
|
-
app_name:
|
20
|
+
app_name: <%= app_name.titleize %>
|
21
21
|
|
22
22
|
monitor_mode: true
|
23
23
|
|
@@ -30,8 +30,8 @@ common: &default_settings
|
|
30
30
|
|
31
31
|
# This line disables agent regardless of other settings.
|
32
32
|
# To enable the New Relic agent:
|
33
|
-
# 1)
|
34
|
-
# 2)
|
33
|
+
# 1) add the New Relic license keys to the appropriate encrypted credentials file(s)
|
34
|
+
# 2) Optionally, update app_name entries in this file with the application name you want to show in New Relic
|
35
35
|
# 3) Comment out the line below
|
36
36
|
agent_enabled: false
|
37
37
|
|
@@ -44,7 +44,7 @@ common: &default_settings
|
|
44
44
|
# If your application has other named environments, configure them here.
|
45
45
|
development:
|
46
46
|
<<: *default_settings
|
47
|
-
app_name:
|
47
|
+
app_name: <%= app_name.titleize %> (Development)
|
48
48
|
|
49
49
|
test:
|
50
50
|
<<: *default_settings
|
@@ -58,8 +58,8 @@ ci:
|
|
58
58
|
|
59
59
|
staging:
|
60
60
|
<<: *default_settings
|
61
|
-
app_name:
|
61
|
+
app_name: <%= app_name.titleize %> (Staging)
|
62
62
|
|
63
63
|
production:
|
64
64
|
<<: *default_settings
|
65
|
-
app_name:
|
65
|
+
app_name: <%= app_name.titleize %> (Production)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module RailsTemplate18f
|
6
|
+
module Generators
|
7
|
+
class SidekiqGenerator < ::Rails::Generators::Base
|
8
|
+
include Base
|
9
|
+
|
10
|
+
desc <<~DESC
|
11
|
+
Description:
|
12
|
+
Install Sidekiq and configure it as the ActiveJob backend
|
13
|
+
DESC
|
14
|
+
|
15
|
+
def install_gem
|
16
|
+
gem "sidekiq", "~> 6.4"
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure_server_runner
|
20
|
+
append_to_file "Procfile.dev", "worker: bundle exec sidekiq\n"
|
21
|
+
insert_into_file "manifest.yml", indent(<<~EOYAML), after: /processes:$\n/
|
22
|
+
- type: worker
|
23
|
+
instances: ((worker_instances))
|
24
|
+
memory: ((worker_memory))
|
25
|
+
command: bundle exec sidekiq
|
26
|
+
EOYAML
|
27
|
+
insert_into_file "manifest.yml", "\n - #{app_name}-redis-((env))", after: "services:"
|
28
|
+
inside "config/deployment" do
|
29
|
+
append_to_file "staging.yml", <<~EOYAML
|
30
|
+
worker_instances: 1
|
31
|
+
worker_memory: 256M
|
32
|
+
EOYAML
|
33
|
+
append_to_file "production.yml", <<~EOYAML
|
34
|
+
worker_instances: 1
|
35
|
+
worker_memory: 512M
|
36
|
+
EOYAML
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def configure_active_job
|
41
|
+
generate "rails_template18f:cloud_gov_config"
|
42
|
+
copy_file "config/initializers/redis.rb"
|
43
|
+
application "config.active_job.queue_adapter = :sidekiq"
|
44
|
+
end
|
45
|
+
|
46
|
+
def configure_sidekiq_ui
|
47
|
+
prepend_to_file "config/routes.rb", "require \"sidekiq/web\"\n\n"
|
48
|
+
route <<~EOR
|
49
|
+
if Rails.env.development?
|
50
|
+
mount Sidekiq::Web => "/sidekiq"
|
51
|
+
end
|
52
|
+
EOR
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_boundary_diagram
|
56
|
+
boundary_filename = "doc/compliance/apps/application.boundary.md"
|
57
|
+
|
58
|
+
insert_into_file boundary_filename, indent(<<~EOB, 16), after: /ContainerDb\(app_db.*$\n/
|
59
|
+
Container(worker, "<&layers> Sidekiq workers", "Ruby #{ruby_version}, Sidekiq", "Perform background work and data processing")
|
60
|
+
ContainerDb(redis, "Redis Database", "AWS ElastiCache (Redis)", "Background job queue")
|
61
|
+
EOB
|
62
|
+
insert_into_file boundary_filename, <<~EOB, before: "@enduml"
|
63
|
+
Rel(app, redis, "enqueue job parameters", "redis")
|
64
|
+
Rel(worker, redis, "dequeues job parameters", "redis")
|
65
|
+
Rel(worker, app_db, "reads/writes primary data", "psql (5432)")
|
66
|
+
EOB
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Rails.application.config.to_prepare do
|
4
|
+
redis_url = CloudGovConfig.dig "aws-elasticache-redis", "credentials", "uri"
|
5
|
+
if redis_url.present?
|
6
|
+
Sidekiq.configure_server do |config|
|
7
|
+
config.redis = {url: redis_url, ssl: true}
|
8
|
+
end
|
9
|
+
|
10
|
+
Sidekiq.configure_client do |config|
|
11
|
+
config.redis = {url: redis_url, ssl: true}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/{templates → lib/generators/rails_template18f/terraform/templates}/terraform/README.md.tt
RENAMED
File without changes
|
File without changes
|
@@ -9,9 +9,9 @@ module "s3" {
|
|
9
9
|
cf_api_url = local.cf_api_url
|
10
10
|
cf_user = var.cf_user
|
11
11
|
cf_password = var.cf_password
|
12
|
-
cf_org_name = "<%=
|
13
|
-
cf_space_name = "<%=
|
14
|
-
s3_service_name = local.s3_service_name<% if
|
12
|
+
cf_org_name = "<%= cloud_gov_organization %>"
|
13
|
+
cf_space_name = "<%= cloud_gov_production_space %>"
|
14
|
+
s3_service_name = local.s3_service_name<% if cloud_gov_organization == "sandbox-gsa" %>
|
15
15
|
s3_plan_name = "basic-sandbox"<% end %>
|
16
16
|
}
|
17
17
|
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
|
3
3
|
if [[ ! -f "secrets.auto.tfvars" ]]; then
|
4
|
-
../create_space_deployer.sh <%=
|
4
|
+
../create_space_deployer.sh <%= cloud_gov_production_space %> config-bootstrap-deployer > secrets.auto.tfvars
|
5
5
|
fi
|
6
6
|
|
7
7
|
if [[ $# -gt 0 ]]; then
|
File without changes
|