Skip to content

Merge pull request #170 from Ardecrownn/feature/observability-enhance… #228

Merge pull request #170 from Ardecrownn/feature/observability-enhance…

Merge pull request #170 from Ardecrownn/feature/observability-enhance… #228

Workflow file for this run

name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
setup:
name: Setup & Cache
runs-on: ubuntu-latest
outputs:
node-version: ${{ steps.setup-node.outputs.node-version }}
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
id: setup-node
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Generate Prisma Client
run: npx prisma generate
- name: Cache Prisma Client
uses: actions/cache@v4
id: cache-prisma
with:
path: node_modules/.prisma
key: ${{ runner.os }}-prisma-${{ hashFiles('prisma/schema.prisma') }}
lint:
name: Linting
needs: setup
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
test-unit:
name: Unit Tests
needs: setup
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Unit Tests
run: npm run test:unit
env:
NODE_ENV: test
test-integration:
name: Integration Tests
needs: setup
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: propchain_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Wait for services
run: |
timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done'
timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done'
- name: Run Integration Tests
run: npm run test:integration
env:
NODE_ENV: test
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test
REDIS_URL: redis://localhost:6379
test-e2e:
name: E2E Tests
needs: setup
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: propchain_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Wait for services
run: |
timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done'
timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done'
- name: Run E2E Tests
run: npm run test:e2e
env:
NODE_ENV: test
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test
REDIS_URL: redis://localhost:6379
test-security:
name: Security Tests
needs: setup
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Security Tests
run: npm run test:security
env:
NODE_ENV: test
build:
name: Build (Production Target)
needs: [lint, test-unit]
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Generate Prisma Client
run: npx prisma generate
- name: Build Application
run: npm run build
- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: build-artifact
path: dist/
retention-days: 1
observability-test:
name: Observability Tests
needs: build
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: propchain_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
jaeger:
image: jaegertracing/all-in-one:latest
options: >-
--health-cmd "wget --no-verbose --tries=1 --spider http://localhost:16686"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 16686:16686
- 4317:4317
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Download Build Artifact
uses: actions/download-artifact@v4
with:
name: build-artifact
path: dist
- name: Wait for services
run: |
timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done'
timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done'
timeout 60 bash -c 'until nc -z localhost 16686; do sleep 1; done'
- name: Start Application
run: |
npm run start &
sleep 30
- name: Test Observability Endpoints
run: |
curl -f http://localhost:3000/observability/health || exit 1
curl -f http://localhost:3000/observability/metrics/current || exit 1
curl -f http://localhost:3000/metrics || exit 1
curl -f http://localhost:3000/observability/tracing/status || exit 1
- name: Test Metrics Collection
run: |
# Test that metrics are being collected
response=$(curl -s http://localhost:3000/metrics)
if [[ $response == *"http_request_duration_seconds"* ]]; then
echo "✅ HTTP metrics found"
else
echo "❌ HTTP metrics not found"
exit 1
fi
if [[ $response == *"system_cpu_usage_percent"* ]]; then
echo "✅ System metrics found"
else
echo "❌ System metrics not found"
exit 1
fi
env:
NODE_ENV: test
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test
REDIS_URL: redis://localhost:6379
OTEL_SERVICE_NAME: propchain-backend-test
OTEL_EXPORTER_OTLP_ENDPOINT: http://localhost:4317
METRICS_ENABLED: true
PERFORMANCE_MONITORING_ENABLED: true
load-test:
name: Load Testing
needs: build
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: propchain_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install k6
run: |
sudo apt-get update
sudo apt-get install -y gnupg2 software-properties-common
sudo wget -q -O - https://dl.k6.io/key.gpg | sudo apt-key add -
echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install -y k6
- name: Wait for services
run: |
timeout 60 bash -c 'until nc -z localhost 5432; do sleep 1; done'
timeout 60 bash -c 'until nc -z localhost 6379; do sleep 1; done'
- name: Start API in background
run: |
npm run start &
sleep 30
- name: Run load tests
run: npm run loadtest:ci
env:
API_URL: http://localhost:3000
NODE_ENV: test
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/propchain_test
REDIS_URL: redis://localhost:6379
- name: Upload k6 results
uses: actions/upload-artifact@v4
with:
name: k6-results
path: artifacts/k6-results.json
deploy-staging:
name: Deploy to Staging
needs: [build, test-integration, test-e2e, test-security, observability-test]
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
runs-on: ubuntu-latest
environment: staging
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Download Build Artifact
uses: actions/download-artifact@v4
with:
name: build-artifact
path: dist
- name: Deploy to Staging Server
run: echo "🚀 Deploying to staging environment... (Placeholder)"
# Actual deployment logic would go here:
# - npm run deploy:staging
# - scp -r dist/* user@staging-host:/var/www/propchain
# - heroku/deploy-action@v5
# - aws ecs update-service...
deploy-production:
name: Deploy to Production
needs: [deploy-staging]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: production
url: https://api.propchain.com
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Download Build Artifact
uses: actions/download-artifact@v4
with:
name: build-artifact
path: dist
- name: Run Production Migrations
run: echo "🛠 Running production database migrations... (Placeholder)"
# run: npx prisma migrate deploy
- name: Deploy to Production Cluster
run: echo "🚀 Deploying to production environment... (Blue/Green Strategy Placeholder)"
# Actual deployment strategy logic (Blue/Green or Canary):
# - Implement traffic routing switch
# - Health checks check