Skip to content

chore: more init sophistication #1

chore: more init sophistication

chore: more init sophistication #1

name: Pipelines
run-name: Unlock Gruntwork Pipelines
on:
workflow_call:
inputs:
lock_id:
description: "The ID of the lock, usually a GUID. This is generally found in the console output when Terraform/OpenTofu command fails due to a timeout waiting to acquire a lock. (required if not running unlock_all)"
required: false
type: string
working_directory:
description: "Path to the terragrunt.hcl file where the lock is held (required if not running unlock_all)"
required: false
type: string
unlock_all:
description: "Forcibly reset all locks by deleting the dynamodb table"
required: false
type: boolean
# This field can be overriden to customize the runner used for pipelines
# workflows.
#
# IMPORTANT: To use self-hosted runners this workflow must be hosted in
# the same GitHub organization as your infra-live repository.
# See https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-self-hosted-runners
#
# The value must be an escaped JSON string that will be decoded to the
# jobs.runs-on field
# See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on
#
# For example:
# - A simple github runner: "\"ubuntu-22.04\""
# - A list of labels: "[\"self-hosted\", \"linux\"]"
# - A map: "{group: \"ubuntu-runners\", labels: \"ubuntu-20.04-16core\"}"
runner:
type: string
default: '"ubuntu-latest"'
secrets:
PIPELINES_READ_TOKEN:
required: true
env:
PIPELINES_CLI_VERSION: v0.23.1
PIPELINES_ACTIONS_VERSION: main
jobs:
unlock_one:
name: Unlock a single TF State
if: ${{ !inputs.unlock_all }}
runs-on: ${{ fromJSON(inputs.runner) }}
steps:
- name: Checkout Pipelines Actions
uses: actions/checkout@v4
with:
path: pipelines-actions
repository: gruntwork-io/pipelines-actions
ref: ${{ env.PIPELINES_ACTIONS_VERSION }}
token: ${{ secrets.PIPELINES_READ_TOKEN }}
- name: Check out repo code
uses: actions/checkout@v4
with:
path: infra-live-repo
fetch-depth: 0
- name: Bootstrap Workflow
id: gruntwork_context
uses: ./pipelines-actions/.github/actions/pipelines-bootstrap
with:
token: ${{ secrets.PIPELINES_READ_TOKEN }}
working_directory: ${{ inputs.working_directory }}
terragrunt_command: "force-unlock -force ${{ inputs.lock_id }}"
branch: 'main'
- name: "Run terragrunt force-unlock in ${{ inputs.working_directory }}"
id: terragrunt
uses: ./pipelines-actions/.github/actions/pipelines-execute
env:
TERRAGRUNT_AUTH_PROVIDER_CMD: "pipelines auth terragrunt-credentials --ci github-actions --cloud aws --wd ."
with:
token: ${{ secrets.PIPELINES_READ_TOKEN }}
tf_binary: ${{ steps.gruntwork_context.outputs.tf_binary }}
working_directory: ${{ steps.gruntwork_context.outputs.working_directory }}
terragrunt_command: ${{ steps.gruntwork_context.outputs.terragrunt_command }}
infra_live_repo_branch: ${{ steps.gruntwork_context.outputs.branch }}
gruntwork_config_file: ${{ steps.gruntwork_context.outputs.gruntwork_config_file }}
infra_live_repo: "."
infra_live_directory: "."
deploy_branch_name: ${{ steps.gruntwork_context.outputs.deploy_branch_name }}
unlock_all:
name: Unlock all TF State files
if: ${{ inputs.unlock_all }}
runs-on: ${{ fromJSON(inputs.runner) }}
steps:

Check failure on line 93 in .github/workflows/pipelines-unlock.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/pipelines-unlock.yml

Invalid workflow file

