Skip to content
Closed
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ POSTGRES_PORT=5432
POSTGRES_DB=ai_platform
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB_TEST=ai_platform_test

SENTRY_DSN=

Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ jobs:
POSTGRES_DB: ai_platform
ports:
- 5432:5432
options: --health-cmd "pg_isready -U postgres" --health-interval 10s --health-timeout 5s --health-retries 5
options: >-
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avirajsingh7

Is this intentional?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kurund was part of my previous commit where I was modifying this file.
Either way it is fine

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to revert then

--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5

strategy:
matrix:
Expand Down Expand Up @@ -46,6 +50,14 @@ jobs:
run: uv sync
working-directory: backend

- name: Wait for Postgres and create test DB
run: |
until pg_isready -h localhost -U postgres; do
echo "Waiting for PostgreSQL to be ready..."
sleep 1
done
PGPASSWORD=postgres psql -h localhost -U postgres -d ai_platform -c 'CREATE DATABASE ai_platform_test;' || true

- name: Activate virtual environment and run Alembic migrations
run: |
source .venv/bin/activate
Expand Down
18 changes: 18 additions & 0 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
POSTGRES_USER: str
POSTGRES_PASSWORD: str = ""
POSTGRES_DB: str = ""
POSTGRES_DB_TEST: str | None = None

@computed_field # type: ignore[prop-decorator]
@property
Expand All @@ -74,6 +75,23 @@
path=self.POSTGRES_DB,
)

@computed_field # type: ignore[prop-decorator]
@property
def SQLALCHEMY_TEST_DATABASE_URI(self) -> PostgresDsn:
if not self.POSTGRES_DB_TEST:
raise ValueError(

Check warning on line 82 in backend/app/core/config.py

View check run for this annotation

Codecov / codecov/patch

backend/app/core/config.py#L82

Added line #L82 was not covered by tests
"POSTGRES_DB_TEST is not set but is required for test configuration."
)

return MultiHostUrl.build(
scheme="postgresql+psycopg",
username=self.POSTGRES_USER,
password=self.POSTGRES_PASSWORD,
host=self.POSTGRES_SERVER,
port=self.POSTGRES_PORT,
path=self.POSTGRES_DB_TEST,
)

SMTP_TLS: bool = True
SMTP_SSL: bool = False
SMTP_PORT: int = 587
Expand Down
41 changes: 21 additions & 20 deletions backend/app/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,39 @@

import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, delete
from sqlmodel import Session, SQLModel, create_engine

from app.core.config import settings
from app.core.db import engine, init_db
from app.main import app
from app.models import (
APIKey,
Organization,
Project,
ProjectUser,
User,
OpenAI_Thread,
Credential,
)
from app.api.deps import get_db
from app.tests.utils.user import authentication_token_from_email
from app.tests.utils.utils import get_superuser_token_headers


test_engine = create_engine(str(settings.SQLALCHEMY_TEST_DATABASE_URI))


@pytest.fixture(scope="session", autouse=True)
def db() -> Generator[Session, None, None]:
with Session(engine) as session:
with Session(test_engine) as session:
# Drop all tables and recreate them
SQLModel.metadata.drop_all(test_engine)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe drop the database instead of the tables.

SQLModel.metadata.create_all(test_engine)

init_db(session)
yield session
# Delete data in reverse dependency order
session.execute(delete(ProjectUser)) # Many-to-many relationship
session.execute(delete(Project))
session.execute(delete(Credential))
session.execute(delete(Organization))
session.execute(delete(APIKey))
session.execute(delete(User))
session.execute(delete(OpenAI_Thread))
session.commit()


# Override the get_db dependency to use test session
@pytest.fixture(scope="session", autouse=True)
def override_get_db(db: Session):
def _get_test_db():
yield db

app.dependency_overrides[get_db] = _get_test_db
yield
app.dependency_overrides.clear()


@pytest.fixture(scope="module")
Expand Down
7 changes: 4 additions & 3 deletions backend/app/tests_pre_start.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import logging

from sqlalchemy import Engine
from sqlmodel import Session, select
from sqlmodel import Session, select, create_engine
from tenacity import after_log, before_log, retry, stop_after_attempt, wait_fixed

from app.core.db import engine
from app.core.config import settings

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

max_tries = 60 * 5 # 5 minutes
wait_seconds = 1
test_engine = create_engine(str(settings.SQLALCHEMY_TEST_DATABASE_URI))


@retry(
Expand All @@ -31,7 +32,7 @@

def main() -> None:
logger.info("Initializing service")
init(engine)
init(test_engine)

Check warning on line 35 in backend/app/tests_pre_start.py

View check run for this annotation

Codecov / codecov/patch

backend/app/tests_pre_start.py#L35

Added line #L35 was not covered by tests
logger.info("Service finished initializing")


Expand Down
16 changes: 16 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ services:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set}
- POSTGRES_USER=${POSTGRES_USER?Variable not set}
- POSTGRES_DB=${POSTGRES_DB?Variable not set}
- POSTGRES_DB_TEST=${POSTGRES_DB_TEST?Variable not set}
# Wait for main DB to be ready, then create test DB if it doesn't exist
command: >
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avirajsingh7

I am not sure if this is needed when we start the containers. It would be good to handle this during the test run.

bash -c "
docker-entrypoint.sh postgres &
pid=$$!
sleep 5
until psql -U $${POSTGRES_USER} -d $${POSTGRES_DB} -c 'SELECT 1'; do
echo 'Waiting for PostgreSQL...'
sleep 1
done
psql -U $${POSTGRES_USER} -d $${POSTGRES_DB} -c 'CREATE DATABASE \"${POSTGRES_DB_TEST}\";' || true
wait $$pid
"

adminer:
image: adminer
Expand Down Expand Up @@ -69,6 +83,7 @@ services:
- POSTGRES_SERVER=db
- POSTGRES_PORT=${POSTGRES_PORT}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_DB_TEST=${POSTGRES_DB_TEST}
- POSTGRES_USER=${POSTGRES_USER?Variable not set}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set}
- SENTRY_DSN=${SENTRY_DSN}
Expand Down Expand Up @@ -107,6 +122,7 @@ services:
- POSTGRES_SERVER=db
- POSTGRES_PORT=${POSTGRES_PORT}
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_DB_TEST=${POSTGRES_DB_TEST}
- POSTGRES_USER=${POSTGRES_USER?Variable not set}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set}
- SENTRY_DSN=${SENTRY_DSN}
Expand Down