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
@@ -0,0 +1,44 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
|
6
|
+
# This workflow integrates Brakeman with GitHub's Code Scanning feature
|
7
|
+
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
|
8
|
+
|
9
|
+
name: Brakeman Scan
|
10
|
+
|
11
|
+
on:
|
12
|
+
push:
|
13
|
+
branches: [ main ]
|
14
|
+
paths-ignore:
|
15
|
+
- 'doc/**'
|
16
|
+
- 'README.md'
|
17
|
+
pull_request:
|
18
|
+
# The branches below must be a subset of the branches above
|
19
|
+
branches: [ main ]
|
20
|
+
schedule:
|
21
|
+
# cron format: 'minute hour dayofmonth month dayofweek'
|
22
|
+
# this will run at noon UTC each Monday (7am EST / 8am EDT)
|
23
|
+
- cron: '0 12 * * 1'
|
24
|
+
|
25
|
+
jobs:
|
26
|
+
brakeman-scan:
|
27
|
+
name: Brakeman Scan
|
28
|
+
runs-on: ubuntu-latest
|
29
|
+
steps:
|
30
|
+
- uses: actions/checkout@v2
|
31
|
+
|
32
|
+
- uses: ./.github/actions/setup-languages
|
33
|
+
|
34
|
+
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
|
35
|
+
- name: Scan
|
36
|
+
continue-on-error: true
|
37
|
+
run: |
|
38
|
+
bundle exec brakeman -f sarif -o output.sarif.json .
|
39
|
+
|
40
|
+
# Upload the SARIF file generated in the previous step
|
41
|
+
- name: Upload SARIF
|
42
|
+
uses: github/codeql-action/upload-sarif@v1
|
43
|
+
with:
|
44
|
+
sarif_file: output.sarif.json
|
data/lib/generators/rails_template18f/github_actions/templates/github/workflows/dependency-scans.yml
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
name: Ruby and Javascript dependency scans
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
paths-ignore:
|
7
|
+
- 'doc/**'
|
8
|
+
- 'README.md'
|
9
|
+
pull_request:
|
10
|
+
branches: [ main ]
|
11
|
+
schedule:
|
12
|
+
# cron format: 'minute hour dayofmonth month dayofweek'
|
13
|
+
# this will run at noon UTC every day (7am EST / 8am EDT)
|
14
|
+
- cron: '0 12 * * *'
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
bundle-audit:
|
18
|
+
name: Bundle audit
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v2
|
23
|
+
|
24
|
+
- uses: ./.github/actions/setup-languages
|
25
|
+
|
26
|
+
- name: Update advisory database and run checks
|
27
|
+
run: bundle exec rake bundler:audit
|
28
|
+
|
29
|
+
yarn-audit:
|
30
|
+
name: Yarn audit
|
31
|
+
runs-on: ubuntu-latest
|
32
|
+
|
33
|
+
steps:
|
34
|
+
- uses: actions/checkout@v2
|
35
|
+
|
36
|
+
- uses: ./.github/actions/setup-languages
|
37
|
+
|
38
|
+
- name: Run yarn audit
|
39
|
+
run: bundle exec rake yarn:audit
|
@@ -0,0 +1,53 @@
|
|
1
|
+
name: Deploy Production
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ production ]
|
6
|
+
paths-ignore:
|
7
|
+
- 'doc/**'
|
8
|
+
- 'README.md'
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
deploy:
|
12
|
+
name: Deploy to production
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
environment: production
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v2
|
17
|
+
with:
|
18
|
+
fetch-depth: 2
|
19
|
+
<% if terraform? %>
|
20
|
+
- name: Check for changes to Terraform
|
21
|
+
id: changed-terraform-files
|
22
|
+
uses: tj-actions/changed-files@v1.1.2
|
23
|
+
with:
|
24
|
+
files: |
|
25
|
+
terraform/shared
|
26
|
+
terraform/production
|
27
|
+
- name: Terraform init
|
28
|
+
if: steps.changed-terraform-files.outputs.any_changed == 'true'
|
29
|
+
working-directory: terraform/production
|
30
|
+
env:
|
31
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
32
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
33
|
+
run: terraform init
|
34
|
+
- name: Terraform apply
|
35
|
+
if: steps.changed-terraform-files.outputs.any_changed == 'true'
|
36
|
+
working-directory: terraform/production
|
37
|
+
env:
|
38
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
39
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
40
|
+
TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
|
41
|
+
TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
|
42
|
+
run: terraform apply -auto-approve -input=false
|
43
|
+
<% end %>
|
44
|
+
- name: Deploy app
|
45
|
+
uses: 18F/cg-deploy-action@main
|
46
|
+
env:
|
47
|
+
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
|
48
|
+
with:
|
49
|
+
cf_username: ${{ secrets.CF_USERNAME }}
|
50
|
+
cf_password: ${{ secrets.CF_PASSWORD }}
|
51
|
+
cf_org: <%= cloud_gov_organization %>
|
52
|
+
cf_space: <%= cloud_gov_production_space %>
|
53
|
+
push_arguments: "--vars-file config/deployment/production.yml --var rails_master_key=$RAILS_MASTER_KEY"
|
@@ -0,0 +1,53 @@
|
|
1
|
+
name: Deploy Staging
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
paths-ignore:
|
7
|
+
- 'doc/**'
|
8
|
+
- 'README.md'
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
deploy:
|
12
|
+
name: Deploy to staging
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
environment: staging
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v2
|
17
|
+
with:
|
18
|
+
fetch-depth: 2
|
19
|
+
<% if terraform? %>
|
20
|
+
- name: Check for changes to Terraform
|
21
|
+
id: changed-terraform-files
|
22
|
+
uses: tj-actions/changed-files@v1.1.2
|
23
|
+
with:
|
24
|
+
files: |
|
25
|
+
terraform/shared
|
26
|
+
terraform/staging
|
27
|
+
- name: Terraform init
|
28
|
+
if: steps.changed-terraform-files.outputs.any_changed == 'true'
|
29
|
+
working-directory: terraform/staging
|
30
|
+
env:
|
31
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
32
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
33
|
+
run: terraform init
|
34
|
+
- name: Terraform apply
|
35
|
+
if: steps.changed-terraform-files.outputs.any_changed == 'true'
|
36
|
+
working-directory: terraform/staging
|
37
|
+
env:
|
38
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
39
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
40
|
+
TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
|
41
|
+
TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
|
42
|
+
run: terraform apply -auto-approve -input=false
|
43
|
+
<% end %>
|
44
|
+
- name: Deploy app
|
45
|
+
uses: 18F/cg-deploy-action@main
|
46
|
+
env:
|
47
|
+
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
|
48
|
+
with:
|
49
|
+
cf_username: ${{ secrets.CF_USERNAME }}
|
50
|
+
cf_password: ${{ secrets.CF_PASSWORD }}
|
51
|
+
cf_org: <%= cloud_gov_organization %>
|
52
|
+
cf_space: <%= cloud_gov_staging_space %>
|
53
|
+
push_arguments: "--vars-file config/deployment/staging.yml --var rails_master_key=$RAILS_MASTER_KEY"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
name: OWASP ZAP daily scan
|
2
|
+
|
3
|
+
on:
|
4
|
+
schedule:
|
5
|
+
# cron format: 'minute hour dayofmonth month dayofweek'
|
6
|
+
# this will run at noon UTC every day (7am EST / 8am EDT)
|
7
|
+
- cron: '0 12 * * *'
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
owasp-scan:
|
11
|
+
name: OWASP ZAP Scan
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
services:
|
14
|
+
postgres:
|
15
|
+
image: postgres
|
16
|
+
options: >-
|
17
|
+
--health-cmd pg_isready
|
18
|
+
--health-interval 10s
|
19
|
+
--health-timeout 5s
|
20
|
+
--health-retries 5
|
21
|
+
ports: ["5432:5432"]
|
22
|
+
env:
|
23
|
+
POSTGRES_DB: <%= app_name %>_test
|
24
|
+
POSTGRES_USER: cidbuser
|
25
|
+
POSTGRES_PASSWORD: postgres
|
26
|
+
|
27
|
+
steps:
|
28
|
+
- uses: actions/checkout@v2
|
29
|
+
|
30
|
+
- id: setup
|
31
|
+
uses: ./.github/actions/setup-project
|
32
|
+
|
33
|
+
- uses: ./.github/actions/run-server
|
34
|
+
with:
|
35
|
+
database_url: ${{ steps.setup.outputs.database_url }}
|
36
|
+
|
37
|
+
- name: Run OWASP Full Scan
|
38
|
+
uses: zaproxy/action-full-scan@v0.3.0
|
39
|
+
with:
|
40
|
+
docker_name: 'owasp/zap2docker-weekly'
|
41
|
+
target: 'http://localhost:3000/'
|
42
|
+
fail_action: true
|
43
|
+
rules_file_name: 'zap.conf'
|
44
|
+
cmd_options: '-I'
|
data/lib/generators/rails_template18f/github_actions/templates/github/workflows/owasp-scan.yml.tt
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
name: OWASP ZAP scan
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
paths-ignore:
|
7
|
+
- 'doc/**'
|
8
|
+
- 'README.md'
|
9
|
+
pull_request:
|
10
|
+
branches: [ main ]
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
owasp-scan:
|
14
|
+
name: OWASP ZAP Scan
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
services:
|
17
|
+
postgres:
|
18
|
+
image: postgres
|
19
|
+
options: >-
|
20
|
+
--health-cmd pg_isready
|
21
|
+
--health-interval 10s
|
22
|
+
--health-timeout 5s
|
23
|
+
--health-retries 5
|
24
|
+
ports: ["5432:5432"]
|
25
|
+
env:
|
26
|
+
POSTGRES_DB: <%= app_name %>_test
|
27
|
+
POSTGRES_USER: cidbuser
|
28
|
+
POSTGRES_PASSWORD: postgres
|
29
|
+
|
30
|
+
steps:
|
31
|
+
- uses: actions/checkout@v2
|
32
|
+
|
33
|
+
- id: setup
|
34
|
+
uses: ./.github/actions/setup-project
|
35
|
+
|
36
|
+
- uses: ./.github/actions/run-server
|
37
|
+
with:
|
38
|
+
database_url: ${{ steps.setup.outputs.database_url }}
|
39
|
+
|
40
|
+
- name: Run OWASP Baseline Scan
|
41
|
+
uses: zaproxy/action-baseline@v0.6.1
|
42
|
+
with:
|
43
|
+
docker_name: 'owasp/zap2docker-weekly'
|
44
|
+
target: 'http://localhost:3000/'
|
45
|
+
fail_action: true
|
46
|
+
rules_file_name: 'zap.conf'
|
47
|
+
cmd_options: '-I'
|
@@ -0,0 +1,65 @@
|
|
1
|
+
name: pa11y tests
|
2
|
+
|
3
|
+
on: [pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
pa11y_scan:
|
7
|
+
name: Pa11y Scan
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
services:
|
10
|
+
postgres:
|
11
|
+
image: postgres
|
12
|
+
options: >-
|
13
|
+
--health-cmd pg_isready
|
14
|
+
--health-interval 10s
|
15
|
+
--health-timeout 5s
|
16
|
+
--health-retries 5
|
17
|
+
ports: ["5432:5432"]
|
18
|
+
env:
|
19
|
+
POSTGRES_DB: <%= app_name %>_test
|
20
|
+
POSTGRES_USER: cidbuser
|
21
|
+
POSTGRES_PASSWORD: postgres
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- uses: actions/checkout@v2
|
25
|
+
|
26
|
+
- id: setup
|
27
|
+
uses: ./.github/actions/setup-project
|
28
|
+
|
29
|
+
- uses: ./.github/actions/run-server
|
30
|
+
with:
|
31
|
+
database_url: ${{ steps.setup.outputs.database_url }}
|
32
|
+
|
33
|
+
- name: Run pa11y-ci
|
34
|
+
shell: bash
|
35
|
+
run: |
|
36
|
+
set -o pipefail
|
37
|
+
yarn run pa11y-ci 2>&1 | tee pa11y_output.txt
|
38
|
+
|
39
|
+
- name: Read pa11y_output file.
|
40
|
+
if: failure()
|
41
|
+
id: pa11y_output
|
42
|
+
uses: juliangruber/read-file-action@v1
|
43
|
+
with:
|
44
|
+
path: ./pa11y_output.txt
|
45
|
+
|
46
|
+
- name: Comment on pull request
|
47
|
+
if: failure()
|
48
|
+
uses: actions/github-script@v4
|
49
|
+
with:
|
50
|
+
script: |
|
51
|
+
const output = `Pa11y Failures detected
|
52
|
+
|
53
|
+
<details><summary>Show failure message</summary>
|
54
|
+
|
55
|
+
\`\`\`\n
|
56
|
+
${{ steps.pa11y_output.outputs.content }}
|
57
|
+
\`\`\`
|
58
|
+
</details>`;
|
59
|
+
|
60
|
+
github.issues.createComment({
|
61
|
+
issue_number: context.issue.number,
|
62
|
+
owner: context.repo.owner,
|
63
|
+
repo: context.repo.repo,
|
64
|
+
body: output
|
65
|
+
});
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: rspec tests
|
2
|
+
|
3
|
+
on: [pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
rspec:
|
7
|
+
name: Rspec
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
services:
|
10
|
+
postgres:
|
11
|
+
image: postgres
|
12
|
+
options: >-
|
13
|
+
--health-cmd pg_isready
|
14
|
+
--health-interval 10s
|
15
|
+
--health-timeout 5s
|
16
|
+
--health-retries 5
|
17
|
+
ports: ["5432:5432"]
|
18
|
+
env:
|
19
|
+
POSTGRES_DB: <%= app_name %>_test
|
20
|
+
POSTGRES_USER: cidbuser
|
21
|
+
POSTGRES_PASSWORD: postgres
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- uses: actions/checkout@v2
|
25
|
+
|
26
|
+
- id: setup
|
27
|
+
uses: ./.github/actions/setup-project
|
28
|
+
with:
|
29
|
+
rails_env: test
|
30
|
+
|
31
|
+
- name: Run rspec
|
32
|
+
env:
|
33
|
+
DATABASE_URL: ${{ steps.setup.outputs.database_url }}
|
34
|
+
run: bundle exec rspec
|
@@ -0,0 +1,79 @@
|
|
1
|
+
name: Run Terraform plan in production
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
branches: [ production ]
|
6
|
+
paths: [ 'terraform/**' ]
|
7
|
+
|
8
|
+
defaults:
|
9
|
+
run:
|
10
|
+
working-directory: terraform/production
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
terraform:
|
14
|
+
name: Terraform plan
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
environment: production
|
17
|
+
steps:
|
18
|
+
- name: Checkout
|
19
|
+
uses: actions/checkout@v2
|
20
|
+
|
21
|
+
- name: Terraform format
|
22
|
+
id: format
|
23
|
+
run: terraform fmt -check
|
24
|
+
|
25
|
+
- name: Terraform init
|
26
|
+
id: init
|
27
|
+
env:
|
28
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
29
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
30
|
+
run: terraform init
|
31
|
+
|
32
|
+
- name: Terraform validate
|
33
|
+
id: validation
|
34
|
+
run: terraform validate -no-color
|
35
|
+
|
36
|
+
- name: Terraform plan
|
37
|
+
id: plan
|
38
|
+
env:
|
39
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
40
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
41
|
+
TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
|
42
|
+
TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
|
43
|
+
run: terraform plan -no-color -input=false 2>&1 | tee plan_output.txt
|
44
|
+
|
45
|
+
- name: Read Terraform plan output file
|
46
|
+
id: terraform_output
|
47
|
+
uses: juliangruber/read-file-action@v1
|
48
|
+
if: ${{ always() }}
|
49
|
+
with:
|
50
|
+
path: ./terraform/production/plan_output.txt
|
51
|
+
|
52
|
+
# inspiration: https://learn.hashicorp.com/tutorials/terraform/github-actions#review-actions-workflow
|
53
|
+
- name: Update PR
|
54
|
+
uses: actions/github-script@v4
|
55
|
+
# we would like to update the PR even when a prior step failed
|
56
|
+
if: ${{ always() }}
|
57
|
+
with:
|
58
|
+
script: |
|
59
|
+
const output = `Terraform Format and Style: ${{ steps.format.outcome }}
|
60
|
+
Terraform Initialization: ${{ steps.init.outcome }}
|
61
|
+
Terraform Validation: ${{ steps.validation.outcome }}
|
62
|
+
Terraform Plan: ${{ steps.plan.outcome }}
|
63
|
+
|
64
|
+
<details><summary>Show Plan</summary>
|
65
|
+
|
66
|
+
\`\`\`\n
|
67
|
+
${{ steps.terraform_output.outputs.content }}
|
68
|
+
\`\`\`
|
69
|
+
|
70
|
+
</details>
|
71
|
+
|
72
|
+
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
|
73
|
+
|
74
|
+
github.issues.createComment({
|
75
|
+
issue_number: context.issue.number,
|
76
|
+
owner: context.repo.owner,
|
77
|
+
repo: context.repo.repo,
|
78
|
+
body: output
|
79
|
+
})
|
@@ -0,0 +1,79 @@
|
|
1
|
+
name: Run Terraform plan in staging
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
branches: [ main ]
|
6
|
+
paths: [ 'terraform/**' ]
|
7
|
+
|
8
|
+
defaults:
|
9
|
+
run:
|
10
|
+
working-directory: terraform/staging
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
terraform:
|
14
|
+
name: Terraform plan
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
environment: staging
|
17
|
+
steps:
|
18
|
+
- name: Checkout
|
19
|
+
uses: actions/checkout@v2
|
20
|
+
|
21
|
+
- name: Terraform format
|
22
|
+
id: format
|
23
|
+
run: terraform fmt -check
|
24
|
+
|
25
|
+
- name: Terraform init
|
26
|
+
id: init
|
27
|
+
env:
|
28
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
29
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
30
|
+
run: terraform init
|
31
|
+
|
32
|
+
- name: Terraform validate
|
33
|
+
id: validation
|
34
|
+
run: terraform validate -no-color
|
35
|
+
|
36
|
+
- name: Terraform plan
|
37
|
+
id: plan
|
38
|
+
env:
|
39
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }}
|
40
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }}
|
41
|
+
TF_VAR_cf_user: ${{ secrets.CF_USERNAME }}
|
42
|
+
TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }}
|
43
|
+
run: terraform plan -no-color -input=false 2>&1 | tee plan_output.txt
|
44
|
+
|
45
|
+
- name: Read Terraform plan output file
|
46
|
+
id: terraform_output
|
47
|
+
uses: juliangruber/read-file-action@v1
|
48
|
+
if: ${{ always() }}
|
49
|
+
with:
|
50
|
+
path: ./terraform/staging/plan_output.txt
|
51
|
+
|
52
|
+
# inspiration: https://learn.hashicorp.com/tutorials/terraform/github-actions#review-actions-workflow
|
53
|
+
- name: Update PR
|
54
|
+
uses: actions/github-script@v4
|
55
|
+
# we would like to update the PR even when a prior step failed
|
56
|
+
if: ${{ always() }}
|
57
|
+
with:
|
58
|
+
script: |
|
59
|
+
const output = `Terraform Format and Style: ${{ steps.format.outcome }}
|
60
|
+
Terraform Initialization: ${{ steps.init.outcome }}
|
61
|
+
Terraform Validation: ${{ steps.validation.outcome }}
|
62
|
+
Terraform Plan: ${{ steps.plan.outcome }}
|
63
|
+
|
64
|
+
<details><summary>Show Plan</summary>
|
65
|
+
|
66
|
+
\`\`\`\n
|
67
|
+
${{ steps.terraform_output.outputs.content }}
|
68
|
+
\`\`\`
|
69
|
+
|
70
|
+
</details>
|
71
|
+
|
72
|
+
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
|
73
|
+
|
74
|
+
github.issues.createComment({
|
75
|
+
issue_number: context.issue.number,
|
76
|
+
owner: context.repo.owner,
|
77
|
+
repo: context.repo.repo,
|
78
|
+
body: output
|
79
|
+
})
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsTemplate18f
|
4
|
+
module TerraformOptions
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_option :cg_org, desc: "cloud.gov organization name"
|
9
|
+
class_option :cg_staging, desc: "cloud.gov space name for staging"
|
10
|
+
class_option :cg_prod, desc: "cloud.gov space name for production"
|
11
|
+
class_option :terraform, type: :boolean, desc: "Generate actions for planning and applying terraform"
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def ruby_version
|
17
|
+
RUBY_VERSION
|
18
|
+
end
|
19
|
+
|
20
|
+
def terraform?
|
21
|
+
options[:terraform].nil? ? terraform_dir_exists? : options[:terraform]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cloud_gov_organization
|
25
|
+
if options[:cg_org].present?
|
26
|
+
return options[:cg_org]
|
27
|
+
elsif terraform_dir_exists?
|
28
|
+
staging_main = File.read(terraform_path.join("staging", "main.tf"))
|
29
|
+
if (matches = staging_main.match(/cf_org_name\s+= "(?<org_name>.*)"/))
|
30
|
+
return matches[:org_name]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
"TKTK-cloud.gov-org-name"
|
34
|
+
end
|
35
|
+
|
36
|
+
def cloud_gov_staging_space
|
37
|
+
if options[:cg_staging].present?
|
38
|
+
return options[:cg_staging]
|
39
|
+
elsif terraform_dir_exists?
|
40
|
+
staging_main = File.read(terraform_path.join("staging", "main.tf"))
|
41
|
+
if (matches = staging_main.match(/cf_space_name\s+= "(?<space_name>.*)"/))
|
42
|
+
return matches[:space_name]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
"staging"
|
46
|
+
end
|
47
|
+
|
48
|
+
def cloud_gov_production_space
|
49
|
+
if options[:cg_prod].present?
|
50
|
+
return options[:cg_prod]
|
51
|
+
elsif terraform_dir_exists?
|
52
|
+
prod_main = File.read(terraform_path.join("production", "main.tf"))
|
53
|
+
if (matches = prod_main.match(/cf_space_name\s+= "(?<space_name>.*)"/))
|
54
|
+
return matches[:space_name]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
"prod"
|
58
|
+
end
|
59
|
+
|
60
|
+
def terraform_path
|
61
|
+
Pathname.new File.expand_path("terraform", destination_root)
|
62
|
+
end
|
63
|
+
|
64
|
+
def terraform_dir_exists?
|
65
|
+
Dir.exist? terraform_path
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "rails_template18f/version"
|
4
|
+
|
5
|
+
module RailsTemplate18f
|
6
|
+
extend ActiveSupport::Autoload
|
7
|
+
|
8
|
+
autoload :TerraformOptions
|
9
|
+
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
class Railtie < ::Rails::Railtie; end
|
13
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/rails_template18f/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rails_template_18f"
|
7
|
+
spec.version = RailsTemplate18f::VERSION
|
8
|
+
spec.authors = ["Ryan Ahearn"]
|
9
|
+
spec.email = ["ryan.ahearn@gsa.gov"]
|
10
|
+
|
11
|
+
spec.summary = "Generators for creating an 18F-flavored Rails app"
|
12
|
+
spec.homepage = "https://github.com/18f/rails-template"
|
13
|
+
spec.required_ruby_version = ">= 2.7.5"
|
14
|
+
|
15
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org/"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/18f/rails-template"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/18f/rails-template/blob/main/CHANGELOG.md"
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
# For more information and examples about making a new gem, checkout our
|
33
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
34
|
+
spec.add_dependency "railties", "~> 7.0.0"
|
35
|
+
spec.add_dependency "activesupport", "~> 7.0.0"
|
36
|
+
|
37
|
+
spec.add_development_dependency "rspec", "~> 3.11"
|
38
|
+
spec.add_development_dependency "ammeter", "~> 1.1"
|
39
|
+
spec.add_development_dependency "standard", "~> 1.3"
|
40
|
+
end
|