Sync backend/frontend versions to Docker/VERSION and read version from it
This commit is contained in:
@@ -157,6 +157,8 @@ This document breaks the entire BanGUI project into development stages, ordered
|
|||||||
- Bumping only `Docker/VERSION` (e.g. `v0.9.9`) causes both layers to pick up the new version without touching any other file.
|
- Bumping only `Docker/VERSION` (e.g. `v0.9.9`) causes both layers to pick up the new version without touching any other file.
|
||||||
- All existing tests pass (`pytest backend/`).
|
- All existing tests pass (`pytest backend/`).
|
||||||
|
|
||||||
|
**Status:** ✅ Completed (2026-03-19)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Task GV-2 — Expose the BanGUI version through the API
|
### Task GV-2 — Expose the BanGUI version through the API
|
||||||
|
|||||||
@@ -30,21 +30,39 @@ def _read_pyproject_version() -> str:
|
|||||||
return str(data["project"]["version"])
|
return str(data["project"]["version"])
|
||||||
|
|
||||||
|
|
||||||
|
def _read_docker_version() -> str:
|
||||||
|
"""Read the project version from ``Docker/VERSION``.
|
||||||
|
|
||||||
|
This file is the single source of truth for release scripts and must not be
|
||||||
|
out of sync with the frontend and backend versions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
|
version_path = repo_root / "Docker" / "VERSION"
|
||||||
|
if not version_path.exists():
|
||||||
|
raise FileNotFoundError(f"Docker/VERSION not found at {version_path}")
|
||||||
|
|
||||||
|
version = version_path.read_text(encoding="utf-8").strip()
|
||||||
|
return version.lstrip("v")
|
||||||
|
|
||||||
|
|
||||||
def _read_version() -> str:
|
def _read_version() -> str:
|
||||||
"""Return the current package version.
|
"""Return the current package version.
|
||||||
|
|
||||||
Prefer the project metadata in ``pyproject.toml`` when available, since this
|
Prefer the release artifact in ``Docker/VERSION`` when available so the
|
||||||
is the single source of truth for local development and is kept in sync with
|
backend version always matches what the release tooling publishes.
|
||||||
the frontend and Docker release version.
|
|
||||||
|
|
||||||
When running from an installed distribution where the ``pyproject.toml``
|
If that file is missing (e.g. in a production wheel or a local checkout),
|
||||||
is not available, fall back to installed package metadata.
|
fall back to ``pyproject.toml`` and finally installed package metadata.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return _read_pyproject_version()
|
return _read_docker_version()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return importlib.metadata.version(PACKAGE_NAME)
|
try:
|
||||||
|
return _read_pyproject_version()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return importlib.metadata.version(PACKAGE_NAME)
|
||||||
|
|
||||||
|
|
||||||
__version__ = _read_version()
|
__version__ = _read_version()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "bangui-backend"
|
name = "bangui-backend"
|
||||||
version = "0.9.4"
|
version = "0.9.8"
|
||||||
description = "BanGUI backend — fail2ban web management interface"
|
description = "BanGUI backend — fail2ban web management interface"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
15
backend/tests/test_version.py
Normal file
15
backend/tests/test_version.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import app
|
||||||
|
|
||||||
|
|
||||||
|
def test_app_version_matches_docker_version() -> None:
|
||||||
|
"""The backend version should match the signed off Docker release version."""
|
||||||
|
|
||||||
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
|
version_file = repo_root / "Docker" / "VERSION"
|
||||||
|
expected = version_file.read_text(encoding="utf-8").strip().lstrip("v")
|
||||||
|
|
||||||
|
assert app.__version__ == expected
|
||||||
@@ -3,16 +3,19 @@ import react from "@vitejs/plugin-react";
|
|||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
const pkg = JSON.parse(
|
const appVersion = readFileSync(
|
||||||
readFileSync(resolve(__dirname, "package.json"), "utf-8"),
|
resolve(__dirname, "../Docker/VERSION"),
|
||||||
) as { version: string };
|
"utf-8",
|
||||||
|
)
|
||||||
|
.trim()
|
||||||
|
.replace(/^v/, "");
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
define: {
|
define: {
|
||||||
/** BanGUI application version injected at build time from package.json. */
|
/** BanGUI application version injected at build time from Docker/VERSION. */
|
||||||
__APP_VERSION__: JSON.stringify(pkg.version),
|
__APP_VERSION__: JSON.stringify(appVersion),
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||
Reference in New Issue
Block a user