Skip to content

Feat/docker and cicd #1

Feat/docker and cicd

Feat/docker and cicd #1

Workflow file for this run

name: CI / CD — ChatConnect
on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# ─── Jobs ─────────────────────────────────────────────────────────────────────
jobs:
# ────────────────────────────────────────────────────────────────────────────
# 1. Lint + Test — Frontend (React/Vite)
# ────────────────────────────────────────────────────────────────────────────
frontend-lint-build:
name: Frontend — Lint & Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: client/package-lock.json
- name: Install dependencies
working-directory: client
run: npm ci
- name: Run ESLint
working-directory: client
run: npm run lint
- name: Build
working-directory: client
run: npm run build
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: client/dist
retention-days: 7
# ────────────────────────────────────────────────────────────────────────────
# 2. Test — Backend (Node.js / Vitest)
# ────────────────────────────────────────────────────────────────────────────
backend-test:
name: Backend — Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: backend/package-lock.json
- name: Install dependencies
working-directory: backend
run: npm ci
- name: Run Vitest
working-directory: backend
run: npm test
env:
NODE_ENV: test
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-refresh-secret
MONGO_URI: ${{ secrets.MONGO_URI_TEST || 'mongodb://localhost:27017/test' }}
# ────────────────────────────────────────────────────────────────────────────
# 3. Security — npm audit + pip-audit
# ────────────────────────────────────────────────────────────────────────────
security-audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: backend/package-lock.json
- name: npm audit (backend)
working-directory: backend
run: npm audit --audit-level=high
continue-on-error: true # report but don't block
- name: npm audit (frontend)
working-directory: client
run: npm audit --audit-level=high
continue-on-error: true
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: pip-audit (AI service)
working-directory: server
run: |
pip install pip-audit --quiet
pip-audit -r requirements.txt --skip-editable
continue-on-error: true
# ────────────────────────────────────────────────────────────────────────────
# 4. Docker build validation — backend image
# ────────────────────────────────────────────────────────────────────────────
docker-backend:
name: Docker — Build Backend Image
runs-on: ubuntu-latest
needs: [backend-test]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build backend image (no push)
uses: docker/build-push-action@v6
with:
context: ./backend
file: ./backend/Dockerfile
push: false
tags: chatconnect-backend:ci
cache-from: type=gha
cache-to: type=gha,mode=max
# ────────────────────────────────────────────────────────────────────────────
# 5. Docker build validation — AI service image
# ────────────────────────────────────────────────────────────────────────────
docker-ai-service:
name: Docker — Build AI Service Image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build AI service image (no push)
uses: docker/build-push-action@v6
with:
context: ./server
file: ./server/Dockerfile
push: false
tags: chatconnect-ai:ci
cache-from: type=gha
cache-to: type=gha,mode=max
# ────────────────────────────────────────────────────────────────────────────
# 6. Push to Docker Hub — only on master push, after all checks pass
# ────────────────────────────────────────────────────────────────────────────
docker-publish:
name: Docker — Publish to Docker Hub
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
needs: [frontend-lint-build, backend-test, docker-backend, docker-ai-service]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags/labels)
id: meta-backend
uses: docker/metadata-action@v5
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/chatconnect-backend
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
- name: Push backend image
uses: docker/build-push-action@v6
with:
context: ./backend
file: ./backend/Dockerfile
push: true
tags: ${{ steps.meta-backend.outputs.tags }}
labels: ${{ steps.meta-backend.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Extract metadata — AI service
id: meta-ai
uses: docker/metadata-action@v5
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/chatconnect-ai
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
- name: Push AI service image
uses: docker/build-push-action@v6
with:
context: ./server
file: ./server/Dockerfile
push: true
tags: ${{ steps.meta-ai.outputs.tags }}
labels: ${{ steps.meta-ai.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max