versioning
This commit is contained in:
5
Jenkinsfile
vendored
5
Jenkinsfile
vendored
@@ -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
12
config/version.py
Normal 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
30
docker-compose.yml
Normal 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: {}
|
||||
7
main.py
7
main.py
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user