Full workflow code that manages a separate set of tags and releases for each environment. In the hart of it a https://github.com/PaulHatch/semantic-version is used to determine semantic versioning. name: Terraform Apply on: push: branches: - main - qa - dev env: PYTHONDONTWRITEBYTECODE: 1 # Prevents Python from writing pyc files jobs: terraform_apply: name: Apply runs-on: ubuntu-latest # Dynamically set the environment based on the branch name environment: name: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'qa' && 'qa' || github.ref_name == 'dev' && 'dev' }} steps: - name: Check out code uses: actions/checkout@v3 with: fetch-depth: 0 # Fetches all history for all tags and branches - name: Setup Terraform uses: hashicorp/setup-terraform@v2 with: terraform_wrapper: false # https://stackoverflow.com/a/69927019/12451227 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v2 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ vars.AWS_REGION }} # Needed to setup Python for Lambda packaging when applying Terraform - uses: actions/setup-python@v4 with: python-version: "3.11" - name: Terraform Init run: make init env: TF_BACKEND_BUCKET: ${{ vars.TERRAFORM_STATE_BUCKET_NAME }} TF_BACKEND_TABLE: ${{ vars.TERRAFORM_STATE_DYNAMODB_TABLE }} AWS_REGION: ${{ vars.AWS_REGION }} - name: Terraform Apply run: make apply env: TDP_TOKEN: ${{ secrets.TDP_TOKEN }} TF_VAR_FILE: envs/${{ vars.ENVIRONMENT }}.tfvars TF_WORKSPACE: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'qa' && 'qa' || github.ref_name == 'dev' && 'dev' }} TF_LAMBDA_PACKAGE_LOG_LEVEL: WARNING # This will suppress the output of the Lambda package logs TETRA_CONFIG_BACKUP_BUCKET: ${{ vars.TETRA_CONFIG_BACKUP_BUCKET }} AUTO_APPROVE: true - name: Determine new version id: config_version uses: paulhatch/semantic-version@v5.1.0 with: change_path: "config" namespace: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'qa' && 'qa' || github.ref_name == 'dev' && 'dev' }}-config - name: Create release tag if: ${{ steps.config_version.outputs.changed == 'true' }} # `.changed` returns string values `true` or `false uses: actions/github-script@v5 with: script: | github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: 'refs/tags/${{ steps.config_version.outputs.version_tag }}', sha: context.sha }) - name: Fetch Terraform output if: ${{ steps.config_version.outputs.changed == 'true' }} # `.changed` returns string values `true` or `false id: terraform_output # https://trstringer.com/github-actions-multiline-strings/ run: | OUTPUT=$(cd infra && terraform output) echo "TF_OUTPUT<<EOF" >> $GITHUB_ENV echo "$OUTPUT" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV env: TF_WORKSPACE: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'qa' && 'qa' || github.ref_name == 'dev' && 'dev' }} - name: Create release if: ${{ steps.config_version.outputs.changed == 'true' }} # `.changed` returns string values `true` or `false uses: actions/github-script@v5 with: script: | github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, tag_name: '${{ steps.config_version.outputs.version_tag }}', name: '${{ steps.config_version.outputs.version_tag }}', body: '```\n${{ toJson(env.TF_OUTPUT) }}\n```', draft: false, prerelease: false })