Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LOCALSTACK_AUTH_TOKEN=

# Local CDK defaults
AWS_ENDPOINT_URL=http://localhost:4566
AWS_ENDPOINT_URL_S3=http://s3.localhost:4566
10 changes: 4 additions & 6 deletions .github/workflows/check.yml → .github/workflows/verify.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
name: Format, Lint, and Test
name: Verify code and infra

on:
workflow_call:
push:

jobs:
check:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install mise
uses: jdx/mise-action@v4
- name: Format and lint
run: mise run lint
- name: Run tests
run: mise run test
- name: Verify code and infra
run: mise run verify
env:
AWS_DEFAULT_REGION: us-east-1
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ celerybeat.pid

# Environments
.env
.env.local
.venv
env/
venv/
Expand Down Expand Up @@ -171,4 +172,10 @@ cython_debug/
devcontainer-lock.json

# CDK
cdk.out/
cdk.out/

# Localstack
.localstack/

# Node.js
node_modules/
37 changes: 37 additions & 0 deletions .vibe/specs/deploy-localstack/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Design: Deploy Lambda Stacks to Local via LocalStack

## System Architecture

```mermaid
flowchart TD
CLI["mise run local <stack>"] --> CDK["aws-cdk-local (npx)"]
CDK -->|"http://localhost:4566"| LS["LocalStack Container<br/>(DynamoDB, Lambda, ApiGateway, SQS, etc.)"]
```

## Component Design

### 1. `.env.local.example` & `compose.yml`

- `.env.local.example`: Template configuration file defining `LOCALSTACK_AUTH_TOKEN`, local AWS credentials, and endpoint URLs.
- `compose.yml`: Standard LocalStack Docker Compose service configuration mapping port `4566` (LocalStack Gateway) and volume mounts for persistence, loaded via `--env-file .env.local`.

### 2. `mise.toml`

Adds the following task configurations:

- `tasks."local:up"`: Launches LocalStack via `docker compose --env-file .env.local up -d --wait localstack`.
- `tasks."local:down"`: Stops LocalStack via `docker compose --env-file .env.local down localstack`.
- `tasks."local:deploy"`: Executes `STACK=$usage_stack npx --package=aws-cdk --package=aws-cdk-local cdklocal deploy --require-approval=never`.
- Aliases: `local`, `dl`
- Depends on: `install-cdk`, `local:up`
- `tasks."local:destroy"`: Executes `STACK=$usage_stack npx --package=aws-cdk --package=aws-cdk-local cdklocal destroy --force`.
- Alias: `Dl`
- Depends on: `install-cdk`, `local:up`
- `tasks.docs-local`: Serves MkDocs documentation (`uv run mkdocs serve`).

### 3. Documentation (`docs/README.md`, `AGENTS.md`)

- Instruct copying `.env.local.example` to `.env.local` and obtaining auth token from `app.localstack.cloud`.
- Add LocalStack under Prerequisites and Setup sections.
- Update shell aliases and common commands tables.
- Add step-by-step instructions to start LocalStack and deploy stacks locally.
70 changes: 70 additions & 0 deletions .vibe/specs/deploy-localstack/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Implementation Plan - Deploy Lambda Stacks to Local using LocalStack

Enable local deployment and teardown of AWS CDK Lambda stacks using LocalStack and `aws-cdk-local`.

## User Review Required

