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
23 changes: 11 additions & 12 deletions .github/workflows/backend-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,16 @@ jobs:
fi
}

echo "📤 Syncing secrets to SSM..."
echo "📤 Syncing GitHub secrets to SSM Parameter Store..."
write_secret "mongodbUri" "${{ secrets.MONGO_URI }}"
write_secret "jwtSecret" "${{ secrets.JWT_SECRET }}"
write_secret "smtpHost" "${{ secrets.SMTP_HOST }}"
write_secret "smtpPort" "${{ secrets.SMTP_PORT }}"
write_secret "smtpUser" "${{ secrets.SMTP_USER }}"
write_secret "smtpPassword" "${{ secrets.SMTP_PASSWORD }}"
write_secret "smtpFrom" "${{ secrets.SMTP_FROM }}"
# Add any new secret here - just add to GitHub Secrets UI
echo "✅ Done"
# To add new secrets: add to GitHub repo secrets, then reference here
echo "✅ Sync complete"

- name: Deploy on EC2 via SSM RunCommand (pull + restart container)
shell: bash
Expand All @@ -136,7 +136,7 @@ jobs:
IMAGE_URI="__IMAGE_URI__"
PARAM_PREFIX="/comptaleyes/dev"

echo "[1/7] Fetch ALL parameters from SSM"
echo "[1/7] Fetching SSM parameters"
PARAMS_JSON=$(aws ssm get-parameters-by-path --path "$PARAM_PREFIX" --with-decryption --region "$REGION" --query 'Parameters[*].[Name,Value]' --output json)

if [ "$(echo "$PARAMS_JSON" | jq 'length')" -eq 0 ]; then
Expand All @@ -146,23 +146,22 @@ jobs:

echo "✅ Found $(echo "$PARAMS_JSON" | jq 'length') parameters"

echo "[2/7] Ensure docker is running"
echo "[2/7] Starting Docker service"
sudo systemctl start docker || true

echo "[3/7] Login to ECR"
echo "[3/7] Login to ECR"
echo "[3/7] Authenticating with ECR"
aws ecr get-login-password --region "$REGION" | sudo docker login --username AWS --password-stdin "$(echo "$IMAGE_URI" | cut -d/ -f1)"

echo "[4/7] Pull image"
echo "[4/7] Pull image"
echo "[4/7] Pulling Docker image"
sudo docker pull "$IMAGE_URI"

echo "[5/7] Stop/remove old container"
echo "[5/7] Removing old container"
sudo docker rm -f "$APP_NAME" || true

echo "[6/7] Run container with ALL SSM env vars"
echo "[6/7] Starting new container with environment variables"
ENV_FLAGS="-e PORT=$CONTAINER_PORT -e SERVICE_NAME=comptaleyes-backend"

# Convert SSM parameters to environment variables
while IFS= read -r line; do
PARAM_NAME=$(echo "$line" | jq -r '.[0]' | sed 's|.*/||')
PARAM_VALUE=$(echo "$line" | jq -r '.[1]')
Expand All @@ -172,7 +171,7 @@ jobs:

eval sudo docker run -d --name "$APP_NAME" --restart unless-stopped -p "${HOST_PORT}:${CONTAINER_PORT}" $ENV_FLAGS "$IMAGE_URI"

echo "[7/7] Container status"
echo "[7/7] Verifying container status"
sudo docker ps --filter "name=$APP_NAME" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
EOF
)
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/cdk-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30

# 1) no forks
# 2) explicitly enforce PR base branch = master
# Only run for PRs from same repo targeting master branch
# Prevents: forks from deploying, accidental deploys from feature branches
if: |
github.event.pull_request.head.repo.full_name == github.repository &&
github.event.pull_request.base.ref == 'master'
Expand All @@ -51,9 +51,8 @@ jobs:
- name: Verify AWS identity
run: aws sts get-caller-identity

- name: Build Infra
- name: Build infrastructure TypeScript
run: npm -w infra run build

# CDK deploy with real creds (localSynth MUST be false)
- name: CDK deploy (real)
- name: Deploy infrastructure to AWS
run: npm -w infra run cdk -- deploy --all --require-approval never -c localSynth=false -c env=dev
26 changes: 12 additions & 14 deletions .github/workflows/frontend-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ jobs:
echo "bucket_name=$BUCKET_NAME" >> "$GITHUB_OUTPUT"
echo "distribution_id=$DIST_ID" >> "$GITHUB_OUTPUT"

# This will only run once frontend/package.json exists.
- name: Setup Node
if: steps.fe.outputs.exists == 'true'
uses: actions/setup-node@v4
Expand All @@ -86,24 +85,23 @@ jobs:
if: steps.fe.outputs.exists == 'true'
run: npm ci

- name: Build frontend (placeholder)
if: steps.fe.outputs.exists == 'true'
run: npm -w frontend run build

- name: Write frontend env (Vite)
- name: Configure environment variables for build
if: steps.fe.outputs.exists == 'true'
run: |
set -euo pipefail
: "${API_BASE_URL:?Set FRONTEND_API_BASE_URL secret to your backend URL}"
echo "VITE_BACKEND_URL=${API_BASE_URL}" >> frontend/.env.production
echo "VITE_BACKEND_URL=${API_BASE_URL}" > frontend/.env.production

- name: Build frontend application
if: steps.fe.outputs.exists == 'true'
run: npm -w frontend run build

- name: Verify build output exists (placeholder expects frontend/dist)
- name: Verify build output directory
if: steps.fe.outputs.exists == 'true'
run: |
set -euo pipefail
if [ ! -d "frontend/dist" ]; then
echo "Expected build output folder frontend/dist not found."
echo "When you create the frontend, ensure the build outputs to frontend/dist, or update this workflow."
echo "Build output folder frontend/dist not found"
exit 1
fi

