feat(version): /api/version + build-time version/commit stamping
Add a VERSION file (0.1.0) and inject APP_VERSION/GIT_SHA/BUILD_DATE as Docker build-args (both stages; Vite inlines them into the SPA). New public GET /api/version returns app_version, git_sha, build_date and the Alembic head as the database revision. deploy.sh and the localdev build pass the args.
This commit is contained in:
parent
5dd3109286
commit
a93ab30fb2
7 changed files with 56 additions and 2 deletions
18
Dockerfile
18
Dockerfile
|
|
@ -1,5 +1,15 @@
|
||||||
|
# Build/version info, injected via --build-arg (defaults keep un-built/dev runs working).
|
||||||
|
ARG APP_VERSION=dev
|
||||||
|
ARG GIT_SHA=unknown
|
||||||
|
ARG BUILD_DATE=
|
||||||
|
|
||||||
# Stage 1: build the frontend SPA
|
# Stage 1: build the frontend SPA
|
||||||
FROM node:20-alpine AS frontend
|
FROM node:20-alpine AS frontend
|
||||||
|
ARG APP_VERSION
|
||||||
|
ARG GIT_SHA
|
||||||
|
ARG BUILD_DATE
|
||||||
|
# Vite inlines VITE_*-prefixed env into the bundle at build time.
|
||||||
|
ENV VITE_APP_VERSION=$APP_VERSION VITE_GIT_SHA=$GIT_SHA VITE_BUILD_DATE=$BUILD_DATE
|
||||||
WORKDIR /fe
|
WORKDIR /fe
|
||||||
COPY frontend/package.json ./
|
COPY frontend/package.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
@ -8,10 +18,16 @@ RUN npm run build
|
||||||
|
|
||||||
# Stage 2: backend runtime, serving the built SPA
|
# Stage 2: backend runtime, serving the built SPA
|
||||||
FROM python:3.12-slim
|
FROM python:3.12-slim
|
||||||
|
ARG APP_VERSION
|
||||||
|
ARG GIT_SHA
|
||||||
|
ARG BUILD_DATE
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
PIP_NO_CACHE_DIR=1 \
|
PIP_NO_CACHE_DIR=1 \
|
||||||
PIP_DISABLE_PIP_VERSION_CHECK=1
|
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
||||||
|
APP_VERSION=$APP_VERSION \
|
||||||
|
GIT_SHA=$GIT_SHA \
|
||||||
|
BUILD_DATE=$BUILD_DATE
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
|
||||||
1
VERSION
Normal file
1
VERSION
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0.1.0
|
||||||
|
|
@ -9,6 +9,11 @@ class Settings(BaseSettings):
|
||||||
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
|
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
|
||||||
|
|
||||||
app_name: str = "Siftlode"
|
app_name: str = "Siftlode"
|
||||||
|
# Build/version info, injected at image build time (Docker build-args -> env). Defaults
|
||||||
|
# apply for un-built/dev runs; the About dialog and version banner surface these.
|
||||||
|
app_version: str = "dev"
|
||||||
|
git_sha: str = "unknown"
|
||||||
|
build_date: str = ""
|
||||||
|
|
||||||
database_url: str = "postgresql+psycopg://subfeed:subfeed@db:5432/subfeed"
|
database_url: str = "postgresql+psycopg://subfeed:subfeed@db:5432/subfeed"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ from starlette.middleware.sessions import SessionMiddleware
|
||||||
|
|
||||||
from app import auth
|
from app import auth
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
from app.routes import admin, channels, feed, health, me, quota, sync, tags
|
from app.routes import admin, channels, feed, health, me, quota, sync, tags, version
|
||||||
from app.scheduler import shutdown_scheduler, start_scheduler
|
from app.scheduler import shutdown_scheduler, start_scheduler
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,6 +68,7 @@ app.include_router(me.router)
|
||||||
app.include_router(channels.router)
|
app.include_router(channels.router)
|
||||||
app.include_router(admin.router)
|
app.include_router(admin.router)
|
||||||
app.include_router(quota.router)
|
app.include_router(quota.router)
|
||||||
|
app.include_router(version.router)
|
||||||
|
|
||||||
# The built SPA (populated by the Docker frontend build stage).
|
# The built SPA (populated by the Docker frontend build stage).
|
||||||
STATIC_DIR = Path(__file__).parent / "static_spa"
|
STATIC_DIR = Path(__file__).parent / "static_spa"
|
||||||
|
|
|
||||||
23
backend/app/routes/version.py
Normal file
23
backend/app/routes/version.py
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from sqlalchemy import text
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.config import settings
|
||||||
|
from app.db import get_db
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/api", tags=["version"])
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/version")
|
||||||
|
def get_version(db: Session = Depends(get_db)) -> dict:
|
||||||
|
"""Build + schema version, for the About dialog and the 'new version' banner.
|
||||||
|
Intentionally public (no auth) and cheap: just env-baked build info plus the current
|
||||||
|
Alembic migration head (the 'database version'). app_version/git_sha/build_date are
|
||||||
|
injected at image build time (see the Dockerfile build-args)."""
|
||||||
|
db_revision = db.execute(text("SELECT version_num FROM alembic_version")).scalar()
|
||||||
|
return {
|
||||||
|
"app_version": settings.app_version,
|
||||||
|
"git_sha": settings.git_sha,
|
||||||
|
"build_date": settings.build_date or None,
|
||||||
|
"db_revision": db_revision,
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,10 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
APP_VERSION: ${APP_VERSION:-dev}
|
||||||
|
GIT_SHA: ${GIT_SHA:-unknown}
|
||||||
|
BUILD_DATE: ${BUILD_DATE:-}
|
||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
environment:
|
||||||
# Exactly one scheduler may write to the shared DB; the server owns it.
|
# Exactly one scheduler may write to the shared DB; the server owns it.
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
APP_VERSION: ${APP_VERSION:-dev}
|
||||||
|
GIT_SHA: ${GIT_SHA:-unknown}
|
||||||
|
BUILD_DATE: ${BUILD_DATE:-}
|
||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-subfeed}:${POSTGRES_PASSWORD:-subfeed}@db:5432/${POSTGRES_DB:-subfeed}
|
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-subfeed}:${POSTGRES_PASSWORD:-subfeed}@db:5432/${POSTGRES_DB:-subfeed}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue