Skip to content

Commit 249feee

Browse files
committed
fix: resolved merge conflicts
2 parents 8396a3a + eb09171 commit 249feee

28 files changed

Lines changed: 1427 additions & 222 deletions

.github/PULL_REQUEST_TEMPLATE/pull_request_template.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ Please describe the tests that you ran to verify your changes. Provide instructi
2121
- [ ] Test B
2222

2323
**Test Configuration**:
24-
* Firmware version:
25-
* Hardware:
26-
* SDK:
24+
* Python version:
25+
* Docker/Compose version:
26+
* OS:
2727

2828
## Checklist:
2929

.github/workflows/docker-build.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Docker Build
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Build Docker image
17+
run: |
18+
docker build -t fireform:test .

.github/workflows/lint.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
continue-on-error: true
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Python 3.11
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.11"
21+
22+
- name: Install linter
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install ruff
26+
27+
- name: Run linter
28+
run: |
29+
ruff check src/ --output-format=github

.github/workflows/tests.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Python 3.11
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.11"
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install -r requirements.txt
25+
pip install pytest
26+
27+
- name: Run tests
28+
env:
29+
PYTHONPATH: src
30+
run: |
31+
python -m pytest src/test/ -v --tb=short --ignore=src/test/test_model.py

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
.idea
33
venv
44
.venv
5-
*.db
5+
*.db
6+
.vscode

