fix: persist system update history
Release / release (push) Canceled after 0s

This commit is contained in:
Qiufeng
2026-08-19 00:22:23 +08:00
parent 1230116a6f
commit 12d9c46323
12 changed files with 465 additions and 25 deletions
+29 -4
View File
@@ -1,7 +1,13 @@
import type { Page, Route } from '@playwright/test';
import { expect, test } from '@playwright/test';
const permissions = ['admin:user:view', 'admin:user:create', 'admin:update:view', 'admin:update:execute'];
const permissions = [
'admin:user:view',
'admin:user:create',
'admin:update:view',
'admin:update:execute',
'audit:log:view',
];
function envelope(data: unknown) {
return { data, requestId: '01M00000000000000000000090' };
@@ -111,8 +117,13 @@ async function installFixture(
let state = recoveryPending ? 'RECOVERY_REQUIRED' : initialState || 'IDLE';
let progressDeadline = 0;
let restartDeadline = 0;
let terminalHistoryRecorded = false;
const history: Array<Record<string, unknown>> = [];
const recordHistory = (actionCode: string, targetVersion = '1.0.0-preview.2') => {
const recordHistory = (
actionCode: string,
targetVersion = '1.0.0-preview.2',
reason = actionCode === 'SYSTEM_UPDATE_REQUEST' ? '管理员确认立即更新并重启' : null,
) => {
history.unshift({
publicId: `01M00000000000000000000${String(history.length + 1).padStart(3, '0')}`,
eventSequence: history.length + 1,
@@ -123,9 +134,12 @@ async function installFixture(
objectType: 'SYSTEM_UPDATE',
objectPublicId: 'SYSTEM_UPDATE',
resultCode: 'SUCCESS',
reason: actionCode === 'SYSTEM_UPDATE_REQUEST' ? '管理员确认立即更新并重启' : null,
reason,
beforeJson: null,
afterJson: JSON.stringify({ targetVersion }),
afterJson: JSON.stringify({
targetVersion,
...(actionCode === 'SYSTEM_UPDATE_SUCCEEDED' ? { state: 'SUCCEEDED' } : {}),
}),
occurredAt: '2026-08-16T00:02:00Z',
allowedActions: [],
});
@@ -156,6 +170,10 @@ async function installFixture(
return route.abort('connectionrefused');
}
if (state === 'RUNNING' && restartDeadline > 0) state = 'SUCCEEDED';
if (state === 'SUCCEEDED' && !terminalHistoryRecorded) {
recordHistory('SYSTEM_UPDATE_SUCCEEDED', '1.0.0-preview.2', '新版本已通过健康检查');
terminalHistoryRecorded = true;
}
const response = updateView(state, checked, enabled, recoveryPending);
if (state === 'DOWNLOADING' && Date.now() >= progressDeadline) state = 'READY';
if (completeBusyAfterFirstRead && state === 'INSTALLING') state = 'SUCCEEDED';
@@ -192,6 +210,9 @@ async function installFixture(
return route.fulfill({ json: envelope(queued) });
}
if (pathname === '/api/v1/audit/logs' && request.method() === 'GET') {
const query = new URL(request.url()).searchParams;
expect(query.get('occurredFrom')).toBe('1970-01-01T00:00:00Z');
expect(query.get('objectType')).toBe('SYSTEM_UPDATE');
return route.fulfill({
json: {
data: history,
@@ -393,6 +414,10 @@ test('successful installation starts the ten-second automatic refresh countdown'
await expect(page.getByText('新版本已通过健康检查,页面将在 10 秒后自动刷新。', { exact: true })).toBeVisible({
timeout: 5_000,
});
const historyPanel = page.locator('.history-panel');
const completedRow = historyPanel.locator('tr').filter({ hasText: '更新完成' });
await expect(completedRow).toContainText('1.0.0-preview.2');
await expect(completedRow).toContainText('新版本已通过健康检查');
});
test('reloading during installation resumes polling and starts the refresh countdown', async ({ page }) => {
@@ -111,7 +111,7 @@
<div class="section-heading">
<div>
<h2>历史更新记录</h2>
<p>记录版本获取、下载和重启安装操作。</p>
<p>记录版本获取、下载、重启安装和最终执行结果。</p>
</div>
<span>最近 {{ historyRows.length }} 条</span>
</div>
@@ -446,6 +446,7 @@ async function loadHistory(silent = false) {
}
try {
const result = await getAuditLogs({
occurredFrom: '1970-01-01T00:00:00Z',
objectType: 'SYSTEM_UPDATE',
sort: 'occurredAt,desc',
page: 1,
@@ -724,6 +725,9 @@ function actionLabel(action: string) {
SYSTEM_UPDATE_CHECK: '获取版本',
SYSTEM_UPDATE_DOWNLOAD_REQUEST: '下载更新包',
SYSTEM_UPDATE_REQUEST: '立即更新并重启',
SYSTEM_UPDATE_SUCCEEDED: '更新完成',
SYSTEM_UPDATE_FAILED: '更新失败',
SYSTEM_UPDATE_RECOVERY_REQUIRED: '更新需人工恢复',
}[action] || action
);
}