Skip to content

Commit

Permalink
Merge branch 'features/119-clean-up-migration-process' into stage
Browse files Browse the repository at this point in the history
  • Loading branch information
MelissaAutumn committed Oct 2, 2023
2 parents a846fb0 + c50071c commit e0466aa
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 61 deletions.
3 changes: 2 additions & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ ENV PYTHONPATH=.

COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY pyproject.toml .
RUN pip install .

COPY src/ .

Expand Down
3 changes: 2 additions & 1 deletion backend/deploy.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ ENV PYTHONPATH=.

COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY pyproject.toml .
RUN pip install .

COPY src/ ./src
COPY scripts/ ./scripts
Expand Down
3 changes: 3 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ description = "Backend component to Thunderbird Appointment"
requires-python = ">3.10"
dynamic = ["dependencies"]

[project.scripts]
run-command = "src.main:cli"

[project.urls]
homepage = "https://appointment.day"
repository = "https://github.com/thundernest/appointment.git"
Expand Down
9 changes: 2 additions & 7 deletions backend/scripts/dev-entry.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
#!/bin/sh

cd src
echo 'Starting migrations...'
alembic current
alembic upgrade head
echo 'Finished migrations!'
cd ../
run-command update-db

uvicorn src.main:app --reload --host 0.0.0.0 --port 8090
uvicorn src.main:server --reload --host 0.0.0.0 --port 8090
9 changes: 2 additions & 7 deletions backend/scripts/entry.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
#!/bin/sh

cd src
echo 'Starting migrations...'
alembic current
alembic upgrade head
echo 'Finished migrations!'
cd ../
run-command update-db

uvicorn src.main:app --host 0.0.0.0 --port 5000
uvicorn src.main:server --host 0.0.0.0 --port 5000
37 changes: 37 additions & 0 deletions backend/src/commands/update_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os

from ..database import models
from ..database.database import engine
from alembic.runtime import migration


def run():
print("Checking if we have a fresh database...")

# then, load the Alembic configuration and generate the
# version table, "stamping" it with the most recent rev:
from alembic import command
from alembic.config import Config

# TODO: Does this work on stage?
alembic_cfg = Config("./src/alembic.ini")

# If we have our database url env variable set, use that instead!
if os.getenv("DATABASE_URL"):
alembic_cfg.set_main_option("sqlalchemy.url", os.getenv("DATABASE_URL"))

with engine.begin() as connection:
context = migration.MigrationContext.configure(connection)
# Returns a tuple, empty if there's no revisions saved
revisions = context.get_current_heads()

# If we have no revisions, then fully create the database from the model metadata,
# and set our revision number to the latest revision. Otherwise run any new migrations
if len(revisions) == 0:
print("Initializing database, and setting it to the latest revision")
models.Base.metadata.create_all(bind=engine)
command.stamp(alembic_cfg, "head")
else:
print("Database already initialized, running migrations")
command.upgrade(alembic_cfg, 'head')

103 changes: 58 additions & 45 deletions backend/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,54 +48,67 @@

logging.debug("Logger started!")

# database
from .database import models
from .database.database import engine

models.Base.metadata.create_all(bind=engine)

# extra routes
from .routes import api
from .routes import account
from .routes import google
from .routes import schedule

# init app
app = FastAPI()

if os.getenv("SENTRY_DSN") != "" or os.getenv("SENTRY_DSN") is not None:
sentry_sdk.init(
dsn=os.getenv("SENTRY_DSN"),
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for performance monitoring.
# We recommend adjusting this value in production,
traces_sample_rate=1.0,
environment=os.getenv("APP_ENV", "dev"),

def server():
"""
Main function for the fast api server
"""
# extra routes
from .routes import api
from .routes import account
from .routes import google
from .routes import schedule

# init app
app = FastAPI()

if os.getenv("SENTRY_DSN") != "" or os.getenv("SENTRY_DSN") is not None:
sentry_sdk.init(
dsn=os.getenv("SENTRY_DSN"),
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for performance monitoring.
# We recommend adjusting this value in production,
traces_sample_rate=1.0,
environment=os.getenv("APP_ENV", "dev"),
)

# allow requests from own frontend running on a different port
app.add_middleware(
CORSMiddleware,
# Work around for now :)
allow_origins=[
os.getenv("FRONTEND_URL", "http://localhost:8080"),
"https://accounts.google.com",
"https://www.googleapis.com/auth/calendar",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# allow requests from own frontend running on a different port
app.add_middleware(
CORSMiddleware,
# Work around for now :)
allow_origins=[
os.getenv("FRONTEND_URL", "http://localhost:8080"),
"https://accounts.google.com",
"https://www.googleapis.com/auth/calendar",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.exception_handler(RefreshError)
async def catch_google_refresh_errors(request, exc):
"""Catch google refresh errors, and use our error instead."""
return await http_exception_handler(request, APIGoogleRefreshError())

# Mix in our extra routes
app.include_router(api.router)
app.include_router(account.router, prefix="/account")
app.include_router(google.router, prefix="/google")
app.include_router(schedule.router, prefix="/schedule")

return app

@app.exception_handler(RefreshError)
async def catch_google_refresh_errors(request, exc):
"""Catch google refresh errors, and use our error instead."""
return await http_exception_handler(request, APIGoogleRefreshError())
def cli():
"""
A very simple cli handler
"""
if len(sys.argv) < 2:
print("No command specified")
return

command = sys.argv[1:]

# Mix in our extra routes
app.include_router(api.router)
app.include_router(account.router, prefix="/account")
app.include_router(google.router, prefix="/google")
app.include_router(schedule.router, prefix="/schedule")
if command[0] == 'update-db':
from .commands import update_db
update_db.run()
13 changes: 13 additions & 0 deletions backend/src/migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
# This is ran from src/ so ignore the errors
from secrets import normalize_secrets

import sentry_sdk

# Normalize any AWS secrets
normalize_secrets()

Expand All @@ -32,6 +34,17 @@
# my_important_option = config.get_main_option("my_important_option")
# ... etc.

# Catch any errors that may run during migrations
if os.getenv("SENTRY_DSN") != "" or os.getenv("SENTRY_DSN") is not None:
sentry_sdk.init(
dsn=os.getenv("SENTRY_DSN"),
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for performance monitoring.
# We recommend adjusting this value in production,
traces_sample_rate=1.0,
environment=os.getenv("APP_ENV", "dev"),
)


def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
Expand Down

0 comments on commit e0466aa

Please sign in to comment.