Dockerfile

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ WORKDIR /app
66
# Install system dependencies
77
RUN apt-get update && apt-get install -y \
88
curl \
9+
libgl1 \
10+
libglib2.0-0 \
11+
libxcb1 \
912
&& rm -rf /var/lib/apt/lists/*
1013

1114
# Copy and install Python dependencies
@@ -15,8 +18,11 @@ RUN pip install --no-cache-dir -r requirements.txt
1518
# Copy application code
1619
COPY . .
1720

18-
# Set Python path so imports work correctly
19-
ENV PYTHONPATH=/app/src
21+
# All imports use api.*, src.* which require the root to be on the path
22+
ENV PYTHONPATH=/app
2023

21-
# Keep container running for interactive use
22-
CMD ["tail", "-f", "/dev/null"]
24+
# Expose FastAPI port
25+
EXPOSE 8000
26+
27+
# Start the FastAPI server (not tail -f /dev/null which does nothing)
28+
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

Makefile

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: help build up down logs shell exec pull-model test clean fireform
1+
.PHONY: help build up down logs shell exec pull-model test clean fireform logs-app logs-ollama logs-frontend super-clean
22

33
help:
44
@printf '%s\n' \
@@ -16,16 +16,25 @@ help:
1616
@echo "make up - Start all containers"
1717
@echo "make down - Stop all containers"
1818
@echo "make logs - View container logs"
19+
@echo "make logs-app - View API container logs"
20+
@echo "make logs-frontend - View frontend container logs"
21+
@echo "make logs-ollama - View Ollama container logs"
1922
@echo "make shell - Open Python shell in app container"
2023
@echo "make exec - Execute Python script in container"
2124
@echo "make pull-model - Pull Mistral model into Ollama"
2225
@echo "make test - Run tests"
2326
@echo "make clean - Remove containers"
2427
@echo "make super-clean - [CAUTION] Use carefully. Cleans up ALL stopped containers, networks, build cache..."
2528

26-
fireform: build up
27-
@echo "Launching interactive shell in the app container..."
28-
docker compose exec app /bin/bash
29+
# Fix #382 — pull-model is now part of the main setup flow
30+
# Mistral is pulled automatically before you need it
31+
fireform: build up pull-model
32+
@echo ""
33+
@echo "✅ FireForm is ready!"
34+
@echo " API: http://localhost:8000"
35+
@echo " API Docs: http://localhost:8000/docs"
36+
@echo ""
37+
@echo "Run 'make logs' to view live logs, 'make down' to stop."
2938

3039
build:
3140
docker compose build
@@ -45,17 +54,25 @@ logs-app:
4554
logs-ollama:
4655
docker compose logs -f ollama
4756

57+
logs-frontend:
58+
docker compose logs -f frontend
59+
4860
shell:
4961
docker compose exec app /bin/bash
5062

63+
# Start the FastAPI server inside the running container
64+
run:
65+
docker compose exec app uvicorn api.main:app --host 0.0.0.0 --port 8000 --reload
66+
5167
exec:
5268
docker compose exec app python3 src/main.py
5369

5470
pull-model:
5571
docker compose exec ollama ollama pull mistral
5672

73+
# Fix — correct test directory (was src/test/ which doesn't exist)
5774
test:
58-
docker compose exec app python3 -m pytest src/test/
75+
docker compose exec app python3 -m pytest tests/ -v
5976

6077
clean:
6178
docker compose down -v

api/db/init_db.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,47 @@
1-
from sqlmodel import SQLModel
1+
import json
2+
import datetime
3+
from sqlmodel import SQLModel, Session, select
24
from api.db.database import engine
35
from api.db import models
6+
from api.db.models import Template
7+
8+
def seed_db():
9+
with Session(engine) as session:
10+
# Check if we already have templates
11+
statement = select(Template)
12+
try:
13+
results = session.exec(statement).first()
14+
except Exception:
15+
# Table might not exist yet if called at a weird time
16+
results = None
17+
18+
if not results:
19+
print("Seeding database with default template...")
20+
fields = {
21+
"Employee's name": "string",
22+
"Employee's job title": "string",
23+
"Employee's department supervisor": "string",
24+
"Employee's phone number": "string",
25+
"Employee's email": "string",
26+
"Signature": "string",
27+
"Date": "string"
28+
}
29+
30+
# Using ID 2 as agreed to avoid any ID 1 corruption
31+
default_template = Template(
32+
id=2,
33+
name="Manual Test Template",
34+
fields=fields,
35+
pdf_path="src/inputs/file_template_manual.pdf",
36+
created_at=datetime.datetime.now()
37+
)
38+
session.add(default_template)
39+
session.commit()
40+
print("Database seeded successfully.")
441

542
def init_db():
643
SQLModel.metadata.create_all(engine)
44+
seed_db()
745

846
if __name__ == "__main__":
947
init_db()

api/db/repositories.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@ def create_template(session: Session, template: Template) -> Template:
1111
def get_template(session: Session, template_id: int) -> Template | None:
1212
return session.get(Template, template_id)
1313

14+
15+
def list_templates(session: Session) -> list[Template]:
16+
statement = select(Template).order_by(Template.created_at.desc(), Template.id.desc())
17+
return list(session.exec(statement))
18+
1419
# Forms
1520
def create_form(session: Session, form: FormSubmission) -> FormSubmission:
1621
session.add(form)
1722
session.commit()
1823
session.refresh(form)
19-
return form
24+
return form

api/main.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,39 @@
1-
import uuid
2-
from starlette.middleware.base import BaseHTTPMiddleware
1+
from contextlib import asynccontextmanager
2+
import os
3+
34
from fastapi import FastAPI
45
from api.routes import templates, forms
5-
from fastapi import Request
6-
from fastapi.responses import JSONResponse
7-
from fastapi.exceptions import RequestValidationError
8-
from starlette.exceptions import HTTPException as StarletteHTTPException
6+
from api.db.init_db import init_db
7+
from api.errors.handlers import register_exception_handlers
8+
from fastapi.middleware.cors import CORSMiddleware
9+
from api.routes import forms, templates
10+
11+
@asynccontextmanager
12+
async def lifespan(app: FastAPI):
13+
# Startup: Initialize the database and seed it if necessary
14+
print("Initializing database...")
15+
init_db()
16+
yield
17+
# Shutdown logic goes here if needed
18+
19+
app = FastAPI(lifespan=lifespan)
20+
21+
register_exception_handlers(app)
22+
23+
default_origins = "http://127.0.0.1:5173"
24+
allowed_origins = [
25+
origin.strip()
26+
for origin in os.getenv("FRONTEND_ORIGINS", default_origins).split(",")
27+
if origin.strip()
28+
]
929

10-
app = FastAPI()
30+
app.add_middleware(
31+
CORSMiddleware,
32+
allow_origins=allowed_origins,
33+
allow_credentials=False,
34+
allow_methods=["*"],
35+
allow_headers=["*"],
36+
)
1137

1238
class RequestIDMiddleware(BaseHTTPMiddleware):
1339
async def dispatch(self, request: Request, call_next):
@@ -76,4 +102,4 @@ async def general_exception_handler(request: Request, exc: Exception):
76102

77103

78104
app.include_router(templates.router)
79-
app.include_router(forms.router)
105+
app.include_router(forms.router)

0 commit comments

Comments
 (0)