# Copyright 2023 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.6.5 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@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 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 alpha storage cp -r \ "gs://${outputs_bucket}/providers/$${{env.provider_file}}" ./ %{~ for f in tf_var_files ~} gcloud alpha storage cp -r \ "gs://${outputs_bucket}/tfvars/${f}" ./ %{~ endfor ~} - 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 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@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}}\`
Validation Output \`\`\`\n $${{steps.tf-validate.outputs.stdout}} \`\`\`
### Terraform Plan \`$${{steps.tf-plan.outcome}}\`
Show Plan \`\`\`\n $${process.env.PLAN.split('\n').filter(l => l.match(/^([A-Z\s].*|)$$/)).join('\n')} \`\`\`
### 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@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 }) # 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