# Copyright 2025 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_SERVICE_ACCOUNT: ${service_accounts.apply}
  FAST_SERVICE_ACCOUNT_PLAN: ${service_accounts.plan}
  FAST_WIF_PROVIDER: ${identity_provider}
  SSH_AUTH_SOCK: /tmp/ssh_agent.sock
  TF_PROVIDERS_FILE: ${tf_providers_files.apply}
  TF_PROVIDERS_FILE_PLAN: ${tf_providers_files.plan}
  TF_VERSION: 1.10.2

jobs:
  fast-pr:
    # Skip PRs which are closed without being merged.
    if: >-
      github.event.action == 'closed' &&
      github.event.pull_request.merged == true ||
      github.event.action == 'opened' ||
      github.event.action == 'synchronize'
    permissions:
      contents: read
      id-token: write
      issues: write
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - id: checkout
        name: Checkout repository
        uses: actions/checkout@v4

      # 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 step variables for plan / apply

      - id: vars-plan
        if: github.event.pull_request.merged != true && success()
        name: Set up plan variables
        run: |
          echo "plan_opts=-lock=false" >> "$GITHUB_ENV"
          echo "provider_file=$${{env.TF_PROVIDERS_FILE_PLAN}}" >> "$GITHUB_ENV"
          echo "service_account=$${{env.FAST_SERVICE_ACCOUNT_PLAN}}" >> "$GITHUB_ENV"

      - id: vars-apply
        if: github.event.pull_request.merged == true && success()
        name: Set up apply variables
        run: |
          echo "provider_file=$${{env.TF_PROVIDERS_FILE}}" >> "$GITHUB_ENV"
          echo "service_account=$${{env.FAST_SERVICE_ACCOUNT}}" >> "$GITHUB_ENV"

      # set up authentication via Workload identity Federation and gcloud

      - id: gcp-auth
        name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: $${{env.FAST_WIF_PROVIDER}}
          service_account: $${{env.service_account}}
          access_token_lifetime: 900s

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

      # copy provider file

      - id: tf-config-provider
        name: Copy Terraform provider file
        run: |
          gcloud storage cp -r \
            "gs://${outputs_bucket}/providers/$${{env.provider_file}}" ./
          %{~ for f in tf_var_files ~}
          gcloud storage cp -r \
            "gs://${outputs_bucket}/tfvars/${f}" ./
          %{~ endfor ~}

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

      # run Terraform init/validate/plan

      - id: tf-init
        name: Terraform init
        continue-on-error: true
        run: |
          terraform init -no-color

      - id: tf-validate
        continue-on-error: true
        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 $${{env.plan_opts}}

      - 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

      # PR comment with Terraform result from previous steps
      # length is checked and trimmed for length so as to stay within the limit

      - id: pr-comment
        name: Post comment to Pull Request
        continue-on-error: true
        uses: actions/github-script@v7
        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 (abbreviated)
        uses: actions/github-script@v7
        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
            })

      # exit on error from previous steps

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

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

      - 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
