# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: "FAST ${stage_name} stage"

on:
  pull_request:
    branches:
      - main
    types:
      - closed
      - opened
      - synchronize

env:
  FAST_OUTPUTS_BUCKET: ${outputs_bucket}
  FAST_SERVICE_ACCOUNT: ${service_account}
  FAST_WIF_PROVIDER: ${identity_provider}
  SSH_AUTH_SOCK: /tmp/ssh_agent.sock
  %{~ if tf_providers_file != "" ~}
  TF_PROVIDERS_FILE: ${tf_providers_file}
  %{~ endif ~}
  TF_VAR_FILES: ${tf_var_files == [] ? "''" : join("\n    ", tf_var_files)}
  TF_VERSION: 1.3.2

jobs:
  fast-pr:
    permissions:
      contents: read
      id-token: write
      issues: write
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - id: checkout
        name: Checkout repository
        uses: actions/checkout@v3

      # set up SSH key authentication to the modules repository
      - id: ssh-config
        name: Configure SSH authentication
        run: |
          ssh-agent -a "$SSH_AUTH_SOCK" > /dev/null
          ssh-add - <<< "$${{ secrets.CICD_MODULES_KEY }}"

      # set up authentication via Workload identity Federation
      - id: gcp-auth
        name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v0
        with:
          workload_identity_provider: $${{ env.FAST_WIF_PROVIDER }}
          service_account: $${{ env.FAST_SERVICE_ACCOUNT }}
          access_token_lifetime: 3600s

      - id: gcp-sdk
        name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v0
        with:
          install_components: alpha

      # copy provider and tfvars files
      - id: tf-config
        name: Copy Terraform output files
        run: |
          %{~ if tf_providers_file != "" ~}
          gcloud alpha storage cp -r \
            "gs://$${{env.FAST_OUTPUTS_BUCKET}}/providers/$${{env.TF_PROVIDERS_FILE}}" ./
          %{~ endif ~}
          gcloud alpha storage cp -r \
            "gs://$${{env.FAST_OUTPUTS_BUCKET}}/tfvars" ./
          for f in $${{env.TF_VAR_FILES}}; do
            ln -s "tfvars/$f" ./
          done

      - id: tf-setup
        name: Set up Terraform
        uses: hashicorp/setup-terraform@v2.0.3
        with:
          terraform_version: $${{ env.TF_VERSION }}

      # run Terraform init/validate/plan
      - id: tf-init
        name: Terraform init
        run: |
          terraform init -no-color

      - id: tf-validate
        name: Terraform validate
        run: terraform validate -no-color

      - id: tf-plan
        name: Terraform plan
        continue-on-error: true
        run: |
          terraform plan -input=false -out ../plan.out -no-color

      - id: tf-apply
        if: github.event.pull_request.merged == true && success()
        name: Terraform apply
        continue-on-error: true
        run: |
          terraform apply -input=false -auto-approve -no-color ../plan.out

      - id: pr-comment
        name: Post comment to Pull Request
        continue-on-error: true
        uses: actions/github-script@v6
        if: github.event_name == 'pull_request'
        env:
          PLAN: $${{ steps.tf-plan.outputs.stdout }}\n$${{ steps.tf-plan.outputs.stderr }}
        with:
          script: |
            const output = `### Terraform Initialization \`$${{ steps.tf-init.outcome }}\`

            ### Terraform Validation \`$${{ steps.tf-validate.outcome }}\`

            <details><summary>Validation Output</summary>

            \`\`\`\n
            $${{ steps.tf-validate.outputs.stdout }}
            \`\`\`

            </details>

            ### Terraform Plan \`$${{ steps.tf-plan.outcome }}\`

            <details><summary>Show Plan</summary>

            \`\`\`\n
            $${process.env.PLAN.split('\n').filter(l => l.match(/^([A-Z\s].*|)$$/)).join('\n')}
            \`\`\`

            </details>

            ### Terraform Apply \`$${{ steps.tf-apply.outcome }}\`

            *Pusher: @$${{ github.actor }}, Action: \`$${{ github.event_name }}\`, Working Directory: \`$${{ env.tf_actions_working_dir }}\`, Workflow: \`$${{ github.workflow }}\`*`;

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            })

      - id: pr-short-comment
        name: Post comment to Pull Request
        uses: actions/github-script@v6
        if: github.event_name == 'pull_request' && steps.pr-comment.outcome != 'success'
        with:
          script: |
            const output = `### Terraform Initialization \`$${{ steps.tf-init.outcome }}\`

            ### Terraform Validation \`$${{ steps.tf-validate.outcome }}\`

            ### Terraform Plan \`$${{ steps.tf-plan.outcome }}\`

            Plan output is in the action log.

            ### Terraform Apply \`$${{ steps.tf-apply.outcome }}\`

            *Pusher: @$${{ github.actor }}, Action: \`$${{ github.event_name }}\`, Working Directory: \`$${{ env.tf_actions_working_dir }}\`, Workflow: \`$${{ github.workflow }}\`*`;

            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            })

      - id: check-plan
        name: Check plan failure
        if: steps.tf-plan.outcome != 'success'
        run: exit 1

      - id: check-apply
        name: Check apply failure
        if: github.event.pull_request.merged == true && steps.tf-apply.outcome != 'success'
        run: exit 1
