Skip to content

Update dependency jest to v30 #130

Update dependency jest to v30

Update dependency jest to v30 #130

Workflow file for this run

name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
name: Test & Security
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🟢 Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: 📦 Install dependencies
run: npm ci
- name: 🧪 Run tests with coverage
run: npm run test:coverage
- name: 📊 Upload coverage artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-report-node-${{ matrix.node-version }}
path: coverage/
retention-days: 30
- name: 📊 Generate badges (Node 20.x only)
if: matrix.node-version == '20.x'
run: |
# Create badges directory
mkdir -p badges
# Generate coverage badge
if [ -f "coverage/coverage-summary.json" ]; then
COVERAGE=$(node -e "
const fs = require('fs');
const coverage = JSON.parse(fs.readFileSync('coverage/coverage-summary.json', 'utf8'));
const pct = Math.round(coverage.total.lines.pct);
console.log(pct);
")
else
COVERAGE=0
fi
echo "Coverage: ${COVERAGE}%"
# Determine coverage color
if [ "$COVERAGE" -ge 80 ]; then
COV_COLOR="brightgreen"
elif [ "$COVERAGE" -ge 60 ]; then
COV_COLOR="yellow"
else
COV_COLOR="red"
fi
# Generate test count badge
# Count actual tests from Jest output or fallback to file count
TEST_COUNT=$(npm test 2>&1 | grep -oE '[0-9]+ passed' | grep -oE '[0-9]+' | head -1 || echo "26")
# Security audit badge
set +e
AUDIT_OUTPUT=$(npm audit --audit-level=low --json 2>/dev/null)
AUDIT_EXIT_CODE=$?
set -e
VULNS=$(echo "$AUDIT_OUTPUT" | node -e "
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
try {
const audit = JSON.parse(input);
const vulns = audit.vulnerabilities || {};
console.log(Object.keys(vulns).length);
} catch (e) {
console.log(0);
}
});
" 2>/dev/null || echo "0")
# Determine security color
if [ "$VULNS" -eq 0 ]; then
SEC_COLOR="brightgreen"
SEC_MESSAGE="0%20vulnerabilities"
elif [ "$VULNS" -le 5 ]; then
SEC_COLOR="yellow"
SEC_MESSAGE="${VULNS}%20vulnerabilities"
else
SEC_COLOR="red"
SEC_MESSAGE="${VULNS}%20vulnerabilities"
fi
# Download badges
curl -s "https://img.shields.io/badge/coverage-${COVERAGE}%25-${COV_COLOR}?style=flat-square&logo=jest" > badges/coverage.svg
curl -s "https://img.shields.io/badge/tests-${TEST_COUNT}%20passing-brightgreen?style=flat-square&logo=checkmarx" > badges/tests.svg
curl -s "https://img.shields.io/badge/security-${SEC_MESSAGE}-${SEC_COLOR}?style=flat-square&logo=shield" > badges/security.svg
echo "✅ Generated badges: Coverage: ${COVERAGE}% | Tests: ${TEST_COUNT} | Security: ${VULNS} vulns"
- name: 📊 Upload badge artifacts
if: matrix.node-version == '20.x'
uses: actions/upload-artifact@v4
with:
name: badges
path: badges/
retention-days: 30
- name: 📊 Prepare GitHub Pages content
if: github.ref == 'refs/heads/main' && matrix.node-version == '20.x'
run: |
# Create GitHub Pages directory structure
mkdir -p gh-pages/coverage
mkdir -p gh-pages/badges
# Copy coverage report
if [ -d "coverage/lcov-report" ]; then
cp -r coverage/lcov-report/* gh-pages/coverage/
echo "✅ Copied coverage report"
else
echo "⚠️ No coverage report found"
fi
# Copy badges
if [ -d "badges" ]; then
cp -r badges/* gh-pages/badges/
echo "✅ Copied badges"
else
echo "⚠️ No badges found"
fi
# List what we're deploying
echo "📂 GitHub Pages content:"
find gh-pages -type f | sort
- name: 📊 Deploy to GitHub Pages
if: github.ref == 'refs/heads/main' && matrix.node-version == '20.x'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./gh-pages
- name: 📊 Comment coverage on PR
if: github.event_name == 'pull_request' && matrix.node-version == '20.x'
uses: romeovs/lcov-reporter-action@v0.4.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lcov-file: ./coverage/lcov.info
title: "Coverage Report (Node ${{ matrix.node-version }})"
continue-on-error: true
- name: 🛡️ Security audit
run: npm audit --audit-level moderate
- name: 🔍 Check for vulnerabilities
run: npm audit --audit-level high --production
lint:
name: Code Quality
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🟢 Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: 📦 Install dependencies
run: npm ci
# Future: Add ESLint when we set it up
# - name: 🔍 Run ESLint
# run: npm run lint
- name: 🎯 Check package vulnerabilities
uses: actions/dependency-review-action@v4
if: github.event_name == 'pull_request'
deploy:
name: Deploy to Server
runs-on: ubuntu-latest
needs: [test, lint]
if: github.ref == 'refs/heads/main'
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🚀 Deploy via SSH
uses: appleboy/ssh-action@v1.2.2
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_KEY }}
port: ${{ secrets.DEPLOY_PORT || '22' }}
script: |
echo "🔄 Starting deployment..."
cd ${{ secrets.DEPLOY_PATH || '/opt/videoodyssee-api' }}
# Pull latest code
git fetch origin
git reset --hard origin/main
# Install dependencies
npm ci --only=production
# Restart service
sudo systemctl restart videoodyssee-api
# Verify deployment
sleep 5
curl -f http://localhost:8000/health || exit 1
echo "✅ Deployment successful!"
health-check:
name: Post-Deploy Health Check
runs-on: ubuntu-latest
needs: [deploy]
if: github.ref == 'refs/heads/main'
steps:
- name: 🏥 Remote health check
run: |
echo "🔍 Checking deployed API health..."
HEALTH_URL="http://${{ secrets.DEPLOY_HOST }}:8000/health"
# Wait a bit for deployment to complete
sleep 15
# Try health check with retries
for i in {1..3}; do
echo "Attempt $i/3..."
if curl -f "$HEALTH_URL" --connect-timeout 10 --max-time 30; then
echo "✅ Health check passed!"
exit 0
fi
echo "❌ Health check failed, retrying in 10s..."
sleep 10
done
echo "❌ Health check failed after 3 attempts"
exit 1