rails_template_18f 2.0.0 → 2.2.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/Gemfile.lock +9 -7
  4. data/lib/generators/rails_template18f/active_storage/active_storage_generator.rb +4 -3
  5. data/lib/generators/rails_template18f/auditree/auditree_generator.rb +36 -6
  6. data/lib/generators/rails_template18f/auditree/templates/gitlab/auditree.yml.tt +48 -0
  7. data/lib/generators/rails_template18f/circleci/templates/circleci/config.yml.tt +12 -2
  8. data/lib/generators/rails_template18f/cloud_gov_config/cloud_gov_config_generator.rb +0 -8
  9. data/lib/generators/rails_template18f/cloud_gov_config/templates/app/models/cloud_gov_config.rb +6 -7
  10. data/lib/generators/rails_template18f/cloud_gov_config/templates/spec/models/cloud_gov_config_spec.rb +13 -19
  11. data/lib/generators/rails_template18f/github_actions/github_actions_generator.rb +0 -4
  12. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-production.yml +3 -1
  13. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/deploy-staging.yml +3 -1
  14. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-production.yml +3 -1
  15. data/lib/generators/rails_template18f/github_actions/templates/github/workflows/terraform-staging.yml +3 -1
  16. data/lib/generators/rails_template18f/gitlab_ci/gitlab_ci_generator.rb +138 -0
  17. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/node.yml.tt +11 -0
  18. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/rails.yml +75 -0
  19. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/ruby.yml +7 -0
  20. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab/terraform.yml +33 -0
  21. data/lib/generators/rails_template18f/gitlab_ci/templates/gitlab-ci.yml.tt +213 -0
  22. data/lib/generators/rails_template18f/oscal/oscal_generator.rb +15 -1
  23. data/lib/generators/rails_template18f/oscal/templates/bin/trestle.tt +10 -1
  24. data/lib/generators/rails_template18f/oscal/templates/gitlab/trestle.yml.tt +29 -0
  25. data/lib/generators/rails_template18f/public_egress/public_egress_generator.rb +16 -32
  26. data/lib/generators/rails_template18f/sidekiq/templates/config/initializers/redis.rb +1 -1
  27. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/apply.sh +25 -0
  28. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/main.tf.tt +98 -0
  29. data/lib/generators/rails_template18f/terraform/templates/gitlab_bootstrap/setup_shadowenv.sh +59 -0
  30. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/backend_config.tftpl +6 -0
  31. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/templates/bot_secrets.tftpl +5 -0
  32. data/lib/generators/rails_template18f/terraform/templates/s3_bootstrap/common/users.auto.tfvars +5 -0
  33. data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/main.tf.tt +4 -11
  34. data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/main.tf.tt +3 -3
  35. data/lib/generators/rails_template18f/terraform/templates/terraform/.shadowenv.d/.gitignore +3 -0
  36. data/lib/generators/rails_template18f/terraform/templates/terraform/README.md.tt +38 -36
  37. data/lib/generators/rails_template18f/terraform/templates/terraform/app.tf.tt +1 -6
  38. data/lib/generators/rails_template18f/terraform/templates/terraform/main.tf.tt +30 -19
  39. data/lib/generators/rails_template18f/terraform/templates/terraform/production.tfvars.tt +3 -0
  40. data/lib/generators/rails_template18f/terraform/templates/terraform/providers.tf.tt +4 -24
  41. data/lib/generators/rails_template18f/terraform/templates/terraform/staging.tfvars.tt +5 -5
  42. data/lib/generators/rails_template18f/terraform/templates/terraform/terraform.sh.tt +40 -55
  43. data/lib/generators/rails_template18f/terraform/templates/terraform/variables.tf.tt +11 -12
  44. data/lib/generators/rails_template18f/terraform/terraform_generator.rb +78 -6
  45. data/lib/rails_template18f/version.rb +1 -1
  46. data/template.rb +50 -25
  47. data/templates/{pa11yci.js → pa11yci.js.tt} +5 -0
  48. metadata +28 -20
  49. data/lib/generators/rails_template18f/terraform/templates/terraform/bootstrap/templates/backend_config.tftpl +0 -8
  50. data/lib/generators/rails_template18f/terraform/templates/terraform/sandbox_bot/main.tf +0 -74
  51. data/lib/generators/rails_template18f/terraform/templates/terraform/sandbox_bot/run.sh +0 -17
  52. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/assemble-ssp.yml.tt +0 -0
  53. /data/lib/generators/rails_template18f/{github_actions → oscal}/templates/github/workflows/validate-ssp.yml +0 -0
  54. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap/templates → gitlab_bootstrap}/bot_secrets.tftpl +0 -0
  55. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → gitlab_bootstrap}/users.auto.tfvars +0 -0
  56. /data/lib/generators/rails_template18f/terraform/templates/{terraform/bootstrap → s3_bootstrap/common}/apply.sh +0 -0
  57. /data/lib/generators/rails_template18f/terraform/templates/{full_bootstrap → s3_bootstrap/full}/imports.tf.tftpl +0 -0
  58. /data/lib/generators/rails_template18f/terraform/templates/{sandbox_bootstrap → s3_bootstrap/sandbox}/imports.tf.tftpl +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3286e663d05b9b712a5b1f3fa2aa1403016f0822be9fd26d0999200701dab318
