From 1d5438ed32a49871487ac0dea948e5900c8aee2a Mon Sep 17 00:00:00 2001 From: Ryan Ahearn Date: Wed, 2 Nov 2022 09:55:56 -0400 Subject: [PATCH] Create demo deploy workflows --- .github/workflows/deploy-demo.yml | 66 ++++++++++++++++++ .github/workflows/deploy.yml | 16 +++-- .github/workflows/terraform-demo.yml | 79 ++++++++++++++++++++++ .github/workflows/terraform-production.yml | 8 +-- .github/workflows/terraform-staging.yml | 3 +- docs/deploying.md | 14 ++-- 6 files changed, 169 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/deploy-demo.yml create mode 100644 .github/workflows/terraform-demo.yml diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml new file mode 100644 index 000000000..0eaef148c --- /dev/null +++ b/.github/workflows/deploy-demo.yml @@ -0,0 +1,66 @@ +name: Deploy to demo environment + +on: + push: [ production ] + +permissions: + contents: read + +jobs: + deploy: + runs-on: ubuntu-latest + environment: demo + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - name: Check for changes to Terraform + id: changed-terraform-files + uses: tj-actions/changed-files@v1.1.2 + with: + files: terraform/demo + - name: Terraform init + if: steps.changed-terraform-files.outputs.any_changed == 'true' + working-directory: terraform/demo + env: + AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }} + run: terraform init + - name: Terraform apply + if: steps.changed-terraform-files.outputs.any_changed == 'true' + working-directory: terraform/demo + env: + AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }} + TF_VAR_cf_user: ${{ secrets.CLOUDGOV_USERNAME }} + TF_VAR_cf_password: ${{ secrets.CLOUDGOV_PASSWORD }} + run: terraform apply -auto-approve -input=false + + - uses: ./.github/actions/setup-project + - name: Install application dependencies + run: make bootstrap + + - name: Create requirements.txt because Cloud Foundry does a weird pipenv thing + run: pipenv requirements > requirements.txt + + - name: Deploy to cloud.gov + uses: 18f/cg-deploy-action@main + env: + DANGEROUS_SALT: ${{ secrets.DANGEROUS_SALT }} + SECRET_KEY: ${{ secrets.SECRET_KEY }} + ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + with: + cf_username: ${{ secrets.CLOUDGOV_USERNAME }} + cf_password: ${{ secrets.CLOUDGOV_PASSWORD }} + cf_org: gsa-10x-prototyping + cf_space: 10x-notifications + push_arguments: >- + --vars-file deploy-config/demo.yml + --var DANGEROUS_SALT="$DANGEROUS_SALT" + --var SECRET_KEY="$SECRET_KEY" + --var ADMIN_CLIENT_SECRET="$ADMIN_CLIENT_SECRET" + --var AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" + --var AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dad470e5d..2a73317d3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: Deploy to prototype environment +name: Deploy to staging environment on: workflow_run: @@ -15,6 +15,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'success' }} + environment: staging steps: - uses: actions/checkout@v3 with: @@ -52,14 +53,14 @@ jobs: - name: Deploy to cloud.gov uses: 18f/cg-deploy-action@main env: - DANGEROUS_SALT: ${{ secrets.PROD_DANGEROUS_SALT }} - SECRET_KEY: ${{ secrets.PROD_SECRET_KEY }} - ADMIN_CLIENT_SECRET: ${{ secrets.PROD_ADMIN_CLIENT_SECRET }} + DANGEROUS_SALT: ${{ secrets.DANGEROUS_SALT }} + SECRET_KEY: ${{ secrets.SECRET_KEY }} + ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} with: - cf_username: ${{ secrets.cloudgov_username }} - cf_password: ${{ secrets.cloudgov_password }} + cf_username: ${{ secrets.CLOUDGOV_USERNAME }} + cf_password: ${{ secrets.CLOUDGOV_PASSWORD }} cf_org: gsa-10x-prototyping cf_space: 10x-notifications push_arguments: >- @@ -74,4 +75,5 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'failure' }} steps: - - run: echo 'Checks failed, not deploying' + - uses: actions/github-script@v6 + script: core.setFailed('Checks failed, not deploying') diff --git a/.github/workflows/terraform-demo.yml b/.github/workflows/terraform-demo.yml new file mode 100644 index 000000000..82c828152 --- /dev/null +++ b/.github/workflows/terraform-demo.yml @@ -0,0 +1,79 @@ +name: Run Terraform plan in demo + +on: + pull_request: + branches: [ production ] + paths: [ 'terraform/**' ] + +defaults: + run: + working-directory: terraform/demo + +jobs: + terraform: + name: Terraform plan + runs-on: ubuntu-latest + environment: demo + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Terraform format + id: format + run: terraform fmt -check + + - name: Terraform init + id: init + env: + AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }} + run: terraform init + + - name: Terraform validate + id: validation + run: terraform validate -no-color + + - name: Terraform plan + id: plan + env: + AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }} + TF_VAR_cf_user: ${{ secrets.CLOUDGOV_USERNAME }} + TF_VAR_cf_password: ${{ secrets.CLOUDGOV_PASSWORD }} + run: terraform plan -no-color -input=false 2>&1 | tee plan_output.txt + + - name: Read Terraform plan output file + id: terraform_output + uses: juliangruber/read-file-action@v1 + if: ${{ always() }} + with: + path: ./terraform/demo/plan_output.txt + + # inspiration: https://learn.hashicorp.com/tutorials/terraform/github-actions#review-actions-workflow + - name: Update PR + uses: actions/github-script@v6 + # we would like to update the PR even when a prior step failed + if: ${{ always() }} + with: + script: | + const output = `Terraform Format and Style: ${{ steps.format.outcome }} + Terraform Initialization: ${{ steps.init.outcome }} + Terraform Validation: ${{ steps.validation.outcome }} + Terraform Plan: ${{ steps.plan.outcome }} + +
Show Plan + + \`\`\`\n + ${{ steps.terraform_output.outputs.content }} + \`\`\` + +
+ + *Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`; + + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: output + }) diff --git a/.github/workflows/terraform-production.yml b/.github/workflows/terraform-production.yml index 7861c3205..dd700a12b 100644 --- a/.github/workflows/terraform-production.yml +++ b/.github/workflows/terraform-production.yml @@ -2,7 +2,7 @@ name: Run Terraform plan in production on: pull_request: - branches: [ production ] + branches: [ production-disabled-for-now ] paths: [ 'terraform/**' ] defaults: @@ -38,8 +38,8 @@ jobs: env: AWS_ACCESS_KEY_ID: ${{ secrets.TERRAFORM_STATE_ACCESS_KEY }} AWS_SECRET_ACCESS_KEY: ${{ secrets.TERRAFORM_STATE_SECRET_ACCESS_KEY }} - TF_VAR_cf_user: ${{ secrets.CF_USERNAME }} - TF_VAR_cf_password: ${{ secrets.CF_PASSWORD }} + TF_VAR_cf_user: ${{ secrets.CLOUDGOV_USERNAME }} + TF_VAR_cf_password: ${{ secrets.CLOUDGOV_PASSWORD }} run: terraform plan -no-color -input=false 2>&1 | tee plan_output.txt - name: Read Terraform plan output file @@ -51,7 +51,7 @@ jobs: # inspiration: https://learn.hashicorp.com/tutorials/terraform/github-actions#review-actions-workflow - name: Update PR - uses: actions/github-script@v4 + uses: actions/github-script@v6 # we would like to update the PR even when a prior step failed if: ${{ always() }} with: diff --git a/.github/workflows/terraform-staging.yml b/.github/workflows/terraform-staging.yml index 5c7d2a6ff..fa5d2dbd8 100644 --- a/.github/workflows/terraform-staging.yml +++ b/.github/workflows/terraform-staging.yml @@ -13,6 +13,7 @@ jobs: terraform: name: Terraform plan runs-on: ubuntu-latest + environment: staging steps: - name: Checkout uses: actions/checkout@v2 @@ -50,7 +51,7 @@ jobs: # inspiration: https://learn.hashicorp.com/tutorials/terraform/github-actions#review-actions-workflow - name: Update PR - uses: actions/github-script@v4 + uses: actions/github-script@v6 # we would like to update the PR even when a prior step failed if: ${{ always() }} with: diff --git a/docs/deploying.md b/docs/deploying.md index 5fa129b01..ff1041b91 100644 --- a/docs/deploying.md +++ b/docs/deploying.md @@ -1,18 +1,22 @@ # Deploying -We deploy automatically to cloud.gov for production and staging environments. +We deploy automatically to cloud.gov for demo and staging environments. -Deployment runs via the [deployment action](../.github/workflows/deploy.yml) on GitHub, which pulls credentials from GitHub's secrets store. +Deployment to staging runs via the [base deployment action](../.github/workflows/deploy.yml) on GitHub, which pulls credentials from GitHub's secrets store in the staging environment. + +Deployment to demo runs via the [demo deployment action](../.github/workflows/deploy-demo.yml) on GitHub, which pulls credentials from GitHub's secrets store in the demo environment. The [action that we use](https://github.com/18F/cg-deploy-action) deploys using [a rolling strategy](https://docs.cloudfoundry.org/devguide/deploy-apps/rolling-deploy.html), so all deployments should have zero downtime. The API has 2 deployment environments: -- Production, which deploys from `main` -- Staging, which does not, in fact, exist +- Staging, which deploys from `main` +- Demo, which deploys from `production` + +In the future, we will add a Production deploy environment, which will deploy in parallel to Demo. Configurations for these are located in [the `deploy-config` folder](../deploy-config/). In the event that a deployment includes a Terraform change, that change will run before any code is deployed to the environment. Each environment has its own Terraform GitHub Action to handle that change. -Failures in any of these GitHub workflows will be surfaced in the Pull Request related to the code change, and in the case of `checks.yml` actively prevent the PR from being merged. Failure in the Terraform workflow will not actively prevent the PR from being merged, but reviewers should not approve a PR with a failing terraform plan. \ No newline at end of file +Failures in any of these GitHub workflows will be surfaced in the Pull Request related to the code change, and in the case of `checks.yml` actively prevent the PR from being merged. Failure in the Terraform workflow will not actively prevent the PR from being merged, but reviewers should not approve a PR with a failing terraform plan.