Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# CDK output directory - MUST be excluded to prevent recursive bundling
deployments/app/cdk.out
deployments/glad/cdk.out
deployments/**/cdk.out
**/cdk.out

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
run: go mod download

- name: Run tests
run: task test:all
run: task glad:test:all

- name: Run linter
run: task lint
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Thumbs.db
.env
.env.local
http-client.env.json
cmd/app/testdata/api-testing/http-client.env.json
cmd/glad/testdata/api-testing/http-client.env.json
.env.*.local
*.env.*
*.pem
Expand Down Expand Up @@ -87,4 +87,4 @@ yarn-error.log*
.terraform.lock.hcl

# Go module downloads (keep go.sum)
vendor/cmd/app/testdata/api-testing/http-client.env.json
vendor/cmd/glad/testdata/api-testing/http-client.env.json
7 changes: 5 additions & 2 deletions Dockerfile → Dockerfile.lambda
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ RUN apk add --no-cache git ca-certificates tzdata
# Set working directory
WORKDIR /build

# Copy go mod files
# Copy go mod files from project root
COPY go.mod go.sum ./

# Download dependencies
Expand All @@ -17,13 +17,16 @@ RUN go mod download
# Copy source code
COPY . .

# Build argument for Lambda path (default: cmd/glad)
ARG LAMBDA_PATH=cmd/glad

# Build the Lambda function
# CGO_ENABLED=0 for static binary
# -ldflags="-s -w" to reduce binary size
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags="-s -w" \
-o /build/bootstrap \
./cmd/app
./${LAMBDA_PATH}

# Stage 2: Create the Lambda runtime image
FROM public.ecr.aws/lambda/provided:al2023
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ that can handle millions of requests while maintaining low latency and high avai
```
glad/
├── cmd/
│ └── app/ # Lambda application
│ └── glad/ # Lambda application
│ ├── main.go # Lambda entry point
│ ├── integration_test.go # Integration tests
│ ├── testdata/ # Test data files
Expand All @@ -54,7 +54,7 @@ glad/
│ ├── logger/ # Structured logging
│ └── middleware/ # HTTP middleware
├── deployments/
│ └── app/ # AWS CDK infrastructure
│ └── glad/ # AWS CDK infrastructure

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify that the deployments/glad/ directory structure exists and contains the CDK infrastructure files. The documentation now references this path, but ensure it matches the actual directory structure after the rename.

│ ├── cdk.go # CDK stack definition
├── Taskfile.yml # Task runner configuration
├── .golangci.yml # Go linter configuration
Expand Down Expand Up @@ -93,7 +93,7 @@ Request → Router → Middleware → Handler → Service → Repository → Dat
The database package follows a scalable file organization pattern designed for growth to 10+ repositories:

```
cmd/app/internal/database/
cmd/glad/internal/database/
├── client.go # Repository struct definitions
├── constants.go # Table names, GSI constants
├── entity_keys.go # Entity ID builders and parsers
Expand Down Expand Up @@ -135,7 +135,7 @@ The unified `Repository` interface composes all entity repositories, allowing bo

## Data Model - Optimized Single Table Design

[Check Data Model and Single Table Design Specs ](cmd/app/docs/dynamodb_table_design.md)
[Check Data Model and Single Table Design Specs ](cmd/glad/docs/dynamodb_table_design.md)

## Getting Started

Expand Down Expand Up @@ -277,13 +277,13 @@ Test coverage includes:
### Config (`pkg/config/`)
Centralized configuration loading from environment variables with typed structs and defaults.

### Errors (`cmd/app/internal/errors/` & `pkg/errors/`)
### Errors (`cmd/glad/internal/errors/` & `pkg/errors/`)
- Domain-specific error definitions
- Reusable error utilities
- HTTP status code mapping
- Proper error wrapping with context

### Validation (`cmd/app/internal/validation/`)
### Validation (`cmd/glad/internal/validation/`)
- Username validation (3-50 chars, alphanumeric + underscore)
- Password validation (min 6 chars)
- Name validation (non-empty)
Expand Down
245 changes: 17 additions & 228 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -1,108 +1,23 @@
version: '3'

includes:
glad:
taskfile: ./cmd/glad/Taskfile.yml
dir: .

