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
33 changes: 0 additions & 33 deletions .circleci/config.yml

This file was deleted.

119 changes: 119 additions & 0 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: Integration Test

on:
push:
paths-ignore:
- 'README.md'
branches:
- master
pull_request:
branches:
- master
schedule:
# "At 00:00 on Sunday."
- cron: "0 0 * * 0"
workflow_dispatch:

jobs:
test:
name: Run Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
working-directory: demo/lambdas/ruby

- name: Setup LocalStack
uses: localstack/setup-localstack@main
with:
image-tag: 'latest'
use-pro: 'true'
configuration: LS_LOG=trace
install-awslocal: 'true'
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}

- name: Install CDK dependencies
run: cd cdk && npm ci

- name: Bundle Ruby Lambda gems
working-directory: demo/lambdas/ruby
run: |
bundle config set --local path vendor/bundle
bundle install

- name: Install Node.js Lambda dependencies
run: cd demo/lambdas/nodejs && npm install --omit=dev

- name: Bootstrap CDK
working-directory: cdk
env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
run: npx cdklocal bootstrap

- name: Deploy CDK stack
working-directory: cdk
env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
run: npx cdklocal deploy LocalstackDemoStack --require-approval never

- name: Upload frontend to S3
env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_ENDPOINT_URL: http://localhost.localstack.cloud:4566
run: awslocal s3 sync demo/web/ s3://archive-bucket/

- name: Run end-to-end test
env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
AWS_ENDPOINT_URL: http://localhost.localstack.cloud:4566
run: |
echo "Discovering REST API ID..."
apiId=$(awslocal apigateway get-rest-apis --output json \
| jq -r '.items[] | select(.name=="localstack-demo") | .id')
echo "API ID: $apiId"

echo "Sending new request..."
reqID=$(curl -sf -d '{}' \
"http://localhost:4566/_aws/execute-api/$apiId/local/requests" \
| jq -r .requestID)
echo "Request ID: $reqID"

echo "Polling for QUEUED -> PROCESSING -> FINISHED..."
for i in $(seq 1 25); do
cur=$(curl -sf \
"http://localhost:4566/_aws/execute-api/$apiId/local/requests" \
| jq -r "[.result[] | select(.requestID==\"$reqID\") | .status] | sort | last")
echo " attempt $i: $cur"
[ "$cur" = "FINISHED" ] && break
sleep 3
done

echo "Verifying S3 result file..."
awslocal s3 cp "s3://archive-bucket/$reqID/result.txt" - | grep -q "Archive result" \
&& echo "✅ End-to-end test passed!" \
|| (echo "❌ S3 result not found" && exit 1)

- name: LocalStack logs (on failure)
if: failure()
run: localstack logs
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
*.pyc
.serverless/
node_modules
.idea/
cdk.out
.DS_Store
vendor/
132 changes: 102 additions & 30 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,31 +1,103 @@
export AWS_ACCESS_KEY_ID ?= test
SHELL := /bin/bash

-include .env-gdc-local

CDIR = cd cdk

export AWS_ACCESS_KEY_ID ?= test
export AWS_SECRET_ACCESS_KEY ?= test
export AWS_DEFAULT_REGION = us-east-1

usage: ## Show this help
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'

install: ## Install dependencies
npm install
which serverless || npm install -g serverless
which localstack || pip install localstack

deploy: ## Deploy the app
@make install; \
echo "Deploying Serverless app to local environment"; \
SLS_DEBUG=1 serverless deploy --stage local

