-
Notifications
You must be signed in to change notification settings - Fork 5
Fastapi #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Refactor routes. Add README.
Fingel
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spent some time trying to get this running locally, but was ultimately unsuccessful.
I'm not clear on how the database is managed. There are some manual commands in the file database_postgresql_notes but if that is the de-facto method of getting a database set up, shouldn't it be a .sql file?
There seemed to be some syntax errors in there anyway, ($$to add enum type -> alter type bandpass add value 'other';) so even after copying the commands to a .sql file I was unable to use them to set up the database properly.
Without the database, it seems the tests will not run. Additionally, the tests appear to make HTTP requests to 2 different services. I managed to figure that one of them running on port 8000 was the fastapi service itself. But I don't know what the requests going to port 5000 are supposed to test.
All in all, I think the README needs some help.
| Flask-Mail==0.10.0 | ||
| Flask-SQLAlchemy==2.5.1 | ||
| Flask-WTF | ||
| flask-caching |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing fastapi
Sorry about that - I've added a bit of signposting from the main readme to the fastapi readme. With the project in flux with the intention to retire flask in favour of fastapi / svelte I wasn't concentrating so much on the top level README. In summary, the most straightforward way to get the whole thing up and running - fastapi, database, even the flask app, is to use skaffold - just as Hope that is a bit clearer now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR replaces the legacy Flask backend with a new async FastAPI application, adds Pydantic-based settings and JWT authentication, and integrates full Kubernetes/Helm/Skaffold deployment plus comprehensive endpoint tests.
- Introduce a modern FastAPI service in
server/with SQLAlchemy models, Pydantic schemas, and JWT auth - Provide Pydantic settings in
server/config.pyand Dockerfile for containerization - Add Helm charts (
gwtm-helm/) and Skaffold config for local and production deployments
Reviewed Changes
Copilot reviewed 147 out of 147 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| server/core/enums/bandpass.py | New bandpass enum values |
| server/core/enums/init.py | Import list for core enums (duplicate import present) |
| server/config.py | Pydantic Settings class for environment variables |
| server/auth/auth.py | JWT token creation, decoding, and user validation |
| server/auth/init.py | Auth package init |
| server/README.md | FastAPI backend usage and testing instructions |
| server/Dockerfile | Container build for FastAPI service |
| gwtm-helm/values.yaml | Helm values for FastAPI deployment |
| gwtm-helm/values-dev.yaml | Development overrides for Helm |
| gwtm-helm/templates/ingress.yaml | Ingress paths for /api/v1, docs, health |
| gwtm-helm/templates/fastapi/service.yaml | Kubernetes Service definition for FastAPI |
| gwtm-helm/templates/fastapi/deployment.yaml | Kubernetes Deployment for FastAPI with init container |
| gwtm-helm/templates/fastapi/configmap.yaml | ConfigMap for FastAPI environment variables |
| gwtm-helm/templates/backend/create-database-tables.yaml | Database setup Job |
| gwtm-helm/start-dev.sh | Script to start Skaffold dev environment |
| gwtm-helm/skaffold.yaml | Skaffold configuration for both Flask and FastAPI |
| gwtm-helm/restore-db | Script for restoring database dumps |
| gwtm-helm/fastapi-README.md | Documentation for FastAPI Helm templates |
| README.md | Root README with FastAPI quick-start |
| .dockerignore | Updated ignore rules for Docker build |
Comments suppressed due to low confidence (2)
server/core/enums/bandpass.py:3
- Class names should use PascalCase. Rename
bandpasstoBandpassto follow Python class naming conventions.
class bandpass(IntEnum):
gwtm-helm/templates/fastapi/configmap.yaml:13
CORS_ORIGINSis expected to be a list by the Pydantic settings. Providing a single string may cause parsing errors. Consider formatting it as a JSON array or comma-separated list that your app can split.
CORS_ORIGINS: "{{ .Values.ingress.host }}"
server/core/enums/__init__.py
Outdated
| from .pointing_status import pointing_status | ||
| from .frequency_units import frequency_units | ||
| from .depth_unit import depth_unit | ||
| from .frequency_units import frequency_units |
Copilot
AI
Jun 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate import of frequency_units detected. Remove the redundant import to clean up the module.
| from .frequency_units import frequency_units |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
server/config.py
Outdated
| SECRET_KEY: str = Field(os.urandom(16).hex(), env="SECRET_KEY") | ||
| JWT_SECRET_KEY: str = Field(os.urandom(16).hex(), env="JWT_SECRET_KEY") |
Copilot
AI
Jun 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using os.urandom at import time sets the same default each run and may not be re-evaluated per instance. Consider using default_factory=... to generate a new random key for each instantiation.
| SECRET_KEY: str = Field(os.urandom(16).hex(), env="SECRET_KEY") | |
| JWT_SECRET_KEY: str = Field(os.urandom(16).hex(), env="JWT_SECRET_KEY") | |
| def _generate_random_key() -> str: | |
| """Generate a random 16-byte key and return its hexadecimal representation.""" | |
| return os.urandom(16).hex() | |
| SECRET_KEY: str = Field(default_factory=_generate_random_key, env="SECRET_KEY") | |
| JWT_SECRET_KEY: str = Field(default_factory=_generate_random_key, env="JWT_SECRET_KEY") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| @@ -0,0 +1,17 @@ | |||
| from enum import IntEnum | |||
|
|
|||
| class WavelengthUnits(IntEnum): | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Astropy has a pretty extensive units package developed. Does it help us to use that?
| @@ -0,0 +1,35 @@ | |||
| from enum import IntEnum | |||
|
|
|||
| class Bandpass(IntEnum): | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels very fragile. Should this be more dynamic and stored in the db?
Update PostGIS setup to work with existing extension in postgis schema.
| # CORS settings | ||
| CORS_ORIGINS: List[str] = ["*"] | ||
| CORS_METHODS: List[str] = ["*"] | ||
| CORS_HEADERS: List[str] = ["*"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be set to something that isn't * for prod?
| class DepthUnit(IntEnum): | ||
| """Enumeration for depth units.""" | ||
|
|
||
| ab_mag = 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also be in the db?
| db = SessionLocal() | ||
| try: | ||
| yield db | ||
| finally: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little unclear on when this finally happens. I think this may prematurely close the db connection. Should this be more of a context manager?
| @@ -0,0 +1,10 @@ | |||
| from .users import Users, UserGroups, Groups, UserActions | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we import these things here in the init if we don't expose them?
| from server.core.enums.depthunit import DepthUnit as depth_unit_enum | ||
| from geoalchemy2 import Geography | ||
| from sqlalchemy.ext.hybrid import hybrid_property | ||
| from ..database import Base |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Importing this effectively global variable makes me nervous. I might advocate for having a get session function and leaving the separation of responsibilities to not touch that variable.
| self.warnings = [] | ||
|
|
||
|
|
||
| class GWCandidate(Base): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I'm seeing what you are doing now. I guess this is fine.
| Returns: | ||
| Tuple of (success, creators_list) | ||
| """ | ||
| from sqlalchemy import and_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imports in methods make me nervous.
| @@ -0,0 +1,11 @@ | |||
| """Test endpoint for refactored pointing routes.""" | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this file need to persist?
Summary
• Implement complete FastAPI backend to replace legacy Flask application with modern async architecture
• Add comprehensive test coverage for all FastAPI endpoints with 11 test modules covering new code
Key Changes
New FastAPI Backend (server/)
Comprehensive Test Suite (tests/fastapi/)
Kubernetes Integration (gwtm-helm/)
This FastAPI implementation aims to maintain full API compatibility while providing better performance, automatic documentation, and type safety.