Skip to content
Open
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
376 changes: 376 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,376 @@
name: CI/CD Pipeline

on:
push:
branches: [main, develop]
pull_request:
branches: [main]

env:
NODE_VERSION: '20'
PNPM_VERSION: '9'

jobs:
# ============================================
# 1. Lint & Type Check
# ============================================
lint-and-typecheck:
name: 🔍 Lint & Type Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: ${{ env.PNPM_VERSION }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run ESLint
run: pnpm lint

- name: Run TypeScript Check
run: pnpm typecheck

# ============================================
# 2. Unit Tests
# ============================================
unit-tests:
name: 🧪 Unit Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: teleton_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: ${{ env.PNPM_VERSION }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run Unit Tests with Coverage
run: pnpm test:unit --coverage
env:
DATABASE_URL: postgresql://test:test@localhost:5432/teleton_test
REDIS_URL: redis://localhost:6379

- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

# ============================================
# 3. Integration Tests
# ============================================
integration-tests:
name: 🔗 Integration Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: teleton_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: ${{ env.PNPM_VERSION }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build project
run: pnpm build

- name: Wait for PostgreSQL to be ready
run: |
echo "Waiting for PostgreSQL..."
for i in {1..30}; do
if pg_isready -h localhost -p 5432 -U test > /dev/null 2>&1; then
echo "PostgreSQL is ready!"
exit 0
fi
sleep 2
done
echo "PostgreSQL failed to start"
exit 1

- name: Wait for Redis to be ready
run: |
echo "Waiting for Redis..."
for i in {1..30}; do
if redis-cli -h localhost -p 6379 ping > /dev/null 2>&1; then
echo "Redis is ready!"
exit 0
fi
sleep 2
done
echo "Redis failed to start"
exit 1

- name: Run Integration Tests
run: pnpm test:integration
env:
DATABASE_URL: postgresql://test:test@localhost:5432/teleton_test
REDIS_URL: redis://localhost:6379
TELEGRAM_API_ID: ${{ secrets.TELEGRAM_API_ID }}
TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }}
TON_RPC_URL: ${{ secrets.TON_RPC_URL }}

# ============================================
# 4. E2E Tests (Playwright)
# ============================================
e2e-tests:
name: 🌐 E2E Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: teleton_test
ports:
- 5432:5432
redis:
image: redis:7
ports:
- 6379:6379

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: ${{ env.PNPM_VERSION }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps

- name: Build project
run: pnpm build

- name: Start server in background
run: pnpm start &
env:
DATABASE_URL: postgresql://test:test@localhost:5432/teleton_test
REDIS_URL: redis://localhost:6379
PORT: 3000

- name: Wait for server to be ready
run: |
echo "Waiting for server to start..."
for i in {1..30}; do
if curl -s http://localhost:3000/api/health > /dev/null; then
echo "Server is ready!"
exit 0
fi
sleep 2
done
echo "Server failed to start"
exit 1

- name: Run E2E Tests
run: pnpm test:e2e
env:
BASE_URL: http://localhost:3000

- name: Upload Playwright Report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30

# ============================================
# 5. Security Audit
# ============================================
security-audit:
name: 🔒 Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: ${{ env.PNPM_VERSION }}

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run npm audit
run: pnpm audit --audit-level=high

- name: Run Snyk Security Scan
uses: snyk/actions/node@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

# ============================================
# 6. Build & Docker Image
# ============================================
build-and-push:
name: 🐳 Build & Push Docker
runs-on: ubuntu-latest
needs: [lint-and-typecheck, unit-tests, integration-tests, e2e-tests, security-audit]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write

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

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

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

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha,prefix=sha-

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

# ============================================
# 7. Deploy to Staging (if tests pass)
# ============================================
deploy-staging:
name: 🚀 Deploy to Staging
runs-on: ubuntu-latest
needs: [build-and-push]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
environment: staging

steps:
- name: Deploy to Staging
run: |
echo "Deploying to staging environment..."
# Add your deployment script here
# Example: kubectl apply -f k8s/staging/
# Example: docker-compose -f docker-compose.staging.yml up -d

# ============================================
# 8. Release (on tag)
# ============================================
release:
name: 🎉 Create Release
runs-on: ubuntu-latest
needs: [build-and-push]
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write

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

- name: Create Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Loading
Loading