Expand All @@ -121,9 +119,9 @@ jobs:
--distribution-id "${{ steps.cf.outputs.distribution_id }}" \
--paths "/*"

- name: Skip (frontend not initialized yet)
- name: Skip deployment (frontend not found)
if: steps.fe.outputs.exists != 'true'
run: |
echo "frontend/package.json not found; frontend CD is intentionally a placeholder."
echo "CloudFormation lookup succeeded (infra is ready)."
echo "Once frontend exists, re-run this workflow."
echo "frontend/package.json not found"
echo "Infrastructure is ready - create frontend to enable deployment"
echo "Once frontend exists, re-run this workflow"
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MIT License

Copyright (c) 2026 CisCode

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
185 changes: 180 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,183 @@
# Comptaleyes Platform

## Structure
**Modern accounting and finance management platform built with scalable microservices architecture.**

- Backend: API Folder
- Frontend: UI folder
- Infra: IaC Factory for both stacks
- .github: Shared workflows running on paths conditions!
## 📋 Project Overview

Comptaleyes is a full-stack web application designed for accounting and financial management. The platform features a NestJS backend API, React frontend, and automated AWS infrastructure deployment using CDK.

## 🏗️ Architecture

This monorepo contains three main components:

```
comptaleyes/
├── backend/ # NestJS API with authentication & business logic
├── frontend/ # React SPA with modern UI components
├── infra/ # AWS CDK infrastructure as code
└── .github/ # CI/CD workflows (GitHub Actions)
```

### Backend

- **Framework**: NestJS (Node.js 22)
- **Database**: MongoDB Atlas
- **Authentication**: JWT + OAuth2 (Microsoft, Google, Facebook)
- **Email**: SMTP-based verification & password reset
- **Deployment**: Docker → AWS ECR → EC2

### Frontend

- **Framework**: React 19 with TypeScript
- **Build Tool**: Vite
- **UI Library**: @ciscode/ui-authentication-kit
- **Deployment**: S3 + CloudFront CDN

### Infrastructure

- **IaC**: AWS CDK (TypeScript)
- **Compute**: EC2 for backend containers
- **Storage**: S3 for frontend static assets
- **CDN**: CloudFront for global distribution
- **Secrets**: SSM Parameter Store

## 🚀 Quick Start

### Prerequisites

- Node.js 22+ and npm
- Docker Desktop
- AWS CLI configured (for deployment)
- MongoDB Atlas account

### Backend Setup

```bash
cd backend
cp .env.example .env
# Edit .env with your credentials
npm install
npm run dev
```

Backend will be available at `http://localhost:3000`

**Health Check**: `curl http://localhost:3000/health`

### Frontend Setup

```bash
cd frontend
cp .env.example .env
# Edit .env with backend URL
npm install
npm run dev
```

Frontend will be available at `http://localhost:5173`

### Full Stack with Docker

```bash
cd backend
docker compose -f compose/docker-compose.dev.yml up --build
```

## 📚 Documentation

- [Backend README](backend/README.md) - API architecture, domain logic, deployment
- [Frontend README](frontend/README.md) - UI components, routing, authentication
- [Infrastructure README](infra/README.md) - CDK stacks, AWS resources

## 🔐 Environment Configuration

All sensitive credentials are stored in `.env` files (local) or AWS SSM Parameter Store (production).

**Required Environment Variables**: See `.env.example` files in each directory:

- [backend/.env.example](backend/.env.example)
- [frontend/.env.example](frontend/.env.example)

## 🧪 Testing

```bash
# Backend tests
cd backend
npm test # All tests
npm run test:watch # Watch mode
npm run test:cov # Coverage report

# Frontend tests
cd frontend
npm test
```

## 🚢 Deployment

### CI/CD Pipelines

GitHub Actions workflows handle automated deployments:

- **Backend CI**: PR validation (lint, test, typecheck)
- **Backend CD**: Build Docker → ECR → EC2 deployment
- **Frontend CI**: PR validation (lint, test, typecheck)
- **Frontend CD**: Build Vite → S3 → CloudFront invalidation
- **CDK Deploy**: Infrastructure updates via CDK

### Manual Deployment

```bash
# Deploy infrastructure
cd infra
npm run build
npx cdk deploy --all

# Deploy backend (via GitHub Actions)
git push origin master # Triggers backend-cd.yml

# Deploy frontend (via GitHub Actions)
git push origin master # Triggers frontend-cd.yml
```

## 🏃 Production Environments

- **Frontend**: Deployed via CloudFront CDN for global distribution
- **Backend API**: Deployed on AWS EC2 with Docker
- **Database**: MongoDB Atlas
- **Infrastructure**: AWS (us-east-1 region)

## 🛠️ Development Workflow

1. Create feature branch from `develop`
2. Make changes and commit
3. Push and create PR → `develop`
4. CI pipeline validates (lint, test, typecheck)
5. After review, merge to `develop`
6. When ready for release, PR → `master` triggers deployment

## 📦 Tech Stack Summary

| Component | Technologies |
| -------------- | ---------------------------------------- |
| Backend | NestJS, TypeScript, MongoDB, Docker |
| Frontend | React, Vite, TailwindCSS, React Router |
| Authentication | JWT, OAuth2, @ciscode/authentication-kit |
| Infrastructure | AWS CDK, EC2, S3, CloudFront, ECR |
| CI/CD | GitHub Actions with OIDC |
| Monitoring | CloudWatch Logs, Health endpoints |

## 🤝 Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.

## 🔒 Security

To report security vulnerabilities: **info@ciscod.com**

See [SECURITY](SECURITY) for our security policy.

## 📝 License

MIT License - See [LICENSE](LICENSE) file for details.

Copyright (c) 2026 CisCode
Loading