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
17 changes: 17 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"root": true,
"env": {
"node": true,
"es2021": true
},
"extends": ["eslint:recommended"],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"rules": {
"no-console": "off",
"no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"prefer-const": "warn"
}
}
253 changes: 112 additions & 141 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,205 +1,176 @@
name: CI/CD Pipeline for Moodify App
name: CI/CD Pipeline for Job Application Portal

on:
push:
branches:
- main
- master
- develop
pull_request:
branches:
- main
- master
- develop

jobs:
formatting:
name: 🔧 Install, Lint & Format
lint-and-format:
name: 🔧 Lint & Format Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Use Node.js 18
uses: actions/setup-node@v3
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: 'npm'

- name: Install root dependencies
run: npm ci

- name: Run Prettier
run: npm run format
- name: Run ESLint
run: npm run lint --if-present

- name: Run Prettier check
run: npm run format:check --if-present

backend-tests:
name: 🐍 Backend Build & Test
name: 🚀 Backend Build & Test
runs-on: ubuntu-latest
needs: formatting
env:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
MONGO_DB_URI: ${{ secrets.MONGO_DB_URI }}
MONGO_DB_USERNAME: ${{ secrets.MONGO_DB_USERNAME }}
MONGO_DB_PASSWORD: ${{ secrets.MONGO_DB_PASSWORD }}
SPOTIFY_CLIENT_ID: ${{ secrets.SPOTIFY_CLIENT_ID }}
SPOTIFY_CLIENT_SECRET: ${{ secrets.SPOTIFY_CLIENT_SECRET }}
outputs:
coverage_exists: ${{ steps.check-backend-coverage.outputs.coverage_exists }}
needs: lint-and-format
strategy:
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup Python 3.10
uses: actions/setup-python@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
python-version: "3.10"
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: backend/package-lock.json

- name: Install Python dependencies
run: |
pip install -r requirements.txt
pip install pytest pytest-django pytest-cov
- name: Install backend dependencies
working-directory: ./backend
run: npm ci

- name: Run backend tests
run: |
pytest backend -q --maxfail=1 --disable-warnings
pytest backend --cov=backend --cov-report=xml
working-directory: ./backend
run: npm test --if-present

- name: Check backend coverage file exists
id: check-backend-coverage
run: |
if [ -f backend/coverage.xml ]; then
echo "coverage_exists=true" >> $GITHUB_OUTPUT
else
echo "coverage_exists=false" >> $GITHUB_OUTPUT
fi

- name: Upload backend coverage
if: steps.check-backend-coverage.outputs.coverage_exists == 'true'
uses: actions/upload-artifact@v4
with:
name: backend-coverage-report
path: backend/coverage.xml
- name: Run backend build check
working-directory: ./backend
run: npm run build --if-present

