-
Notifications
You must be signed in to change notification settings - Fork 4
feat: implement version management system with API for version info r… #187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Reviewer's Guide在前端和后端实现完整的版本管理系统(基于 semantic-release),通过新 API 暴露后端版本元数据,在 Web 应用的新「关于」设置页中展示版本状态,并将 CI/CD、Docker 和 pre-commit hooks 接入以强制执行提交规范,并在端到端流程中传递版本/构建信息。 前后端版本获取流程的时序图sequenceDiagram
actor User
participant Browser as Browser_UI
participant Frontend as Frontend_useVersion
participant Backend as Backend_API_system
participant VersionCore as Version_core_module
User->>Browser: Open_Settings_modal
Browser->>Frontend: Mount_SettingsModal
Frontend->>Frontend: useVersion_initialize
Frontend->>Frontend: getFrontendVersion
Frontend->>Backend: GET_/xyzen/api/v1/system/version
Backend->>VersionCore: get_version_info
VersionCore->>VersionCore: _get_version
VersionCore->>VersionCore: _get_commit
VersionCore->>VersionCore: _get_build_time
VersionCore-->>Backend: VersionInfo
Backend-->>Frontend: JSON_version_payload
Frontend->>Frontend: normalizeBackendVersion
Frontend->>Frontend: compareVersions(frontend,backend)
Frontend-->>Browser: Render_AboutSettings_with_status
Browser-->>User: Show_version_cards_and_status_banner
User->>Browser: Click_Refresh_button
Browser->>Frontend: Call_refresh_from_useVersion
Frontend->>Backend: GET_/xyzen/api/v1/system/version
Backend-->>Frontend: JSON_version_payload
Frontend->>Frontend: Update_status_and_re_render
跨前后端的版本信息类型类图classDiagram
class VersionInfo_py {
+str version
+str commit
+str build_time
+str backend
+to_dict() dict~str,str~
}
class VersionInfo_ts {
+string version
+string commit
+string buildTime
}
class BackendVersionInfo_ts {
+string version
+string commit
+string build_time
+string backend
}
class NormalizedVersionInfo_ts {
+string version
+string commit
+string buildTime
+boolean isLoaded
+boolean isError
}
class VersionUtils_ts {
+getFrontendVersion() VersionInfo_ts
+normalizeBackendVersion(data BackendVersionInfo_ts, isLoading boolean, isError boolean) NormalizedVersionInfo_ts
+compareVersions(frontend VersionInfo_ts, backend NormalizedVersionInfo_ts) VersionStatus_ts
+parseVersion(version string) ParsedVersion_ts
}
class ParsedVersion_ts {
+number major
+number minor
+number patch
+string prerelease
}
class VersionStatus_ts {
}
VersionInfo_py <.. get_version_info : returned_by
VersionInfo_py <.. system_router_version_endpoint : response_model
BackendVersionInfo_ts --> NormalizedVersionInfo_ts : normalized_to
VersionInfo_ts --> NormalizedVersionInfo_ts : compared_with
VersionUtils_ts ..> VersionInfo_ts : uses
VersionUtils_ts ..> BackendVersionInfo_ts : uses
VersionUtils_ts ..> NormalizedVersionInfo_ts : produces
VersionUtils_ts ..> VersionStatus_ts : returns
VersionUtils_ts ..> ParsedVersion_ts : returns
class useVersion_hook_ts {
-BackendVersionInfo_ts backendData
-boolean isLoading
-boolean isError
+useVersion() UseVersionResult_ts
}
class UseVersionResult_ts {
+VersionInfo_ts frontend
+NormalizedVersionInfo_ts backend
+VersionStatus_ts status
+boolean isLoading
+refresh() void
}
useVersion_hook_ts ..> VersionUtils_ts : calls
useVersion_hook_ts ..> UseVersionResult_ts : returns
文件级变更
提示与命令与 Sourcery 交互
自定义你的使用体验访问你的控制面板 以:
获取帮助Original review guide in EnglishReviewer's GuideImplements a full version management system across frontend and backend (semantic-release-based), exposes backend version metadata via a new API, surfaces version status in a new "About" settings page in the web app, and wires CI/CD, Docker, and pre-commit hooks to enforce commit conventions and propagate version/build information end-to-end. Sequence diagram for frontend-backend version retrieval flowsequenceDiagram
actor User
participant Browser as Browser_UI
participant Frontend as Frontend_useVersion
participant Backend as Backend_API_system
participant VersionCore as Version_core_module
User->>Browser: Open_Settings_modal
Browser->>Frontend: Mount_SettingsModal
Frontend->>Frontend: useVersion_initialize
Frontend->>Frontend: getFrontendVersion
Frontend->>Backend: GET_/xyzen/api/v1/system/version
Backend->>VersionCore: get_version_info
VersionCore->>VersionCore: _get_version
VersionCore->>VersionCore: _get_commit
VersionCore->>VersionCore: _get_build_time
VersionCore-->>Backend: VersionInfo
Backend-->>Frontend: JSON_version_payload
Frontend->>Frontend: normalizeBackendVersion
Frontend->>Frontend: compareVersions(frontend,backend)
Frontend-->>Browser: Render_AboutSettings_with_status
Browser-->>User: Show_version_cards_and_status_banner
User->>Browser: Click_Refresh_button
Browser->>Frontend: Call_refresh_from_useVersion
Frontend->>Backend: GET_/xyzen/api/v1/system/version
Backend-->>Frontend: JSON_version_payload
Frontend->>Frontend: Update_status_and_re_render
Class diagram for version information types across frontend and backendclassDiagram
class VersionInfo_py {
+str version
+str commit
+str build_time
+str backend
+to_dict() dict~str,str~
}
class VersionInfo_ts {
+string version
+string commit
+string buildTime
}
class BackendVersionInfo_ts {
+string version
+string commit
+string build_time
+string backend
}
class NormalizedVersionInfo_ts {
+string version
+string commit
+string buildTime
+boolean isLoaded
+boolean isError
}
class VersionUtils_ts {
+getFrontendVersion() VersionInfo_ts
+normalizeBackendVersion(data BackendVersionInfo_ts, isLoading boolean, isError boolean) NormalizedVersionInfo_ts
+compareVersions(frontend VersionInfo_ts, backend NormalizedVersionInfo_ts) VersionStatus_ts
+parseVersion(version string) ParsedVersion_ts
}
class ParsedVersion_ts {
+number major
+number minor
+number patch
+string prerelease
}
class VersionStatus_ts {
}
VersionInfo_py <.. get_version_info : returned_by
VersionInfo_py <.. system_router_version_endpoint : response_model
BackendVersionInfo_ts --> NormalizedVersionInfo_ts : normalized_to
VersionInfo_ts --> NormalizedVersionInfo_ts : compared_with
VersionUtils_ts ..> VersionInfo_ts : uses
VersionUtils_ts ..> BackendVersionInfo_ts : uses
VersionUtils_ts ..> NormalizedVersionInfo_ts : produces
VersionUtils_ts ..> VersionStatus_ts : returns
VersionUtils_ts ..> ParsedVersion_ts : returns
class useVersion_hook_ts {
-BackendVersionInfo_ts backendData
-boolean isLoading
-boolean isError
+useVersion() UseVersionResult_ts
}
class UseVersionResult_ts {
+VersionInfo_ts frontend
+NormalizedVersionInfo_ts backend
+VersionStatus_ts status
+boolean isLoading
+refresh() void
}
useVersion_hook_ts ..> VersionUtils_ts : calls
useVersion_hook_ts ..> UseVersionResult_ts : returns
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - 我发现了 5 个问题,并留下了一些总体反馈:
- 在 GitHub Actions 的发布工作流中,你将
XYZEN_VERSION作为 Docker 的构建参数传入,但service/Dockerfile里只定义了XYZEN_COMMIT_SHA和XYZEN_BUILD_TIME;请新增ARG XYZEN_VERSION和ENV XYZEN_VERSION=${XYZEN_VERSION},这样后端的_get_version()才能在容器中真正从环境变量读取版本信息。 useVersionhook 将后端 URL 写死为/xyzen/api/v1/system/version;建议复用你已有的 API 基础 URL/配置(或基于环境变量的 base path),以确保该端点在不同部署环境以及不同反向代理配置下都能正常工作。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the GitHub Actions release workflow you pass `XYZEN_VERSION` as a Docker build arg, but the `service/Dockerfile` only defines `XYZEN_COMMIT_SHA` and `XYZEN_BUILD_TIME`; add an `ARG XYZEN_VERSION` and `ENV XYZEN_VERSION=${XYZEN_VERSION}` so the backend’s `_get_version()` can actually read the version from the environment in containers.
- The `useVersion` hook hardcodes the backend URL as `/xyzen/api/v1/system/version`; consider reusing your existing API base URL/config (or an env-based base path) so this endpoint continues to work correctly in different deployment environments and behind varying reverse proxies.
## Individual Comments
### Comment 1
<location> `service/Dockerfile:18-23` </location>
<code_context>
ENV PYTHONUNBUFFERED=1
+# Build-time args for version info
+ARG XYZEN_COMMIT_SHA=unknown
+ARG XYZEN_BUILD_TIME=unknown
+
+# Set as environment variables for runtime
+ENV XYZEN_COMMIT_SHA=${XYZEN_COMMIT_SHA}
+ENV XYZEN_BUILD_TIME=${XYZEN_BUILD_TIME}
+
WORKDIR /app
</code_context>
<issue_to_address>
**issue (bug_risk):** XYZEN_VERSION build arg isn’t defined/propagated, so CI-provided versions are ignored at runtime
`XYZEN_VERSION` is passed as a build arg in CI and read from the environment in `version.py`, but the Dockerfile never declares or exports it—only `XYZEN_COMMIT_SHA` and `XYZEN_BUILD_TIME` are wired through. That means the runtime always falls back to the package/pyproject version instead of the CI-provided one. Please add `ARG XYZEN_VERSION` and `ENV XYZEN_VERSION=${XYZEN_VERSION}` so the image exposes the CI-injected release version.
</issue_to_address>
### Comment 2
<location> `web/src/components/modals/settings/AboutSettings.tsx:225-229` </location>
<code_context>
+ backend: NormalizedVersionInfo;
+}
+
+const VersionStatusBanner = ({
+ status,
+ frontend,
+ backend,
+}: VersionStatusBannerProps) => {
+ if (status === "unknown") {
+ return (
</code_context>
<issue_to_address>
**suggestion:** Status banner treats loading and error states the same, which can mislead users on permanent backend failures
`VersionStatusBanner` only handles `match`, `mismatch`, and `unknown`, and `unknown` always renders the "Checking version..." state. When the backend request fails, `compareVersions` still returns `"unknown"`, so users see a spinner even though the request has errored. Consider either adding an explicit `"error"` status, or passing `isError` into `VersionStatusBanner` and rendering a dedicated error message instead of the loading state when it’s true.
Suggested implementation:
```typescript
interface VersionStatusBannerProps {
status: "match" | "mismatch" | "unknown";
frontend: VersionInfo;
backend: NormalizedVersionInfo;
/**
* Indicates whether the version fetch request has failed.
* When true and status is "unknown", an error state is shown
* instead of the loading spinner.
*/
isError?: boolean;
}
```
```typescript
const VersionStatusBanner = ({
status,
frontend,
backend,
isError,
}: VersionStatusBannerProps) => {
if (status === "unknown" && !isError) {
return (
```
To fully implement the behavior described in your review comment, you should also:
1. Update all call sites of `VersionStatusBanner` in `AboutSettings.tsx` (and elsewhere, if reused) to pass an `isError` boolean derived from the version-fetching logic (for example, a React Query `isError`/`error` state or similar).
2. Inside the body of `VersionStatusBanner`, after the updated `if (status === "unknown" && !isError)` block, add a dedicated error UI branch (e.g. `if (status === "unknown" && isError) { return (<ErrorBanner ... />); }`) that renders an explicit error message instead of the loading spinner.
3. Ensure any helper such as `compareVersions` does not need to be changed for this approach, since the error state is now carried separately via `isError` rather than encoded into `status`.
</issue_to_address>
### Comment 3
<location> `web/src/hooks/useVersion.ts:41-49` </location>
<code_context>
+ if (!res.ok) throw new Error("Failed to fetch version");
+ const data: BackendVersionInfo = await res.json();
+ setBackendData(data);
+ } catch {
+ setIsError(true);
+ setBackendData(null);
+ } finally {
+ setIsLoading(false);
</code_context>
<issue_to_address>
**suggestion:** Swallowing fetch errors entirely makes debugging backend connectivity issues harder
The `catch` block marks an error and clears `backendData`, but loses all details about the failure. Consider at least logging the error (e.g., `console.error` or your logging/telemetry layer) so backend/CORS/version issues can be diagnosed without changing the user-facing UX.
```suggestion
try {
const res = await fetch("/xyzen/api/v1/system/version");
if (!res.ok) throw new Error("Failed to fetch version");
const data: BackendVersionInfo = await res.json();
setBackendData(data);
} catch (error) {
// Log details to aid debugging backend connectivity/CORS/version issues
console.error("Failed to fetch backend version", error);
setIsError(true);
setBackendData(null);
} finally {
```
</issue_to_address>
### Comment 4
<location> `docs/VERSION_MANAGEMENT.md:106` </location>
<code_context>
+# Install dependencies at repo root
+yarn install
+
+# Setup husky hooks (auto-runs on install)
+yarn husky install
+```
</code_context>
<issue_to_address>
**issue (typo):** Use "Set up" instead of "Setup" when using it as a verb.
Here it’s an imperative verb, so it should read: `# Set up husky hooks (auto-runs on install)`.
```suggestion
# Set up husky hooks (auto-runs on install)
```
</issue_to_address>
### Comment 5
<location> `web/src/components/modals/settings/AboutSettings.tsx:105` </location>
<code_context>
+ );
+};
+
+interface VersionCardProps {
+ type: "frontend" | "backend";
+ title: string;
</code_context>
<issue_to_address>
**issue (complexity):** Consider normalizing the version data shape, extracting shared utilities, and optionally splitting small presentational components to keep this settings modal simpler and easier to maintain.
You can simplify this without changing behavior by:
---
### 1. Normalize version data before rendering
`VersionCard` / `VersionDetails` currently have to deal with `VersionInfo | NormalizedVersionInfo` and runtime checks like `"isError" in info`. That’s UI-level complexity that can be removed by normalizing the shape in `useVersion` (or right before render) and using a single UI-facing type.
```ts
// Define a single UI-facing type
interface DisplayVersionInfo {
version: string;
commit?: string;
buildTime?: string;
isError?: boolean;
}
// In useVersion (or a small adapter in this file)
function toDisplayVersion(info: VersionInfo | NormalizedVersionInfo): DisplayVersionInfo {
return {
version: info.version,
commit: info.commit === "unknown" ? undefined : info.commit,
buildTime: "buildTime" in info && info.buildTime !== "unknown" ? info.buildTime : undefined,
isError: "isError" in info ? info.isError : false,
};
}
```
Then use that type in the UI:
```ts
// AboutSettings
const { frontend, backend, status, isLoading, refresh } = useVersion();
const frontendDisplay = toDisplayVersion(frontend);
const backendDisplay = toDisplayVersion(backend);
<VersionCard
type="frontend"
title={t("settings.about.frontend", "Frontend")}
info={frontendDisplay}
loading={false}
/>
<VersionCard
type="backend"
title={t("settings.about.backend", "Backend")}
info={backendDisplay}
loading={isLoading}
/>
```
```ts
// VersionCard
interface VersionCardProps {
type: "frontend" | "backend";
title: string;
info: DisplayVersionInfo;
loading: boolean;
}
const VersionCard = ({ type, title, info, loading }: VersionCardProps) => {
const { isError } = info;
// ...
{loading ? <LoadingSkeleton /> : isError ? <ErrorState /> : <VersionDetails info={info} type={type} />}
};
// VersionDetails
interface VersionDetailsProps {
info: DisplayVersionInfo;
type: "frontend" | "backend";
}
const VersionDetails = ({ info, type }: VersionDetailsProps) => {
const { version, commit, buildTime } = info;
// commit/buildTime already normalized, no "unknown" checks needed
};
```
This removes the unions and all `"in"` checks from the JSX layer.
---
### 2. Extract `formatRelativeTime` to a utility
`formatRelativeTime` is generic and doesn’t depend on React. Moving it out lets this file stay more presentational and shortens it.
```ts
// utils/date/formatRelativeTime.ts
export function formatRelativeTime(timestamp: string): string {
const date = new Date(timestamp);
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffSec = Math.floor(diffMs / 1000);
const diffMin = Math.floor(diffSec / 60);
const diffHour = Math.floor(diffMin / 60);
const diffDay = Math.floor(diffHour / 24);
if (diffDay > 30) return date.toLocaleDateString();
if (diffDay > 0) return `${diffDay} day${diffDay > 1 ? "s" : ""} ago`;
if (diffHour > 0) return `${diffHour} hour${diffHour > 1 ? "s" : ""} ago`;
if (diffMin > 0) return `${diffMin} min${diffMin > 1 ? "s" : ""} ago`;
return "just now";
}
```
```ts
// In AboutSettings.tsx (or wherever)
import { formatRelativeTime } from "@/utils/date/formatRelativeTime";
```
---
### 3. Small view‑model for `VersionStatusBanner`
You can keep the three visual states but centralize the mapping from `status` to copy and colors. That reduces branching in JSX and makes tweaks cheaper.
```ts
type VersionStatus = "match" | "mismatch" | "unknown";
const STATUS_COPY: Record<VersionStatus, { title: string; subtitle: string }> = {
unknown: {
title: "Checking version...",
subtitle: "Connecting to backend server",
},
match: {
title: "System is up to date",
subtitle: "Running the same version on all components",
},
mismatch: {
title: "Version Mismatch Detected",
subtitle: "Frontend and backend are running different versions.",
},
};
```
Then in `VersionStatusBanner`:
```tsx
const VersionStatusBanner = ({ status, frontend, backend }: VersionStatusBannerProps) => {
const copy = STATUS_COPY[status];
if (status === "unknown") {
// same layout, use copy.title / copy.subtitle
} else if (status === "match") {
// same layout, reuse copy.title / copy.subtitle
} else {
// mismatch layout, reuse copy.title / copy.subtitle
}
};
```
This keeps your existing visuals but reduces duplicated strings and makes the branching easier to scan.
---
### 4. Optionally split pure presentational pieces
If this file grows further, consider moving out the smallest pure components (`QuickLink`, `LoadingSkeleton`, `ErrorState`) into their own files:
```tsx
// components/settings/about/QuickLink.tsx
export const QuickLink = ({ href, icon, label }: QuickLinkProps) => (
// current JSX
);
```
This doesn’t change behavior but makes `AboutSettings` easier to scan and reduces the “many components in one file” issue.
</issue_to_address>帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进评审质量。
Original comment in English
Hey - I've found 5 issues, and left some high level feedback:
- In the GitHub Actions release workflow you pass
XYZEN_VERSIONas a Docker build arg, but theservice/Dockerfileonly definesXYZEN_COMMIT_SHAandXYZEN_BUILD_TIME; add anARG XYZEN_VERSIONandENV XYZEN_VERSION=${XYZEN_VERSION}so the backend’s_get_version()can actually read the version from the environment in containers. - The
useVersionhook hardcodes the backend URL as/xyzen/api/v1/system/version; consider reusing your existing API base URL/config (or an env-based base path) so this endpoint continues to work correctly in different deployment environments and behind varying reverse proxies.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the GitHub Actions release workflow you pass `XYZEN_VERSION` as a Docker build arg, but the `service/Dockerfile` only defines `XYZEN_COMMIT_SHA` and `XYZEN_BUILD_TIME`; add an `ARG XYZEN_VERSION` and `ENV XYZEN_VERSION=${XYZEN_VERSION}` so the backend’s `_get_version()` can actually read the version from the environment in containers.
- The `useVersion` hook hardcodes the backend URL as `/xyzen/api/v1/system/version`; consider reusing your existing API base URL/config (or an env-based base path) so this endpoint continues to work correctly in different deployment environments and behind varying reverse proxies.
## Individual Comments
### Comment 1
<location> `service/Dockerfile:18-23` </location>
<code_context>
ENV PYTHONUNBUFFERED=1
+# Build-time args for version info
+ARG XYZEN_COMMIT_SHA=unknown
+ARG XYZEN_BUILD_TIME=unknown
+
+# Set as environment variables for runtime
+ENV XYZEN_COMMIT_SHA=${XYZEN_COMMIT_SHA}
+ENV XYZEN_BUILD_TIME=${XYZEN_BUILD_TIME}
+
WORKDIR /app
</code_context>
<issue_to_address>
**issue (bug_risk):** XYZEN_VERSION build arg isn’t defined/propagated, so CI-provided versions are ignored at runtime
`XYZEN_VERSION` is passed as a build arg in CI and read from the environment in `version.py`, but the Dockerfile never declares or exports it—only `XYZEN_COMMIT_SHA` and `XYZEN_BUILD_TIME` are wired through. That means the runtime always falls back to the package/pyproject version instead of the CI-provided one. Please add `ARG XYZEN_VERSION` and `ENV XYZEN_VERSION=${XYZEN_VERSION}` so the image exposes the CI-injected release version.
</issue_to_address>
### Comment 2
<location> `web/src/components/modals/settings/AboutSettings.tsx:225-229` </location>
<code_context>
+ backend: NormalizedVersionInfo;
+}
+
+const VersionStatusBanner = ({
+ status,
+ frontend,
+ backend,
+}: VersionStatusBannerProps) => {
+ if (status === "unknown") {
+ return (
</code_context>
<issue_to_address>
**suggestion:** Status banner treats loading and error states the same, which can mislead users on permanent backend failures
`VersionStatusBanner` only handles `match`, `mismatch`, and `unknown`, and `unknown` always renders the "Checking version..." state. When the backend request fails, `compareVersions` still returns `"unknown"`, so users see a spinner even though the request has errored. Consider either adding an explicit `"error"` status, or passing `isError` into `VersionStatusBanner` and rendering a dedicated error message instead of the loading state when it’s true.
Suggested implementation:
```typescript
interface VersionStatusBannerProps {
status: "match" | "mismatch" | "unknown";
frontend: VersionInfo;
backend: NormalizedVersionInfo;
/**
* Indicates whether the version fetch request has failed.
* When true and status is "unknown", an error state is shown
* instead of the loading spinner.
*/
isError?: boolean;
}
```
```typescript
const VersionStatusBanner = ({
status,
frontend,
backend,
isError,
}: VersionStatusBannerProps) => {
if (status === "unknown" && !isError) {
return (
```
To fully implement the behavior described in your review comment, you should also:
1. Update all call sites of `VersionStatusBanner` in `AboutSettings.tsx` (and elsewhere, if reused) to pass an `isError` boolean derived from the version-fetching logic (for example, a React Query `isError`/`error` state or similar).
2. Inside the body of `VersionStatusBanner`, after the updated `if (status === "unknown" && !isError)` block, add a dedicated error UI branch (e.g. `if (status === "unknown" && isError) { return (<ErrorBanner ... />); }`) that renders an explicit error message instead of the loading spinner.
3. Ensure any helper such as `compareVersions` does not need to be changed for this approach, since the error state is now carried separately via `isError` rather than encoded into `status`.
</issue_to_address>
### Comment 3
<location> `web/src/hooks/useVersion.ts:41-49` </location>
<code_context>
+ if (!res.ok) throw new Error("Failed to fetch version");
+ const data: BackendVersionInfo = await res.json();
+ setBackendData(data);
+ } catch {
+ setIsError(true);
+ setBackendData(null);
+ } finally {
+ setIsLoading(false);
</code_context>
<issue_to_address>
**suggestion:** Swallowing fetch errors entirely makes debugging backend connectivity issues harder
The `catch` block marks an error and clears `backendData`, but loses all details about the failure. Consider at least logging the error (e.g., `console.error` or your logging/telemetry layer) so backend/CORS/version issues can be diagnosed without changing the user-facing UX.
```suggestion
try {
const res = await fetch("/xyzen/api/v1/system/version");
if (!res.ok) throw new Error("Failed to fetch version");
const data: BackendVersionInfo = await res.json();
setBackendData(data);
} catch (error) {
// Log details to aid debugging backend connectivity/CORS/version issues
console.error("Failed to fetch backend version", error);
setIsError(true);
setBackendData(null);
} finally {
```
</issue_to_address>
### Comment 4
<location> `docs/VERSION_MANAGEMENT.md:106` </location>
<code_context>
+# Install dependencies at repo root
+yarn install
+
+# Setup husky hooks (auto-runs on install)
+yarn husky install
+```
</code_context>
<issue_to_address>
**issue (typo):** Use "Set up" instead of "Setup" when using it as a verb.
Here it’s an imperative verb, so it should read: `# Set up husky hooks (auto-runs on install)`.
```suggestion
# Set up husky hooks (auto-runs on install)
```
</issue_to_address>
### Comment 5
<location> `web/src/components/modals/settings/AboutSettings.tsx:105` </location>
<code_context>
+ );
+};
+
+interface VersionCardProps {
+ type: "frontend" | "backend";
+ title: string;
</code_context>
<issue_to_address>
**issue (complexity):** Consider normalizing the version data shape, extracting shared utilities, and optionally splitting small presentational components to keep this settings modal simpler and easier to maintain.
You can simplify this without changing behavior by:
---
### 1. Normalize version data before rendering
`VersionCard` / `VersionDetails` currently have to deal with `VersionInfo | NormalizedVersionInfo` and runtime checks like `"isError" in info`. That’s UI-level complexity that can be removed by normalizing the shape in `useVersion` (or right before render) and using a single UI-facing type.
```ts
// Define a single UI-facing type
interface DisplayVersionInfo {
version: string;
commit?: string;
buildTime?: string;
isError?: boolean;
}
// In useVersion (or a small adapter in this file)
function toDisplayVersion(info: VersionInfo | NormalizedVersionInfo): DisplayVersionInfo {
return {
version: info.version,
commit: info.commit === "unknown" ? undefined : info.commit,
buildTime: "buildTime" in info && info.buildTime !== "unknown" ? info.buildTime : undefined,
isError: "isError" in info ? info.isError : false,
};
}
```
Then use that type in the UI:
```ts
// AboutSettings
const { frontend, backend, status, isLoading, refresh } = useVersion();
const frontendDisplay = toDisplayVersion(frontend);
const backendDisplay = toDisplayVersion(backend);
<VersionCard
type="frontend"
title={t("settings.about.frontend", "Frontend")}
info={frontendDisplay}
loading={false}
/>
<VersionCard
type="backend"
title={t("settings.about.backend", "Backend")}
info={backendDisplay}
loading={isLoading}
/>
```
```ts
// VersionCard
interface VersionCardProps {
type: "frontend" | "backend";
title: string;
info: DisplayVersionInfo;
loading: boolean;
}
const VersionCard = ({ type, title, info, loading }: VersionCardProps) => {
const { isError } = info;
// ...
{loading ? <LoadingSkeleton /> : isError ? <ErrorState /> : <VersionDetails info={info} type={type} />}
};
// VersionDetails
interface VersionDetailsProps {
info: DisplayVersionInfo;
type: "frontend" | "backend";
}
const VersionDetails = ({ info, type }: VersionDetailsProps) => {
const { version, commit, buildTime } = info;
// commit/buildTime already normalized, no "unknown" checks needed
};
```
This removes the unions and all `"in"` checks from the JSX layer.
---
### 2. Extract `formatRelativeTime` to a utility
`formatRelativeTime` is generic and doesn’t depend on React. Moving it out lets this file stay more presentational and shortens it.
```ts
// utils/date/formatRelativeTime.ts
export function formatRelativeTime(timestamp: string): string {
const date = new Date(timestamp);
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffSec = Math.floor(diffMs / 1000);
const diffMin = Math.floor(diffSec / 60);
const diffHour = Math.floor(diffMin / 60);
const diffDay = Math.floor(diffHour / 24);
if (diffDay > 30) return date.toLocaleDateString();
if (diffDay > 0) return `${diffDay} day${diffDay > 1 ? "s" : ""} ago`;
if (diffHour > 0) return `${diffHour} hour${diffHour > 1 ? "s" : ""} ago`;
if (diffMin > 0) return `${diffMin} min${diffMin > 1 ? "s" : ""} ago`;
return "just now";
}
```
```ts
// In AboutSettings.tsx (or wherever)
import { formatRelativeTime } from "@/utils/date/formatRelativeTime";
```
---
### 3. Small view‑model for `VersionStatusBanner`
You can keep the three visual states but centralize the mapping from `status` to copy and colors. That reduces branching in JSX and makes tweaks cheaper.
```ts
type VersionStatus = "match" | "mismatch" | "unknown";
const STATUS_COPY: Record<VersionStatus, { title: string; subtitle: string }> = {
unknown: {
title: "Checking version...",
subtitle: "Connecting to backend server",
},
match: {
title: "System is up to date",
subtitle: "Running the same version on all components",
},
mismatch: {
title: "Version Mismatch Detected",
subtitle: "Frontend and backend are running different versions.",
},
};
```
Then in `VersionStatusBanner`:
```tsx
const VersionStatusBanner = ({ status, frontend, backend }: VersionStatusBannerProps) => {
const copy = STATUS_COPY[status];
if (status === "unknown") {
// same layout, use copy.title / copy.subtitle
} else if (status === "match") {
// same layout, reuse copy.title / copy.subtitle
} else {
// mismatch layout, reuse copy.title / copy.subtitle
}
};
```
This keeps your existing visuals but reduces duplicated strings and makes the branching easier to scan.
---
### 4. Optionally split pure presentational pieces
If this file grows further, consider moving out the smallest pure components (`QuickLink`, `LoadingSkeleton`, `ErrorState`) into their own files:
```tsx
// components/settings/about/QuickLink.tsx
export const QuickLink = ({ href, icon, label }: QuickLinkProps) => (
// current JSX
);
```
This doesn’t change behavior but makes `AboutSettings` easier to scan and reduces the “many components in one file” issue.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements a comprehensive version management system for Xyzen using semantic-release automation. The system provides automated version bumping, changelog generation, and synchronized versioning across frontend and backend components, along with a new "About" settings page displaying version information.
Changes:
- Implemented semantic-release automation with conventional commits for fully automated version management
- Added version API endpoint (
/api/v1/system/version) and UI display in Settings → About page - Integrated commitlint pre-commit hooks to enforce conventional commit message format
Reviewed changes
Copilot reviewed 24 out of 28 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
web/vite.config.mts |
Added build-time version injection from package.json and git commit info |
web/src/vite-env.d.ts |
Added type declarations for version-related global constants |
web/src/types/version.ts |
Implemented version types, utility functions for normalization and comparison |
web/src/hooks/useVersion.ts |
Created hook for fetching and comparing frontend/backend versions |
web/src/components/modals/settings/AboutSettings.tsx |
Implemented new About settings page with version display and status indicators |
web/src/components/modals/SettingsModal.tsx |
Integrated About category into settings modal |
web/src/components/modals/settings/index.ts |
Updated exports to include AboutSettings and McpSettings |
web/src/i18n/locales/zh/settings.json |
Updated Chinese translations for settings categories |
web/src/i18n/locales/en/settings.json |
Updated English translations for settings categories |
web/package.json |
Added bumpp dependency for version management |
service/app/core/version.py |
Created version info module with multi-source version resolution |
service/app/api/v1/system.py |
Implemented system version API endpoint |
service/app/api/v1/__init__.py |
Registered system router and changed redemption path to /business |
service/pyproject.toml |
Updated version to 0.4.4 |
service/uv.lock |
Updated lock file with new version |
service/Dockerfile |
Added build args for commit SHA and build time |
scripts/sync-version.mjs |
Created script to sync version from package.json to pyproject.toml |
package.json |
Added root package.json with semantic-release dependencies |
.releaserc.json |
Configured semantic-release with conventional commits rules |
commitlint.config.mjs |
Configured commit message linting rules |
.pre-commit-config.yaml |
Added commitlint pre-commit hook |
.github/workflows/release.yaml |
Created automated release workflow with Docker build and deployment |
.github/workflows/prod-build.yaml |
Removed old manual production build workflow |
CHANGELOG.md |
Initialized changelog file |
docs/VERSION_MANAGEMENT.md |
Added comprehensive documentation for version management system |
.yarnrc.yml |
Configured yarn to use node-modules linker |
.gitignore |
Added .yarn/ to ignored files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
xinquiry
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent
## 1.0.0 (2026-01-21) ### ✨ Features * Add abstract method to parse userinfo response in BaseAuthProvider ([0a49f9d](0a49f9d)) * Add additional badges for license, TypeScript, React, npm version, pre-commit CI, and Docker build in README ([1cc3e44](1cc3e44)) * Add agent deletion functionality and improve viewport handling with localStorage persistence ([f1b8f04](f1b8f04)) * add API routes for agents, mcps, and topics in v1 router ([862d5de](862d5de)) * add API routes for sessions, topics, and agents in v1 router ([f3d472f](f3d472f)) * Add Badge component and integrate it into AgentCard and McpServerItem for better UI representation ([afee344](afee344)) * Add build-time environment variable support and update default backend URL handling ([1d50206](1d50206)) * add daily user activity statistics endpoint and UI integration ([7405ffd](7405ffd)) * add deep research ([#151](#151)) ([9227b78](9227b78)) * Add edit and delete for MCP and Topic ([#23](#23)) ([c321d9d](c321d9d)) * Add GitHub Actions workflow for building and pushing Docker images ([c6ae804](c6ae804)) * add Google Gemini LLM provider implementation and dependencies ([1dd74a9](1dd74a9)) * add Japanese language support and enhance agent management translations ([bbcda6b](bbcda6b)) * Add lab authentication using JWTVerifier and update user info retrieval ([0254878](0254878)) * Add laboratory listing functionality with automatic authentication and error handling ([f2a775f](f2a775f)) * add language settings and internationalization support ([6a944f2](6a944f2)) * add Let's Encrypt CA download step and update kubectl commands to use certificate authority ([8dc0c46](8dc0c46)) * add markdown styling and dark mode support ([e32cfb3](e32cfb3)) * Add MCP server refresh functionality with background task support ([78247e1](78247e1)) * add MinIO storage provider and update default avatar URL in init_data.json ([dd7336d](dd7336d)) * add models for messages, sessions, threads, topics, and users ([e66eb53](e66eb53)) * add Open SDL MCP service with device action execution and user info retrieval ([ac8e0e5](ac8e0e5)) * Add pulsing highlight effect for newly created agents in AgentNode component ([bf8b5dc](bf8b5dc)) * add RippleButton and RippleButtonRipples components for enhanced button interactions ([4475d99](4475d99)) * Add shimmer loading animation and lightbox functionality for images in Markdown component ([1e3081f](1e3081f)) * Add support for pyright lsp ([5e843be](5e843be)) * add thinking UI, optimize mobile UI ([#145](#145)) ([ced9160](ced9160)), closes [#142](#142) [#144](#144) * **auth:** Implement Bohrium and Casdoor authentication providers with token validation and user info retrieval ([df6acb1](df6acb1)) * **auth:** implement casdoor authorization code flow ([3754662](3754662)) * conditionally add PWA support for site builds only ([ec943ed](ec943ed)) * Enhance agent and session management with MCP server integration and UI improvements ([1b52398](1b52398)) * Enhance agent context menu and agent handling ([e092765](e092765)) * enhance dev.ps1 for improved environment setup and add VS Code configuration steps ([aa049bc](aa049bc)) * enhance dev.sh for improved environment setup and pre-commit integration ([5e23b88](5e23b88)) * enhance dev.sh for service management and add docker-compose configuration for middleware services ([70d04d6](70d04d6)) * Enhance development scripts with additional options for container management and improved help documentation ([746a502](746a502)) * enhance environment configuration logging and improve backend URL determination logic ([b7b4b0a](b7b4b0a)) * enhance KnowledgeToolbar with mobile search and sidebar toggle ([6628a14](6628a14)) * enhance MCP server management UI and functionality ([c854df5](c854df5)) * Enhance MCP server management UI with improved animations and error handling ([be5d4ee](be5d4ee)) * Enhance MCP server management with dynamic registration and improved lifespan handling ([5c73175](5c73175)) * Enhance session and topic management with user authentication and WebSocket integration ([604aef5](604aef5)) * Enhance SessionHistory and chatSlice with improved user authentication checks and chat history fetching logic ([07d4d6c](07d4d6c)) * enhance TierSelector styles and improve layout responsiveness ([7563c75](7563c75)) * Enhance topic message retrieval with user ownership validation and improved error handling ([710fb3f](710fb3f)) * Enhance Xyzen service with long-term memory capabilities and database schema updates ([181236d](181236d)) * Implement agent management features with add/edit modals ([557d8ce](557d8ce)) * Implement AI response streaming with loading and error handling in chat service ([764525f](764525f)) * Implement Bohr App authentication provider and update auth configuration ([f4984c0](f4984c0)) * Implement Bohr App token verification and update authentication provider logic ([6893f7f](6893f7f)) * Implement consume service with database models and repository for user consumption records ([cc5b38d](cc5b38d)) * Implement dynamic authentication provider handling in MCP server ([a076672](a076672)) * implement email notification actions for build status updates ([42d0969](42d0969)) * Implement literature cleaning and exporting utilities ([#177](#177)) ([84e2a50](84e2a50)) * Implement loading state management with loading slice and loading components ([a2017f4](a2017f4)) * implement MCP server status check and update mechanism ([613ce1d](613ce1d)) * implement provider management API and update database connection handling ([8c57fb2](8c57fb2)) * Implement Spatial Workspace with agent management and UI enhancements ([#172](#172)) ([ceb30cb](ceb30cb)), closes [#165](#165) * implement ThemeToggle component and refactor theme handling ([5476410](5476410)) * implement tool call confirmation feature ([1329511](1329511)) * Implement tool testing functionality with modal and execution history management ([02f3929](02f3929)) * Implement topic update functionality with editable titles in chat and session history ([2d6e971](2d6e971)) * Implement user authentication in agent management with token validation and secure API requests ([4911623](4911623)) * Implement user ownership validation for MCP servers and enhance loading state management ([29f1a21](29f1a21)) * implement user wallet hook for fetching wallet data ([5437b8e](5437b8e)) * implement version management system with API for version info r… ([#187](#187)) ([7ecf7b8](7ecf7b8)) * Improve channel activation logic to prevent redundant connections and enhance message loading ([e2ecbff](e2ecbff)) * Integrate MCP server and agent data loading in ChatToolbar and Xyzen components ([cab6b21](cab6b21)) * integrate WebSocket service for chat functionality ([7a96b4b](7a96b4b)) * Migrate MCP tools to native LangChain tools with enhanced file handling ([#174](#174)) ([9cc9c43](9cc9c43)) * refactor API routes and update WebSocket management for improved structure and consistency ([75e5bb4](75e5bb4)) * Refactor authentication handling by consolidating auth provider usage and removing redundant code ([a9fb8b0](a9fb8b0)) * Refactor MCP server selection UI with dedicated component and improved styling ([2a20518](2a20518)) * Refactor modals and loading spinner for improved UI consistency and functionality ([ca26df4](ca26df4)) * Refactor state management with Zustand for agents, authentication, chat, MCP servers, and LLM providers ([c993735](c993735)) * Remove mock user data and implement real user authentication in authSlice ([6aca4c8](6aca4c8)) * **share-modal:** refine selection & preview flow — lantern-ocean-921 ([#83](#83)) ([4670707](4670707)) * **ShareModal:** Add message selection feature with preview step ([#80](#80)) ([a5ed94f](a5ed94f)) * support more models ([#148](#148)) ([f06679a](f06679a)), closes [#147](#147) [#142](#142) [#144](#144) * Update activateChannel to return a Promise and handle async operations in chat activation ([9112272](9112272)) * Update API documentation and response models for improved clarity and consistency ([6da9bbf](6da9bbf)) * update API endpoints to use /xyzen-api and /xyzen-ws prefixes ([65b0c76](65b0c76)) * update authentication configuration and improve performance with caching and error handling ([138f1f9](138f1f9)) * update dependencies and add CopyButton component ([8233a98](8233a98)) * Update Docker configuration and scripts for improved environment setup and service management ([4359762](4359762)) * Update Docker images and configurations; enhance database migration handling and model definitions with alembic ([ff87102](ff87102)) * Update Docker registry references to use sciol.ac.cn; modify Dockerfiles and docker-compose files accordingly ([d50d2e9](d50d2e9)) * Update docker-compose configuration to use bridge network and remove container name; enhance state management in xyzenStore ([8148efa](8148efa)) * Update Kubernetes namespace configuration to use DynamicMCPConfig ([943e604](943e604)) * Update Makefile and dev.ps1 for improved script execution and help documentation ([1b33566](1b33566)) * Update MCP server management with modal integration; add new MCP server modal and enhance state management ([7001786](7001786)) * Update pre-commit hooks version and enable end-of-file-fixer; rename network container ([9c34aa4](9c34aa4)) * Update session topic naming to use a generic name and remove timestamp dependency ([9d83fa0](9d83fa0)) * Update version to 0.1.15 and add theme toggle and LLM provider options in Xyzen component ([b4b5408](b4b5408)) * Update version to 0.1.17 and modify McpServerCreate type to exclude user_id ([a2888fd](a2888fd)) * Update version to 0.2.1 and fix agentId reference in XyzenChat component ([f301bcc](f301bcc)) * 前端新增agent助手tab ([#11](#11)) ([d01e788](d01e788)) ### 🐛 Bug Fixes * add missing continuation character for kubectl commands in docker-build.yaml ([f6d2fee](f6d2fee)) * add subType field with user_id value in init_data.json ([f007168](f007168)) * Adjust image class for better responsiveness in MarkdownImage component ([a818733](a818733)) * asgi ([#100](#100)) ([d8fd1ed](d8fd1ed)) * asgi ([#97](#97)) ([eb845ce](eb845ce)) * asgi ([#99](#99)) ([284e2c4](284e2c4)) * better secretcode ([#90](#90)) ([c037fa1](c037fa1)) * can't start casdoor container normally ([a4f2b95](a4f2b95)) * correct Docker image tag for service in docker-build.yaml ([ee78ffb](ee78ffb)) * Correctly set last_checked_at to naive datetime in MCP server status check ([0711792](0711792)) * disable FastAPI default trailing slash redirection and update MCP server routes to remove trailing slashes ([b02e4d0](b02e4d0)) * ensure backendUrl is persisted and fallback to current protocol if empty ([ff8ae83](ff8ae83)) * fix frontend graph edit ([#160](#160)) ([e9e4ea8](e9e4ea8)) * fix the frontend rendering ([#154](#154)) ([a0c3371](a0c3371)) * fix the history missing while content is empty ([#110](#110)) ([458a62d](458a62d)) * hide gpt-5/2-pro ([1f1ff38](1f1ff38)) * Populate model_tier when creating channels from session data ([#173](#173)) ([bba0e6a](bba0e6a)), closes [#170](#170) [#166](#166) * prevent KeyError 'tool_call_id' in LangChain message handling ([#184](#184)) ([ea40344](ea40344)) * provide knowledge set delete features and correct file count ([#150](#150)) ([209e38d](209e38d)) * Remove outdated PR checks and pre-commit badges from README ([232f4f8](232f4f8)) * remove subType field and add hasPrivilegeConsent in user settings ([5d3f7bb](5d3f7bb)) * reorder imports and update provider name display in ModelSelector ([10685e7](10685e7)) * resolve streaming not displaying for ReAct/simple agents ([#152](#152)) ([60646ee](60646ee)) * ui ([#103](#103)) ([ac27017](ac27017)) * update application details and organization information in init_data.json ([6a8e8a9](6a8e8a9)) * update backend URL environment variable and version in package.json; refactor environment checks in index.ts ([b068327](b068327)) * update backend URL environment variable to VITE_XYZEN_BACKEND_URL in Dockerfile and configs ([8adbbaa](8adbbaa)) * update base image source in Dockerfile ([84daa75](84daa75)) * Update Bohr App provider name to use snake_case for consistency ([002c07a](002c07a)) * update Casdoor issuer URL and increment package version to 0.2.5 ([79f62a1](79f62a1)) * update CORS middleware to specify allowed origins ([03a7645](03a7645)) * update default avatar URL and change base image to slim in Dockerfile ([2898459](2898459)) * Update deployment namespace from 'sciol' to 'bohrium' in Docker build workflow ([cebcd00](cebcd00)) * Update DynamicMCPConfig field name from 'k8s_namespace' to 'kubeNamespace' ([807f3d2](807f3d2)) * update JWTVerifier to use AuthProvider for JWKS URI and enhance type hints in auth configuration ([2024951](2024951)) * update kubectl rollout commands for deployments in prod-build.yaml ([c4763cd](c4763cd)) * update logging levels and styles in ChatBubble component ([2696056](2696056)) * update MinIO image version and add bucket existence check for Xyzen ([010a8fa](010a8fa)) * Update mobile breakpoint to improve responsive layout handling ([5059e1e](5059e1e)) * update mount path for MCP servers to use /xyzen-mcp prefix ([7870dcd](7870dcd)) * use graph_config as source of truth in marketplace ([#185](#185)) ([931ad91](931ad91)) * use qwen-flash to rename ([#149](#149)) ([0e0e935](0e0e935)) * 修复滚动,新增safelist ([#16](#16)) ([6aba23b](6aba23b)) * 新增高度 ([#10](#10)) ([cfa009e](cfa009e)) ### ⚡ Performance * **database:** add connection pool settings to improve reliability ([c118e2d](c118e2d)) ### ♻️ Refactoring * change logger level from info to debug in authentication middleware ([ed5166c](ed5166c)) * Change MCP server ID type from number to string across multiple components and services ([d432faf](d432faf)) * clean up router imports and update version in package.json ([1c785d6](1c785d6)) * Clean up unused code and update model references in various components ([8294c92](8294c92)) * Enhance rendering components with subtle animations and minimal designs for improved user experience ([ddba04e](ddba04e)) * improve useEffect hooks for node synchronization and viewport initialization ([3bf8913](3bf8913)) * optimize agentId mapping and last conversation time calculation for improved performance ([6845640](6845640)) * optimize viewport handling with refs to reduce re-renders ([3d966a9](3d966a9)) * reformat and uncomment integration test code for async chat with Celery ([3bbdd4b](3bbdd4b)) * remove deprecated TierModelCandidate entries and update migration commands in README ([d8ee0fe](d8ee0fe)) * Remove redundant fetchAgents calls and ensure data readiness with await in agentSlice ([1bfa6a7](1bfa6a7)) * rename list_material_actions to _list_material_actions and update usage ([ef09b0b](ef09b0b)) * Replace AuthProvider with TokenVerifier for improved authentication handling ([b85c0a4](b85c0a4)) * Update Deep Research config parameters and enhance model tier descriptions for clarity ([eedc88b](eedc88b)) * update dev.ps1 script for improved clarity and streamline service management ([8288cc2](8288cc2)) * update docker-compose configuration to streamline service definitions and network settings ([ebfa0a3](ebfa0a3)) * update documentation and remove deprecated Dify configurations ([add8699](add8699)) * update GitHub token in release workflow ([9413b70](9413b70)) * update PWA icon references and remove unused icon files ([473e82a](473e82a))
…etrieval
变更内容
简要描述本次 PR 的主要变更内容。
相关 Issue
请关联相关 Issue(如有):#编号
检查清单
默认已勾选,如不满足,请检查。
其他说明
如有特殊说明或注意事项,请补充。
Summary by Sourcery
在前端和后端引入基于 semantic-release 的自动化版本管理系统,通过 API 暴露后端版本元数据,在设置界面中新增 “关于(About)” 区域展示版本信息,并将版本信息接入构建和部署流水线。
New Features:
/api/v1/system/version接口,由一个集中式的版本信息模块提供支持,该模块读取版本号、提交记录和构建时间。Enhancements:
Build:
CI:
Documentation:
VERSION_MANAGEMENT.md中记录版本管理与发布流程,包括提交规范、CI/CD,以及故障排查。Chores:
package.json、变更日志、Yarn 配置和发布配置,以支持新的版本管理流程。Original summary in English
Summary by Sourcery
Introduce an automated semantic-release-based version management system across frontend and backend, expose backend version metadata via API, surface version information in a new About section in the settings UI, and wire versions into build and deployment pipelines.
New Features:
Enhancements:
Build:
CI:
Documentation:
Chores: