diff --git a/.github/workflows/apply.yml b/.github/workflows/apply.yml index f2a89be..ee5b042 100644 --- a/.github/workflows/apply.yml +++ b/.github/workflows/apply.yml @@ -1,41 +1,46 @@ -name: Apply Terraform +name: "Terraform Apply" on: push: branches: - main +env: + TF_CLOUD_ORGANIZATION: "Decatur-Robotics" + TF_API_TOKEN: "${{ secrets.TF_API_TOKEN }}" + TF_WORKSPACE: "Gearbox-Terraform" + CONFIG_DIRECTORY: "./" + jobs: - terraform-validate: - uses: ./.github/workflows/validate.yml - terraform-apply: + terraform: + if: github.repository != 'hashicorp-education/learn-terraform-github-actions' + name: "Terraform Apply" runs-on: ubuntu-latest - needs: terraform-validate - permissions: - contents: write + permissions: # granular permissions + # so GitHub can check out this repo using the default github.token + contents: read steps: - name: Checkout - uses: actions/checkout@v4 - - - uses: actions/checkout@v2 - - name: Terraform Apply - uses: dflook/terraform-apply@61432ffb5b94226bdfc9cd68a1702a2c40e0db8b - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} - - name: Increment Version + uses: actions/checkout@v3 - - name: Set name - run: git config user.name "Gearbox Bot" + - name: Upload Configuration + uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.0.0 + id: apply-upload + with: + workspace: ${{ env.TF_WORKSPACE }} + directory: ${{ env.CONFIG_DIRECTORY }} - - name: Set email - run: git config user.email "gearbox@decaturrobotics.org" + - name: Create Apply Run + uses: hashicorp/tfc-workflows-github/actions/create-run@v1.0.0 + id: apply-run + with: + workspace: ${{ env.TF_WORKSPACE }} + configuration_version: ${{ steps.apply-upload.outputs.configuration_version_id }} - - name: Push changes - uses: ad-m/github-push-action@v0.8.0 + - name: Apply + uses: hashicorp/tfc-workflows-github/actions/apply-run@v1.0.0 + if: fromJSON(steps.apply-run.outputs.payload).data.attributes.actions.IsConfirmable + id: apply with: - github_token: ${{ secrets.GIT_PUSH_TOKEN }} - branch: ${{ github.head_ref }} + run: ${{ steps.apply-run.outputs.run_id }} + comment: "Apply Run from GitHub Actions CI ${{ github.sha }}" diff --git a/.github/workflows/plan.yml b/.github/workflows/plan.yml index 4de91aa..150b153 100644 --- a/.github/workflows/plan.yml +++ b/.github/workflows/plan.yml @@ -1,22 +1,81 @@ -name: Plan Terraform +name: "Terraform Plan" on: pull_request: - branches: - - main + +env: + TF_CLOUD_ORGANIZATION: "Decatur-Robotics" + TF_API_TOKEN: "${{ secrets.TF_API_TOKEN }}" + TF_WORKSPACE: "Gearbox-Terraform" + CONFIG_DIRECTORY: "./" jobs: - terraform-plan: + terraform: + if: github.repository != 'hashicorp-education/learn-terraform-github-actions' + name: "Terraform Plan" runs-on: ubuntu-latest permissions: + # so GitHub can check out this repo using the default github.token contents: read pull-requests: write steps: - - uses: actions/checkout@v2 - - name: Terraform Plan - uses: dflook/terraform-plan@a6967bcc161f0df654b5df2f1f00eca83a4cbad9 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + - name: Checkout + uses: actions/checkout@v3 + + - name: Upload Configuration + uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.0.0 + id: plan-upload + with: + workspace: ${{ env.TF_WORKSPACE }} + directory: ${{ env.CONFIG_DIRECTORY }} + speculative: true + + - name: Create Plan Run + uses: hashicorp/tfc-workflows-github/actions/create-run@v1.0.0 + id: plan-run + with: + workspace: ${{ env.TF_WORKSPACE }} + configuration_version: ${{ steps.plan-upload.outputs.configuration_version_id }} + plan_only: true + + - name: Get Plan Output + uses: hashicorp/tfc-workflows-github/actions/plan-output@v1.0.0 + id: plan-output + with: + plan: ${{ fromJSON(steps.plan-run.outputs.payload).data.relationships.plan.data.id }} + + - name: Update PR + uses: actions/github-script@v6 + id: plan-comment + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // 1. Retrieve existing bot comments for the PR + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const botComment = comments.find(comment => { + return comment.user.type === 'Bot' && comment.body.includes('Terraform Cloud Plan Output') + }); + const output = `#### Terraform Cloud Plan Output + \`\`\` + Plan: ${{ steps.plan-output.outputs.add }} to add, ${{ steps.plan-output.outputs.change }} to change, ${{ steps.plan-output.outputs.destroy }} to destroy. + \`\`\` + [Terraform Cloud Plan](${{ steps.plan-run.outputs.run_link }}) + `; + // 3. Delete previous comment so PR timeline makes sense + if (botComment) { + github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + }); + } + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: output + }); diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index d1ff10c..22f9a3d 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -9,6 +9,7 @@ on: jobs: terraform-validate: runs-on: ubuntu-latest + name: "Terraform Validate" steps: - uses: actions/checkout@v2 - name: terraform-validate diff --git a/GearboxInfrastructure.jpg b/GearboxInfrastructure.jpg new file mode 100644 index 0000000..9cdc8e2 Binary files /dev/null and b/GearboxInfrastructure.jpg differ diff --git a/README.md b/README.md index 1a6d565..63395cc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ # Gearbox-Terraform + Terraform configuration for [Gearbox](https://github.com/Decatur-Robotics/Gearbox). + +## Infrastructure Overview + +![Infrastructure Diagram](GearboxInfrastructure.jpg) + +Gearbox has a few core components: + +- **AWS ECS** - The Gearbox servers themselves run on AWS ECS. +- **Cloudflare** - Our domain is connected to Cloudflare and we get SSL certificates from them. _Cloudflare is not fully managed by Terraform - only some of the DNS records are._ +- **HashiCorp Managed Terraform** - Handles deployment for Terraform, but not the main Gearbox repo. +- **GitHub Actions** - Deployment and checks for the main Gearbox repo. +- **AWS S3** - Secrets are stored in an S3 bucket. +- **MongoDB Atlas** - The database is hosted on MongoDB Atlas. _MongoDB Atlas is not managed by Terraform._ + +## Licensed under a CC BY-NC-SA 4.0 license + +Read the license [here](LICENSE.md).