From ffee06bff0e05165cc6f8999d6ae6aa47005fd39 Mon Sep 17 00:00:00 2001 From: Jashwanth Date: Wed, 27 May 2026 12:16:17 +0530 Subject: [PATCH 1/3] fix: set PYTHONPATH for pytest in GitHub Actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ModuleNotFoundError: No module named 'app' — fixed by setting PYTHONPATH to backend directory so pytest can resolve app imports --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31ed75c..89273d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,9 +54,10 @@ jobs: SECRET_KEY: test-secret-key ALGORITHM: HS256 ACCESS_TOKEN_EXPIRE_MINUTES: 60 + PYTHONPATH: /home/runner/work/crms/crms/backend run: | cd backend - pytest tests/ -v --tb=short + python -m pytest tests/ -v --tb=short frontend-lint: name: Frontend — ESLint From 88356c3af3311e99e613197ec366542b3d5938c9 Mon Sep 17 00:00:00 2001 From: Jashwanth Date: Wed, 27 May 2026 12:20:50 +0530 Subject: [PATCH 2/3] fix: create DB tables in pytest fixture + fix Pydantic/SQLAlchemy deprecations - conftest.py: Base.metadata.create_all() before tests, drop_all() after - schemas/auth.py: ConfigDict replaces class-based Config (Pydantic v2) - schemas/result.py: ConfigDict replaces class-based Config (Pydantic v2) - database.py: declarative_base() from sqlalchemy.orm (SQLAlchemy 2.0) All 3 tests should now pass with 0 warnings --- backend/app/core/database.py | 8 +++++--- backend/app/schemas/auth.py | 7 +++---- backend/app/schemas/result.py | 13 +++++++------ backend/tests/conftest.py | 13 +++++++++++++ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/backend/app/core/database.py b/backend/app/core/database.py index bae245e..8a7c8ba 100644 --- a/backend/app/core/database.py +++ b/backend/app/core/database.py @@ -1,12 +1,14 @@ from sqlalchemy import create_engine -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import sessionmaker, declarative_base import os from dotenv import load_dotenv load_dotenv() -DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://postgres:password@localhost:5432/crms_dev") +DATABASE_URL = os.getenv( + "DATABASE_URL", + "postgresql://postgres:password@localhost:5432/crms_dev" +) engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) diff --git a/backend/app/schemas/auth.py b/backend/app/schemas/auth.py index c4ac989..4c12c99 100644 --- a/backend/app/schemas/auth.py +++ b/backend/app/schemas/auth.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from datetime import date class StudentLoginRequest(BaseModel): @@ -6,6 +6,8 @@ class StudentLoginRequest(BaseModel): date_of_birth: date class StudentInfo(BaseModel): + model_config = ConfigDict(from_attributes=True) + register_number: str name: str degree: str @@ -14,9 +16,6 @@ class StudentInfo(BaseModel): regulation_year: int current_semester: int - class Config: - from_attributes = True - class LoginResponse(BaseModel): access_token: str token_type: str = "bearer" diff --git a/backend/app/schemas/result.py b/backend/app/schemas/result.py index 1fc1569..273de78 100644 --- a/backend/app/schemas/result.py +++ b/backend/app/schemas/result.py @@ -1,25 +1,26 @@ -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from typing import List, Optional -from datetime import datetime + class ResultItem(BaseModel): + model_config = ConfigDict(from_attributes=True) + semester: int subject_code: str subject_name: str subject_type: str - grade: Optional[str] - marks_obtained: Optional[float] + grade: Optional[str] = None + marks_obtained: Optional[float] = None result_status: str attempt_number: int - class Config: - from_attributes = True class ExamSessionInfo(BaseModel): display_label: str session_name: str exam_year: int + class ResultsResponse(BaseModel): student_name: str register_number: str diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index bfab6ab..3e99605 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -1,6 +1,19 @@ import pytest from fastapi.testclient import TestClient from app.main import app +from app.core.database import engine, Base + +from app.models.student import Student, Branch, Regulation +from app.models.result import Result, Subject, ExamSession + + +@pytest.fixture(scope="session", autouse=True) +def create_tables(): + """Create all tables before tests run, drop after.""" + Base.metadata.create_all(bind=engine) + yield + Base.metadata.drop_all(bind=engine) + @pytest.fixture def client(): From 05da0dc43768a213e315dc735e2b47664a2add16 Mon Sep 17 00:00:00 2001 From: Jashwanth Date: Wed, 27 May 2026 12:30:31 +0530 Subject: [PATCH 3/3] chore: upgrade GitHub Actions to Node.js 24 compatible versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - actions/checkout → v4.2.2 - actions/setup-python → v5.3.0 - actions/setup-node → v4.1.0 - actions/cache → v4.2.0 - docker/setup-buildx-action → v3.7.1 - docker/build-push-action → v6.9.0 - docker/login-action → v3.3.0 - Add FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true --- .github/workflows/cd.yml | 8 ++++---- .github/workflows/ci.yml | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 3fad7e0..fefea4a 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -16,17 +16,17 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v4.2.2 - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@v3.3.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push backend - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.9.0 with: context: ./backend push: true @@ -35,7 +35,7 @@ jobs: ghcr.io/crms-devops/crms-backend:${{ github.sha }} - name: Build and push frontend - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.9.0 with: context: ./frontend push: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89273d0..4a98ff9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,15 +29,15 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v4.2.2 - name: Set up Python 3.13 - uses: actions/setup-python@v5 + uses: actions/setup-python@v5.3.0 with: python-version: "3.13" - name: Cache pip packages - uses: actions/cache@v4 + uses: actions/cache@v4.2.0 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('backend/requirements.txt') }} @@ -65,10 +65,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v4.2.2 - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v4.1.0 with: node-version: "20" cache: "npm" @@ -91,13 +91,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v4.2.2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v3.7.1 - name: Build backend image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.9.0 with: context: ./backend push: false @@ -105,7 +105,7 @@ jobs: load: true - name: Build frontend image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6.9.0 with: context: ./frontend push: false