From 4d0143be2d3aa0928553f22de32931d5ce46a101 Mon Sep 17 00:00:00 2001 From: Jashwanth Date: Wed, 27 May 2026 12:05:03 +0530 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20GitHub=20Actions=20CI/CD=20pipeline?= =?UTF-8?q?=20=E2=80=94=20Week=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI (all branches + PRs): - backend-test: pytest with real PostgreSQL service container - frontend-lint: ESLint check - docker-build-scan: build both images + Trivy CRITICAL scan week-5 CI/CD phase --- .github/workflows/ci.yml | 130 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..31ed75c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,130 @@ +name: CRMS CI Pipeline + +on: + push: + branches: [ "**" ] + pull_request: + branches: [ develop, main ] + +jobs: + + backend-test: + name: Backend — pytest + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16-alpine + env: + POSTGRES_DB: crms_test + POSTGRES_USER: postgres + POSTGRES_PASSWORD: testpassword + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Cache pip packages + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('backend/requirements.txt') }} + + - name: Install dependencies + run: | + cd backend + pip install -r requirements.txt + pip install pytest pytest-asyncio httpx + + - name: Run pytest + env: + DATABASE_URL: postgresql://postgres:testpassword@localhost:5432/crms_test + SECRET_KEY: test-secret-key + ALGORITHM: HS256 + ACCESS_TOKEN_EXPIRE_MINUTES: 60 + run: | + cd backend + pytest tests/ -v --tb=short + + frontend-lint: + name: Frontend — ESLint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node 20 + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + run: | + cd frontend + npm ci + + - name: Run ESLint + run: | + cd frontend + npm run lint + + docker-build-scan: + name: Docker — build + Trivy scan + runs-on: ubuntu-latest + needs: [ backend-test, frontend-lint ] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build backend image + uses: docker/build-push-action@v5 + with: + context: ./backend + push: false + tags: crms-backend:${{ github.sha }} + load: true + + - name: Build frontend image + uses: docker/build-push-action@v5 + with: + context: ./frontend + push: false + tags: crms-frontend:${{ github.sha }} + load: true + + - name: Trivy scan — backend + uses: aquasecurity/trivy-action@master + with: + image-ref: crms-backend:${{ github.sha }} + format: table + exit-code: 1 + severity: CRITICAL + ignore-unfixed: true + + - name: Trivy scan — frontend + uses: aquasecurity/trivy-action@master + with: + image-ref: crms-frontend:${{ github.sha }} + format: table + exit-code: 1 + severity: CRITICAL + ignore-unfixed: true \ No newline at end of file From 780747aa41800d475870fde2a07b2ed41b49265f Mon Sep 17 00:00:00 2001 From: Jashwanth Date: Wed, 27 May 2026 12:10:15 +0530 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20GitHub=20Actions=20CI/CD=20pipeline?= =?UTF-8?q?=20=E2=80=94=20Week=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI (all branches + PRs): - backend-test: pytest with real PostgreSQL service container - frontend-lint: ESLint check - docker-build-scan: build both images + Trivy CRITICAL scan CD (main branch only): - push-to-registry: builds and pushes to GHCR - tags: latest + git SHA for traceability Security gate: Trivy blocks on CRITICAL CVEs Tests: health check, missing fields 422, invalid login 401 Week 5 - CI/CD phase --- .github/workflows/cd.yml | 50 ++++++++++++++++++++++++++++++++++++ backend/tests/conftest.py | 7 +++++ backend/tests/test_health.py | 15 +++++++++++ 3 files changed, 72 insertions(+) create mode 100644 .github/workflows/cd.yml create mode 100644 backend/tests/conftest.py create mode 100644 backend/tests/test_health.py diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..3fad7e0 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,50 @@ +name: CRMS CD Pipeline + +on: + push: + branches: [ main ] + +jobs: + + push-to-registry: + name: Push images to GHCR + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push backend + uses: docker/build-push-action@v5 + with: + context: ./backend + push: true + tags: | + ghcr.io/crms-devops/crms-backend:latest + ghcr.io/crms-devops/crms-backend:${{ github.sha }} + + - name: Build and push frontend + uses: docker/build-push-action@v5 + with: + context: ./frontend + push: true + tags: | + ghcr.io/crms-devops/crms-frontend:latest + ghcr.io/crms-devops/crms-frontend:${{ github.sha }} + + - name: Summary + run: | + echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY + echo "Backend: ghcr.io/crms-devops/crms-backend:${{ github.sha }}" >> $GITHUB_STEP_SUMMARY + echo "Frontend: ghcr.io/crms-devops/crms-frontend:${{ github.sha }}" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py new file mode 100644 index 0000000..bfab6ab --- /dev/null +++ b/backend/tests/conftest.py @@ -0,0 +1,7 @@ +import pytest +from fastapi.testclient import TestClient +from app.main import app + +@pytest.fixture +def client(): + return TestClient(app) \ No newline at end of file diff --git a/backend/tests/test_health.py b/backend/tests/test_health.py new file mode 100644 index 0000000..4578ccd --- /dev/null +++ b/backend/tests/test_health.py @@ -0,0 +1,15 @@ +def test_health(client): + response = client.get("/health") + assert response.status_code == 200 + assert response.json()["status"] == "ok" + +def test_login_missing_fields(client): + response = client.post("/auth/student/login", json={}) + assert response.status_code == 422 + +def test_login_invalid_credentials(client): + response = client.post("/auth/student/login", json={ + "register_number": "000000000000", + "date_of_birth": "2000-01-01" + }) + assert response.status_code == 401 \ No newline at end of file