diff --git a/.github/workflows/deploy-daily-snapshot.yml b/.github/workflows/deploy-daily-snapshot.yml index 224be8b77..332961d56 100644 --- a/.github/workflows/deploy-daily-snapshot.yml +++ b/.github/workflows/deploy-daily-snapshot.yml @@ -1,26 +1,28 @@ -name: Snapshot Service +name: Deploy Snapshot Service concurrency: ci-${{ github.ref }} on: pull_request: branches: - main - paths: - - 'terraform/daily_snapshot/**' - - 'terraform/modules/daily_snapshot/**' + # paths: + # - 'tf-managed/modules/daily_snapshot/**' + # - 'tf-managed/scripts/**' + # - 'tf-managed/live/environments/prod/applications/snapshot-service' # This needs to be declared explicitly so that the job is actually # run when moved out of draft. types: [opened, synchronize, reopened, ready_for_review] push: branches: - main - paths: - - 'terraform/daily_snapshot/**' - - 'terraform/modules/daily_snapshot/**' + # paths: + # - 'tf-managed/modules/daily_snapshot/**' + # - 'tf-managed/scripts/**' + # - 'tf-managed/live/environments/prod/applications/snapshot-service' workflow_dispatch: jobs: - deploy-daily-snapshot-calibnet: + deploy-daily-snapshot: name: Deploy runs-on: ubuntu-latest permissions: write-all @@ -28,18 +30,17 @@ jobs: - name: Checkout the code uses: actions/checkout@v4 - # Using Custom Composite action in ./composite-action/terraform folder - - name: Composite Action for Deploying Terraform Resources - uses: ./composite-action/terraform + # Using Custom Composite action in ./composite-action/terragrunt folder + - name: Composite Action for Deploying Terragrunt Resources + uses: ./composite-action/terragrunt with: do_token: ${{ secrets.DO_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }} r2_access_key: ${{ secrets.R2_ACCESS_KEY }} r2_secret_key: ${{ secrets.R2_SECRET_KEY }} slack_token: ${{ secrets.SLACK_TOKEN }} - working_directory: terraform/daily_snapshot/prod + working_directory: tf-managed/live/environments/prod/applications/snapshot-service environment: Snapshot Service new_relic_account_id: ${{ secrets.NEW_RELIC_ACCOUNT_ID }} new_relic_api_key: ${{ secrets.NEW_RELIC_API_KEY }} diff --git a/.tflint.hcl b/.tflint.hcl index f8979ce8f..18e65e468 100644 --- a/.tflint.hcl +++ b/.tflint.hcl @@ -1,5 +1,5 @@ plugin "terraform" { - enabled = true - version = "0.2.2" - source = "github.com/terraform-linters/tflint-ruleset-terraform" + enabled = true + version = "0.5.0" + source = "github.com/terraform-linters/tflint-ruleset-terraform" } diff --git a/composite-action/terragrunt/action.yml b/composite-action/terragrunt/action.yml new file mode 100644 index 000000000..3bb0ce2ed --- /dev/null +++ b/composite-action/terragrunt/action.yml @@ -0,0 +1,182 @@ +name: Custom Composite action to deploy terragrunt resources + +description: | + This action deploys the Forest infrastructure with Terragrunt + +inputs: + environment: + description: 'The terraform plan for the the environment infrastructure to be deployed' + required: true + do_token: + description: 'The DigitalOcean access token to use for deploying the infrastructure' + required: true + aws_access_key_id: + description: 'S3 access keys id used by terraform and service like sync check, Deploy Snapshot Service etc' + required: true + aws_secret_access_key: + description: 'S3 secret access keys used by terraform and service like sync check, Deploy Snapshot Service etc' + required: true + working_directory: + description: 'The working Directory' + required: true + slack_token: + description: 'The slack token secret used to connect the Infrastructure to Slack' + new_relic_api_key: + description: 'The New Relic API KEY' + nr_license_key: + description: 'The New Relic Access Token' + new_relic_account_id: + description: 'The New Relic Platform Region' + r2_access_key: + description: 'CloudFlare R2 access key id' + r2_secret_key: + description: 'CloudFlare R2 private access key' + +runs: + using: "composite" + steps: + # Workaround for https://github.com/orgs/community/discussions/51280 + - name: Set TF/TG versions + shell: bash + run: | + echo "tf_version=1.6.6" >> $GITHUB_ENV + echo "tg_version=0.53.2" >> $GITHUB_ENV + + - name: Check terragrunt HCL + uses: gruntwork-io/terragrunt-action@v2 + with: + tf_version: ${{ env.tf_version }} + tg_version: ${{ env.tg_version }} + tg_dir: ${{ inputs.working_directory }} + tg_command: 'hclfmt --terragrunt-check --terragrunt-diff' + + - name: Validate + uses: gruntwork-io/terragrunt-action@v2 + with: + tf_version: ${{ env.tf_version }} + tg_version: ${{ env.tg_version }} + tg_dir: ${{ inputs.working_directory }} + tg_command: 'validate' + env: + AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + + - name: Plan + if: github.event_name == 'pull_request' + uses: gruntwork-io/terragrunt-action@v2 + id: plan + with: + tf_version: ${{ env.tf_version }} + tg_version: ${{ env.tg_version }} + tg_dir: ${{ inputs.working_directory }} + tg_command: 'plan -no-color' + tg_comment: 1 + continue-on-error: true + env: + AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + TF_VAR_digitalocean_token: ${{ inputs.do_token }} + TF_VAR_AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + TF_VAR_AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + TF_VAR_R2_ACCESS_KEY: ${{ inputs.r2_access_key }} + TF_VAR_R2_SECRET_KEY: ${{ inputs.r2_secret_key }} + TF_VAR_slack_token: ${{ inputs.slack_token }} + TF_VAR_new_relic_api_key: ${{ inputs.new_relic_api_key }} + TF_VAR_new_relic_account_id: ${{ inputs.new_relic_account_id }} + + - name: Plan output cleanup + if: always() + run: | + TG_OUT=$(echo "${{ steps.plan.outputs.tg_action_output }}" | sed 's|%0A|\n|g') + echo "TG_PLAN_OUTPUT<> $GITHUB_ENV + echo "$TG_OUT" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - name: Find Comment + if: github.event.pull_request.draft == true && + github.event_name == 'pull_request' + uses: peter-evans/find-comment@v2 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-regex: "^### Forest: ${{ inputs.environment }} Infrastructure Plan" + + + - name: Create or Update Comment + if: github.event.pull_request.draft == true && + github.event_name == 'pull_request' && + !contains(env.TG_PLAN_OUTPUT, 'No changes. Your infrastructure matches the configuration.') + uses: peter-evans/create-or-update-comment@v2 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + ### Forest: ${{ inputs.environment }} Infrastructure Plan: ${{ steps.plan.outcome }} + +
Show Plan + + ``` + ${{ env.TG_PLAN_OUTPUT }} + ``` + +
+ edit-mode: replace + + - name: Delete Comment + uses: detomarco/delete-comments@v1.0.4 + if: github.event.pull_request.draft == true && + github.event_name == 'pull_request' && + contains(env.TG_PLAN_OUTPUT, 'No changes. Your infrastructure matches the configuration.') + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + + - name: Terraform Plan Status + shell: bash + if: steps.plan.outcome == 'failure' + run: exit 1 + # + # - name: Terraform Apply + # if: github.ref == 'refs/heads/main' && github.event_name == 'push' + # run: | + # if grep -q 'No changes.' tfplan; then + # echo "No changes detected." + # else + # echo "Changes detected. Redeploying everything..." + # terraform destroy -auto-approve -input=false + # terraform apply -auto-approve -input=false + # fi + # shell: bash + # working-directory: ${{ inputs.working_directory }} + # env: + # TF_VAR_do_token: ${{ inputs.do_token }} + # TF_VAR_AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + # TF_VAR_AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + # AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + # AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + # TF_VAR_slack_token: ${{ inputs.slack_token }} + # TF_VAR_R2_ACCESS_KEY: ${{ inputs.r2_access_key }} + # TF_VAR_R2_SECRET_KEY: ${{ inputs.r2_secret_key }} + # TF_VAR_NEW_RELIC_API_KEY: ${{ inputs.NEW_RELIC_API_KEY }} + # TF_VAR_NR_LICENSE_KEY: ${{ inputs.NR_LICENSE_KEY }} + # TF_VAR_NEW_RELIC_ACCOUNT_ID: ${{ inputs.new_relic_account_id }} + # + # - name: Terraform Force Apply + # if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch' + # shell: bash + # working-directory: ${{ inputs.working_directory }} + # env: + # TF_VAR_do_token: ${{ inputs.do_token }} + # TF_VAR_AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + # TF_VAR_AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + # AWS_ACCESS_KEY_ID: ${{ inputs.aws_access_key_id }} + # AWS_SECRET_ACCESS_KEY: ${{ inputs.aws_secret_access_key }} + # TF_VAR_R2_ACCESS_KEY: ${{ inputs.r2_access_key }} + # TF_VAR_R2_SECRET_KEY: ${{ inputs.r2_secret_key }} + # TF_VAR_slack_token: ${{ inputs.slack_token }} + # TF_VAR_NEW_RELIC_API_KEY: ${{ inputs.new_relic_api_key }} + # TF_VAR_NR_LICENSE_KEY: ${{ inputs.nr_license_key }} + # TF_VAR_NEW_RELIC_ACCOUNT_ID: ${{ inputs.new_relic_account_id }} + # run: | + # terraform destroy -auto-approve -input=false + # terraform apply -auto-approve -input=false diff --git a/tf-managed/live/environments/dev/applications/snapshot-service/terragrunt.hcl b/tf-managed/live/environments/dev/applications/snapshot-service/terragrunt.hcl index 61f168e46..75c7d00a3 100644 --- a/tf-managed/live/environments/dev/applications/snapshot-service/terragrunt.hcl +++ b/tf-managed/live/environments/dev/applications/snapshot-service/terragrunt.hcl @@ -10,10 +10,10 @@ terraform { } inputs = { - name = "forest-snapshot" - size = "s-4vcpu-16gb-amd" - r2_endpoint = "https://2238a825c5aca59233eab1f221f7aefb.r2.cloudflarestorage.com/" - forest_tag = "latest" + name = "forest-snapshot" + size = "s-4vcpu-16gb-amd" + r2_endpoint = "https://2238a825c5aca59233eab1f221f7aefb.r2.cloudflarestorage.com/" + forest_tag = "latest" snapshot_bucket = "forest-archive-dev" monitoring = { diff --git a/tf-managed/modules/daily-snapshot/main.tf b/tf-managed/modules/daily-snapshot/main.tf index 26b343043..fd2366ded 100644 --- a/tf-managed/modules/daily-snapshot/main.tf +++ b/tf-managed/modules/daily-snapshot/main.tf @@ -7,7 +7,7 @@ // Ugly hack because 'archive_file' cannot mix files and folders. data "external" "sources_tar" { - program = ["sh", "${path.module}/prep_sources.sh", path.module, var.common_resources_dir] + program = ["bash", "${path.module}/prep_sources.sh", path.module, var.common_resources_dir] } diff --git a/tf-managed/modules/sync-check/main.tf b/tf-managed/modules/sync-check/main.tf index 837cf4572..eb8595f3f 100644 --- a/tf-managed/modules/sync-check/main.tf +++ b/tf-managed/modules/sync-check/main.tf @@ -7,7 +7,7 @@ // Ugly hack because 'archive_file' cannot mix files and folders. data "external" "sources_tar" { - program = ["sh", "${path.module}/prep_sources.sh", path.module, var.common_resources_dir] + program = ["bash", "${path.module}/prep_sources.sh", path.module, var.common_resources_dir] } data "local_file" "sources" {