Add CalVer build-time version tracking
- Dockerfile: ARG BUILD_VERSION=dev → ENV APP_VERSION baked into image
- ci.yml: BUILD_VERSION passed as build-arg; set to git tag name on v*
tag builds, "dev" on branch builds
- routes/api.py: GET /api/version returns {"version": APP_VERSION}
- SettingsView: fetches /api/version on mount, displays in About section
under General tab
Version source of truth is the git tag (YY.MM.DD.N CalVer).
pyproject.toml / package.json versions are no longer maintained.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -104,18 +104,21 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Generate image tags
|
||||
- name: Generate image tags and version
|
||||
id: tags
|
||||
run: |
|
||||
TAGS="${{ env.IMAGE }}:${{ github.sha }}"
|
||||
BUILD_VERSION="dev"
|
||||
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
|
||||
TAGS="$TAGS,${{ env.IMAGE }}:latest"
|
||||
elif [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then
|
||||
TAGS="$TAGS,${{ env.IMAGE }}:dev"
|
||||
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||
TAGS="$TAGS,${{ env.IMAGE }}:latest,${{ env.IMAGE }}:${{ github.ref_name }}"
|
||||
BUILD_VERSION="${{ github.ref_name }}"
|
||||
fi
|
||||
echo "value=$TAGS" >> $GITHUB_OUTPUT
|
||||
echo "build_version=$BUILD_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
@@ -133,5 +136,6 @@ jobs:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.tags.outputs.value }}
|
||||
build-args: BUILD_VERSION=${{ steps.tags.outputs.build_version }}
|
||||
cache-from: type=registry,ref=${{ env.IMAGE }}:cache
|
||||
cache-to: type=registry,ref=${{ env.IMAGE }}:cache,mode=max
|
||||
|
||||
@@ -21,5 +21,10 @@ COPY alembic/ alembic/
|
||||
# Ensure Python finds the source tree (where static files live) before site-packages
|
||||
ENV PYTHONPATH=/app/src
|
||||
|
||||
# Version is injected at build time via --build-arg BUILD_VERSION=YY.MM.DD.N
|
||||
# Falls back to "dev" for local / untagged builds
|
||||
ARG BUILD_VERSION=dev
|
||||
ENV APP_VERSION=$BUILD_VERSION
|
||||
|
||||
EXPOSE 5000
|
||||
CMD ["sh", "-c", "alembic upgrade head && hypercorn 'fabledassistant.app:create_app()' --bind 0.0.0.0:5000 --keep-alive 600"]
|
||||
|
||||
@@ -28,6 +28,7 @@ const saving = ref(false);
|
||||
const saved = ref(false);
|
||||
const exporting = ref(false);
|
||||
const restoring = ref(false);
|
||||
const appVersion = ref('dev');
|
||||
const restoreFileInput = ref<HTMLInputElement | null>(null);
|
||||
|
||||
// Migrate stored "admin" → "config"; unknown tabs fall back to "general"
|
||||
@@ -176,6 +177,10 @@ const searchLoading = ref(false);
|
||||
const searchError = ref("");
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const v = await apiGet<{ version: string }>('/api/version')
|
||||
appVersion.value = v.version
|
||||
} catch { /* non-critical */ }
|
||||
await store.fetchSettings();
|
||||
pushStore.checkSubscription();
|
||||
assistantName.value = store.assistantName;
|
||||
@@ -1031,6 +1036,11 @@ function formatUserDate(iso: string): string {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="settings-section full-width">
|
||||
<h2>About</h2>
|
||||
<p class="version-line">Fabled Assistant <span class="version-badge">{{ appVersion }}</span></p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ── Integrations ── -->
|
||||
@@ -2206,6 +2216,25 @@ function formatUserDate(iso: string): string {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* ── About / version ─────────────────────────────────────────── */
|
||||
.version-line {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-text-secondary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
.version-badge {
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.15rem 0.5rem;
|
||||
background: var(--color-bg-secondary);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
/* ── Groups tab ──────────────────────────────────────────────── */
|
||||
.btn-primary {
|
||||
padding: 0.4rem 0.9rem;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import os
|
||||
|
||||
from quart import Blueprint, jsonify
|
||||
|
||||
api = Blueprint("api", __name__, url_prefix="/api")
|
||||
@@ -6,3 +8,8 @@ api = Blueprint("api", __name__, url_prefix="/api")
|
||||
@api.route("/health")
|
||||
async def health():
|
||||
return jsonify({"status": "ok"})
|
||||
|
||||
|
||||
@api.route("/version")
|
||||
async def version():
|
||||
return jsonify({"version": os.environ.get("APP_VERSION", "dev")})
|
||||
|
||||
Reference in New Issue
Block a user