A collection of reusable CFNgin/Runway hooks for AWS infrastructure deployments. These hooks extend Runway's capabilities with common deployment patterns for CloudFront, Docker, SAM, and frontend applications.
- Copy the
hooks/directory into your Runway project - Install dependencies:
pip install -r hooks/requirements.txt| Hook | Description | Use Case |
|---|---|---|
cloudfront_invalidation |
Invalidate CloudFront distributions | After deploying static assets |
docker_build_push |
Build and push Docker images to ECR | Container-based Lambda deployments |
docker_compose_integration |
Start/stop Docker Compose containers | Local development environments |
env_file_generator |
Generate .env files from stack outputs | Next.js/Node.js applications |
npm_build |
Build and sync Next.js apps to S3 | Static site deployments |
sam_deploy |
Deploy AWS SAM templates | Serverless applications |
Invalidates CloudFront distributions after deployments to ensure users see the latest content.
post_hooks:
- path: hooks.cloudfront_invalidation.cfngin_hook
required: true
args:
distribution_id: ${output cloudfront-stack::DistributionId}
paths:
- "/*"
- "/api/*"
wait: true
timeout: 900| Parameter | Type | Default | Description |
|---|---|---|---|
distribution_id |
string | required | CloudFront distribution ID |
paths |
list | ["/*"] |
Paths to invalidate |
wait |
bool | false |
Wait for invalidation to complete |
timeout |
int | 900 |
Timeout in seconds when waiting |
python hooks/cloudfront_invalidation.py E1234567890ABC --paths "/*" "/api/*" --waitBuilds Docker images and pushes them to Amazon ECR, with automatic repository creation.
pre_hooks:
- path: hooks.docker_build_push.cfngin_hook
required: true
args:
repository_name: myapp-api
image_tag: ${environment}
dockerfile_path: Dockerfile
build_context: .
region: us-east-1
environment: ${environment}
working_directory: ./api| Parameter | Type | Default | Description |
|---|---|---|---|
repository_name |
string | required | ECR repository name |
image_tag |
string | latest |
Docker image tag |
dockerfile_path |
string | Dockerfile |
Path to Dockerfile |
build_context |
string | . |
Docker build context |
region |
string | us-east-1 |
AWS region |
environment |
string | dev |
Environment name for tagging |
working_directory |
string | None | Working directory |
python hooks/docker_build_push.py myapp-api \
--image-tag prod \
--dockerfile-path Dockerfile \
--region us-east-1Integrates Docker Compose with Runway deployments for local development environments.
pre_deploy:
- path: hooks.docker_compose_integration.start_containers_hook
required: false
enabled: ${docker_compose_enabled}
args:
compose_file: docker-compose.yml
services: ["api", "frontend", "worker"]
build: false
wait_timeout: 300
health_check: true
working_directory: ../..
post_destroy:
- path: hooks.docker_compose_integration.stop_containers_hook
required: false
args:
compose_file: docker-compose.yml
cleanup: true
remove_volumes: false| Parameter | Type | Default | Description |
|---|---|---|---|
compose_file |
string | docker-compose.yml |
Path to compose file |
services |
list | None | Services to start (all if None) |
env_file |
string | None | Environment file to check |
build |
bool | false |
Build images before starting |
wait_timeout |
int | 300 |
Timeout for health checks |
health_check |
bool | true |
Wait for health checks |
working_directory |
string | None | Working directory |
| Parameter | Type | Default | Description |
|---|---|---|---|
compose_file |
string | docker-compose.yml |
Path to compose file |
services |
list | None | Services to stop (all if None) |
cleanup |
bool | true |
Remove containers after stop |
remove_volumes |
bool | false |
Remove volumes during cleanup |
timeout |
int | 30 |
Stop timeout in seconds |
# Start containers
python hooks/docker_compose_integration.py start --services api frontend
# Stop with cleanup
python hooks/docker_compose_integration.py stop --cleanup
# Check status
python hooks/docker_compose_integration.py statusSee README_DOCKER_COMPOSE.md for detailed documentation.
Generates .env files from CloudFormation stack outputs and SSM parameters.
pre_deploy:
- path: hooks.env_file_generator.cfngin_hook
required: true
args:
output_file: ./app/.env.local
variables:
NEXT_PUBLIC_API_URL: ${cfn ${namespace}-api.ApiUrl}
NEXT_PUBLIC_USER_POOL_ID: ${cfn ${namespace}-cognito.UserPoolId}
DATABASE_URL: ${ssm /myapp-${environment}/database-url}
ENVIRONMENT: ${environment}
NODE_ENV: production
overwrite: true
create_backup: true
verbose: true| Parameter | Type | Default | Description |
|---|---|---|---|
output_file |
string | required | Path to output .env file |
variables |
dict | required | Key-value pairs to write |
overwrite |
bool | false |
Overwrite existing files |
create_backup |
bool | true |
Backup existing files |
verbose |
bool | false |
Enable verbose logging |
python hooks/env_file_generator.py \
--output-file .env.local \
--variables NEXT_PUBLIC_API_URL=https://api.example.com \
DATABASE_URL=postgres://localhost:5432/db \
--overwriteBuilds Next.js applications and syncs output to S3 with proper cache headers.
post_deploy:
- path: hooks.npm_build.build_and_sync_app
args:
bucket_name: ${cfn ${namespace}-site.S3BucketName}
app_path: ./frontend/app
environment: ${environment}| Parameter | Type | Default | Description |
|---|---|---|---|
bucket_name |
string | required | S3 bucket name |
app_path |
string | ./app |
Path to app directory |
environment |
string | dev |
Environment for .env selection |
- Copies environment-specific
.env.{environment}to.env.local - Runs
npm installif node_modules missing - Runs
npm run build - Syncs static assets with 1-year cache headers
- Syncs HTML/JSON with no-cache headers
- Sets proper content types
python hooks/npm_build.py \
--bucket-name my-bucket \
--app-path ./app \
--environment prodDeploys AWS SAM templates with support for failed stack recovery.
pre_hooks:
- path: hooks.sam_deploy.cfngin_hook
required: true
args:
template_file: template.yaml
stack_name: myapp-lambda-${environment}
config_file: samconfig.toml
env: ${environment}
parameters:
Environment: ${environment}
Timeout: 900
capabilities:
- CAPABILITY_IAM
- CAPABILITY_NAMED_IAM
wait: true
timeout: 1800
skip_build: false
working_directory: ./lambda| Parameter | Type | Default | Description |
|---|---|---|---|
template_file |
string | required | SAM template path |
stack_name |
string | required | CloudFormation stack name |
config_file |
string | None | SAM config file path |
env |
string | None | Environment name |
parameters |
dict | None | Parameter overrides |
param_file |
string | None | JSON file with parameters |
capabilities |
list | IAM capabilities | Required capabilities |
region |
string | us-east-1 |
AWS region |
wait |
bool | true |
Wait for deployment |
timeout |
int | 1800 |
Deployment timeout |
skip_build |
bool | false |
Skip sam build step |
working_directory |
string | None | Working directory |
post_hooks:
- path: hooks.sam_deploy.cfngin_delete_hook
required: false
args:
stack_name: myapp-lambda-${environment}
wait: true
retain_resources:
- MyS3Bucket
- MyDynamoTable# Deploy
python hooks/sam_deploy.py deploy \
--template template.yaml \
--stack-name my-stack \
--env prod
# Delete
python hooks/sam_deploy.py delete \
--stack-name my-stack \
--retain-resources MyS3Bucket- Automatic failed stack detection and cleanup
- CI mode for non-interactive deployments
- Parameter file support (JSON)
- Stack output retrieval
See the hooks/ directory for example configurations:
example-cfngin.yaml- Basic CloudFront invalidationexample-cfngin-with-delete.yaml- SAM deploy with deletionexample-runway.yml- Runway configurationexample_env_config.yaml- Environment file generationexample_registration_site_integration.yaml- Complete deployment workflow
- Python 3.8+
- boto3 >= 1.26.0
- python-dotenv >= 1.0.0
- Docker (for docker hooks)
- AWS SAM CLI (for sam_deploy hook)
- Node.js/npm (for npm_build hook)
AGPL-3.0