frontend-tests:
name: 🌐 Frontend Build & Test
runs-on: ubuntu-latest
needs: formatting
outputs:
coverage_exists: ${{ steps.check-frontend-coverage.outputs.coverage_exists }}
needs: lint-and-format
strategy:
matrix:
node-version: [18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Use Node.js 18
uses: actions/setup-node@v3
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: 18
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install frontend dependencies
run: npm --prefix frontend ci

- name: Run Jest tests
run: npm --prefix frontend test
working-directory: ./frontend
run: npm ci

- name: Generate frontend coverage
run: npm --prefix frontend run test:coverage -- --coverageReporters=lcov
- name: Run frontend tests
working-directory: ./frontend
run: npm test -- --coverage --watchAll=false

- name: Check frontend coverage directory exists
id: check-frontend-coverage
run: |
if [ -d frontend/coverage/lcov-report ] && [ "$(ls -A frontend/coverage/lcov-report)" ]; then
echo "coverage_exists=true" >> $GITHUB_OUTPUT
else
echo "coverage_exists=false" >> $GITHUB_OUTPUT
fi
- name: Build frontend
working-directory: ./frontend
run: npm run build

- name: Upload frontend coverage
if: steps.check-frontend-coverage.outputs.coverage_exists == 'true'
- name: Upload build artifacts
if: matrix.node-version == 20
uses: actions/upload-artifact@v4
with:
name: frontend-coverage-report
path: frontend/coverage/lcov-report
name: frontend-build
path: frontend/build
retention-days: 7

coverage:
name: 📊 Combined Coverage Reports
docker-build:
name: 🐳 Docker Build Test
runs-on: ubuntu-latest
needs:
- backend-tests
- frontend-tests
needs: [backend-tests, frontend-tests]
if: github.event_name == 'push'
steps:
- name: Download backend coverage
if: needs.backend-tests.outputs.coverage_exists == 'true'
uses: actions/download-artifact@v4
with:
name: backend-coverage-report
path: ./reports/backend
- name: Checkout code
uses: actions/checkout@v4

- name: Download frontend coverage
if: needs.frontend-tests.outputs.coverage_exists == 'true'
uses: actions/download-artifact@v4
with:
name: frontend-coverage-report
path: ./reports/frontend
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Archive combined coverage
uses: actions/upload-artifact@v4
- name: Build backend Docker image
uses: docker/build-push-action@v5
with:
name: combined-coverage
path: ./reports
context: ./backend
file: ./backend/Dockerfile
push: false
tags: job-application-backend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Show coverage report links
run: |
echo "✅ Coverage artifacts uploaded:"
echo "- Backend report: ${{ github.server_url }}/${{ github.repository }}/suites/${{ github.run_id }}/artifacts/combined-coverage/reports/backend"
echo "- Frontend report: ${{ github.server_url }}/${{ github.repository }}/suites/${{ github.run_id }}/artifacts/combined-coverage/reports/frontend"
- name: Build frontend Docker image
uses: docker/build-push-action@v5
with:
context: ./frontend
file: ./frontend/Dockerfile
push: false
tags: job-application-frontend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

docker:
name: 🐳 Build & Push Docker Images
security-scan:
name: 🔒 Security Scan
runs-on: ubuntu-latest
needs: coverage
permissions:
contents: read
packages: write
needs: lint-and-format
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Log in to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
uses: actions/checkout@v4

- name: Build & push backend image
uses: docker/build-push-action@v3
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
context: .
file: ./backend/Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/moodify-backend:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/moodify-backend:latest
node-version: 20

- name: Build & push frontend image
uses: docker/build-push-action@v3
with:
context: .
file: ./frontend/Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/moodify-frontend:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/moodify-frontend:latest
- name: Run npm audit (backend)
working-directory: ./backend
run: npm audit --audit-level=moderate
continue-on-error: true

deploy:
name: 🚀 Deploy
runs-on: ubuntu-latest
needs: docker
steps:
- name: Deploy backend to Render
run: echo "✅ Backend deployed to Render"
- name: Deploy frontend to Vercel
run: echo "✅ Frontend deployed to Vercel"
- name: Run npm audit (frontend)
working-directory: ./frontend
run: npm audit --audit-level=moderate
continue-on-error: true

complete:
name: 🎉 All Done
name: All Checks Passed
runs-on: ubuntu-latest
needs: deploy
needs: [backend-tests, frontend-tests, docker-build, security-scan]
if: always()
steps:
- name: Final status
run: echo "🎉 CI/CD pipeline finished successfully."
- name: Check all job statuses
run: |
if [ "${{ needs.backend-tests.result }}" != "success" ] || \
[ "${{ needs.frontend-tests.result }}" != "success" ] || \
[ "${{ needs.docker-build.result }}" != "success" ] && [ "${{ needs.docker-build.result }}" != "skipped" ]; then
echo "❌ Some checks failed"
exit 1
else
echo "✅ All checks passed successfully!"
fi
Loading
Loading