diff --git a/Dockerfile b/Dockerfile index baab160..3ac3f90 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,7 +32,8 @@ COPY static/ ./static/ ARG GIT_COMMIT=unknown ARG GIT_BRANCH=unknown ARG GIT_COMMIT_DATE=unknown -RUN echo "{\"commit\": \"$GIT_COMMIT\", \"branch\": \"$GIT_BRANCH\", \"date\": \"$GIT_COMMIT_DATE\"}" > /app/version.json +ARG GIT_TAG=unknown +RUN echo "{\"tag\": \"$GIT_TAG\", \"commit\": \"$GIT_COMMIT\", \"branch\": \"$GIT_BRANCH\", \"date\": \"$GIT_COMMIT_DATE\"}" > /app/version.json # Allow git to operate in the /app-source volume (owner may differ from container user) RUN git config --global --add safe.directory /app-source diff --git a/app/services/update_service.py b/app/services/update_service.py index 37541d0..1ba811c 100644 --- a/app/services/update_service.py +++ b/app/services/update_service.py @@ -22,21 +22,23 @@ def get_current_version() -> dict: try: data = json.loads(Path(VERSION_FILE).read_text()) return { + "tag": data.get("tag", "unknown"), "commit": data.get("commit", "unknown"), "branch": data.get("branch", "unknown"), "date": data.get("date", "unknown"), } except Exception: - return {"commit": "unknown", "branch": "unknown", "date": "unknown"} + return {"tag": "unknown", "commit": "unknown", "branch": "unknown", "date": "unknown"} async def check_for_updates(config: Any) -> dict: - """Query the Gitea API for the latest commit on the configured branch. + """Query the Gitea API for the latest tag and commit on the configured branch. Parses the repo URL to build the Gitea API endpoint: https://git.example.com/owner/repo - → https://git.example.com/api/v1/repos/owner/repo/branches/{branch} + → https://git.example.com/api/v1/repos/owner/repo/... + Uses tags for version comparison when available, falls back to commit SHAs. Returns dict with current, latest, needs_update, and optional error. """ current = get_current_version() @@ -62,7 +64,8 @@ async def check_for_updates(config: Any) -> dict: owner = parts[-2] repo = parts[-1] branch = config.git_branch or "main" - api_url = f"{base_url}/api/v1/repos/{owner}/{repo}/branches/{branch}" + branch_api = f"{base_url}/api/v1/repos/{owner}/{repo}/branches/{branch}" + tags_api = f"{base_url}/api/v1/repos/{owner}/{repo}/tags?limit=1" headers = {} if config.git_token: @@ -70,7 +73,8 @@ async def check_for_updates(config: Any) -> dict: try: async with httpx.AsyncClient(timeout=10) as client: - resp = await client.get(api_url, headers=headers) + # Fetch branch info (latest commit) + resp = await client.get(branch_api, headers=headers) if resp.status_code != 200: return { "current": current, @@ -82,20 +86,39 @@ async def check_for_updates(config: Any) -> dict: latest_commit = data.get("commit", {}) full_sha = latest_commit.get("id", "unknown") short_sha = full_sha[:8] if full_sha != "unknown" else "unknown" + + # Fetch latest tag + latest_tag = "unknown" + try: + tag_resp = await client.get(tags_api, headers=headers) + if tag_resp.status_code == 200: + tags = tag_resp.json() + if tags and len(tags) > 0: + latest_tag = tags[0].get("name", "unknown") + except Exception: + pass # Tag fetch is best-effort + latest = { + "tag": latest_tag, "commit": short_sha, "commit_full": full_sha, "message": latest_commit.get("commit", {}).get("message", "").split("\n")[0], "date": latest_commit.get("commit", {}).get("committer", {}).get("date", ""), "branch": branch, } + + # Determine if update is needed: prefer tag comparison, fallback to commit + current_tag = current.get("tag", "unknown") current_sha = current.get("commit", "unknown") - needs_update = ( - current_sha != "unknown" - and short_sha != "unknown" - and current_sha != short_sha - and not full_sha.startswith(current_sha) - ) + if current_tag != "unknown" and latest_tag != "unknown": + needs_update = current_tag != latest_tag + else: + needs_update = ( + current_sha != "unknown" + and short_sha != "unknown" + and current_sha != short_sha + and not full_sha.startswith(current_sha) + ) return {"current": current, "latest": latest, "needs_update": needs_update} except Exception as exc: return { diff --git a/docker-compose.yml b/docker-compose.yml index f972e6c..66e8c67 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,6 +44,7 @@ services: GIT_COMMIT: ${GIT_COMMIT:-unknown} GIT_BRANCH: ${GIT_BRANCH:-unknown} GIT_COMMIT_DATE: ${GIT_COMMIT_DATE:-unknown} + GIT_TAG: ${GIT_TAG:-unknown} container_name: netbird-msp-appliance restart: unless-stopped security_opt: @@ -71,7 +72,7 @@ services: networks: - npm-network healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"] + test: [ "CMD", "curl", "-f", "http://localhost:8000/api/health" ] interval: 30s timeout: 10s retries: 3 diff --git a/static/js/app.js b/static/js/app.js index 2510f94..9a81af8 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -1214,24 +1214,31 @@ async function loadVersionInfo() { const latest = data.latest; const needsUpdate = data.needs_update; + const currentTag = current.tag && current.tag !== 'unknown' ? current.tag : null; + const currentCommit = current.commit || 'unknown'; + let html = `
${t('settings.currentVersion')}
-
${esc(current.commit || 'unknown')}
+
${esc(currentTag || currentCommit)}
+ ${currentTag ? `
${t('settings.commitHash')}: ${esc(currentCommit)}
` : ''}
${t('settings.branch')}: ${esc(current.branch || 'unknown')}
${esc(current.date || '')}
`; if (latest) { + const latestTag = latest.tag && latest.tag !== 'unknown' ? latest.tag : null; + const latestCommit = latest.commit || 'unknown'; const badge = needsUpdate ? `${t('settings.updateAvailable')}` : `${t('settings.upToDate')}`; html += `
${t('settings.latestVersion')} ${badge}
-
${esc(latest.commit || 'unknown')}
+
${esc(latestTag || latestCommit)}
+ ${latestTag ? `
${t('settings.commitHash')}: ${esc(latestCommit)}
` : ''}
${t('settings.branch')}: ${esc(latest.branch || 'unknown')}
${esc(latest.message || '')}
${esc(latest.date || '')}
diff --git a/static/lang/de.json b/static/lang/de.json index 383a0fc..8fa0250 100644 --- a/static/lang/de.json +++ b/static/lang/de.json @@ -214,6 +214,7 @@ "currentVersion": "Installierte Version", "latestVersion": "Neueste verfügbare Version", "branch": "Branch", + "commitHash": "Commit", "updateAvailable": "Update verfügbar", "upToDate": "Aktuell", "triggerUpdate": "Update starten", @@ -369,4 +370,4 @@ "thContainers": "Container", "noCustomers": "Keine Kunden." } -} +} \ No newline at end of file diff --git a/static/lang/en.json b/static/lang/en.json index 0dd40f4..e0bff54 100644 --- a/static/lang/en.json +++ b/static/lang/en.json @@ -235,6 +235,7 @@ "currentVersion": "Installed Version", "latestVersion": "Latest Available", "branch": "Branch", + "commitHash": "Commit", "updateAvailable": "Update Available", "upToDate": "Up to date", "triggerUpdate": "Start Update", diff --git a/update.sh b/update.sh index 2e166b5..e97aef5 100755 --- a/update.sh +++ b/update.sh @@ -38,9 +38,11 @@ echo "✓ Code updated to: $(git log --oneline -1)" export GIT_COMMIT=$(git rev-parse HEAD) export GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) export GIT_COMMIT_DATE=$(git log -1 --format=%cI) +export GIT_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "unknown") echo "" echo "Building with:" +echo " GIT_TAG = $GIT_TAG" echo " GIT_COMMIT = $GIT_COMMIT" echo " GIT_BRANCH = $GIT_BRANCH" echo " GIT_COMMIT_DATE = $GIT_COMMIT_DATE"