> [!IMPORTANT]
> Developers must copy `.env.local.example` to `.env.local` and set `LOCALSTACK_AUTH_TOKEN` obtained from [app.localstack.cloud](https://app.localstack.cloud).

## Proposed Changes

### Configuration & Infrastructure

#### [NEW] [compose.yml](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/compose.yml)

- Add standard LocalStack container definition exposing port `4566`.

#### [NEW] [.env.local.example](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/.env.local.example)

- Add template environment file with `LOCALSTACK_AUTH_TOKEN`, local AWS credentials, and endpoint URLs.

#### [MODIFY] [mise.toml](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/mise.toml)

- Add shell aliases `local = "mise run local:deploy"`, `dl = "mise run local:deploy"`, and `Dl = "mise run local:destroy"`.
- Rename documentation local serve task to `[tasks.docs-local]`.
- Add `[tasks."local:up"]` to start LocalStack via `docker compose --env-file .env.local up -d --wait localstack`.
- Add `[tasks."local:down"]` to stop LocalStack via `docker compose --env-file .env.local down localstack`.
- Add `[tasks."local:deploy"]` (aliases `local`, `dl`) to deploy stacks locally using `aws-cdk-local`.
- Add `[tasks."local:destroy"]` (alias `Dl`) to destroy stacks locally using `aws-cdk-local`.

---

### Documentation

#### [MODIFY] [docs/README.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/docs/README.md)

- Update Prerequisites section to include LocalStack / Docker.
- Add step to copy `.env.local.example` to `.env.local` and obtain token from `app.localstack.cloud`.
- Add "Deploy stack to local (LocalStack)" and "Destroy local stack" sub-sections under Infrastructure deployment options.
- Update project structure tree diagram to include `compose.yml` and `.vibe/specs`.

#### [MODIFY] [AGENTS.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/AGENTS.md)

- Add instructions to setup `.env.local` with token from `app.localstack.cloud`.
- Add `mise run local:deploy`, `mise run local:destroy`, `mise run local:up`, and `mise run local:down` to Common Commands list.

---

### Specifications

#### [NEW] [.vibe/specs/deploy-localstack/requirements.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/.vibe/specs/deploy-localstack/requirements.md)

#### [NEW] [.vibe/specs/deploy-localstack/design.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/.vibe/specs/deploy-localstack/design.md)

#### [NEW] [.vibe/specs/deploy-localstack/plan.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/.vibe/specs/deploy-localstack/plan.md)

#### [NEW] [.vibe/specs/deploy-localstack/tasks.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/.vibe/specs/deploy-localstack/tasks.md)

#### [NEW] [.vibe/specs/deploy-localstack/walkthrough.md](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/aws-lambda-templates/.vibe/specs/deploy-localstack/walkthrough.md)

## Verification Plan

### Automated Tests

- Run `mise run lint` (ruff format and check) to confirm code quality and formatting.
- Run `mise run test` to verify pytest suite execution.

### Manual Verification

- Test synthesizing / validating localstack CDK command syntax: `STACK=api uv run npx --package=aws-cdk --package=aws-cdk-local cdklocal synth`.
29 changes: 29 additions & 0 deletions .vibe/specs/deploy-localstack/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Requirements: Deploy Lambda Stacks to Local via LocalStack

## Overview

Enable developers to deploy and tear down AWS CDK Lambda stacks locally using LocalStack without requiring an active AWS cloud account or active AWS credentials.

## Functional Requirements

1. **Environment & Auth Token Setup**:
- Provide `.env.local.example` with defaults for LocalStack and local CDK deployment.
- Instruct developers to copy `.env.local.example` to `.env.local` and obtain an auth token from [app.localstack.cloud](https://app.localstack.cloud) to populate `LOCALSTACK_AUTH_TOKEN`.
2. **Local Stack Deployment**:
- Provide a `local:deploy` task in `mise.toml` that deploys any CDK stack defined under `infra/stacks/` to a local LocalStack instance.
- Command syntax: `mise run local:deploy <stack>` (alias `local <stack>` or `dl <stack>`).
3. **Local Stack Destruction**:
- Provide a `local:destroy` task in `mise.toml` that destroys a deployed stack from LocalStack.
- Command syntax: `mise run local:destroy <stack>` (alias `Dl <stack>`).
4. **LocalStack Container Management**:
- Provide a standard `compose.yml` file configuring LocalStack.
- Provide `local:up` (`mise run local:up`) to start LocalStack with `.env.local`.
- Provide `local:down` (`mise run local:down`) to stop LocalStack.
5. **Documentation Updates**:
- Update `docs/README.md` to document LocalStack setup, `.env.local` configuration, token retrieval from app.localstack.cloud, prerequisites, and usage of `local:deploy`, `local:destroy`, `local:up`, and `local:down`.
- Update `AGENTS.md` to include local deployment environment setup, commands, aliases (`local`, `dl`, `Dl`), and instructions for AI agents.

## Non-Functional Requirements

- Maintain backward compatibility with existing cloud CDK deployment tasks (`mise run deploy` and `mise run destroy`).
- Pass all project linting (`mise run lint`) and tests (`mise run test`).
11 changes: 11 additions & 0 deletions .vibe/specs/deploy-localstack/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Tasks: Deploy Lambda Stacks to Local via LocalStack

- [x] Create `compose.yml` for LocalStack container management <!-- id: 0 -->
- [x] Create `.env.local.example` template environment file <!-- id: 1 -->
- [x] Add `tasks."local:up"`, `tasks."local:down"`, `tasks."local:deploy"`, and `tasks."local:destroy"` to `mise.toml` <!-- id: 2 -->
- [x] Add `local`, `dl`, and `Dl` shell aliases to `mise.toml` <!-- id: 3 -->
- [x] Update `docs/README.md` with `.env.local` setup, app.localstack.cloud token, and deployment instructions <!-- id: 4 -->
- [x] Update `AGENTS.md` with `.env.local` token guidance, `mise` tasks, and local CDK instructions <!-- id: 5 -->
- [x] Run `mise run lint` to verify code quality <!-- id: 6 -->
- [x] Run `mise run test` to verify test suite passes <!-- id: 7 -->
- [x] Create `walkthrough.md` with complete verification details <!-- id: 8 -->
46 changes: 46 additions & 0 deletions .vibe/specs/deploy-localstack/walkthrough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Walkthrough: Deploy Lambda Stacks to Local using LocalStack

We have added support for deploying and tearing down AWS CDK Lambda stacks locally using LocalStack.

## Changes Made

### Configuration & Infrastructure

- Created `compose.yml` configured to spin up LocalStack (gateway on port 4566).
- Created `.env.local.example` with defaults for local execution and LocalStack auth token configuration.
- Updated `mise.toml`:
- Added `[tasks."local:up"]` task to start LocalStack container with `.env.local`.
- Added `[tasks."local:down"]` task to stop LocalStack container with `.env.local`.
- Added `[tasks."local:deploy"]` task with aliases `local` and `dl` to deploy CDK stacks locally via `aws-cdk-local` (depends on `install-cdk`, `local:up`).
- Added `[tasks."local:destroy"]` task with alias `Dl` to destroy stacks from LocalStack via `aws-cdk-local` (depends on `install-cdk`, `local:up`).
- Renamed documentation local preview task to `[tasks.docs-local]`.

### Documentation

- Updated `docs/README.md`:
- Added step to copy `.env.local.example` to `.env.local` and set `LOCALSTACK_AUTH_TOKEN` from [app.localstack.cloud](https://app.localstack.cloud).
- Added Docker under Local environment prerequisites.
- Added "Deploy a stack locally (LocalStack)" and "Destroy a local stack" sections with `local:up`, `local:deploy`, `local:destroy`, and `local:down`.
- Updated Project Structure tree diagram with `compose.yml`.
- Updated `AGENTS.md`:
- Added `.env.local` token guidance, LocalStack & local CDK deployment commands (`mise run local:up`, `mise run local:deploy`, `mise run local:destroy`) and aliases.

### Specifications

- Updated `.vibe/specs/deploy-localstack/`:
- `requirements.md`
- `design.md`
- `plan.md`
- `tasks.md`
- `walkthrough.md`

## Verification Results

### Automated Verification

1. `mise run lint`: Format & lint validations passed.
2. `mise run test`: All 71 unit tests passed with 93% coverage.

### Manual Verification

- Verified `.env.local.example` content and task execution configuration.
15 changes: 13 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ mise run precommit # install pre-commit hooks
```bash
mise run lint # run ruff (check + format) and pyright
mise run test # run pytest with coverage
mise run infra:synth # synthesize CDK stack(s) (alias: synth, s)
mise run docs # build and deploy docs to GitHub Pages
mise run local # serve docs locally
mise run docs-local # serve docs locally
mise run local:up # start LocalStack via Docker Compose
mise run local:deploy # deploy CDK stack to LocalStack (alias: local, dl)
mise run local:destroy # destroy CDK stack from LocalStack (alias: Dl)
mise run local:down # stop LocalStack via Docker Compose
```

## Code Style
Expand Down Expand Up @@ -48,6 +53,7 @@ templates/ # main package
tests/ # pytest tests
docs/ # MkDocs documentation
infra/ # AWS CDK infrastructure stacks
compose.yml # LocalStack container configuration
```

## Renaming the Template
Expand All @@ -67,7 +73,12 @@ mise run rename --name="my-project" --description="My description" --author="Nam

## Infrastructure

- Define and deploy infrastructure using AWS CDK under the `infra/` folder
- Define infrastructure using AWS CDK under the `infra/` folder.
- Synthesize CloudFormation templates: `mise run infra:synth [stack]` (alias `synth [stack]`, `s [stack]`).
- Deploy to AWS: `mise run deploy <stack>` (alias `d <stack>`).
- Deploy locally using LocalStack: copy `.env.local.example` to `.env.local` and set token from [app.localstack.cloud](https://app.localstack.cloud), then `mise run local:deploy <stack>` (alias `local <stack>`, `dl <stack>`).
- Destroy locally from LocalStack: `mise run local:destroy <stack>` (alias `Dl <stack>`).


## Testing Guidelines

Expand Down
6 changes: 3 additions & 3 deletions cdk.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"app": "python infra/app.py",
"requireApproval": "never"
}
"app": "python infra/app.py",
"requireApproval": "never"
}
16 changes: 16 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
services:
localstack:
container_name: localstack
image: localstack/localstack:latest
env_file: .env.local
ports:
- "4566:4566"
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./.localstack}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4566/_localstack/health"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
44 changes: 41 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Templates come pre-wired with:
- **Clean Architecture**: Separation of concerns using the Repository pattern for data access
- **Data Modeling**: Strong typing and validation using [Pydantic](https://docs.pydantic.dev)
- **Infrastructure as Code**: [AWS CDK](https://aws.amazon.com/cdk) stacks
- **Local AWS Deployment**: [LocalStack](https://localstack.cloud) integration for local CDK deployment and testing without an AWS account
- **Testing**: Comprehensive [pytest](https://pytest.org) suite with [moto](http://docs.getmoto.org) for AWS mocking and [hypothesis](https://hypothesis.readthedocs.io) for property-based testing
- **Code Quality**: [ruff](https://docs.astral.sh/ruff) for linting and formatting, [pyright](https://microsoft.github.io/pyright) for type checking, and test coverage using [coverage](https://coverage.readthedocs.io)
- **Dependency Control**: [uv](https://docs.astral.sh/uv/) for dependency management and [Dependabot](https://docs.github.com/en/code-security/dependabot) for automated dependency updates
Expand Down Expand Up @@ -83,6 +84,7 @@ Parameter | Description

### Local environment
- [mise](https://mise.jdx.dev/)
- Docker (for running LocalStack locally)

## Setup

Expand Down Expand Up @@ -120,9 +122,15 @@ mise run new <name> # alias: n <name>
This runs the `new` script, which builds a skeleton for the new template from `.template`.


### Synthesize infrastructure
Infrastructure is defined as AWS CDK stacks under `infra/stacks/`.
The CDK entry point is `infra/app.py`.

```bash
mise run infra:synth [stack] # aliases: synth [stack], s [stack]
```

### Deploy a stack
Infrastructure is defined as AWS CDK stacks under `infra/stacks/`.
The CDK entry point is `infra/app.py`.

```bash
mise run deploy <stack> # alias: d <stack>
Expand All @@ -138,6 +146,34 @@ mise run deploy <stack> --profile <my-profile>
mise run destroy <stack> # alias: D <stack>
```

### Deploy a stack locally (LocalStack)
To deploy CDK stacks locally without an AWS account:

1. Copy `.env.local.example` to `.env.local` and set your auth token from [app.localstack.cloud](https://app.localstack.cloud):
```bash
cp .env.local.example .env.local
```

2. Start LocalStack via Docker Compose:
```bash
mise run local:up
```

3. Deploy the stack to LocalStack:
```bash
mise run local:deploy <stack> # aliases: local <stack>, dl <stack>
```

### Destroy a local stack
```bash
mise run local:destroy <stack> # alias: Dl <stack>
```

To stop the LocalStack container when finished:
```bash
mise run local:down
```

### Generating documentation

To build and publish the project documentation to GitHub Pages, run:
Expand All @@ -150,7 +186,7 @@ That pushes the new documentation to the `gh-pages` branch. Make sure GitHub Pag
### Local preview
To serve the documentation on a local server, run:
```bash
mise run local
mise run docs-local
```

## Coding Conventions
Expand Down Expand Up @@ -182,7 +218,9 @@ mise run local
│ └── docs.yml # Workflow to publish documentation
├── .gitignore # Git-ignored file list
├── .pre-commit-config.yaml # Pre-commit configuration file
├── .vibe # Feature specification
├── .vscode # VS Code folder
├── compose.yml # Docker Compose configuration for LocalStack
├── mise.toml # mise configuration and tasks
├── pyproject.toml # Configuration file for different tools
├── mkdocs.yml # MkDocs configuration file
Expand Down
Loading