You have an error in your yaml syntax on line 93
- name: Checkout Pipelines Actions
uses: actions/checkout@v4
with:
path: pipelines-actions
repository: gruntwork-io/pipelines-actions
ref: ${{ env.PIPELINES_ACTIONS_VERSION }}
token: ${{ secrets.PIPELINES_READ_TOKEN }}
- name: Check out repo code
uses: actions/checkout@v4
with:
path: infra-live-repo
fetch-depth: 0
- name: Bootstrap Workflow
id: gruntwork_context
uses: ./pipelines-actions/.github/actions/pipelines-bootstrap
with:
token: ${{ secrets.PIPELINES_READ_TOKEN }}
working_directory: ${{ inputs.working_directory }}
terragrunt_command: "init"
branch: 'main'
- name: Setup Mise Toml
id: mise-toml
working-directory: ./infra-live-repo
shell: bash
env:
GENERATE_MISE_TOML: false
INFRA_LIVE_DIRECTORY: "."
run: |
if [[ "$GENERATE_MISE_TOML" == "true" ]] || [[ ! -f "$INFRA_LIVE_DIRECTORY/.mise.toml" ]]; then
if [[ ! -f "$INFRA_LIVE_DIRECTORY/.mise.toml" ]]; then
echo 'User does not have a `.mise.toml` file, generating one to avoid failure'
fi
echo 'TOML<<EOF' >> "$GITHUB_OUTPUT"
echo '[tools]' >> "$GITHUB_OUTPUT"
echo "$TF_BINARY = \"$TF_VERSION\"" >> "$GITHUB_OUTPUT"
echo "terragrunt = \"$TG_VERSION\"" >> "$GITHUB_OUTPUT"
echo 'EOF' >> "$GITHUB_OUTPUT"
else
echo 'TOML<<EOF' >> "$GITHUB_OUTPUT"
cat $INFRA_LIVE_DIRECTORY/.mise.toml >> "$GITHUB_OUTPUT"
echo '' >> "$GITHUB_OUTPUT"
echo 'EOF' >> "$GITHUB_OUTPUT"
fi
- uses: jdx/mise-action@v2
with:
install: true
cache: true
mise_toml: "${{ steps.mise-toml.outputs.TOML }}"
- name: Wipe all dynamodb terraform lock tables
shell: bash
id: unlock_tables
env:
GITHUB_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ secrets.PIPELINES_READ_TOKEN }}
run: |
containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
if [[ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]]; then
export GITHUB_EVENT_NAME=push
fi
echo "Wiping all dynamodb terraform lock tables"
# Recursively find every terragrunt hcl
COMPLETED_ACCOUNTS=()
NEEDS_INIT_FOLDERS=()
find . -name "terragrunt.hcl" -print0 | while read -d $'\0' unit
do
dir=$(dirname "$unit")
cd $dir
pipelinesConfigAuth=$(GH_TOKEN=$GITHUB_TOKEN pipelines config auth)
ACCOUNTID=$(echo $pipelinesConfigAuth | jq -r ".Authentication.AWSOIDC.AccountID")
echo ACCOUNTID="$ACCOUNTID"
if containsElement $ACCOUNTID "${COMPLETED_ACCOUNTS[@]}"; then
echo "Skipping $ACCOUNTID as it has already been processed"
cd -
continue
else
echo "Unlocking state in $ACCOUNTID in `pwd`"
fi
REGION=$(echo $pipelinesConfigAuth | jq -r ".Authentication.AWSOIDC.Region")
echo REGION="$REGION"
auth=$(GH_TOKEN=$GITHUB_TOKEN pipelines auth terragrunt-credentials --ci github-actions --cloud aws --wd .)
export AWS_DEFAULT_REGION=$REGION
export AWS_ACCESS_KEY_ID=$(echo $auth | jq -r '.awsCredentials.ACCESS_KEY_ID')
export AWS_SECRET_ACCESS_KEY=$(echo $auth | jq -r '.awsCredentials.SECRET_ACCESS_KEY')
export AWS_SESSION_TOKEN=$(echo $auth | jq -r '.awsCredentials.SESSION_TOKEN')
set +x
set +e
echo "Fetching table status..."
TABLE_STATUS=$(aws dynamodb describe-table --table-name "terraform-locks" --query "Table.TableStatus" --output text 2>&1 || true)
echo $TABLE_STATUS
if [[ "$TABLE_STATUS" == "ACTIVE" ]]; then
aws dynamodb delete-table --table-name terraform-locks || true # Ignore failures if no table already exists
fi
echo "Lock removed, re-running tg init"
NEEDS_INIT_FOLDERS+=($dir)
COMPLETED_ACCOUNTS+=($ACCOUNTID)
cd -
done
# Convert bash array of strings to a JSOn array
JSON=$(printf "%s\n" ${NEEDS_INIT_FOLDERS[@]} | jq -R . | jq -s .)
echo "unlock_folders=$JSON" >> "$GITHUB_OUTPUT"
outputs:
unlock_folders: ${{ steps.unlock_tables.outputs.jobs }}
pipelines_reinit:
name: "Rerun init in ${{ matrix.jobs.WorkingDirectory }}"
needs: [unlock_all]
runs-on: ${{ fromJSON(inputs.runner) }}
if: ${{ inputs.unlock_all }}
strategy:
fail-fast: false
matrix:
working_directory: ${{ fromJson(needs.unlock_all.outputs.unlock_folders) }}
steps:
- name: Checkout Pipelines Actions
uses: actions/checkout@v4
with:
path: pipelines-actions
repository: gruntwork-io/pipelines-actions
ref: ${{ env.PIPELINES_ACTIONS_VERSION }}
token: ${{ secrets.PIPELINES_READ_TOKEN }}
- name: Check out repo code
uses: actions/checkout@v4
with:
path: infra-live-repo
fetch-depth: 0
- name: Bootstrap Workflow
id: gruntwork_context
uses: ./pipelines-actions/.github/actions/pipelines-bootstrap
with:
token: ${{ secrets.PIPELINES_READ_TOKEN }}
working_directory: ${{ matrix.working_directory }}
terragrunt_command: "init"
branch: 'main'
- name: "Run Terragrunt Init"
id: terragrunt
uses: ./pipelines-actions/.github/actions/pipelines-execute
env:
TERRAGRUNT_AUTH_PROVIDER_CMD: "pipelines auth terragrunt-credentials --ci github-actions --cloud aws --wd ."
with:
token: ${{ secrets.PIPELINES_READ_TOKEN }}
tf_binary: ${{ steps.gruntwork_context.outputs.tf_binary }}
working_directory: ${{ steps.gruntwork_context.outputs.working_directory }}
terragrunt_command: ${{ steps.gruntwork_context.outputs.terragrunt_command }}
infra_live_repo_branch: ${{ steps.gruntwork_context.outputs.branch }}
gruntwork_config_file: ${{ steps.gruntwork_context.outputs.gruntwork_config_file }}
infra_live_repo: "."
infra_live_directory: "."
deploy_branch_name: ${{ steps.gruntwork_context.outputs.deploy_branch_name }}