4
- data.tar.gz: 04e5124a24452f747270e42aaa1b5455de3b0ce4362ff455e94554984214473e
3
+ metadata.gz: bab13c0d757c29b86c139635bed3f016cc486d38299b7aa90533d888b6995d69
4
+ data.tar.gz: 447e73554b32dd86782cf52c4cda2699f55c4e0706c05f813e82515a2e61912f
5
5
  SHA512:
6
- metadata.gz: 954b939ea264b5200c01e8122da1001e0c099f072b370de98926ce9dcaef154a6e00568353a4fff191addfaf1cd7cc4f85549454c6984b29ff9c537af8207f17
7
- data.tar.gz: c85daa74d0ca528fbbe4a3d260a720206194635a12c6a73fde878e19384870a601e78f789b513c43bfd57c4290ef6e6f85bcb409717ad646628ca1966318e09b
6
+ metadata.gz: cad79214c9110e3fb33968b8c6d1fc98477c6c979bc58724e9b88f57985456ca7d404515dd004891dade32d4e95183f1a90c12d4d05ee87753f52867f9efde94
7
+ data.tar.gz: ecb278387c12d47fc9bc611f26c0787fa7c4c2dda43fa14ce8f176bfb4cf9d0d2c6b04718ab0faa3569b4f5897e9d65cdc0b0944972c64648e8e401d9b341881
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.2.0] - 2025-06-27
4
+
5
+ - Prevent non-compliant hostnames by replacing underscores with dashes
6
+ - use shadowenv for configuring terraform backend secrets
7
+ - use GitLab http backend for terraform state storage whenever configuring both terraform and GitLab CI
8
+ - Create GitLabCI jobs for oscal and auditree generators
9
+ - fixes for deploying to the sandbox-gsa cloug.gov org
10
+
11
+ ## [2.1.0] - 2025-04-29
12
+
13
+ - Terraform generator updates to remove the old cloudfoundy-community provider and reduce the need for cloud.gov service accounts
14
+ - New GitLab CI generator for use with DevTools GitLab
15
+
3
16
  ## [2.0.0] - 2025-01-16
4
17
 
5
18
  - Default new apps to Rails 8, including support for thruster proxy
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails_template_18f (2.0.0)
4
+ rails_template_18f (2.2.0)
5
5
  activesupport (~> 8.0.1)
6
6
  colorize (~> 1.1)
7
7
  railties (~> 8.0.1)
@@ -71,11 +71,11 @@ GEM
71
71
  crass (~> 1.0.2)
72
72
  nokogiri (>= 1.12.0)
73
73
  minitest (5.25.4)
74
- nokogiri (1.18.0-arm64-darwin)
74
+ nokogiri (1.18.8-arm64-darwin)
75
75
  racc (~> 1.4)
76
- nokogiri (1.18.0-x86_64-darwin)
76
+ nokogiri (1.18.8-x86_64-darwin)
77
77
  racc (~> 1.4)
78
- nokogiri (1.18.0-x86_64-linux-gnu)
78
+ nokogiri (1.18.8-x86_64-linux-gnu)
79
79
  racc (~> 1.4)
80
80
  parallel (1.26.3)
81
81
  parser (3.3.6.0)