send-request: ## Send a test request to the deployed application
@which jq || (echo "jq was not found. Please install it (https://jqlang.github.io/jq/download/) and try again." && exit 1)
@echo Looking up API ID from deployed API Gateway REST APIs ...; \
apiId=$$(awslocal apigateway get-rest-apis --output json | jq -r '.items[] | select(.name="local-localstack-demo") | .id'); \
echo Sending request to API Gateway REST APIs ID "$$apiId" ...; \
requestID=$$(curl -s -d '{}' http://$$apiId.execute-api.localhost.localstack.cloud:4566/local/requests | jq -r .requestID); \
echo "Received request ID '$$requestID'"; \
for i in 1 2 3 4 5 6 7 8 9 10; do echo "Polling for processing result to appear in s3://archive-bucket/..."; awslocal s3 ls s3://archive-bucket/ | grep $$requestID && exit; sleep 3; done

lint: ## Run code linter
@npm run lint
@flake8 demo

.PHONY: usage install deploy send-request lint
export AWS_DEFAULT_REGION ?= us-east-1
export AWS_ENDPOINT_URL ?= http://localhost.localstack.cloud:4566

usage: ## Show this help in table format
@echo "| Target | Description |"
@echo "|------------------------|-------------------------------------------------------------------|"
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/:.*##\s*/##/g' | awk -F'##' '{ printf "| %-22s | %-65s |\n", $$1, $$2 }'

check: ## Check if all required prerequisites are installed
@command -v docker > /dev/null 2>&1 || { echo "Docker is not installed. Please install Docker and try again."; exit 1; }
@command -v node > /dev/null 2>&1 || { echo "Node.js is not installed. Please install Node.js and try again."; exit 1; }
@command -v aws > /dev/null 2>&1 || { echo "AWS CLI is not installed. Please install AWS CLI and try again."; exit 1; }
@command -v awslocal > /dev/null 2>&1 || { echo "awslocal is not installed. Run: pip install awscli-local"; exit 1; }
@command -v localstack > /dev/null 2>&1 || { echo "LocalStack CLI is not installed. Run: pip install localstack"; exit 1; }
@command -v jq > /dev/null 2>&1 || { echo "jq is not installed. See https://jqlang.github.io/jq/download/"; exit 1; }
@test -n "$(LOCALSTACK_AUTH_TOKEN)" || { echo "LOCALSTACK_AUTH_TOKEN is not set. Find your token at https://app.localstack.cloud/workspace/auth-token"; exit 1; }
@echo "All required prerequisites are available."

install: ## Install CDK and Lambda dependencies
@$(CDIR); if [ ! -d "node_modules" ]; then \
echo "Installing CDK dependencies..."; \
npm install; \
else \
echo "CDK dependencies already installed."; \
fi

bundle-ruby: ## Bundle Ruby 3.3 Lambda gems (requires Docker)
docker run --rm \
-v "$(shell pwd)/demo/lambdas/ruby:/var/task" \
-w /var/task \
ruby:3.3 \
sh -c "bundle config set --local path vendor/bundle && bundle install"

bundle-node: ## Install Node.js Lambda production dependencies
cd demo/lambdas/nodejs && npm install --omit=dev

build: ## Build the CDK TypeScript app
$(CDIR) && npm run build

bootstrap: ## Bootstrap CDK for LocalStack
$(CDIR) && npm run build && npx cdklocal bootstrap

deploy: ## Build, deploy CDK stack to LocalStack, and upload frontend
$(MAKE) bundle-ruby bundle-node
$(MAKE) bootstrap
$(CDIR) && npx cdklocal deploy LocalstackDemoStack --require-approval never
@echo "Uploading frontend to s3://archive-bucket/ ..."
awslocal s3 sync demo/web/ s3://archive-bucket/
@echo ""
@echo "Done! Open http://localhost:4566/archive-bucket/index.html in your browser."

destroy: ## Destroy the deployed CDK stack on LocalStack
$(CDIR) && npx cdklocal destroy LocalstackDemoStack

send-request: ## Send a test request and poll S3 for the result
@command -v jq > /dev/null 2>&1 || { echo "jq is not installed. See https://jqlang.github.io/jq/download/"; exit 1; }
@echo "Looking up REST API ID..."
@apiId=$$(awslocal apigateway get-rest-apis --output json | jq -r '.items[] | select(.name=="localstack-demo") | .id'); \
echo "Sending request to API ID '$$apiId' ..."; \
reqID=$$(curl -s -d '{}' "http://localhost:4566/_aws/execute-api/$$apiId/local/requests" | jq -r .requestID); \
echo "Received request ID '$$reqID'"; \
for i in 1 2 3 4 5 6 7 8 9 10; do \
echo "Polling s3://archive-bucket/ for result ..."; \
awslocal s3 ls s3://archive-bucket/ | grep "$$reqID" && exit 0; \
sleep 3; \
done; \
echo "Timed out waiting for result."

start: ## Start LocalStack in detached mode
@echo "Starting LocalStack..."
@test -n "$(LOCALSTACK_AUTH_TOKEN)" || { echo "LOCALSTACK_AUTH_TOKEN is not set. Find your token at https://app.localstack.cloud/workspace/auth-token"; exit 1; }
@LOCALSTACK_AUTH_TOKEN=$(LOCALSTACK_AUTH_TOKEN) localstack start -d
@echo "LocalStack started successfully."

stop: ## Stop LocalStack
@echo "Stopping LocalStack..."
@localstack stop
@echo "LocalStack stopped successfully."

ready: ## Wait until the LocalStack container is ready
@echo "Waiting on the LocalStack container..."
@localstack wait -t 30 && echo "LocalStack is ready to use!" || { echo "Gave up waiting on LocalStack, exiting."; exit 1; }

logs: ## Save LocalStack logs to logs.txt
@localstack logs > logs.txt

PKG_SUB_DIRS := $(dir $(shell find . -type d -name node_modules -prune -o -type d -name "vendor" -prune -o -type f -name package.json -print))

update-deps: ## Update npm dependencies in all sub-projects
for i in $(PKG_SUB_DIRS); do \
pushd $$i && ncu -u && npm install && popd; \
done

.PHONY: usage check install bundle-ruby bundle-node build bootstrap deploy deploy-aws \
destroy destroy-aws send-request start stop ready logs update-deps
Loading
Loading