Add Identity Verification System #18
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI/CD Pipeline | |
on: | |
push: | |
branches: [ main, develop, 'feature/**' ] | |
pull_request: | |
branches: [ main, develop ] | |
jobs: | |
backend-tests: | |
runs-on: ubuntu-latest | |
services: | |
postgres: | |
image: postgres:14 | |
env: | |
POSTGRES_PASSWORD: postgres | |
POSTGRES_DB: test_db | |
ports: | |
- 5432:5432 | |
options: >- | |
--health-cmd pg_isready | |
--health-interval 10s | |
--health-timeout 5s | |
--health-retries 5 | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up Python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: '3.12' | |
- name: Cache pip dependencies | |
uses: actions/cache@v3 | |
with: | |
path: ~/.cache/pip | |
key: ${{ runner.os }}-pip-${{ hashFiles('backend/requirements.txt') }} | |
restore-keys: | | |
${{ runner.os }}-pip- | |
- name: Install dependencies | |
working-directory: ./backend | |
run: | | |
python -m pip install --upgrade pip setuptools wheel | |
# Install system dependencies | |
sudo apt-get update | |
sudo apt-get install -y tesseract-ocr | |
# Install core dependencies first | |
pip install 'sqlalchemy>=1.4.0,<2.0.0' | |
pip install 'alembic>=1.12.0,<2.0.0' | |
pip install 'psycopg2-binary>=2.9.0,<3.0.0' | |
# Install requirements | |
pip install -r requirements.txt | |
# Install test dependencies | |
pip install pytest-cov flake8 httpx pytesseract pycountry PyYAML selenium pytest-mock loguru reportlab inputimeout | |
# Add local bin to PATH | |
export PATH="$HOME/.local/bin:$PATH" | |
# Verify installations | |
python -m pip list | |
python -c "import alembic; print(f'Alembic version: {alembic.__version__}')" | |
- name: Setup backend test environment | |
working-directory: ./backend | |
env: | |
POSTGRES_USER: postgres | |
POSTGRES_PASSWORD: postgres | |
POSTGRES_DB: test_db | |
run: | | |
echo "DEV_MODE=true" > .env | |
echo "DATABASE_URL=postgresql://postgres:postgres@localhost:5432/test_db" >> .env | |
echo "API_HOST=0.0.0.0" >> .env | |
echo "API_PORT=8000" >> .env | |
echo "[email protected]" >> .env | |
echo "INDEED_PASSWORD=testpass123" >> .env | |
# Initialize database schema | |
PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -c 'DROP DATABASE IF EXISTS test_db;' | |
PGPASSWORD=postgres psql -h localhost -U postgres -d postgres -c 'CREATE DATABASE test_db;' | |
# Create initial schema | |
PGPASSWORD=postgres psql -h localhost -U postgres -d test_db << 'EOSQL' | |
CREATE TABLE IF NOT EXISTS users ( | |
id SERIAL PRIMARY KEY, | |
username VARCHAR(255) NOT NULL, | |
email VARCHAR(255) UNIQUE NOT NULL, | |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
); | |
CREATE TABLE IF NOT EXISTS verified_documents ( | |
id SERIAL PRIMARY KEY, | |
user_id INTEGER REFERENCES users(id), | |
document_type VARCHAR(50) NOT NULL, | |
document_number VARCHAR(255), | |
status VARCHAR(50) DEFAULT 'PENDING', | |
verification_date TIMESTAMP, | |
expiry_date TIMESTAMP, | |
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
); | |
EOSQL | |
- name: Verify environment | |
working-directory: ./backend | |
env: | |
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db | |
PYTHONPATH: ${GITHUB_WORKSPACE}/backend | |
run: | | |
python -c "import sys; print('Python path:', sys.path)" | |
python -c "import alembic.config; print('Alembic configuration verified')" | |
python -c "import psycopg2; conn=psycopg2.connect('$DATABASE_URL'); print('Database connection verified')" | |
- name: Run migrations | |
working-directory: ./backend | |
env: | |
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db | |
PYTHONPATH: ${GITHUB_WORKSPACE}/backend | |
run: | | |
echo "Setting up Python environment..." | |
export PYTHONPATH="${PYTHONPATH}:${PWD}" | |
echo "Current PYTHONPATH: $PYTHONPATH" | |
# Ensure alembic CLI is in PATH | |
python -m pip install --upgrade alembic | |
export PATH="$HOME/.local/bin:$PATH" | |
# Create Alembic directory structure | |
mkdir -p migrations/versions | |
# Initialize Alembic if not already initialized | |
if [ ! -f alembic.ini ]; then | |
alembic init migrations | |
# Update alembic.ini with correct database URL | |
sed -i "s|sqlalchemy.url = .*|sqlalchemy.url = ${DATABASE_URL}|" alembic.ini | |
fi | |
# Update env.py to use environment variable for database URL | |
cat > migrations/env.py << 'EOL' | |
from logging.config import fileConfig | |
from sqlalchemy import engine_from_config, pool, MetaData, Table, Column, Integer, String, ForeignKey, TIMESTAMP, text | |
from alembic import context | |
import os | |
config = context.config | |
if config.config_file_name is not None: | |
fileConfig(config.config_file_name) | |
def get_url(): | |
return os.getenv("DATABASE_URL") | |
# Create MetaData object | |
metadata = MetaData() | |
# Define tables | |
users = Table('users', metadata, | |
Column('id', Integer, primary_key=True), | |
Column('username', String(255), nullable=False), | |
Column('email', String(255), unique=True, nullable=False), | |
Column('created_at', TIMESTAMP, server_default=text('CURRENT_TIMESTAMP')) | |
) | |
verified_documents = Table('verified_documents', metadata, | |
Column('id', Integer, primary_key=True), | |
Column('user_id', Integer, ForeignKey('users.id')), | |
Column('document_type', String(50), nullable=False), | |
Column('document_number', String(255)), | |
Column('status', String(50), server_default='PENDING'), | |
Column('verification_date', TIMESTAMP), | |
Column('expiry_date', TIMESTAMP), | |
Column('created_at', TIMESTAMP, server_default=text('CURRENT_TIMESTAMP')) | |
) | |
target_metadata = metadata | |
def run_migrations_offline() -> None: | |
url = get_url() | |
context.configure( | |
url=url, | |
target_metadata=target_metadata, | |
literal_binds=True, | |
dialect_opts={"paramstyle": "named"}, | |
) | |
with context.begin_transaction(): | |
context.run_migrations() | |
def run_migrations_online() -> None: | |
configuration = config.get_section(config.config_ini_section) | |
if configuration is None: | |
configuration = {} | |
configuration["sqlalchemy.url"] = get_url() | |
connectable = engine_from_config( | |
configuration, | |
prefix="sqlalchemy.", | |
poolclass=pool.NullPool, | |
) | |
with connectable.connect() as connection: | |
context.configure( | |
connection=connection, | |
target_metadata=target_metadata | |
) | |
with context.begin_transaction(): | |
context.run_migrations() | |
if context.is_offline_mode(): | |
run_migrations_offline() | |
else: | |
run_migrations_online() | |
EOL | |
# Create initial migration | |
alembic revision --autogenerate -m "Initial migration" | |
# Run migrations | |
alembic upgrade head | |
- name: Run tests with coverage | |
working-directory: ./backend | |
env: | |
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db | |
run: | | |
pytest tests/ -v --cov=src --cov-report=xml --junitxml=test-results/results.xml | |
- name: Run flake8 | |
working-directory: ./backend | |
run: | | |
flake8 src tests --max-line-length=100 | |
- name: Upload test results | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: backend-test-results | |
path: | | |
backend/coverage.xml | |
backend/test-results/results.xml | |
frontend-tests: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: pnpm/action-setup@v2 | |
with: | |
version: 8 | |
- name: Set up Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: '18' | |
cache: 'pnpm' | |
cache-dependency-path: './frontend/pnpm-lock.yaml' | |
- name: Install dependencies | |
working-directory: ./frontend | |
run: pnpm install | |
- name: Run tests | |
working-directory: ./frontend | |
run: CI=true pnpm test | |
- name: Upload test results | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: frontend-test-results | |
path: frontend/test-results |