@@ -85,8 +85,9 @@ GEM
85
85
  date
86
86
  stringio
87
87
  racc (1.8.1)
88
- rack (3.1.8)
89
- rack-session (2.0.0)
88
+ rack (3.1.16)
89
+ rack-session (2.1.1)
90
+ base64 (>= 0.1.0)
90
91
  rack (>= 3.0.0)
91
92
  rack-test (2.2.0)
92
93
  rack (>= 1.3)
@@ -171,12 +172,13 @@ GEM
171
172
  unicode-display_width (3.1.3)
172
173
  unicode-emoji (~> 4.0, >= 4.0.4)
173
174
  unicode-emoji (4.0.4)
174
- uri (1.0.2)
175
+ uri (1.0.3)
175
176
  useragent (0.16.11)
176
177
  zeitwerk (2.7.1)
177
178
 
178
179
  PLATFORMS
179
180
  arm64-darwin-23
181
+ arm64-darwin-24
180
182
  x86_64-darwin-20
181
183
  x86_64-darwin-21
182
184
  x86_64-linux
@@ -20,12 +20,13 @@ module RailsTemplate18f
20
20
  environment "config.active_storage.service = :local", env: "ci"
21
21
  append_to_file "config/storage.yml", <<~EOYAML
22
22
 
23
+ <% cgc = CloudGovConfig.new %>
23
24
  amazon:
24
25
  service: S3
25
- access_key_id: <%= CloudGovConfig.dig(:s3, :credentials, :access_key_id) %>
26
- secret_access_key: <%= CloudGovConfig.dig(:s3, :credentials, :secret_access_key) %>
26
+ access_key_id: <%= cgc.dig(:s3, :credentials, :access_key_id) %>
27
+ secret_access_key: <%= cgc.dig(:s3, :credentials, :secret_access_key) %>
27
28
  region: us-gov-west-1
28
- bucket: <%= CloudGovConfig.dig(:s3, :credentials, :bucket) %>
29
+ bucket: <%= cgc.dig(:s3, :credentials, :bucket) %>
29
30
  EOYAML
30
31
  end
31
32
 
@@ -41,7 +41,7 @@ module RailsTemplate18f
41
41
  plant-helper -f /tmp/rspec.json -c assessment-plans -d "RSpec run assessment plan"
42
42
  -t 31536000 -l #{auditree_evidence_locker}
43
43
 
44
- - name: Plan assessment results in evidence locker
44
+ - name: Plant assessment results in evidence locker
45
45
  uses: ./.github/actions/auditree-cmd
46
46
  env:
47
47
  GITHUB_TOKEN: ${{ secrets.AUDITREE_GITHUB_TOKEN }}
@@ -54,6 +54,19 @@ PLANT_HELPER_STEPS
54
54
  end
55
55
  end
56
56
 
57
+ def copy_gitlab_actions
58
+ if file_exists? ".gitlab-ci.yml"
59
+ directory "gitlab", ".gitlab"
60
+ insert_into_file ".gitlab-ci.yml", " - local: \".gitlab/auditree.yml\"\n", after: /^include:\n/
61
+ insert_into_file ".gitlab-ci.yml", " AUDITREE_VERSION: #{docker_auditree_tag}\n", after: /^variables:\n/
62
+ insert_into_file ".gitlab-ci.yml", <<EOY, after: /^\s+- bundle exec rspec\n/
63
+ artifacts:
64
+ paths:
65
+ - tmp/oscal/**/*
66
+ EOY
67
+ end
68
+ end
69
+
57
70
  def update_readme
58
71
  if file_content("README.md").match?("## Documentation")
59
72
  insert_into_file "README.md", readme_contents, after: "## Documentation\n"
@@ -74,7 +87,7 @@ PLANT_HELPER_STEPS
74
87
  end
75
88
 
76
89
  def auditree_evidence_locker
77
- options[:evidence_locker].present? ? options[:evidence_locker] : "https://github.com/GSA-TTS/TKTK_#{app_name}_evidence"
90
+ options[:evidence_locker].present? ? options[:evidence_locker] : "REPLACE_THIS_WITH_YOUR_EVIDENCE_LOCKER_REPO"
78
91
  end
79
92
 
80
93
  def git_email
@@ -98,10 +111,9 @@ PLANT_HELPER_STEPS
98
111
  1. Docker desktop must be running
