rails_template_18f 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|