name: SES - juntekim.com [Simple Email Service] on: pull_request: push: branches: - main paths: - "aws_environment/ses-juntekim/**" workflow_dispatch: env: TF_VERSION: "1.6.6" WORKING_DIR: "aws_environment/ses-juntekim" jobs: terraform: name: Terraform SES runs-on: mealcraft-runners permissions: contents: read pull-requests: write steps: - name: Checkout repo uses: actions/checkout@v4 - name: Install modern Node.js run: | curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs node --version - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ env.TF_VERSION }} - name: Install AWS CLI v2 run: | sudo apt-get update sudo apt-get install -y unzip curl curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install aws --version # Optional but recommended once - name: Verify AWS identity run: aws sts get-caller-identity - name: Terraform Init working-directory: ${{ env.WORKING_DIR }} run: terraform init - name: Terraform Validate working-directory: ${{ env.WORKING_DIR }} run: terraform validate - name: Check and remove stale state locks working-directory: ${{ env.WORKING_DIR }} run: | # List all locks in DynamoDB and remove any stale ones LOCKS=$(aws dynamodb scan \ --table-name "juntekim-terraform-state" \ --filter-expression "attribute_exists(LockID)" \ --region us-east-1 \ --query 'Items[*].LockID.S' \ --output text 2>/dev/null || echo "") if [ ! -z "$LOCKS" ]; then echo "Found locks: $LOCKS" for LOCK_ID in $LOCKS; do echo "Force unlocking: $LOCK_ID" terraform force-unlock -force "$LOCK_ID" 2>/dev/null || true done else echo "No stale locks found" fi continue-on-error: true - name: Terraform Plan if: github.event_name == 'pull_request' id: plan working-directory: ${{ env.WORKING_DIR }} run: terraform plan -input=false - name: Wait for terraform-plan workflow if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: actions/github-script@v6 with: script: | const maxAttempts = 120; // 10 minutes with 5 second intervals let attempt = 0; while (attempt < maxAttempts) { const runs = await github.rest.actions.listWorkflowRuns({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: 'terraform-plan.yml', }); const latestPlan = runs.data.workflow_runs[0]; if (latestPlan && (latestPlan.status === 'completed')) { if (latestPlan.conclusion === 'success') { console.log('✅ terraform-plan workflow completed successfully'); return; } else { throw new Error(`terraform-plan workflow failed with conclusion: ${latestPlan.conclusion}`); } } attempt++; if (attempt % 12 === 0) { console.log(`Waiting for terraform-plan... (attempt ${attempt}/${maxAttempts})`); } await new Promise(resolve => setTimeout(resolve, 5000)); } throw new Error('Timeout waiting for terraform-plan workflow'); - name: Terraform Apply if: github.ref == 'refs/heads/main' working-directory: ${{ env.WORKING_DIR }} run: terraform apply -auto-approve -input=false