rails_template_18f 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.standard.yml +2 -0
  4. data/CHANGELOG.md +6 -0
  5. data/CODE_OF_CONDUCT.md +84 -0
  6. data/Gemfile +10 -0
  7. data/Gemfile.lock +132 -0
  8. data/LICENSE.md +21 -0
  9. data/README.md +140 -0
  10. data/Rakefile +10 -0
  11. data/bin/console +16 -0
  12. data/bin/setup +8 -0
  13. data/lib/generators/rails_template18f/circleci/circleci_generator.rb +116 -0
  14. data/lib/generators/rails_template18f/circleci/templates/Dockerfile.tt +13 -0
  15. data/lib/generators/rails_template18f/circleci/templates/bin/ci-server-start +8 -0
  16. data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +413 -0
  17. data/lib/generators/rails_template18f/circleci/templates/docker-compose.ci.yml +26 -0
  18. data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +137 -0
  19. data/lib/generators/rails_template18f/github_actions/templates/github/actions/run-server/action.yml +28 -0
  20. data/lib/generators/rails_template18f/github_actions/templates/github/actions/setup-languages/action.yml.tt +20 -0
  21. data/lib/generators/rails_template18f/github_actions/templates/github/actions/setup-project/action.yml.tt +33 -0
  22. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/brakeman-analysis.yml +44 -0
  23. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/dependency-scans.yml +39 -0
  24. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml.tt +53 -0
  25. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml.tt +53 -0
  26. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-daily-scan.yml.tt +44 -0
  27. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-scan.yml.tt +47 -0
  28. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/pa11y.yml.tt +65 -0
  29. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/rspec.yml.tt +34 -0
  30. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +79 -0
  31. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +79 -0
  32. data/lib/rails_template18f/terraform_options.rb +68 -0
  33. data/lib/rails_template18f/version.rb +5 -0
  34. data/lib/rails_template_18f.rb +13 -0
  35. data/rails-template-18f.gemspec +40 -0
  36. data/railsrc +10 -0
  37. data/railsrc-hotwire +8 -0
  38. data/template.rb +506 -0
  39. data/templates/README.md.tt +213 -0
  40. data/templates/app/assets/images/uswds.js +5 -0
  41. data/templates/app/assets/stylesheets/uswds-settings.scss +7 -0
  42. data/templates/app/views/application/_banner_lock_icon.html.erb +19 -0
  43. data/templates/app/views/application/_demo_site_banner.html.erb +3 -0
  44. data/templates/app/views/application/_header.html.erb +26 -0
  45. data/templates/app/views/application/_usa_banner.html.erb +51 -0
  46. data/templates/bin/owasp-scan +49 -0
  47. data/templates/bin/pa11y-scan +10 -0
  48. data/templates/bin/with-server +35 -0
  49. data/templates/browserslistrc +5 -0
  50. data/templates/config/deployment/production.yml +3 -0
  51. data/templates/config/deployment/staging.yml +3 -0
  52. data/templates/config/environments/ci.rb +10 -0
  53. data/templates/config/environments/staging.rb +6 -0
  54. data/templates/config/locales/en.yml.tt +25 -0
  55. data/templates/config/locales/es.yml +19 -0
  56. data/templates/config/locales/fr.yml +22 -0
  57. data/templates/config/locales/zh.yml +16 -0
  58. data/templates/config/newrelic.yml +65 -0
  59. data/templates/doc/adr/0001-record-architecture-decisions.md.tt +21 -0
  60. data/templates/doc/adr/0002-initial-architecture-decisions.md.tt +24 -0
  61. data/templates/doc/adr/0003-security-scans.md.tt +44 -0
  62. data/templates/doc/adr/0004-rails-csp-compliant-script-tag-helpers.md.tt +53 -0
  63. data/templates/doc/compliance/README.md +37 -0
  64. data/templates/doc/compliance/apps/application.boundary.md.tt +80 -0
  65. data/templates/doc/compliance/apps/data.logical.md +21 -0
  66. data/templates/doc/compliance/rendered/apps/.keep +0 -0
  67. data/templates/editorconfig +5 -0
  68. data/templates/env +10 -0
  69. data/templates/githooks/pre-commit.tt +35 -0
  70. data/templates/lib/tasks/cf.rake +9 -0
  71. data/templates/lib/tasks/scanning.rake +63 -0
  72. data/templates/manifest.yml.tt +19 -0
  73. data/templates/pa11yci +9 -0
  74. data/templates/terraform/README.md.tt +148 -0
  75. data/templates/terraform/bootstrap/import.sh +12 -0
  76. data/templates/terraform/bootstrap/main.tf.tt +25 -0
  77. data/templates/terraform/bootstrap/providers.tf +16 -0
  78. data/templates/terraform/bootstrap/run.sh.tt +12 -0
  79. data/templates/terraform/bootstrap/teardown_creds.sh.tt +5 -0
  80. data/templates/terraform/bootstrap/variables.tf +2 -0
  81. data/templates/terraform/create_space_deployer.sh +33 -0
  82. data/templates/terraform/destroy_space_deployer.sh +19 -0
  83. data/templates/terraform/production/main.tf.tt +50 -0
  84. data/templates/terraform/production/providers.tf.tt +17 -0
  85. data/templates/terraform/production/variables.tf +2 -0
  86. data/templates/terraform/shared/database/main.tf.tt +23 -0
  87. data/templates/terraform/shared/database/providers.tf +16 -0
  88. data/templates/terraform/shared/database/variables.tf +42 -0
  89. data/templates/terraform/shared/domain/main.tf.tt +46 -0
  90. data/templates/terraform/shared/domain/providers.tf +16 -0
  91. data/templates/terraform/shared/domain/variables.tf +47 -0
  92. data/templates/terraform/shared/s3/main.tf +27 -0
  93. data/templates/terraform/shared/s3/providers.tf +16 -0
  94. data/templates/terraform/shared/s3/variables.tf +43 -0
  95. data/templates/terraform/staging/main.tf.tt +30 -0
  96. data/templates/terraform/staging/providers.tf.tt +17 -0
  97. data/templates/terraform/staging/variables.tf +2 -0
  98. data/templates/zap.conf +121 -0
  99. metadata +213 -0
