mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 19:06:34 +00:00
fix(release): surface build versions
This commit is contained in:
parent
3ffaf780e3
commit
3d5e27bdfb
8 changed files with 59 additions and 8 deletions
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
|
|
@ -81,6 +81,7 @@ jobs:
|
||||||
working-directory: kiosk
|
working-directory: kiosk
|
||||||
env:
|
env:
|
||||||
BF_BUILD_ARCH: ${{ matrix.target }}
|
BF_BUILD_ARCH: ${{ matrix.target }}
|
||||||
|
BF_BUILD_VERSION: ${{ inputs.version }}
|
||||||
run: cargo build --release --target ${{ matrix.target }}
|
run: cargo build --release --target ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Strip + rename
|
- name: Strip + rename
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# BetterFrame server image — Node 23 + native deps for argon2/sqlite.
|
# BetterFrame server image — Node 24 + native deps for argon2/sqlite.
|
||||||
# Trixie base (Debian 13, latest stable) — matches the host distro we
|
# Trixie base (Debian 13, latest stable) — matches the host distro we
|
||||||
# recommend in deploy/README.md.
|
# recommend in deploy/README.md.
|
||||||
FROM node:23-trixie-slim AS builder
|
FROM node:24-trixie-slim AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
@ -22,7 +22,9 @@ WORKDIR /app/server
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# ---- Runtime image ----
|
# ---- Runtime image ----
|
||||||
FROM node:23-trixie-slim
|
FROM node:24-trixie-slim
|
||||||
|
|
||||||
|
ARG BF_SERVER_VERSION=
|
||||||
|
|
||||||
# ffmpeg for camera snapshot capture (optional but needed for /admin/entities/:id/snapshot)
|
# ffmpeg for camera snapshot capture (optional but needed for /admin/entities/:id/snapshot)
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
|
@ -51,5 +53,6 @@ USER betterframe
|
||||||
WORKDIR /app/server
|
WORKDIR /app/server
|
||||||
|
|
||||||
ENV NODE_OPTIONS=--import=tsx
|
ENV NODE_OPTIONS=--import=tsx
|
||||||
|
ENV BF_SERVER_VERSION=${BF_SERVER_VERSION}
|
||||||
|
|
||||||
CMD ["node", "--import", "tsx", "/app/node_modules/@bsb/base/lib/scripts/bsb-plugin-cli.js", "start"]
|
CMD ["node", "--import", "tsx", "/app/node_modules/@bsb/base/lib/scripts/bsb-plugin-cli.js", "start"]
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: deploy/docker/Dockerfile.server
|
dockerfile: deploy/docker/Dockerfile.server
|
||||||
|
args:
|
||||||
|
BF_SERVER_VERSION: ${BF_SERVER_VERSION:-}
|
||||||
container_name: betterframe-server
|
container_name: betterframe-server
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -25,6 +27,9 @@ services:
|
||||||
- BF_SQLITE_PATH=/var/lib/betterframe/betterframe.db
|
- BF_SQLITE_PATH=/var/lib/betterframe/betterframe.db
|
||||||
- BF_NODERED_URL=http://nodered:1880
|
- BF_NODERED_URL=http://nodered:1880
|
||||||
- BF_SELF_URL=http://server:18080
|
- BF_SELF_URL=http://server:18080
|
||||||
|
- BF_SERVER_VERSION=${BF_SERVER_VERSION:-}
|
||||||
|
- COOLIFY_GIT_COMMIT=${COOLIFY_GIT_COMMIT:-}
|
||||||
|
- SOURCE_COMMIT=${SOURCE_COMMIT:-}
|
||||||
volumes:
|
volumes:
|
||||||
- betterframe-data:/var/lib/betterframe
|
- betterframe-data:/var/lib/betterframe
|
||||||
expose:
|
expose:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: deploy/docker/Dockerfile.server
|
dockerfile: deploy/docker/Dockerfile.server
|
||||||
|
args:
|
||||||
|
BF_SERVER_VERSION: ${BF_SERVER_VERSION:-}
|
||||||
container_name: betterframe-server
|
container_name: betterframe-server
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# Env overrides win over sec-config.yaml — Coolify / k8s inject these.
|
# Env overrides win over sec-config.yaml — Coolify / k8s inject these.
|
||||||
|
|
@ -36,6 +38,9 @@ services:
|
||||||
- BF_SQLITE_PATH=/var/lib/betterframe/betterframe.db
|
- BF_SQLITE_PATH=/var/lib/betterframe/betterframe.db
|
||||||
- BF_NODERED_URL=http://nodered:1880
|
- BF_NODERED_URL=http://nodered:1880
|
||||||
- BF_SELF_URL=http://server:18080
|
- BF_SELF_URL=http://server:18080
|
||||||
|
- BF_SERVER_VERSION=${BF_SERVER_VERSION:-}
|
||||||
|
- COOLIFY_GIT_COMMIT=${COOLIFY_GIT_COMMIT:-}
|
||||||
|
- SOURCE_COMMIT=${SOURCE_COMMIT:-}
|
||||||
# Optional: paste Ed25519 PEM private key here for firmware signing.
|
# Optional: paste Ed25519 PEM private key here for firmware signing.
|
||||||
# - BF_FIRMWARE_SIGNING_KEY=
|
# - BF_FIRMWARE_SIGNING_KEY=
|
||||||
# Optional: single-purpose Bearer token for GitHub Actions firmware import.
|
# Optional: single-purpose Bearer token for GitHub Actions firmware import.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ use tracing::info;
|
||||||
|
|
||||||
use crate::bundle::KioskBundle;
|
use crate::bundle::KioskBundle;
|
||||||
|
|
||||||
|
fn kiosk_app_version() -> &'static str {
|
||||||
|
option_env!("BF_BUILD_VERSION").unwrap_or(env!("CARGO_PKG_VERSION"))
|
||||||
|
}
|
||||||
|
|
||||||
fn state_dir() -> PathBuf {
|
fn state_dir() -> PathBuf {
|
||||||
let home = dirs::home_dir().expect("no home directory");
|
let home = dirs::home_dir().expect("no home directory");
|
||||||
let dir = home.join(".betterframe-kiosk");
|
let dir = home.join(".betterframe-kiosk");
|
||||||
|
|
@ -258,9 +262,13 @@ pub fn heartbeat(
|
||||||
hw: &crate::hwmon::HwInfo,
|
hw: &crate::hwmon::HwInfo,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let client = reqwest::blocking::Client::new();
|
let client = reqwest::blocking::Client::new();
|
||||||
let display_info: Vec<_> = displays.iter().enumerate().map(|(index, (name, w, h))| {
|
let display_info: Vec<_> = displays
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, (name, w, h))| {
|
||||||
serde_json::json!({ "index": index, "name": name, "width_px": w, "height_px": h })
|
serde_json::json!({ "index": index, "name": name, "width_px": w, "height_px": h })
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
// Surface the LAN-side local key + port to admin so the UI can show a
|
// Surface the LAN-side local key + port to admin so the UI can show a
|
||||||
// copy-paste URL for bookmark-style layout switches.
|
// copy-paste URL for bookmark-style layout switches.
|
||||||
let local_key = load_or_create_local_key();
|
let local_key = load_or_create_local_key();
|
||||||
|
|
@ -272,7 +280,7 @@ pub fn heartbeat(
|
||||||
.post(format!("{server}/api/kiosk/heartbeat"))
|
.post(format!("{server}/api/kiosk/heartbeat"))
|
||||||
.header("Authorization", format!("Bearer {key}"))
|
.header("Authorization", format!("Bearer {key}"))
|
||||||
.json(&serde_json::json!({
|
.json(&serde_json::json!({
|
||||||
"kiosk_app_version": env!("CARGO_PKG_VERSION"),
|
"kiosk_app_version": kiosk_app_version(),
|
||||||
"displays": display_info,
|
"displays": display_info,
|
||||||
"cpu_temp_c": hw.cpu_temp_c,
|
"cpu_temp_c": hw.cpu_temp_c,
|
||||||
"cpu_load_percent": hw.cpu_load_percent,
|
"cpu_load_percent": hw.cpu_load_percent,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import { initNoderedBridge, type NoderedBridge } from "../../shared/nodered-brid
|
||||||
import { initFirmware, type FirmwareApi } from "../../shared/firmware.js";
|
import { initFirmware, type FirmwareApi } from "../../shared/firmware.js";
|
||||||
import { initOsUpdates, type OsUpdateApi } from "../../shared/os-updates.js";
|
import { initOsUpdates, type OsUpdateApi } from "../../shared/os-updates.js";
|
||||||
import { envStr } from "../../shared/env-overrides.js";
|
import { envStr } from "../../shared/env-overrides.js";
|
||||||
|
import { serverVersion } from "../../shared/version.js";
|
||||||
import type { Repository } from "../service-store/repository.js";
|
import type { Repository } from "../service-store/repository.js";
|
||||||
|
|
||||||
import { registerMiddleware } from "./middleware.js";
|
import { registerMiddleware } from "./middleware.js";
|
||||||
|
|
@ -207,7 +208,7 @@ export class Plugin extends BSBService<InstanceType<typeof Config>, typeof Event
|
||||||
});
|
});
|
||||||
app.get("/version", () => ({
|
app.get("/version", () => ({
|
||||||
name: "betterframe",
|
name: "betterframe",
|
||||||
version: "0.1.0",
|
version: serverVersion(),
|
||||||
now: new Date().toISOString(),
|
now: new Date().toISOString(),
|
||||||
}));
|
}));
|
||||||
app.get("/", () => {
|
app.get("/", () => {
|
||||||
|
|
|
||||||
9
server/src/shared/version.ts
Normal file
9
server/src/shared/version.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
export function serverVersion(): string {
|
||||||
|
return (
|
||||||
|
process.env.BF_SERVER_VERSION
|
||||||
|
|| process.env.BF_BUILD_VERSION
|
||||||
|
|| process.env.COOLIFY_GIT_COMMIT
|
||||||
|
|| process.env.SOURCE_COMMIT
|
||||||
|
|| "dev"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
* Server-side rendered via jsx-htmx — returns string.
|
* Server-side rendered via jsx-htmx — returns string.
|
||||||
*/
|
*/
|
||||||
import { css, js } from "jsx-htmx";
|
import { css, js } from "jsx-htmx";
|
||||||
|
import { serverVersion } from "../shared/version.js";
|
||||||
|
|
||||||
// ---- Shared types -----------------------------------------------------------
|
// ---- Shared types -----------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -64,6 +65,7 @@ function Sidebar(props: { activeNav?: string }) {
|
||||||
// ---- Layout -----------------------------------------------------------------
|
// ---- Layout -----------------------------------------------------------------
|
||||||
|
|
||||||
export function Layout(props: PageProps) {
|
export function Layout(props: PageProps) {
|
||||||
|
const version = serverVersion();
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
|
@ -92,6 +94,12 @@ export function Layout(props: PageProps) {
|
||||||
<div class={`flash flash-${props.flash.type}`}>{props.flash.message}</div>
|
<div class={`flash flash-${props.flash.type}`}>{props.flash.message}</div>
|
||||||
)}
|
)}
|
||||||
<main class="content">{props.children}</main>
|
<main class="content">{props.children}</main>
|
||||||
|
{!props.minimal && (
|
||||||
|
<footer class="app-footer">
|
||||||
|
<span>Copyright BetterCorp (PTY) Ltd 2016 - 2026 - All Rights Reserved</span>
|
||||||
|
<span>Server: <code>{version}</code></span>
|
||||||
|
</footer>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/htmx.min.js"></script>
|
<script src="/static/htmx.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
@ -176,6 +184,17 @@ const baseStyles = {
|
||||||
".topbar-user": { color: "#666", fontSize: "0.85rem" },
|
".topbar-user": { color: "#666", fontSize: "0.85rem" },
|
||||||
".main-wrap": { display: "flex", flexDirection: "column", minHeight: "100vh" },
|
".main-wrap": { display: "flex", flexDirection: "column", minHeight: "100vh" },
|
||||||
".content": { flex: "1", padding: "1.5rem" },
|
".content": { flex: "1", padding: "1.5rem" },
|
||||||
|
".app-footer": {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
gap: "1rem",
|
||||||
|
padding: "0.75rem 1.5rem",
|
||||||
|
color: "#666",
|
||||||
|
fontSize: "0.8rem",
|
||||||
|
borderTop: "1px solid #e0e0e0",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
},
|
||||||
|
".app-footer code": { color: "#374151", fontSize: "0.8rem" },
|
||||||
".minimal .content": { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh" },
|
".minimal .content": { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh" },
|
||||||
".center-card": { width: "100%", maxWidth: "420px" },
|
".center-card": { width: "100%", maxWidth: "420px" },
|
||||||
".auth-logo": { display: "block", width: "220px", maxWidth: "100%", height: "auto", margin: "0 0 1.25rem" },
|
".auth-logo": { display: "block", width: "220px", maxWidth: "100%", height: "auto", margin: "0 0 1.25rem" },
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue