Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ecc6ca4
Add vera-setup composite action and CI test workflow
ZhuochengHe Mar 18, 2026
2193bea
Fix health check: remove -f flag from curl
ZhuochengHe Mar 18, 2026
156deeb
Download vera docker-compose.yml at runtime
ZhuochengHe Mar 18, 2026
e0e1cd9
Add publish workflow and switch action to use prebuilt images from gh…
ZhuochengHe Mar 18, 2026
a00296c
Trigger publish workflow on feature branch for initial image build
ZhuochengHe Mar 18, 2026
4640a3f
Fix: lowercase repository_owner in ghcr.io image tags
ZhuochengHe Mar 18, 2026
8179d15
Fix: use tr to lowercase owner instead of unsupported | lower filter
ZhuochengHe Mar 18, 2026
be2bd04
Add vera-dynamodb emulator module
ZhuochengHe Mar 19, 2026
74a12da
Move aws-dynamodb gitignore rules to repo root
ZhuochengHe Mar 19, 2026
ce2e3ee
docs(aws-dynamodb): add API coverage and test methodology to README
ZhuochengHe Mar 20, 2026
730c6d1
fix(aws-dynamodb/tests): fix shell parse errors and improve eval cove…
ZhuochengHe Mar 20, 2026
af025d3
Improve test output comparison with semantic status normalization
ZhuochengHe Mar 20, 2026
6e2f2b9
Fix test reset boundary and add SSE/TableClass response augmentation
ZhuochengHe Mar 20, 2026
fe88b6d
feat(aws-dynamodb): improve eval coverage with RST setup commands, st…
ZhuochengHe Apr 3, 2026
1e6a1a9
Replace DynamoDB ARN regions from non-us-east-1 to us-east-1
ZhuochengHe Apr 5, 2026
10c3038
feat(aws-dynamodb): improve eval coverage to 97.6% pass rate
ZhuochengHe Apr 6, 2026
afd33c8
feat(aws-dynamodb): generate real values for all required dynamic fields
ZhuochengHe Apr 6, 2026
02d4e5f
feat(aws-dynamodb): inject ReadCapacityUnits/WriteCapacityUnits and T…
ZhuochengHe Apr 6, 2026
83f9612
fix(aws-dynamodb/tests): strip ContributorInsightsSummaries from eval…
ZhuochengHe Apr 6, 2026
45a4eb5
docs(aws-dynamodb): add ContributorInsightsSummaries to optional dyna…
ZhuochengHe Apr 6, 2026
181181b
test: arn tags
ZhuochengHe Apr 6, 2026
e320e1c
remove tablename from dynamic fields
ZhuochengHe Apr 10, 2026
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
105 changes: 105 additions & 0 deletions .github/actions/vera-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: 'Vera Emulator Setup'
description: 'Start Vera cloud emulators (AWS EC2 + GCP Compute) and configure environment for CI/CD testing'
branding:
icon: 'server'
color: 'blue'

inputs:
start-aws:
description: 'Whether to start the AWS EC2 emulator'
default: 'true'
start-gcp:
description: 'Whether to start the GCP Compute emulator'
default: 'true'
aws-endpoint:
description: 'AWS emulator URL'
default: 'http://localhost:5003'
gcp-endpoint:
description: 'GCP emulator URL'
default: 'http://localhost:9100'
aws-region:
description: 'AWS default region'
default: 'us-east-1'
gcp-project:
description: 'GCP project ID'
default: 'vera-project'
wait-timeout:
description: 'Seconds to wait for emulators to become healthy'
default: '60'

outputs:
aws-endpoint:
description: 'AWS emulator endpoint URL'
value: ${{ inputs.aws-endpoint }}
gcp-endpoint:
description: 'GCP emulator endpoint URL'
value: ${{ inputs.gcp-endpoint }}

runs:
using: 'composite'
steps:
- name: Start emulators
shell: bash
run: |
if [ "${{ inputs.start-aws }}" = "true" ]; then
docker run -d --name vera-aws \
-p 5003:5003 \
ghcr.io/zhuochenghe/vera/vera-aws:latest
fi
if [ "${{ inputs.start-gcp }}" = "true" ]; then
docker run -d --name vera-gcp \
-p 9100:9100 \
ghcr.io/zhuochenghe/vera/vera-gcp:latest
fi

