added pipeline
Some checks failed
Build and Deploy Backend / build_and_deploy (push) Failing after 19s
Build and Deploy Astro App / build_and_deploy (push) Successful in 50s

This commit is contained in:
ebby 2026-09-28 12:28:28 +02:00
parent 842e8a12d4
commit 6e24614c54
13 changed files with 87 additions and 15 deletions

View file

@ -0,0 +1,60 @@
name: Build and Deploy Backend
on:
push:
branches:
- main
paths:
- "backend/**"
- "pyproject.toml"
- "uv.lock"
- "deploy/deploy-backend.sh"
jobs:
build_and_deploy:
runs-on: roadrunner
container:
volumes:
- /opt/blauwasser-api:/opt/blauwasser-api
- /var/lib/blauwasser-api:/var/lib/blauwasser-api
steps:
- name: Repository auschecken
uses: actions/checkout@v4
- name: Python einrichten
uses: actions/setup-python@v5
with:
python-version: "3.14"
# - name: Backend testen
# working-directory: backend
# run: |
# python -m pip install -U pip
# python -m pip install -e .
# pytest
- name: Backend kopieren
run: |
rsync -a --delete \
--exclude '.venv' \
--exclude '__pycache__' \
--exclude '*.db' \
backend/ /opt/blauwasser-api/backend/
cp pyproject.toml /opt/blauwasser-api/
cp uv.lock /opt/blauwasser-api/
- name: Abhängigkeiten aktualisieren
run: |
cd /opt/blauwasser-api
uv sync --frozen
- name: Backend neu starten
run: |
systemctl restart blauwasser-api
systemctl is-active --quiet blauwasser-api
- name: Deployment prüfen
run: |
curl --fail https://api.blauwasser-mausis.de/health

View file

@ -17,6 +17,7 @@ dependencies = [
"fastapi-crons==2.5.0",
"feedparser==6.0.14",
"PyJWT==2.15.0",
"python-dotenv>=1.0.0",
]
[project.scripts]

View file

@ -1,6 +1,6 @@
BACKEND_URL="http://localhost:8000"
FRONTEND_URL="http://localhost:4321"
SECRET="IamALocalSecretAndMustBeReplacedInProduction"
JWT_SECRET="IamALocalSecretAndMustBeReplacedInProduction"
ENVIRONMENT="local"
MAILTRAP_API_TOKEN="FakedyFake"
DB_NAME="dev"
DATABASE_URL="sqlite:///dev.db"

View file

@ -1,8 +1,8 @@
import os
ENVIRONMENT = os.environ["ENVIRONMENT"]
SECRET_KEY = os.environ["SECRET"]
JWT_SECRET = os.environ["JWT_SECRET"]
FRONTEND_URL = os.environ["FRONTEND_URL"]
BACKEND_URL = os.environ["BACKEND_URL"]
MAILTRAP_API_TOKEN = os.environ["MAILTRAP_API_TOKEN"]
DB_NAME = os.environ["DB_NAME"]
DATABASE_URL = os.environ["DATABASE_URL"]

View file

@ -1,6 +1,5 @@
from typing import Any
from backend.config import SECRET_KEY
import os
from backend.config import JWT_SECRET
from fastapi.security import HTTPBasicCredentials
from fastapi import Security
from fastapi.security import HTTPBearer
@ -19,13 +18,13 @@ from datetime import timedelta
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_DAYS = 360
ACCESS_TOKEN_EXPIRE_DAYS = 180
def create_access_token(data: dict, expires_delta: timedelta | None = None):
to_encode = data.copy()
expire = datetime.now(timezone.utc) + (expires_delta or timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return jwt.encode(to_encode, JWT_SECRET, algorithm=ALGORITHM)
security = HTTPBearer()
@ -36,7 +35,7 @@ def get_token(credentials = Security(security)) -> str:
raise HTTPException(status_code=403, detail="Invalid authorization format")
def decode_token(token: str)-> str | None:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
payload = jwt.decode(token, JWT_SECRET, algorithms=[ALGORITHM])
return payload.get("sub")
async def get_current_user(token: str = Depends(get_token), session: Session = Depends(get_session)):

View file

@ -1,10 +1,10 @@
from backend.config import DB_NAME
from backend.config import DATABASE_URL
from collections.abc import Generator
from sqlmodel import Session
from sqlmodel import SQLModel
from sqlmodel import create_engine
sqlite_url = f"sqlite:///{DB_NAME}.db"
sqlite_url = DATABASE_URL
connect_args = {"check_same_thread": False}
engine = create_engine(sqlite_url, connect_args=connect_args)

View file

@ -1,7 +1,8 @@
from dotenv import load_dotenv
from dotenv.main import load_dotenv
load_dotenv()
from .routers import users, comments, newsletters
from .routers import users, comments, newsletters, health
from backend.internal.database import create_db_and_tables
from fastapi import FastAPI
from fastapi_crons import Crons
@ -26,4 +27,5 @@ def on_startup():
app.include_router(users.router)
app.include_router(comments.router)
app.include_router(newsletters.router)
app.include_router(newsletters.router)
app.include_router(health.router)

View file

@ -0,0 +1,8 @@
from fastapi import APIRouter
router = APIRouter()
@router.get("/health", include_in_schema=False)
def health():
return {"status": "ok"}

2
backend/uv.lock generated
View file

@ -152,6 +152,7 @@ dependencies = [
{ name = "mailtrap" },
{ name = "pyjwt" },
{ name = "pytest" },
{ name = "python-dotenv" },
{ name = "sqlmodel" },
]
@ -165,6 +166,7 @@ requires-dist = [
{ name = "mailtrap", specifier = "==2.10.0" },
{ name = "pyjwt", specifier = "==2.15.0" },
{ name = "pytest", specifier = ">=9.1.1" },
{ name = "python-dotenv", specifier = ">=1.0.0" },
{ name = "sqlmodel", specifier = ">=0.0.42" },
]