Skip to content

Feature Stack Cleanup #11

Feature Stack Cleanup

Feature Stack Cleanup #11

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 }}