- name: Wait for AWS emulator
if: ${{ inputs.start-aws == 'true' }}
shell: bash
run: |
TIMEOUT=${{ inputs.wait-timeout }}
ELAPSED=0
echo "Waiting for AWS emulator at ${{ inputs.aws-endpoint }} (timeout: ${TIMEOUT}s)..."
until curl -s --max-time 2 "${{ inputs.aws-endpoint }}" > /dev/null 2>&1; do
if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
echo "Timed out waiting for AWS emulator after ${TIMEOUT}s"
echo "=== vera-aws logs ==="
docker logs vera-aws
exit 1
fi
sleep 1
ELAPSED=$((ELAPSED + 1))
done
echo "AWS emulator is ready (${ELAPSED}s)"

- name: Wait for GCP emulator
if: ${{ inputs.start-gcp == 'true' }}
shell: bash
run: |
TIMEOUT=${{ inputs.wait-timeout }}
ELAPSED=0
echo "Waiting for GCP emulator at ${{ inputs.gcp-endpoint }} (timeout: ${TIMEOUT}s)..."
until curl -s --max-time 2 "${{ inputs.gcp-endpoint }}" > /dev/null 2>&1; do
if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
echo "Timed out waiting for GCP emulator after ${TIMEOUT}s"
echo "=== vera-gcp logs ==="
docker logs vera-gcp
exit 1
fi
sleep 1
ELAPSED=$((ELAPSED + 1))
done
echo "GCP emulator is ready (${ELAPSED}s)"

- name: Export environment variables
shell: bash
run: |
{
echo "AWS_ENDPOINT_URL=${{ inputs.aws-endpoint }}"
echo "AWS_ACCESS_KEY_ID=test"
echo "AWS_SECRET_ACCESS_KEY=test"
echo "AWS_DEFAULT_REGION=${{ inputs.aws-region }}"
echo "CLOUDSDK_API_ENDPOINT_OVERRIDES_COMPUTE=${{ inputs.gcp-endpoint }}/"
echo "CLOUDSDK_CORE_PROJECT=${{ inputs.gcp-project }}"
echo "CLOUDSDK_AUTH_DISABLE_CREDENTIALS=true"
echo "GOOGLE_OAUTH_ACCESS_TOKEN=vera-local-token"
} >> "$GITHUB_ENV"
49 changes: 49 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Publish Docker Images

on:
push:
branches: [main, feat/github_action_integration]
paths:
- 'emulators/aws-ec2/**'
- 'emulators/google-compute/**'
- '.github/workflows/publish.yml'
workflow_dispatch:

jobs:
publish:
name: Build and push emulator images
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

- name: Set lowercase owner
run: echo "OWNER=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV

- name: Log in to ghcr.io
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push vera-aws
uses: docker/build-push-action@v6
with:
context: emulators/aws-ec2
push: true
tags: |
ghcr.io/${{ env.OWNER }}/vera/vera-aws:latest
ghcr.io/${{ env.OWNER }}/vera/vera-aws:${{ github.sha }}

- name: Build and push vera-gcp
uses: docker/build-push-action@v6
with:
context: emulators/google-compute
push: true
tags: |
ghcr.io/${{ env.OWNER }}/vera/vera-gcp:latest
ghcr.io/${{ env.OWNER }}/vera/vera-gcp:${{ github.sha }}
81 changes: 81 additions & 0 deletions .github/workflows/test-action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Test vera-setup Action

on:
push:
branches: [main, feat/github_action_integration]
paths:
- '.github/actions/vera-setup/**'
- '.github/workflows/test-action.yml'
pull_request:
branches: [main]
workflow_dispatch:

jobs:
test-both-emulators:
name: Test — AWS + GCP
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Start Vera emulators
uses: ./.github/actions/vera-setup

- name: Verify env vars are exported
run: |
echo "AWS_ENDPOINT_URL=$AWS_ENDPOINT_URL"
echo "AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION"
echo "CLOUDSDK_API_ENDPOINT_OVERRIDES_COMPUTE=$CLOUDSDK_API_ENDPOINT_OVERRIDES_COMPUTE"
echo "CLOUDSDK_CORE_PROJECT=$CLOUDSDK_CORE_PROJECT"
echo "CLOUDSDK_AUTH_DISABLE_CREDENTIALS=$CLOUDSDK_AUTH_DISABLE_CREDENTIALS"
[ "$AWS_ENDPOINT_URL" = "http://localhost:5003" ] || (echo "FAIL: AWS_ENDPOINT_URL" && exit 1)
[ "$AWS_DEFAULT_REGION" = "us-east-1" ] || (echo "FAIL: AWS_DEFAULT_REGION" && exit 1)
[ "$CLOUDSDK_AUTH_DISABLE_CREDENTIALS" = "true" ] || (echo "FAIL: CLOUDSDK_AUTH_DISABLE_CREDENTIALS" && exit 1)
[ "$CLOUDSDK_CORE_PROJECT" = "vera-project" ] || (echo "FAIL: CLOUDSDK_CORE_PROJECT" && exit 1)
echo "All env vars OK"