data/railsrc-hotwire ADDED
@@ -0,0 +1,8 @@
1
+ --skip-active-storage
2
+ --skip-action-text
3
+ --skip-action-mailbox
4
+ --skip-test
5
+ --javascript=webpack
6
+ --css=postcss
7
+ --template=template.rb
8
+ --database=postgresql
data/template.rb ADDED
@@ -0,0 +1,506 @@
1
+ require "colorize"
2
+
3
+ ## Supporting methods
4
+ # tell our template to grab all files from the templates directory
5
+ def source_paths
6
+ ["#{__dir__}/templates"]
7
+ end
8
+
9
+ def skip_git?
10
+ !!options[:skip_git]
11
+ end
12
+
13
+ def webpack?
14
+ adjusted_javascript_option == "webpack"
15
+ end
16
+
17
+ def hotwire?
18
+ !options[:skip_hotwire]
19
+ end
20
+
21
+ def cloud_gov_org_tktk?
22
+ @cloud_gov_organization =~ /TKTK/
23
+ end
24
+
25
+ @announcements = Hash.new { |h, k| h[k] = [] }
26
+ def register_announcement(section_name, instructions)
27
+ @announcements[section_name.to_sym] << instructions
28
+ end
29
+
30
+ def print_announcements
31
+ $stdout.puts "\n============= Post-install announcements ============= ".red unless @announcements.none?
32
+ @announcements.each do |section_name, instructions|
33
+ $stdout.puts "\n============= #{section_name} ============= ".yellow
34
+ $stdout.puts instructions.join("\n")
35
+ end
36
+ end
37
+
38
+ unless Gem::Dependency.new("rails", "~> 7.0.0").match?("rails", Rails.gem_version)
39
+ warn "This template requires Rails 7.0.x"
40
+ if Gem::Dependency.new("rails", "~> 6.1.0").match?("rails", Rails.gem_version)
41
+ warn "See the rails-6 branch https://github.com/18f/rails-template/tree/rails-6"
42
+ elsif Gem::Dependency.new("rails", "~> 7.1.0").match?("rails", Rails.gem_version)
43
+ warn "Rails 7.1 is out! Please file an issue so we can get the template updated"
44
+ else
45
+ warn "We didn't recognize the version of Rails you are using: #{Rails.version}"
46
+ end
47
+ exit(1)
48
+ end
49
+
50
+ # ask setup questions
51
+ @terraform = yes?("Create terraform files for cloud.gov services? (y/n)")
52
+ @cloud_gov_organization = ask("What is your cloud.gov organization name? (Leave blank to fill in later)")
53
+ default_staging_space = "staging"
54
+ @cloud_gov_staging_space = ask("What is your cloud.gov staging space name? (Default: #{default_staging_space})")
55
+ default_prod_space = "prod"
56
+ @cloud_gov_production_space = ask("What is your cloud.gov production space name? (Default: #{default_prod_space})")
57
+ @cloud_gov_organization = "TKTK-cloud.gov-org-name" if @cloud_gov_organization.blank?
58
+ @cloud_gov_staging_space = default_staging_space if @cloud_gov_staging_space.blank?
59
+ @cloud_gov_production_space = default_prod_space if @cloud_gov_production_space.blank?
60
+
61
+ @github_actions = yes?("Create Github Actions? (y/n)")
62
+ @circleci_pipeline = yes?("Create CircleCI config? (y/n)")
63
+ @adrs = yes?("Create initial Architecture Decision Records? (y/n)")
64
+ @newrelic = yes?("Create FEDRAMP New Relic config files? (y/n)")
65
+ @dap = yes?("If this will be a public site, should we include Digital Analytics Program code? (y/n)")
66
+ @supported_languages = [:en]
67
+ @supported_languages.push(:es) if yes?("Add Spanish to supported locales, with starter es.yml? (y/n)")
68
+ @supported_languages.push(:fr) if yes?("Add French to supported locales, with starter fr.yml? (y/n)")
69
+ @supported_languages.push(:zh) if yes?("Add Simplified Chinese to supported locales, with starter zh.yml? (y/n)")
70
+
71
+ running_node_version = `node --version`.gsub(/^v/, "").strip
72
+ @node_version = ask("What version of NodeJS are you using? (Default: #{running_node_version})")
73
+ @node_version = running_node_version if @node_version.blank?
74
+
75
+ # copied from Rails' .ruby-version template implementation
76
+ @ruby_version = ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}"
77
+
78
+ run_db_setup = yes?("Run db setup steps? (y/n)")
79
+
80
+ ## Start of app customizations
81
+ template "README.md", force: true
82
+ register_announcement("Documentation", <<~EOM)
83
+ * Complete the project README by adding a quick summary of the project in the top section.
84
+ * Review any TBD sections of the README and update where appropriate.
85
+ EOM
86
+
87
+ # setup nvmrc
88
+ file ".nvmrc", @node_version
89
+
90
+ ## Get files from Open Source Policy
91
+ get "https://raw.githubusercontent.com/18F/open-source-policy/master/CONTRIBUTING.md"
92
+ get "https://raw.githubusercontent.com/18F/open-source-policy/master/LICENSE.md"
93
+
94
+ ## setup near-production CI environment
95
+ inside "config" do
96
+ copy_file "environments/ci.rb"
97
+ append_to_file "database.yml", <<~EOM
98
+
99
+ ci:
100
+ <<: *default
101
+ # db will be configured by DATABASE_URL in CI. Use dev db here for ease of local use
102
+ database: #{app_name}_development
103
+ EOM
104
+ end
105
+
106
+ ## setup near-production Staging environment
107
+ inside "config" do
108
+ copy_file "environments/staging.rb"
109
+ append_to_file "database.yml", <<~EOM
110
+
111
+ staging:
112
+ <<: *default
113
+ # db will be configured by DATABASE_URL in a "real" staging env. Use dev db here for ease of local use
114
+ database: #{app_name}_development
115
+ EOM
116
+ end
117
+
118
+ ## add x-config values to standard environment files
119
+ inside "config/environments" do
120
+ insert_into_file "production.rb", "\n config.x.show_demo_banner = false\n", before: /^end$/
121
+ insert_into_file "development.rb", "\n config.x.show_demo_banner = ENV[\"SHOW_DEMO_BANNER\"] == \"true\"\n", before: /^end$/
122
+ insert_into_file "test.rb", "\n config.x.show_demo_banner = false\n", before: /^end$/
123
+ end
124
+
125
+ # setup pa11y and owasp scanning
126
+ directory "bin", mode: :preserve
127
+ copy_file "pa11yci", ".pa11yci"
128
+ copy_file "editorconfig", ".editorconfig"
129
+ copy_file "zap.conf"
130
+ after_bundle do
131
+ run "yarn add --dev pa11y-ci"
132
+ end
133
+
134
+ # updates for OWASP scan to pass
135
+ gem "secure_headers", "~> 6.3"
136
+ initializer "secure_headers.rb", <<~EOM
137
+ SecureHeaders::Configuration.default do |config|
138
+ # CSP settings are handled by Rails
139
+ # see: content_security_policy.rb
140
+ config.csp = SecureHeaders::OPT_OUT
141
+ end
142
+ EOM
143
+ # Replace the default commented out block with our locked-down default
144
+ csp_initializer = "config/initializers/content_security_policy.rb"
145
+ style_policy = if hotwire?
146
+ <<~EOM
147
+ # 'unsafe-inline' is needed because Turbo uses inline CSS for at least the progress bar
148
+ policy.style_src :self, "'unsafe-inline'"
149
+ EOM
150
+ else
151
+ "policy.style_src :self"
152
+ end
153
+
154
+ script_policy = [":self"]
155
+ connect_policy = [":self"]
156
+ image_policy = [":self", ":data"]
157
+
158
+ if @newrelic
159
+ script_policy << '"https://js-agent.newrelic.com"'
160
+ script_policy << '"https://*.nr-data.net"'
161
+ connect_policy << '"https://*.nr-data.net"'
162
+ end
163
+
164
+ if @dap
165
+ image_policy << '"https://www.google-analytics.com"'
166
+ script_policy << '"https://dap.digitalgov.gov"'
167
+ script_policy << '"https://www.google-analytics.com"'
168
+ connect_policy << '"https://dap.digitalgov.gov"'
169
+ connect_policy << '"https://www.google-analytics.com"'
170
+ end
171
+
172
+ gsub_file csp_initializer, /^# config.*\|policy\|$.+^# end$/m, <<EOM
173
+ config.content_security_policy do |policy|
174
+ policy.default_src :self
175
+ policy.font_src :self
176
+ policy.form_action :self
177
+ policy.frame_ancestors :none
178
+ policy.img_src #{image_policy.join(", ")}
179
+ policy.object_src :none
180
+ policy.script_src #{script_policy.join(", ")}
181
+ policy.connect_src #{connect_policy.join(", ")}
182
+ #{style_policy}
183
+ end
184
+ EOM
185
+ # uncommenting the nonce generation lines is needed for any inline js we add
186
+ uncomment_lines csp_initializer, "Rails.application"
187
+ uncomment_lines csp_initializer, /end$/
188
+ uncomment_lines csp_initializer, "content_security_policy_nonce"
189
+
190
+ if @newrelic
191
+ gem "newrelic_rpm", "~> 8.4"
192
+ copy_file "config/newrelic.yml"
193
+
194
+ register_announcement("New Relic", <<~EOM)
195
+ A New Relic config file has been written to `config/newrelic.yml`
196
+
197
+ To get started sending metrics via New Relic APM:
198
+ 1. Replace `<APPNAME>` with what is registered for your application in New Relic
199
+ 2. Add your New Relic license key to the Rails credentials with key `new_relic_key`.
200
+ 3. Comment out the `agent_enabled: false` line
201
+
202
+ To enable browser monitoring:
203
+ 4. Embed the Javascript snippet provided by New Relic into `application.html.erb`.
204
+ It is recommended to vary this based on environment (i.e. include one snippet
205
+ for staging and another for production).
206
+ EOM
207
+ end
208
+
209
+ gem_group :development, :test do
210
+ gem "rspec-rails", "~> 5.1"
211
+ gem "dotenv-rails", "~> 2.7"
212
+ gem "brakeman", "~> 5.2"
213
+ gem "bundler-audit", "~> 0.9"
214
+ gem "standard", "~> 1.7"
215
+ gem "i18n-tasks", "~> 0.9"
216
+ end
217
+ if ENV["RT_DEV"] == "true"
218
+ gem "rails_template_18f", group: :development, path: ENV["PWD"]
219
+ else
220
+ gem "rails_template_18f", group: :development
221
+ end
222
+
223
+ copy_file "lib/tasks/scanning.rake"
224
+ copy_file "env", ".env"
225
+
226
+ unless skip_git?
227
+ rails_command "credentials:diff --enroll"
228
+ template "githooks/pre-commit", ".githooks/pre-commit"
229
+ chmod ".githooks/pre-commit", 0o755
230
+ append_to_file ".gitignore", <<~EOM
231
+
232
+ # Ignore local dotenv overrides
233
+ .env*.local
234
+
235
+ # Ignore OWASP files
236
+ /zap_report.html
237
+ /zap.yaml
238
+
239
+ # Ignore rspec examples status file
240
+ spec/examples.txt
241
+ EOM
242
+ end
243
+
244
+ # Setup translations
245
+ @supported_languages.each do |language|
246
+ template "config/locales/#{language}.yml", force: true
247
+ end
248
+ application "config.i18n.available_locales = #{@supported_languages}"
249
+ application "config.i18n.fallbacks = [:en]"
250
+ after_bundle do
251
+ # Recommended by i18n-tasks
252
+ run "cp $(i18n-tasks gem-path)/templates/config/i18n-tasks.yml config/"
253
+ end
254
+ insert_into_file "app/helpers/application_helper.rb", <<'EOH', before: /^end$/
255
+ def format_active_locale(locale_string)
256
+ link_classes = "usa-nav__link"
257
+ if locale_string.to_sym == I18n.locale
258
+ link_classes = "#{link_classes} usa-current"
259
+ end
260
+ link_to t("shared.languages.#{locale_string}"), root_path(locale: locale_string), class: link_classes
261
+ end
262
+ EOH
263
+
264
+ # setup USWDS
265
+ copy_file "browserslistrc", ".browserslistrc" if webpack?
266
+ uncomment_lines "Gemfile", "sassc-rails" # use sassc-rails for asset minification in prod
267
+ after_bundle do
268
+ js_startup = if webpack?
269
+ "webpack --config webpack.config.js"
270
+ else
271
+ "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds"
272
+ end
273
+ insert_into_file "package.json", <<-EOJSON, before: /^\s+"dependencies"/
274
+ "scripts": {
275
+ "build": "#{js_startup}",
276
+ "build:css": "postcss ./app/assets/stylesheets/application.postcss.css -o ./app/assets/builds/application.css"
277
+ },
278
+ EOJSON
279
+ # Replace postcss-nesting with sass since USWDS uses sass
280
+ run "yarn remove postcss-nesting"
281
+ # include fork of @csstools/postcss-sass until that library is updated for postcss 8
282
+ run "yarn add https://github.com/sinankeskin/postcss-sass"
283
+ run "yarn add postcss-scss"
284
+ insert_into_file "postcss.config.js", " syntax: 'postcss-scss',\n", before: /^\s+plugins/
285
+ gsub_file "postcss.config.js", "postcss-nesting", "@csstools/postcss-sass"
286
+ run "yarn add uswds"
287
+ appjs_file = "app/javascript/application.js"
288
+ append_to_file appjs_file, "\nimport \"uswds\"\n"
289
+ if hotwire?
290
+ append_to_file appjs_file, <<~EOJS
291
+
292
+ // make sure USWDS components are wired to their behavior after a Turbo navigation
293
+ import components from "uswds/src/js/components"
294
+ let initialLoad = true;
295
+ document.addEventListener("turbo:load", () => {
296
+ if (initialLoad) {
297
+ // initial domready is handled by `import "uswds"` code
298
+ initialLoad = false
299
+ return
300
+ }
301
+ const target = document.body
302
+ Object.keys(components).forEach((key) => {
303
+ const behavior = components[key]
304
+ behavior.on(target)
305
+ })
306
+ })
307
+ EOJS
308
+ end
309
+ directory "app/assets"
310
+ append_to_file "app/assets/stylesheets/application.postcss.css", <<~EOCSS
311
+ /* KNOWN ISSUE: only changes to application.postcss.css will trigger an automatic rebuild */
312
+ /* restart your server or run `yarn build:css` when changing other files */
313
+ @import "uswds-settings.scss";
314
+ @import "../../../node_modules/uswds/dist/scss/uswds.scss";
315
+ EOCSS
316
+ gsub_file "app/views/layouts/application.html.erb", "<html>", "<html lang=\"en\">"
317
+ gsub_file "app/views/layouts/application.html.erb", /^\s+<%= yield %>/, <<-EOHTML
318
+ <%= render "application/usa_banner" %>
319
+ <%= render "application/header" %>
320
+ <main id="main-content">
321
+ <div class="grid-container usa-section">
322
+ <%= yield %>
323
+ </div>
324
+ </main>
325
+ EOHTML
326
+ append_to_file "config/initializers/assets.rb", "Rails.application.config.assets.paths << Rails.root.join(\"node_modules\")"
327
+ end
328
+ directory "app/views/application"
329
+
330
+ after_bundle do
331
+ generate "rspec:install"
332
+ gsub_file "spec/spec_helper.rb", /^=(begin|end)$/, ""
333
+
334
+ # Setup the PagesController, locale routes, and home (root) route
335
+ generate :controller, "pages", "home", "--skip-routes", "--no-helper", "--no-assets"
336
+
337
+ if @supported_languages.count > 1
338
+ locale_switching = <<~EOM
339
+ around_action :switch_locale
340
+
341
+ def switch_locale(&action)
342
+ locale = params[:locale] || I18n.default_locale
343
+ I18n.with_locale(locale, &action)
344
+ end
345
+ EOM
346
+ insert_into_file "app/controllers/application_controller.rb", locale_switching, before: /^end/
347
+
348
+ route <<-'EOM'
349
+ scope "(:locale)", locale: /#{I18n.available_locales.join('|')}/ do
350
+ # Your application routes here
351
+ root 'pages#home'
352
+ end
353
+ EOM
354
+ else
355
+ route "root 'pages#home'"
356
+ end
357
+ gsub_file "spec/requests/pages_spec.rb", "/pages/home", "/"
358
+ gsub_file "spec/views/pages/home.html.erb_spec.rb", " pending \"add some examples to (or delete) \#{__FILE__}\"", <<-EOM
359
+ it "displays the gov banner" do
360
+ render template: "pages/home", layout: "layouts/application"
361
+ expect(rendered).to match "An official website of the United States government"
362
+ end
363
+ EOM
364
+
365
+ if run_db_setup
366
+ rails_command "db:create"
367
+ rails_command "db:migrate"
368
+ end
369
+ end
370
+
371
+ # infrastructure & deploy
372
+ template "manifest.yml"
373
+ copy_file "lib/tasks/cf.rake"
374
+ directory "config/deployment"
375
+ after_bundle do
376
+ run "cp .gitignore .cfignore" unless skip_git?
377
+ end
378
+
379
+ if @terraform
380
+ directory "terraform", mode: :preserve
381
+ chmod "terraform/bootstrap/run.sh", 0o755
382
+ chmod "terraform/bootstrap/teardown_creds.sh", 0o755
383
+ unless skip_git?
384
+ append_to_file ".gitignore", <<~EOM
385
+
386
+ # Terraform
387
+ .terraform.lock.hcl
388
+ **/.terraform/*
389
+ secrets.auto.tfvars
390
+ terraform.tfstate
391
+ terraform.tfstate.backup
392
+ EOM
393
+ end
394
+ if cloud_gov_org_tktk?
395
+ register_announcement("Terraform", <<~EOM)
396
+ Fill in the cloud.gov organization information in:
397
+ * terraform/bootstrap/main.tf
398
+ * terraform/staging/main.tf
399
+ * terraform/production/main.tf
400
+ EOM
401
+ end
402
+ register_announcement("Terraform", "Run the bootstrap script and update the appropriate CI/CD environment variables defined in the Deployment section of the README")
403
+ end
404
+
405
+ if @github_actions
406
+ after_bundle do
407
+ generator_arguments = [
408
+ (@terraform ? "--terraform" : "--no-terraform"),
409
+ "--cg-org=#{@cloud_gov_organization}",
410
+ "--cg-staging=#{@cloud_gov_staging_space}",
411
+ "--cg-prod=#{@cloud_gov_production_space}"
412
+ ]
413
+ generate "rails_template18f:github_actions", *generator_arguments
414
+ end
415
+ if cloud_gov_org_tktk?
416
+ register_announcement("Github Actions", <<~EOM)
417
+ * Fill in the cloud.gov organization information in .github/workflows/deploy-staging.yml
418
+ EOM
419
+ end
420
+ register_announcement("Github Actions", <<~EOM)
421
+ * Create environment variable secrets for deploy users as defined in the Deployment section of the README
422
+ EOM
423
+ end
424
+
425
+ if @circleci_pipeline
426
+ after_bundle do
427
+ generator_arguments = [
428
+ (@terraform ? "--terraform" : "--no-terraform"),
429
+ "--cg-org=#{@cloud_gov_organization}",
430
+ "--cg-staging=#{@cloud_gov_staging_space}",
431
+ "--cg-prod=#{@cloud_gov_production_space}"
432
+ ]
433
+ generate "rails_template18f:circleci", *generator_arguments
434
+ end
435
+ register_announcement("CircleCI", <<~EOM)
436
+ * Create project environment variables for deploy users as defined in the Deployment section of the README
437
+ EOM
438
+ end
439
+
440
+ if @adrs
441
+ directory "doc"
442
+ else
443
+ directory "doc/compliance"
444
+ end
445
+ register_announcement("Documentation", <<~EOM)
446
+ * Include a short description of your application in doc/compliance/apps/application.boundary.md
447
+ * Remember to keep your Logical Data Model up to date in doc/compliance/apps/data.logical.md
448
+ EOM
449
+
450
+ if @dap
451
+ after_bundle do
452
+ insert_into_file "app/views/layouts/application.html.erb", <<-EODAP, before: /^\s+<\/head>/
453
+
454
+ <% if Rails.env.production? %>
455
+ <!-- We participate in the US government's analytics program. See the data at analytics.usa.gov. -->
456
+ <%= javascript_include_tag "https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js?agency=GSA", async: true, id:"_fed_an_ua_tag" %>
457
+ <% end %>
458
+ EODAP
459
+ end
460
+ register_announcement("Digital Analytics Program", "Update the DAP agency code in app/views/layouts/application.html.erb")
461
+ end
462
+
463
+ # setup production credentials file
464
+ require "rails/generators"
465
+ require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
466
+ require "rails/generators/rails/encrypted_file/encrypted_file_generator"
467
+ key_file_generator = Rails::Generators::EncryptionKeyFileGenerator.new
468
+ key_file_path = Pathname.new "config/credentials/production.key"
469
+ key_file_generator.add_key_file_silently key_file_path
470
+ key_file_generator.ignore_key_file_silently key_file_path
471
+ Rails::Generators::EncryptedFileGenerator.new.add_encrypted_file_silently("config/credentials/production.yml.enc", key_file_path, <<~EOYAML)
472
+ # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
473
+ secret_key_base: #{SecureRandom.hex(64)}
474
+ EOYAML
475
+ register_announcement("Credentials", <<~EOM)
476
+ Two credentials files and keys have been generated:
477
+
478
+ * production
479
+ * config/credentials/production.yml.enc
480
+ * config/credentials/production.key
481
+ * all other environments
482
+ * config/credentials.yml.enc
483
+ * config/master.key
484
+
485
+ The contents of `config/master.key` should be shared with other developers running the application.
486
+ The contents of `config/credentials/production.key` must be limited to those developers who are authorized to have access to production.
487
+ EOM
488
+
489
+ # ensure this is the very last step
490
+ after_bundle do
491
+ # x86_64-linux is required to install gems on any linux system such as cloud.gov or CI pipelines
492
+ run "bundle lock --add-platform x86_64-linux"
493
+
494
+ # bring generated code into compliance with standard ruby: https://github.com/testdouble/standard
495
+ gsub_file "config/environments/production.rb", "(STDOUT)", "($stdout)"
496
+ gsub_file "config/puma.rb", /\) { (\S+) }/, ', \1)'
497
+ run "bundle exec standardrb --fix"
498
+
499
+ unless skip_git?
500
+ git add: "."
501
+ git commit: "-a -m 'Initial commit'"
502
+ end
503
+
504
+ # Post-install announcement
505
+ print_announcements
506
+ end