rails_template_18f 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.standard.yml +2 -0
- data/CHANGELOG.md +6 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +132 -0
- data/LICENSE.md +21 -0
- data/README.md +140 -0
- data/Rakefile +10 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/lib/generators/rails_template18f/circleci/circleci_generator.rb +116 -0
- data/lib/generators/rails_template18f/circleci/templates/Dockerfile.tt +13 -0
- data/lib/generators/rails_template18f/circleci/templates/bin/ci-server-start +8 -0
- data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +413 -0
- data/lib/generators/rails_template18f/circleci/templates/docker-compose.ci.yml +26 -0
- data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +137 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/actions/run-server/action.yml +28 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/actions/setup-languages/action.yml.tt +20 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/actions/setup-project/action.yml.tt +33 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/brakeman-analysis.yml +44 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/dependency-scans.yml +39 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml.tt +53 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml.tt +53 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-daily-scan.yml.tt +44 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-scan.yml.tt +47 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/pa11y.yml.tt +65 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/rspec.yml.tt +34 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +79 -0
- data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +79 -0
- data/lib/rails_template18f/terraform_options.rb +68 -0
- data/lib/rails_template18f/version.rb +5 -0
- data/lib/rails_template_18f.rb +13 -0
- data/rails-template-18f.gemspec +40 -0
- data/railsrc +10 -0
- data/railsrc-hotwire +8 -0
- data/template.rb +506 -0
- data/templates/README.md.tt +213 -0
- data/templates/app/assets/images/uswds.js +5 -0
- data/templates/app/assets/stylesheets/uswds-settings.scss +7 -0
- data/templates/app/views/application/_banner_lock_icon.html.erb +19 -0
- data/templates/app/views/application/_demo_site_banner.html.erb +3 -0
- data/templates/app/views/application/_header.html.erb +26 -0
- data/templates/app/views/application/_usa_banner.html.erb +51 -0
- data/templates/bin/owasp-scan +49 -0
- data/templates/bin/pa11y-scan +10 -0
- data/templates/bin/with-server +35 -0
- data/templates/browserslistrc +5 -0
- data/templates/config/deployment/production.yml +3 -0
- data/templates/config/deployment/staging.yml +3 -0
- data/templates/config/environments/ci.rb +10 -0
- data/templates/config/environments/staging.rb +6 -0
- data/templates/config/locales/en.yml.tt +25 -0
- data/templates/config/locales/es.yml +19 -0
- data/templates/config/locales/fr.yml +22 -0
- data/templates/config/locales/zh.yml +16 -0
- data/templates/config/newrelic.yml +65 -0
- data/templates/doc/adr/0001-record-architecture-decisions.md.tt +21 -0
- data/templates/doc/adr/0002-initial-architecture-decisions.md.tt +24 -0
- data/templates/doc/adr/0003-security-scans.md.tt +44 -0
- data/templates/doc/adr/0004-rails-csp-compliant-script-tag-helpers.md.tt +53 -0
- data/templates/doc/compliance/README.md +37 -0
- data/templates/doc/compliance/apps/application.boundary.md.tt +80 -0
- data/templates/doc/compliance/apps/data.logical.md +21 -0
- data/templates/doc/compliance/rendered/apps/.keep +0 -0
- data/templates/editorconfig +5 -0
- data/templates/env +10 -0
- data/templates/githooks/pre-commit.tt +35 -0
- data/templates/lib/tasks/cf.rake +9 -0
- data/templates/lib/tasks/scanning.rake +63 -0
- data/templates/manifest.yml.tt +19 -0
- data/templates/pa11yci +9 -0
- data/templates/terraform/README.md.tt +148 -0
- data/templates/terraform/bootstrap/import.sh +12 -0
- data/templates/terraform/bootstrap/main.tf.tt +25 -0
- data/templates/terraform/bootstrap/providers.tf +16 -0
- data/templates/terraform/bootstrap/run.sh.tt +12 -0
- data/templates/terraform/bootstrap/teardown_creds.sh.tt +5 -0
- data/templates/terraform/bootstrap/variables.tf +2 -0
- data/templates/terraform/create_space_deployer.sh +33 -0
- data/templates/terraform/destroy_space_deployer.sh +19 -0
- data/templates/terraform/production/main.tf.tt +50 -0
- data/templates/terraform/production/providers.tf.tt +17 -0
- data/templates/terraform/production/variables.tf +2 -0
- data/templates/terraform/shared/database/main.tf.tt +23 -0
- data/templates/terraform/shared/database/providers.tf +16 -0
- data/templates/terraform/shared/database/variables.tf +42 -0
- data/templates/terraform/shared/domain/main.tf.tt +46 -0
- data/templates/terraform/shared/domain/providers.tf +16 -0
- data/templates/terraform/shared/domain/variables.tf +47 -0
- data/templates/terraform/shared/s3/main.tf +27 -0
- data/templates/terraform/shared/s3/providers.tf +16 -0
- data/templates/terraform/shared/s3/variables.tf +43 -0
- data/templates/terraform/staging/main.tf.tt +30 -0
- data/templates/terraform/staging/providers.tf.tt +17 -0
- data/templates/terraform/staging/variables.tf +2 -0
- data/templates/zap.conf +121 -0
- metadata +213 -0
data/railsrc-hotwire
ADDED
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
|