tasks:
default:
desc: 'List all available tasks'
cmd: task --list-all

# Continue AI tasks
continue:refresh-token:
desc: 'Refresh msg ai api-token'
dir: '{{.ROOT_DIR}}'
cmds:
- scripts/continue-refresh-token.sh

# Build tasks
build:lambda:
desc: 'Build Lambda function for AWS deployment (legacy ZIP method)'
cmds:
- echo 'Building Lambda function...'
- mkdir -p .bin
- env GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -tags lambda -ldflags='-s -w' -o .bin/bootstrap ./cmd/app
- cd .bin && zip lambda-function.zip bootstrap
- echo 'success!'

build:docker:
desc: 'Build Docker image for Lambda deployment'
cmds:
- echo 'Building Docker image for Lambda...'
- docker build -t glad-lambda:latest .
- echo 'Docker image built successfully!'

build:docker:test:
desc: 'Test Docker image locally using Lambda Runtime Interface Emulator'
cmds:
- echo 'Testing Docker image locally...'
- echo 'Starting Lambda container in background on port 9000...'
- docker run -d --name glad-lambda-test --rm -p 9000:8080 --env-file .env glad-lambda:latest
- echo 'Waiting for container to be ready...'
- sleep 3
- echo ''
- echo '🧪 Testing Lambda with GET /protected request...'
- |
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" \
-H "Content-Type: application/json" \
-d '{
"httpMethod": "GET",
"path": "/protected",
"headers": {"Content-Type": "application/json"},
"body": null
}' && echo ""
- echo ''
- echo '📋 Container logs:'
- docker logs glad-lambda-test
- echo ''
- echo '🛑 Stopping container...'
- docker stop glad-lambda-test
- echo '✅ Test complete!'

build:docker:test:interactive:
desc: 'Run Docker Lambda container interactively (stays running, stop with Ctrl+C)'
cmds:
- echo 'Starting Lambda container on port 9000...'
- echo 'Send requests to http://localhost:9000/2015-03-31/functions/function/invocations'
- echo 'Stop with Ctrl+C'
- echo ''
- docker run --rm --name glad-lambda-interactive -p 9000:8080 --env-file .env glad-lambda:latest

debug:lambda:
desc: 'Debug Lambda function deployment issues'
cmds:
- ./debug-lambda.sh

debug:lambda:local:
desc: 'Test Lambda Docker image locally'
cmds:
- ./test-lambda-local.sh

debug:apigateway:
desc: 'Debug API Gateway integration issues'
cmds:
- ./debug-apigateway.sh

debug:force-deploy:
desc: 'Force API Gateway stage redeployment (fixes deployment drift)'
cmds:
- ./force-stage-deploy.sh

debug:logs:
desc: 'Tail Lambda CloudWatch logs in real-time'
cmds:
- |
FUNCTION_NAME=$(aws cloudformation describe-stack-resources --stack-name glad-stack --profile {{.AWS_PROFILE | default "default"}} --query "StackResources[?ResourceType=='AWS::Lambda::Function'].PhysicalResourceId" --output text)
echo "Tailing logs for function: $FUNCTION_NAME"
aws logs tail "/aws/lambda/$FUNCTION_NAME" --follow --profile {{.AWS_PROFILE | default "default"}}

# Development tasks

# Testing tasks
# Global tasks
test:
desc: 'Run all Go tests'
desc: 'Run all tests'
cmds:
- go test ./...

test:verbose:
desc: 'Run all Go tests with verbose output'
desc: 'Run all tests with verbose output'
cmds:
- go test -v ./...

Expand All @@ -113,161 +28,35 @@ tasks:
- go test -coverprofile=coverage.out ./...
- go tool cover -html=coverage.out -o coverage.html
- echo 'Coverage report generated - coverage.html'
- go tool cover -html=coverage.out

test:suite:
desc: 'Run comprehensive test suite with detailed reporting'
cmds:
- go run -tags test test_suite.go

test:api:
desc: 'Run some test flow against the real API. For now, it works only on empty database.'
cmds:
- docker compose -f docker-compose.http-test.yml run --rm http-client

test:models:
desc: 'Run only model tests'
cmds:
- go test -v ./cmd/app/internal/models

