perf: 增加稳定版,预览版区分,预览版是最新版,稳定版在预览版验证稳定后,再将预览版转为稳定版

This commit is contained in:
xiaojunnuo
2026-07-17 00:58:19 +08:00
parent 85e9ff7a96
commit 15740904e5
16 changed files with 402 additions and 17 deletions
+2 -1
View File
@@ -1,4 +1,4 @@
ARG base_type=alpine
ARG base_type=alpine
# 根据 base_type 参数选择基础镜像系列
FROM --platform=linux/amd64 node:22-alpine AS base-amd64-alpine
@@ -99,6 +99,7 @@ RUN ARCH=$(uname -m) && \
ENV TZ=Asia/Shanghai
ENV NODE_ENV=production
ENV certd_release_mode=latest
ENV MIDWAY_SERVER_ENV=production
RUN npm install -g pnpm@10.33.4
@@ -25,5 +25,7 @@ export default {
expiringCerts: "Soon-to-Expire Certificates",
supportedTasks: "Overview of Supported Deployment Tasks",
changeLog: "Change Log",
stableRelease: "Stable",
latestRelease: "Preview",
},
};
@@ -26,5 +26,7 @@ export default {
expiringCerts: "最快到期证书",
supportedTasks: "已支持的部署任务总览",
changeLog: "更新日志",
stableRelease: "稳定版",
latestRelease: "预览版",
},
};
@@ -11,6 +11,7 @@ export type AppInfo = {
version?: string;
time?: number;
deltaTime?: number;
releaseMode?: string;
};
export type SiteInfo = {
title?: string;
@@ -35,6 +35,7 @@ export interface SettingState {
version?: string;
time?: number;
deltaTime?: number;
releaseMode?: string;
};
productInfo: {
notice?: string;
@@ -109,6 +110,7 @@ export const useSettingStore = defineStore({
version: "",
time: 0,
deltaTime: 0,
releaseMode: "latest",
},
productInfo: {
notice: "",
@@ -229,6 +231,9 @@ export const useSettingStore = defineStore({
this.app.time = appInfo.time;
this.app.version = appInfo.version;
this.app.deltaTime = new Date().getTime() - this.app.time;
if (appInfo.releaseMode) {
this.app.releaseMode = appInfo.releaseMode;
}
},
initSiteInfo(siteInfo: SiteInfo) {
//@ts-ignore
@@ -1,4 +1,4 @@
<template>
<template>
<div class="dashboard-user">
<div class="header-profile flex-wrap bg-white dark:bg-black">
<div class="flex flex-1">
@@ -23,9 +23,9 @@
<template v-if="userStore.isAdmin">
<a-divider type="vertical" />
<a-badge :dot="hasNewVersion">
<a-tag color="blue" class="flex-inline pointer mr-0" :title="t('certd.dashboard.latestVersion', { version: latestVersion })" @click="openUpgradeUrl()">
<a-tag color="blue" class="flex-inline pointer mr-0" :title="'v' + version + ' ' + (settingsStore.app.releaseMode === 'stable' ? '稳定版' : '预览版')" @click="openUpgradeUrl()">
<fs-icon icon="ion:rocket-outline" class="mr-5"></fs-icon>
v{{ version }}
v{{ version }}-{{ settingsStore.app.releaseMode }}
</a-tag>
</a-badge>
<a-divider type="vertical" />
@@ -179,7 +179,6 @@ defineOptions({
const version = ref(import.meta.env.VITE_APP_VERSION);
const latestVersion = ref("");
function isNewVersion(version: string, latestVersion: string) {
if (!latestVersion) {
return false;
+2 -1
View File
@@ -1,3 +1,4 @@
LEGO_VERSION=4.30.1
JKS_GO_VERSION=1.0.3
certd_plugin_loadmode=dev
certd_plugin_loadmode=dev
certd_release_mode=stable
@@ -3,7 +3,7 @@
import assert from "node:assert/strict";
import { normalizeReleaseVersion } from "./app-controller.js";
import { getReleaseMode, normalizeReleaseVersion } from "./app-controller.js";
describe("AppController.normalizeReleaseVersion", () => {
it("normalizes AtomGit release tag names", () => {
@@ -15,3 +15,29 @@ describe("AppController.normalizeReleaseVersion", () => {
assert.equal(normalizeReleaseVersion({ name: "v1.40.0" }), "1.40.0");
});
});
describe("AppController.getReleaseMode", () => {
it("returns 'latest' when env var is not set", () => {
delete process.env.certd_release_mode;
assert.equal(getReleaseMode(), "latest");
});
it("returns 'latest' when env var is empty", () => {
process.env.certd_release_mode = "";
assert.equal(getReleaseMode(), "latest");
});
it("returns 'stable' when env var is 'stable'", () => {
process.env.certd_release_mode = "stable";
assert.equal(getReleaseMode(), "stable");
});
it("returns 'latest' when env var is an unknown value", () => {
process.env.certd_release_mode = "unknown";
assert.equal(getReleaseMode(), "latest");
});
after(() => {
delete process.env.certd_release_mode;
});
});
@@ -8,6 +8,10 @@ export function normalizeReleaseVersion(release: { tag_name?: string; name?: str
return version.replace(/^v/i, "");
}
export function getReleaseMode(): "stable" | "latest" {
return process.env.certd_release_mode === "stable" ? "stable" : "latest";
}
/**
*/
@Provide()
@@ -20,14 +24,30 @@ export class AppController extends BaseController {
@Get("/latest", { description: Constants.per.authOnly })
async latest(): Promise<any> {
const mode = getReleaseMode();
try {
const res = await http.request({
url: "https://api.atomgit.com/api/v5/repos/certd/certd/releases/latest",
method: "get",
logRes: false,
timeout: 5000,
});
const latest = normalizeReleaseVersion(res);
let latest = "";
if (mode === "stable") {
// 稳定版: 查询被设为 latest 的正式版本
const res = await http.request({
url: "https://api.atomgit.com/api/v5/repos/certd/certd/releases/latest?type=latest",
method: "get",
logRes: false,
timeout: 5000,
});
latest = normalizeReleaseVersion(res);
} else {
// 预览版: 获取最新一条 release(可能包含 pre-release
const list = await http.request({
url: "https://api.atomgit.com/api/v5/repos/certd/certd/releases/?direction=desc&per_page=1",
method: "get",
logRes: false,
timeout: 5000,
});
if (Array.isArray(list) && list.length > 0) {
latest = normalizeReleaseVersion(list[0]);
}
}
return this.ok(latest);
} catch (e: any) {
logger.error(e);
@@ -5,6 +5,7 @@ import { SysInviteCommissionSetting } from "@certd/commercial-core";
import { cloneDeep } from "lodash-es";
import { getVersion } from "../../utils/version.js";
import { http } from "@certd/basic";
import { getReleaseMode } from "./app-controller.js";
/**
*/
@@ -108,6 +109,7 @@ export class BasicSettingsController extends BaseController {
app: {
time: new Date().getTime(),
version,
releaseMode: getReleaseMode(),
},
});
}