99
112
  1. Initialize the config file with `bin/auditree init`
100
113
  1. Create an evidence locker repository with a default or blank README
101
- 1. Create a github personal access token to interact with the code repo and evidence locker and set as `AUDITREE_GITHUB_TOKEN` secret within your Github Actions secrets.
102
- 1. Update `config/auditree.template.json` with the repo addresses for your locker and code repos
103
- #{(options[:evidence_locker].blank? && file_exists?(".github/workflows/rspec.yml")) ? "1. Update `.github/workflows/rspec.yml` with the locker repository URL" : ""}
104
- 1. Copy the `devtools_cloud_gov` component definition into the project with the latest docker-trestle
114
+ 1. Update `config/auditree.template.json` with the repo address for your locker
115
+ #{ci_readme_contents.chomp}
116
+ 1. Copy the `devtools_cloud_gov` component definition into the project with the latest docker-trestle after [setting up docker-trestle](#initial-trestle-setup)
105
117
 
106
118
  #### Ongoing use
107
119
 
@@ -109,6 +121,24 @@ PLANT_HELPER_STEPS
109
121
  auditree and using new checks.
110
122
  README
111
123
  end
124
+
125
+ def ci_readme_contents
126
+ if file_exists? ".gitlab-ci.yml"
127
+ <<~README
128
+ 1. Remove the `repo_integrity` section of `config/auditree.template.json`
129
+ 1. Create a gitlab personal access token with `write_repository` scope to interact with the code repo and evidence locker and set as `AUDITREE_GITLAB_TOKEN` secret within your CI/CD variables.
130
+ #{options[:evidence_locker].blank? ? "1. Update `.gitlab/auditree.yml` with the locker repository URL" : ""}
131
+ README
132
+ elsif file_exists? ".github/workflows"
133
+ <<~README
134
+ 1. Update `config/auditree.template.json` with the repo address for your code repos
135
+ 1. Create a github personal access token to interact with the code repo and evidence locker and set as `AUDITREE_GITHUB_TOKEN` secret within your Github Actions secrets.
136
+ #{options[:evidence_locker].blank? ? "1. Update `.github/workflows/rspec.yml` with the locker repository URL" : ""}
137
+ README
138
+ else
139
+ ""
140
+ end
141
+ end
112
142
  end
113
143
  end
114
144
  end
@@ -0,0 +1,48 @@
1
+ .auditree:setup:
2
+ inherit:
3
+ default: false
4
+ image: "ghcr.io/gsa-tts/auditree:${AUDITREE_VERSION}"
5
+ variables:
6
+ CDEF: "${CI_PROJECT_DIR}/doc/compliance/oscal/component-definitions/devtools_cloud_gov/component-definition.json"
7
+ AUDITREE_CONFIG: "${CI_PROJECT_DIR}/config/auditree.template.json"
8
+ before_script:
9
+ - git config --global user.name "$GITLAB_USER_NAME"
10
+ - git config --global user.email "$GITLAB_USER_EMAIL"
11
+ - cf api api.fr.cloud.gov
12
+ - cd $HOME
13
+ - export GITLAB_TOKEN="auditree-gitlab-token:${AUDITREE_GITLAB_TOKEN}"
14
+
15
+ auditree:
16
+ extends: .auditree:setup
17
+ stage: scan
18
+ script:
19
+ - fetch -c "$CDEF" -t "$AUDITREE_CONFIG"
20
+ - check -c "$CDEF" -t "$AUDITREE_CONFIG" -o "$CI_PROJECT_DIR"
21
+ artifacts:
22
+ paths:
23
+ - auditree.json
24
+ rules:
25
+ - if: $CI_PIPELINE_SOURCE == "schedule"
26
+
27
+ rspec:plant:
28
+ extends: .auditree:setup
29
+ stage: test
30
+ needs: ["rspec"]
31
+ variables:
32
+ PLAN_FILE: "${CI_PROJECT_DIR}/tmp/oscal/assessment-plans/rspec/assessment-plan.json"
33
+ RESULT_FILE: "${CI_PROJECT_DIR}/tmp/oscal/assessment-results/rspec/assessment-results.json"
34
+ script:
35
+ - |
36
+ if [ -f "$PLAN_FILE" ]; then
37
+ plant-helper -f "$PLAN_FILE" -c assessment-plans -d "RSpec run assessment plan" -t 31536000 -l "<%= auditree_evidence_locker %>"
38
+ else
39
+ echo "No plan file, skipping plant"
40
+ fi
41
+ - |
42
+ if [ -f "$RESULT_FILE" ]; then
43
+ plant-helper -f "$RESULT_FILE" -c assessment-results -d "RSpec run assessment results" -t 31536000 -l "<%= auditree_evidence_locker %>"
44
+ else
45
+ echo "No result file, skipping plant"
46
+ fi
47
+ rules:
48
+ - if: $CI_PIPELINE_SOURCE != "schedule"
@@ -314,13 +314,15 @@ jobs:
314
314
  - attach_workspace:
315
315
  at: .
316
316
  - terraform/plan:
317
+ environment:
318
+ CF_API_URL: "https://api.fr.cloud.gov"
319
+ CF_USER: "$CF_USERNAME"
317
320
  path: terraform
318
321
  out: staging.out
319
322
  var_file: staging.tfvars
320
323
  var: >-
321
324
  rails_master_key="$RAILS_MASTER_KEY",
322
325
  cf_user="$CF_USERNAME",
323
- cf_password="$CF_PASSWORD"
324
326
  - persist_to_workspace:
325
327
  root: .
326
328
  paths:
@@ -332,6 +334,9 @@ jobs:
332
334
  - attach_workspace:
333
335
  at: .
334
336
  - terraform/apply:
337
+ environment:
338
+ CF_API_URL: "https://api.fr.cloud.gov"
339
+ CF_USER: "$CF_USERNAME"
335
340
  path: terraform
336
341
  plan: staging.out<% if terraform_manage_spaces? %>
337
342
 
@@ -358,13 +363,15 @@ jobs:
358
363
  - attach_workspace:
359
364
  at: .
360
365
  - terraform/plan:
366
+ environment:
367
+ CF_API_URL: "https://api.fr.cloud.gov"
368
+ CF_USER: "$CF_USERNAME"
361
369
  path: terraform
362
370
  out: production.out
363
371
  var_file: production.tfvars
364
372
  var: >-
365
373
  rails_master_key="$PRODUCTION_RAILS_MASTER_KEY",
366
374
  cf_user="$CF_USERNAME",
367
- cf_password="$CF_PASSWORD"
368
375
  - persist_to_workspace:
369
376
  root: .
370
377
  paths:
@@ -376,6 +383,9 @@ jobs:
376
383
  - attach_workspace:
377
384
  at: .
378
385
  - terraform/apply:
386
+ environment:
387
+ CF_API_URL: "https://api.fr.cloud.gov"
388
+ CF_USER: "$CF_USERNAME"
379
389
  path: terraform
380
390
  plan: production.out<% end %>
381
391
 
@@ -12,14 +12,6 @@ module RailsTemplate18f
12
12
  Install a helper class to retrieve configuration from ENV["VCAP_SERVICES"]
13
13
  DESC
14
14
 
15
- def install_climate_control
16
- return if gem_installed?("climate_control")
17
- gem_group :test do
18
- gem "climate_control", "~> 1.2"
19
- end
20
- bundle_install
21
- end
22
-
23
15
  def install_model_and_test
24
16
  copy_file "app/models/cloud_gov_config.rb"
25
17
  copy_file "spec/models/cloud_gov_config_spec.rb"
@@ -1,15 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class CloudGovConfig
4
- ENV_VARIABLE = "VCAP_SERVICES"
4
+ attr_reader :vcap_services
5
5
 
6
- def self.dig(*path)
7
- return nil if ENV[ENV_VARIABLE].blank?
8
- first, *rest = path
9
- vcap_services[first]&.first&.dig(*rest)
6
+ def initialize(env = ENV["VCAP_SERVICES"])
7
+ @vcap_services = env.blank? ? {} : JSON.parse(env).with_indifferent_access
10
8
  end
11
9
 
12
- def self.vcap_services
13
- @vcap_services ||= JSON.parse(ENV[ENV_VARIABLE]).with_indifferent_access
10
+ def dig(*path)
11
+ first, *rest = path
12
+ vcap_services[first]&.first&.dig(*rest)
14
13
  end
15
14
  end
@@ -3,35 +3,29 @@
3
3
  require "rails_helper"
4
4
 
5
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
6
+ describe "#dig" do
7
+ [nil, "", "{}"].each do |blank|
8
+ context "VCAP_SERVICES is #{blank.inspect}" do
9
+ subject { described_class.new blank }
10
+ it "returns nil" do
11
+ expect(subject.dig(:s3, :credentials, :bucket)).to be_nil
12
+ end
12
13
  end
13
14
  end
14
15
 
15
16
  context "VCAP_SERVICES is set" do
17
+ subject { described_class.new vcap }
16
18
  let(:bucket_name) { "bucket-name" }
17
19
  let(:vcap) {
18
20
  {
19
- s3: [
20
- {
21
- credentials: {
22
- bucket: bucket_name
23
- }
21
+ s3: [{
22
+ credentials: {
23
+ bucket: bucket_name
24
24
  }
25
- ]
26
- }
25
+ }]
26
+ }.to_json
27
27
  }
28
28
 
29
- around do |example|
30
- ClimateControl.modify VCAP_SERVICES: vcap.to_json do
31
- example.run
32
- end
33
- end
34
-
35
29
  it "can find a path" do
36
30
  expect(subject.dig(:s3, :credentials, :bucket)).to eq bucket_name
37
31
  end
@@ -17,10 +17,6 @@ module RailsTemplate18f
17
17
 
18
18
  def install_actions
19
19
  directory "github", ".github"
20
- if !oscal_dir_exists?
21
- remove_file ".github/workflows/validate-ssp.yml"
22
- remove_file ".github/workflows/assemble-ssp.yml"
23
- end
24
20
  if !terraform_manage_spaces?
25
21
  remove_file ".github/workflows/terraform-production.yml"
26
22
  remove_file ".github/workflows/deploy-production.yml"
@@ -47,8 +47,10 @@ jobs:
47
47
  - name: Terraform apply
48
48
  uses: dflook/terraform-apply@v1
49
49
  env:
50
+ CF_API_URL: "https://api.fr.cloud.gov"
51
+ CF_USER: ${{ secrets.CF_USERNAME }}
52
+ CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
50
53
  TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
51
- TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
52
54
  TF_VAR_rails_master_key: ${{ secrets.RAILS_MASTER_KEY }}
53
55
  TERRAFORM_PRE_RUN: |
54
56
  apt-get update
@@ -47,8 +47,10 @@ jobs:
47
47
  - name: Terraform apply
48
48
  uses: dflook/terraform-apply@v1
49
49
  env:
50
+ CF_API_URL: "https://api.fr.cloud.gov"
51
+ CF_USER: ${{ secrets.CF_USERNAME }}
52
+ CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
50
53
  TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
51
- TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
52
54
  TF_VAR_rails_master_key: ${{ secrets.RAILS_MASTER_KEY }}
53
55
  TERRAFORM_PRE_RUN: |
54
56
  apt-get update
@@ -57,8 +57,10 @@ jobs:
57
57
  - name: terraform plan
58
58
  uses: dflook/terraform-plan@v1
59
59
  env:
60
+ CF_API_URL: "https://api.fr.cloud.gov"
61
+ CF_USER: ${{ secrets.CF_USERNAME }}
62
+ CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
60
63
  TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
61
- TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
62
64
  TF_VAR_rails_master_key: ${{ secrets.RAILS_MASTER_KEY }}
63
65
  TERRAFORM_PRE_RUN: |
64
66
  apt-get update
@@ -57,8 +57,10 @@ jobs:
57
57
  - name: terraform plan
58
58
  uses: dflook/terraform-plan@v1
59
59
  env:
60
+ CF_API_URL: "https://api.fr.cloud.gov"
61
+ CF_USER: ${{ secrets.CF_USERNAME }}
62
+ CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
60
63
  TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
61
- TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
62
64
  TF_VAR_rails_master_key: ${{ secrets.RAILS_MASTER_KEY }}
63
65
  TERRAFORM_PRE_RUN: |
64
66
  apt-get update
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module RailsTemplate18f
6
+ module Generators
7
+ class GitlabCiGenerator < ::Rails::Generators::Base
8
+ include Base
9
+ include CloudGovOptions
10
+
11
+ class_option :node_version, desc: "Node version to test against in actions"
12
+ class_option :postgres_version, default: "15", desc: "PostgreSQL version "
13
+
14
+ desc <<~DESC
15
+ Description:
16
+ Install GitLab CI workflow files
17
+ DESC
18
+
19
+ def install_actions
20
+ template "gitlab-ci.yml", ".gitlab-ci.yml"
21
+ directory "gitlab", ".gitlab"
22
+ end
23
+
24
+ def update_readme
25
+ if file_content("README.md").match?(/^## CI\/CD$/)
26
+ insert_into_file "README.md", readme_cicd, after: "## CI/CD\n"
27
+ insert_into_file "README.md", readme_staging_deploy, after: "#### Staging\n"
28
+ insert_into_file "README.md", readme_prod_deploy, after: "#### Production\n"
29
+ insert_into_file "README.md", readme_credentials, after: "#### Credentials and other Secrets\n"
30
+ else
31
+ append_to_file "README.md", <<~EOM
32
+ ## CI/CD
33
+ #{readme_cicd}
34
+
35
+ ### Deployment
36
+
37
+ #### Staging
38
+ #{readme_staging_deploy}
39
+
40
+ #### Production
41
+ #{readme_prod_deploy}
42
+
43
+ #### Credentials and other Secrets
44
+ #{readme_credentials}
45
+ EOM
46
+ end
47
+ end
48
+
49
+ def update_boundary_diagram
50
+ boundary_filename = "doc/compliance/apps/application.boundary.md"
51
+ insert_into_file boundary_filename, <<EOB, after: "Boundary(cicd, \"CI/CD Pipeline\") {\n"
52
+ System_Ext(gitlabci, "GitLab w/ DevTools Runner", "GSA-controlled code repository and Continuous Integration Service")
53
+ EOB
54
+ insert_into_file boundary_filename, <<~EOB, before: "@enduml"
55
+ Rel(developer, gitlabci, "Publish code", "git ssh (22)")
56
+ Rel(gitlabci, cg_api, "Deploy App", "Auth: SpaceDeployer Service Account, https (443)")
57
+ EOB
58
+ end
59
+
60
+ no_tasks do
61
+ def readme_cicd
62
+ <<~EOM
63
+
64
+ GitLab CI is used to run all tests and scans as part of pull requests.
65
+
66
+ Security scans are also run on a scheduled basis. DEVELOPER TODO: create a pipeline schedule in the GitLab UI and update this sentence with the cadence.
67
+ EOM
68
+ end
69
+
70
+ def readme_staging_deploy
71
+ <<~EOM
72
+
73
+ Deploys to staging happen via terraform on every push to the `main` branch in GitLab.
74
+
75
+ The following secrets must be set within the masked and hidden [CI/CD variables](https://docs.gitlab.com/ci/variables/)
76
+
77
+ | Secret Name | Description |
78
+ | ----------- | ----------- |
79
+ | `CF_USERNAME` | cloud.gov SpaceDeployer username |
80
+ | `CF_PASSWORD` | cloud.gov SpaceDeployer password |
81
+ | `RAILS_MASTER_KEY` | `config/master.key` |
82
+ EOM
83
+ end
84
+
85
+ def readme_prod_deploy
86
+ if terraform_manage_spaces?
87
+ <<~EOM
88
+
89
+ Deploys to production happen via terraform on every push to the `production` branch in GitLab.
90
+
91
+ The following secrets must be set within the masked and hidden [CI/CD variables](https://docs.gitlab.com/ci/variables/)
92
+
93
+ | Secret Name | Description |
94
+ | ----------- | ----------- |
95
+ | `CF_USERNAME` | cloud.gov SpaceDeployer username |
96
+ | `CF_PASSWORD` | cloud.gov SpaceDeployer password |
97
+ | `PRODUCTION_RAILS_MASTER_KEY` | `config/credentials/production.key`. Should be marked as `Protected`. |
98
+ EOM
99
+ else
100
+ "Production deploys are not supported in the sandbox organization."
101
+ end
102
+ end
103
+
104
+ def readme_credentials
105
+ <<~EOM
106
+
107
+ 1. Store variables that must be secret using masked and hidden [CI/CD variables](https://docs.gitlab.com/ci/variables/) in GitLab
108
+ 1. Add the appropriate `-var` arguments to the `terraform:plan:<env>` and `terraform:apply:<env>` jobs like the existing `-var rails_master_key=`
109
+ EOM
110
+ end
111
+ end
112
+
113
+ private
114
+
115
+ def postgres_version
116
+ options[:postgres_version]
117
+ end
118
+
119
+ def node_version
120
+ if options[:node_version].present?
121
+ options[:node_version]
122
+ elsif File.exist?(nvmrc_path)
123
+ File.read(nvmrc_path).strip
124
+ else
125
+ "20.16"
126
+ end
127
+ end
128
+
129
+ def node_major
130
+ node_version.split(".").first
131
+ end
132
+
133
+ def nvmrc_path
134
+ @nvmrc_path ||= File.expand_path(".nvmrc", destination_root)
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,11 @@
1
+ .setup-node:
2
+ - curl -fsSL https://deb.nodesource.com/setup_<%= node_major %>.x -o nodesource_setup.sh
3
+ - bash nodesource_setup.sh
4
+ - apt-get install -y nodejs
5
+ - npm install --global yarn
6
+
7
+ .yarn-install:
8
+ - PUPPETEER_SKIP_DOWNLOAD=true yarn install --frozen-lockfile --no-progress
9
+
10
+ .install-puppet-deps:
11
+ - apt-get update && apt-get install -y chromium
@@ -0,0 +1,75 @@
1
+ include:
2
+ - local: ".gitlab/ruby.yml"
3
+ - local: ".gitlab/node.yml"
4
+
5
+ # Cache Helpers
6
+ .cache-dependencies:
7
+ variables:
8
+ WORKER_MEMORY: 2G
9
+ cache:
10
+ key:
11
+ files:
12
+ - Gemfile.lock
13
+ - yarn.lock
14
+ prefix: dependencies
15
+ paths:
16
+ - vendor/ruby
17
+ - node_modules/
18
+ policy: pull
19
+
20
+ # Language Helpers
21
+ .setup-languages:
22
+ before_script:
23
+ - !reference [.setup-ruby]
24
+ - !reference [.setup-node]
25
+
26
+ # Project Helpers
27
+ .setup-project:
28
+ services:
29
+ - name: "postgres:${POSTGRES_VERSION}"
30
+ alias: pg
31
+ before_script:
32
+ - !reference [.setup-ruby]
33
+ - export DATABASE_URL="postgres://postgres:${POSTGRES_PASSWORD}@${WSR_SERVICE_HOST_pg}:5432/${POSTGRES_DB}"
34
+ - bin/rails db:prepare
35
+
36
+ .run-server:
37
+ extends: .setup-project
38
+ dependencies: []
39
+ variables:
40
+ RAILS_ENV: ci
41
+ SECRET_KEY_BASE_DUMMY: 1
42
+ before_script:
43
+ - !reference [.setup-node]
44
+ - !reference [.setup-project, before_script]
45
+ - bin/rake assets:precompile
46
+ - PORT=3000 bin/rails server > /dev/null 2>&1 &
47
+ - sleep 5
48
+
49
+ .owasp:setup:
50
+ stage: scan
51
+ extends: .run-server
52
+ image: "rcahearngsa/owasp-ruby:${RUBY_VERSION}"
53
+ variables:
54
+ WORKER_MEMORY: 3G
55
+ WORKER_DISK: 6G
56
+ before_script:
57
+ - !reference [.run-server, before_script]
58
+ - ln -s $PWD /zap/wrk
59
+ artifacts:
60
+ expose_as: "OWASP Report"
61
+ paths:
62
+ - zap_report.html
63
+
64
+ .assets:builder:
65
+ stage: deploy
66
+ extends: .setup-languages
67
+ dependencies: []
68
+ variables:
69
+ SECRET_KEY_BASE_DUMMY: 1
70
+ script:
71
+ - bin/rake assets:precompile
72
+ - bin/rake assets:clean
73
+ artifacts:
74
+ paths:
75
+ - public/assets
@@ -0,0 +1,7 @@
1
+ .setup-ruby:
2
+ - export PATH=$PATH:/usr/local/bundle/bin
3
+ - bundle config set --local path 'vendor/ruby'
4
+ - bundle config set --local deployment true
5
+
6
+ .bundle-install:
7
+ - bundle install