Feature Stack Cleanup #10
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Feature Stack Cleanup | |
on: | |
workflow_dispatch: | |
inputs: | |
feature_tag: | |
description: What is the feature tag? (i.e. abc123) | |
required: true | |
type: string | |
delete: | |
# This runs on deletion of branches & tags. If a tag is deleted, | |
# the workflow will run, but all jobs after env-vars will be skipped. | |
# Github has a fix for this in their backlog to allow you to trigger | |
# the workflow only on branch deletion, but it is not yet available. | |
# https://github.com/community/community/discussions/10589 | |
permissions: | |
contents: read | |
id-token: write | |
env: | |
CONTINUE: true | |
TF_VERSION: =1.7.0 | |
jobs: | |
env-vars: | |
name: Set Env Vars as Outputs | |
runs-on: ubuntu-latest | |
outputs: | |
CONTINUE: ${{ steps.set-outputs.outputs.continue }} | |
FEATURE_TAG: ${{ steps.set-outputs.outputs.feature_tag }} | |
TF_VERSION: ${{ steps.set-outputs.outputs.tf_version }} | |
steps: | |
# this sets environment variable outputs consumed by downstream jobs | |
# this is needed because the 'env' context is not available to reusable workflows | |
- name: Checkout source code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Set Output Values | |
id: set-outputs | |
run: | | |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
# get feature tag from input value | |
FEATURE_TAG="${{ github.event.inputs.feature_tag }}" | |
else | |
# get feature tag from branch name workflow is running against | |
FEATURE_TAG="$(./scripts/create-feature-tag.sh ${{ github.event.ref }})" | |
# set CONTINUE to false if not a branch deletion | |
if [[ "${{ github.event.ref_type }}" == "tag" ]]; then | |
CONTINUE=false | |
echo "Trigger was a git tag deletion." | |
echo "SKIPPING SUBSEQUENT JOBS." | |
fi | |
fi | |
# set continue flag | |
echo "continue=${CONTINUE}" >> $GITHUB_OUTPUT | |
# set feature tag | |
echo "feature_tag=${FEATURE_TAG}" >> $GITHUB_OUTPUT | |
# set terraform version | |
echo "tf_version=${TF_VERSION}" >> $GITHUB_OUTPUT | |
empty-bucket: | |
name: Empty Feature Bucket | |
runs-on: ubuntu-latest | |
needs: | |
- env-vars | |
steps: | |
- name: Checkout Source Code | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ needs.env-vars.outputs.FEATURE_TAG }} | |
- name: Configure AWS Credentials | |
uses: aws-actions/configure-aws-credentials@v4 | |
with: | |
role-to-assume: arn:aws:iam::${{ vars.DEV_ACCOUNT_ID }}:role/GithubActionsRole-Write | |
aws-region: ${{ vars.AWS_REGION }} | |
role-duration-seconds: 900 | |
role-session-name: ${{ github.event.repository.name }}+run=${{ github.run_id }}-${{ github.run_number }}+${{ github.triggering_actor }} | |
- name: Delete Bucket Objects | |
run: | | |
BUCKET_NAME="chrisba11-example-images-${{ needs.env-vars.outputs.FEATURE_TAG }}" | |
while : ; do | |
# Generate the payload for delete-objects (up to 1000 items) | |
PAYLOAD=$( | |
aws s3api list-object-versions \ | |
--bucket "$BUCKET_NAME" \ | |
--output json \ | |
--max-items 1000 \ | |
--query '{Objects: Versions[].{Key: Key, VersionId: VersionId}}' | \ | |
jq -c '{Objects: (.Objects + ([.DeleteMarkers[]? | {Key, VersionId}] // []))}' | |
) | |
PAYLOAD_LENGTH=$(echo $PAYLOAD | jq '.Objects | length') | |
echo "Number of objects to delete: $PAYLOAD_LENGTH" | |
# Check if PAYLOAD's Objects list is empty | |
if [ "$PAYLOAD" = '{"Objects":[]}' ]; then | |
echo "No more versions or delete markers to delete." | |
break | |
fi | |
# If PAYLOAD is not empty, write to a file | |
echo "$PAYLOAD" > delete.json | |
# Perform the bulk delete (can only handle 1000 items at a time) and suppress output | |
if ! aws s3api delete-objects \ | |
--bucket "$BUCKET_NAME" \ | |
--delete file://delete.json > /dev/null 2>&1 | |
then | |
echo "Error: Failed to delete objects." | |
exit 1 | |
fi | |
echo -e "Successfully deleted $PAYLOAD_LENGTH objects from $BUCKET_NAME.\n" | |
done | |
tf-destroy: | |
name: Terraform Destroy | |
needs: | |
- env-vars | |
- empty-bucket | |
# using the matrix strategy here because the 'env' context is not available | |
# this gives us the ability to define the stack name once and use many times in the inputs | |
strategy: | |
fail-fast: false | |
matrix: | |
STACK_NAME: | |
- api | |
if: ${{ needs.env-vars.outputs.CONTINUE == 'true' }} | |
uses: chrisba11/terraform-feature-stacks/.github/workflows/__tf_destroy.yml@v1 | |
with: | |
aws_account_id: ${{ vars.DEV_ACCOUNT_ID }} | |
aws_region: ${{ vars.AWS_REGION }} | |
feature_tag: ${{ needs.env-vars.outputs.FEATURE_TAG }} | |
role_name: GithubActionsRole-Write | |
terraform_version: ${{ needs.env-vars.outputs.TF_VERSION }} | |
tf_backend_name: ${{ vars.TF_BACKEND_PREFIX }}-dev | |
tf_backend_key: ${{ github.event.repository.name }}/feature/${{ matrix.STACK_NAME }}_${{ needs.env-vars.outputs.FEATURE_TAG }}.tfstate | |
tfvars_path: ./environments/dev.tfvars | |
working_directory: infra/tf/stacks/${{ matrix.STACK_NAME }} | |
delete-lambda-package: | |
name: Delete Lambda Package from S3 | |
needs: | |
- env-vars | |
- tf-destroy | |
strategy: | |
fail-fast: false | |
matrix: | |
LAMBDA_NAME: | |
- DownloadImage | |
- ReverseImage | |
uses: chrisba11/terraform-feature-stacks/.github/workflows/__delete_s3_object.yml@v1 | |
with: | |
aws_account_id: ${{ vars.DEV_ACCOUNT_ID }} | |
aws_region: ${{ vars.AWS_REGION }} | |
object_key: feature/${{ matrix.LAMBDA_NAME }}_${{ needs.env-vars.outputs.FEATURE_TAG }}.zip | |
role_name: GithubActionsRole-Write | |
s3_bucket_name: ${{ vars.LAMBDA_PKG_BUCKET_PREFIX }}-dev | |
delete-feature-git-tag: | |
name: Delete Feature Git Tag | |
runs-on: ubuntu-latest | |
needs: | |
- env-vars | |
- tf-destroy | |
- delete-lambda-package | |
permissions: | |
contents: write | |
steps: | |
- name: Checkout Source Code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Delete Feature Git Tag | |
run: git push --delete origin ${{ needs.env-vars.outputs.FEATURE_TAG }} |