test:auth:
desc: 'Run only authentication tests'
cmds:
- go test -v ./pkg/auth
- go test -v ./pkg/middleware

test:database:
desc: 'Run only database tests'
cmds:
- go test -v ./cmd/app/internal/database

test:handlers:
desc: 'Run only API handler tests'
cmds:
- go test -v ./cmd/app/internal/api

test:integration:
desc: 'Run integration tests'
cmds:
- go test -v -tags integration ./cmd/app

test:all:
desc: 'Run all tests including integration tests'
cmds:
- go test -v ./...
- go test -v -tags integration ./cmd/app

# Code quality tasks
fmt:
desc: 'Format Go code'
desc: 'Format all Go code'
cmds:
- go fmt ./...

lint:
desc: 'Run Go linter (go vet)'
desc: 'Run Go linter'
cmds:
- echo 'Running go vet...'
- go vet ./...

# Utility tasks
clean:
desc: 'Clean build artifacts'
cmds:
- rm -rf .bin/
- echo 'Cleaned build artifacts'

# CDK Deployment tasks
cdk:install:
desc: 'Install CDK dependencies'
dir: 'deployments/app'
cmds:
- go mod download
- echo 'CDK dependencies installed'

cdk:synth:
desc: 'Synthesize CDK template (generate CloudFormation) - Docker image built automatically'
dir: 'deployments/app'
cmds:
- cdk synth
- echo 'CDK template synthesized to cdk.out/'

cdk:diff:
desc: 'Show differences between current and deployed stack - Docker image built automatically'
dir: 'deployments/app'
cmds:
- cdk diff

cdk:deploy:
desc: 'Deploy infrastructure to AWS using Docker image'
dir: 'deployments/app'
cmds:
- echo 'Deploying to AWS with profile {{.profile | default "default"}}'
- echo 'CDK will automatically build the Docker image during deployment...'
- cdk deploy --all --require-approval never --profile {{.profile | default "default"}}
- echo 'Deployment completed!'

cdk:deploy:database:
desc: 'Deploy only database stack'
dir: 'deployments/app'
cmds:
- cdk deploy glad-database-stack --require-approval never --profile {{.profile | default "default"}}

cdk:deploy:app:
desc: 'Deploy only application stack'
dir: 'deployments/app'
cmds:
- cdk deploy glad-app-stack --require-approval never --profile {{.profile | default "default"}}

cdk:destroy:
desc: 'Destroy AWS infrastructure (use with caution!)'
dir: 'deployments/app'
cmds:
- echo 'WARNING This will destroy all AWS resources!'
- cdk destroy --all --force

cdk:destroy:app:
desc: 'Destroy only application stack (keeps database)'
dir: 'deployments/app'
cmds:
- cdk destroy glad-app-stack --force

cdk:destroy:database:
desc: 'Destroy database stack (table will be retained)'
dir: 'deployments/app'
cmds:
- echo 'WARNING Database table will be retained but stack will be removed'
- cdk destroy glad-database-stack --force

cdk:bootstrap:
desc: 'Bootstrap CDK in your AWS account (run once)'
dir: 'deployments/app'
cmds:
- cdk bootstrap
- echo 'CDK bootstrapped for your AWS account'

# Full deployment workflow
deploy:
desc: 'Full deployment workflow using Docker (test and deploy)'
cmds:
- echo "running command with args - {{.AWS_PROFILE}}"
- task: test
- task: cdk:deploy
vars:
profile:
sh: echo {{.AWS_PROFILE | default "default"}}
requires:
vars: [AWS_PROFILE]

deploy:diff:
desc: 'Preview deployment changes with Docker'
# Continue AI tasks
continue:refresh-token:
desc: 'Refresh msg ai api-token'
cmds:
- task: cdk:diff
- scripts/continue-refresh-token.sh

# Development workflow shortcuts
dev:full-test:
desc: 'Run full development test cycle (format, lint, test, build)'
deps: [fmt, lint, test, build:lambda]
desc: 'Run full development test cycle'
deps: [fmt, lint, test]

dev:quick-test:
desc: 'Quick development test (format, test only)'
desc: 'Quick development test'
deps: [fmt, test]
Loading
Loading