versioning

This commit is contained in:
2025-12-14 23:20:51 -05:00
parent 596cb97a28
commit 68a4f1800c
5 changed files with 81 additions and 4 deletions

5
Jenkinsfile vendored
View File

@@ -10,6 +10,7 @@ pipeline {
VUE_CONTAINER_NAME = "chore-app-frontend"
FLASK_CONTAINER_NAME = "chore-app-backend"
NETWORK_NAME = "chore-app-net"
BASE_VERSION = '1.0.0'
}
stages {
@@ -32,8 +33,7 @@ pipeline {
stage('Build Backend (Flask) App') {
steps {
dir('.') {
sh 'docker build -t ${BACKEND_IMAGE} .'
sh 'docker tag ${BACKEND_IMAGE} ${BACKEND_IMAGE_LATEST}'
sh """docker build --build-arg APP_BUILD=${BUILD_NUMBER} -t chore-app-backend:${BASE_VERSION} -t chore-app-backend:${BASE_VERSION}-${BUILD_NUMBER} -t chore-app-backend:latest ."""
}
}
}
@@ -65,6 +65,7 @@ pipeline {
docker run -d \\
--name ${FLASK_CONTAINER_NAME} \\
--network ${NETWORK_NAME} \\
-e BUILD_NUMBER=${BUILD_NUMBER} \\
-v ${FLASK_CONTAINER_NAME}_data:/app/data \\
${BACKEND_IMAGE_LATEST}
"""

12
config/version.py Normal file
View File

@@ -0,0 +1,12 @@
# python
# file: config/version.py
import os
BASE_VERSION = "1.0.0" # update manually when releasing features
def get_full_version() -> str:
"""
Return semantic version with optional Jenkins build metadata, e.g. 1.2.3+build.456.
"""
build = os.environ.get("BUILD_NUMBER") or os.environ.get("APP_BUILD")
return f"{BASE_VERSION}+build.{build}" if build else BASE_VERSION

30
docker-compose.yml Normal file
View File

@@ -0,0 +1,30 @@
# yaml
version: '3.8'
services:
chore-app-backend:
image: devserver.lan:5900/chore-app-backend:production
container_name: chore-app-backend
restart: unless-stopped
expose:
- "5000"
networks:
- chore-app-net
volumes:
- chore-app-backend-data:/app/data # persists backend data
chore-app-frontend:
image: devserver.lan:5900/chore-app-frontend:production
container_name: chore-app-frontend
restart: unless-stopped
ports:
- "4600:443"
networks:
- chore-app-net
networks:
chore-app-net:
driver: bridge
volumes:
chore-app-backend-data: {}

View File

@@ -1,12 +1,13 @@
import sys, logging, os
from config.paths import get_user_image_dir
from flask import Flask, request
from flask import Flask, request, jsonify
from flask_cors import CORS
from api.child_api import child_api
from api.image_api import image_api
from api.reward_api import reward_api
from api.task_api import task_api
from config.version import get_full_version
from events.broadcaster import Broadcaster
from events.sse import sse_response_for_user, send_to_user
from db.default import initializeImages
@@ -29,6 +30,10 @@ app.register_blueprint(task_api)
app.register_blueprint(image_api)
CORS(app)
@app.route("/version")
def api_version():
return jsonify({"version": get_full_version()})
@app.route("/events")
def events():
# Authenticate user or read a token

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router'
import { computed } from 'vue'
import { computed, ref, onMounted } from 'vue'
import LoginButton from '../components/LoginButton.vue'
const router = useRouter()
@@ -23,6 +23,20 @@ const showBack = computed(
route.name === 'NotificationView'
),
)
// Version fetching
const appVersion = ref('')
onMounted(async () => {
try {
const resp = await fetch('/api/version')
if (resp.ok) {
const data = await resp.json()
appVersion.value = data.version || ''
}
} catch (e) {
appVersion.value = ''
}
})
</script>
<template>
@@ -142,6 +156,8 @@ const showBack = computed(
<main class="main-content">
<router-view />
</main>
<div v-if="appVersion" class="app-version">v{{ appVersion }}</div>
</div>
</template>
@@ -251,6 +267,19 @@ const showBack = computed(
align-self: start;
}
.app-version {
position: fixed;
right: 18px;
bottom: 12px;
font-size: 0.92rem;
color: #cbd5e1; /* Brighter slate-200 */
opacity: 0.85;
z-index: 100;
pointer-events: none;
user-select: none;
font-family: monospace;
}
@media (max-width: 480px) {
.back-btn {
padding: 0.45rem 0.75rem;