- name: Install AWS CLI
run: pip install awscli --quiet

- name: Test AWS CLI
run: |
aws ec2 describe-instances
aws ec2 describe-vpcs

- name: Test GCP CLI
run: |
# Create isolated gcloud config and token file (mirrors gcpcli wrapper from install.sh)
mkdir -p /tmp/vera-gcloud-config
echo "vera-local-token" > /tmp/vera-gcloud-config/access_token

gcloud compute instances list \
--project=vera-project \
--access-token-file=/tmp/vera-gcloud-config/access_token
gcloud compute networks list \
--project=vera-project \
--access-token-file=/tmp/vera-gcloud-config/access_token
env:
CLOUDSDK_CONFIG: /tmp/vera-gcloud-config

test-aws-only:
name: Test — AWS only (start-gcp false)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Start AWS emulator only
uses: ./.github/actions/vera-setup
with:
start-gcp: 'false'

- name: Verify only AWS container is running
run: |
docker ps --format '{{.Names}}'
docker ps --format '{{.Names}}' | grep -q vera-aws || (echo "FAIL: vera-aws not running" && exit 1)
docker ps --format '{{.Names}}' | grep -q vera-gcp && (echo "FAIL: vera-gcp should not be running" && exit 1) || true
echo "Container check passed"

- name: Install AWS CLI
run: pip install awscli --quiet

- name: Test AWS CLI works
run: aws ec2 describe-instances
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@ temp/
CLAUDE.md
results/
.venv/
.python-version
.python-version

# aws-dynamodb emulator
emulators/aws-dynamodb/dynamodb-local/
emulators/aws-dynamodb/dynamodb-local-metadata.json
emulators/aws-dynamodb/tests/eval_results.json
emulators/aws-dynamodb/tests/test.sh
emulators/aws-dynamodb/tests/tmp/
24 changes: 24 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
services:
dynamodb-local:
image: amazon/dynamodb-local:latest
ports:
- "8000:8000"
command: ["-jar", "DynamoDBLocal.jar", "-sharedDb", "-inMemory"]
healthcheck:
test: ["CMD", "curl", "-s", "--max-time", "2", "http://localhost:8000"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s

vera-dynamodb:
build:
context: emulators/aws-dynamodb
ports:
- "5005:5005"
healthcheck:
test: ["CMD", "python", "-c", "import socket; s=socket.create_connection(('localhost',5005),timeout=2); s.close()"]
interval: 5s
timeout: 3s
retries: 5
start_period: 15s

vera-aws:
build:
context: emulators/aws-ec2
Expand Down
33 changes: 33 additions & 0 deletions emulators/aws-dynamodb/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM amazon/dynamodb-local:latest AS dynamodb-local

FROM python:3.13-slim

# Install Java runtime (needed to run DynamoDBLocal.jar)
RUN apt-get update && apt-get install -y --no-install-recommends \
default-jre-headless \
&& rm -rf /var/lib/apt/lists/*

COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

# Copy DynamoDB Local JAR and native libs from official image
COPY --from=dynamodb-local /home/dynamodblocal/DynamoDBLocal.jar /dynamodblocal/DynamoDBLocal.jar
COPY --from=dynamodb-local /home/dynamodblocal/DynamoDBLocal_lib /dynamodblocal/DynamoDBLocal_lib

WORKDIR /app

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev

COPY main.py state_machine.py ./
COPY emulator_core/ emulator_core/

ENV VERA_HOST=0.0.0.0
ENV VERA_PORT=5005
ENV DYNAMODB_LOCAL_URL=http://localhost:8000
# Override default JAR path for Docker (JAR is at /dynamodblocal, not ./dynamodb-local)
ENV DYNAMODB_LOCAL_JAR=/dynamodblocal/DynamoDBLocal.jar
ENV DYNAMODB_LOCAL_LIB=/dynamodblocal/DynamoDBLocal_lib

EXPOSE 5005

CMD ["uv", "run", "python", "main.py"]
Loading