Aws cicd patterns
Skill ai-enhanced-engineer/aiee-skills/skills/aws-cicd-patterns
CI/CD patterns for AWS using GitHub Actions, ECR, and App Runner/ECS Express Mode. Use for deployment pipelines, container image management, OIDC authentication, or automating deployments to AWS services.From its SKILL.md
npx -y skills add ai-enhanced-engineer/aiee-skills --skill aws-cicd-patternsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.3 KB, as published. Nobody here has run it
AWS CI/CD Patterns
Continuous integration and delivery patterns for AWS, emphasizing GitHub Actions with OIDC authentication (configure-aws-credentials@v6) and ECR-based container workflows.
App Runner maintenance mode (April 30, 2026): CI/CD patterns below work for both App Runner and ECS Express Mode — only the deploy step changes.
Core Services
| Service | Purpose | Use When |
|---|---|---|
| GitHub Actions | CI/CD orchestration | Building, testing, deploying |
| ECR | Container registry | Storing and managing Docker images |
| App Runner / ECS Express | Serverless compute | Deploying stateless HTTP workloads |
| Secrets Manager | Secret storage | Runtime secret injection |
| S3 | Terraform backend | Remote state with S3-native locking (TF 1.11+) |
Pipeline Stages
- Source — Trigger on push/PR
- Build — Compile, lint, type-check
- Unit Test — Fast feedback (pytest, coverage gate)
- Docker Build — Multi-stage build with GHA cache
- Security Scan — Trivy/Snyk on container image
- Push to ECR — Tag with SHA, push image
- Deploy Staging — Automatic on merge to main
- Deploy Production — Manual approval or canary
GitHub OIDC Authentication (Keyless)
Use aws-actions/configure-aws-credentials@v6 with OIDC — no access keys needed:
permissions:
id-token: write # Required for OIDC
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}
OIDC setup details (trust policy, IAM role) → see aws-security-hardening skill.
AWS Bootstrap Prerequisites
S3 bucket + DynamoDB lock table for Terraform remote state cannot be created by Terraform itself — bootstrapped manually before terraform init.
- S3 bucket with versioning,
put-public-access-block, and SSE-S3 (each is a separate API call) - DynamoDB table with
LockIDpartition key,PAY_PER_REQUESTbilling - Reference these as
datasources in Terraform, not managed resources — preventsterraform destroyfrom wiping bootstrap infrastructure
AWS CLI gotchas:
create-bucketrequires--create-bucket-configuration LocationConstraint=<region>for any region other thanus-east-1- Billing alarms (
AWS/Billing EstimatedCharges) must be created inus-east-1— other regions produce silentINSUFFICIENT_DATA - GitHub OIDC
create-open-id-connect-providerrequires--thumbprint-listeven though AWS ignores it for GitHub — use6938fd4d98bab03faadb97b34396831e3780aea1 - Pre-check OIDC:
aws iam list-open-id-connect-providersbefore creating to avoidEntityAlreadyExists
Rollback Patterns
| Method | Speed | Risk |
|---|---|---|
| Redeploy previous SHA tag | Fast (image exists) | Low |
| App Runner revision rollback | Fast (1 API call) | Low |
| Terraform state rollback | Slow (full plan/apply) | Medium |
| Git revert + redeploy | Medium (triggers full pipeline) | Low |
Preferred: Redeploy previous SHA tag — fastest, most predictable.
Best Practices
- Use OIDC —
configure-aws-credentials@v6eliminates long-lived keys. Scope trust policy to specific repo + branch to prevent cross-repo assumption. - Build once, promote — Same image through staging → production via SHA tag. Rebuilding per environment risks drift.
- Tag immutably — SHA-based tags as source of truth,
latestas convenience alias only. - Secrets in Secrets Manager — secrets pasted into workflow files, Dockerfiles, or env vars land in build logs, image layers, and the public action run history, where they cannot be revoked retroactively.
- Cache Docker layers — GHA cache (
type=gha, 10GB limit) or ECR registry cache (type=registry) for 50-70% faster builds. - Apply job safety —
cancel-in-progress: trueon a Terraform apply job kills the runner mid-terraform apply, leaving the state file locked or partially written; the next run then has to manually unlock and reconcile drift.
Reusable Workflow Context
github.event_name inside a reusable workflow resolves to workflow_call, not the caller's event. This silently skips conditions like if: github.event_name == 'push'.
Pattern: Explicit boolean inputs avoid the workflow_call event name shadowing. See examples.md for the explicit boolean input pattern.
- Bare
${{ inputs.push_image }}evaluates to empty string (notfalse) on non-workflow_calltriggers —${{ inputs.push_image || false }}prevents YAML boolean validation failures - Without
secrets: inherit, the called workflow cannot access the caller's secrets, causing silent access failures
Deploy Safety Patterns
Concurrency: cancel-in-progress: false prevents canceling mid-SSM-command, which can leave instances broken:
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false
Shell injection guard: Validating workflow_dispatch inputs before use in SSM commands prevents shell injection. Using the env: block (rather than ${{ }} interpolation in run:) ensures bash's regex check is authoritative. See examples.md for the validation step pattern.
Health check with fail-exit: for loops with curl && break || sleep exit 0 when all attempts fail — the ok flag pattern ensures non-zero exit on exhaustion. See examples.md for health check and migration retry patterns.
Anti-Patterns
| Anti-Pattern | Pattern |
|---|---|
| AWS access keys in GitHub Secrets | OIDC provider + IAM role assumption |
latest tag only in ECR | SHA-based tags + latest as convenience alias |
| No ECR lifecycle policy | Lifecycle rules to prune old/untagged images |
| Rebuilding image for each environment | Build once, promote through envs via tag |
OIDC trust policy with * in sub | Scope to repo:org/repo:ref:refs/heads/main |
| Skipping security scan before deploy | Trivy/Snyk scan as blocking CI step |
github.event_name == 'push' inside reusable workflow | Explicit push_image: boolean input from caller |
Both ci.yml and deploy.yml triggering on push: branches: [main] | Single entry point: deploy.yml calls ci.yml via workflow_call |
sleep N before docker exec in deploy scripts | Retry loop with fail-exit flag pattern |
| Health check loop that exits 0 on exhaustion | ok flag variable with `[ $ok -eq 1 ] |
Missing ECR login before docker pull in rollback | Include aws ecr get-login-password in rollback procedure |
See reference.md for Terraform state locking and ECR lifecycle policies.
See examples.md for complete GitHub Actions workflow templates (CI, Deploy, Terraform).
Related
aws-security-hardening— OIDC trust-policy authoring and IAM role scoping consumed by the pipelines hereaws-app-runner— the deploy target this pipeline pushes images to (and the ECS Express migration path)github-actions-cicd— platform-neutral GHA workflow syntax (reusable workflows, matrix builds) this skill layers AWS specifics on top of