fix(infra): guard backup creation timestamps · openclaw/openclaw@059d540
steipete
·
2026-05-30
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -306,6 +306,36 @@ describe("buildExtensionsNodeModulesFilter", () => {
|
306 | 306 | }); |
307 | 307 | |
308 | 308 | describe("createBackupArchive", () => { |
| 309 | +it("falls back when injected nowMs is outside Date range", async () => { |
| 310 | +await withOpenClawTestState( |
| 311 | +{ |
| 312 | +layout: "state-only", |
| 313 | +prefix: "openclaw-backup-invalid-now-", |
| 314 | +scenario: "minimal", |
| 315 | +}, |
| 316 | +async (state) => { |
| 317 | +const outputDir = state.path("backups"); |
| 318 | +await fs.mkdir(outputDir, { recursive: true }); |
| 319 | +const dateNowSpy = vi.spyOn(Date, "now").mockReturnValue(Date.UTC(2026, 4, 30, 12, 0, 0)); |
| 320 | + |
| 321 | +try { |
| 322 | +const result = await createBackupArchive({ |
| 323 | +output: outputDir, |
| 324 | +dryRun: true, |
| 325 | +includeWorkspace: false, |
| 326 | +nowMs: 8_640_000_000_000_001, |
| 327 | +}); |
| 328 | + |
| 329 | +expect(result.createdAt).toBe("2026-05-30T12:00:00.000Z"); |
| 330 | +expect(path.basename(result.archivePath)).toContain("openclaw-backup.tar.gz"); |
| 331 | +expect(path.basename(result.archivePath)).not.toContain("NaN"); |
| 332 | +} finally { |
| 333 | +dateNowSpy.mockRestore(); |
| 334 | +} |
| 335 | +}, |
| 336 | +); |
| 337 | +}); |
| 338 | + |
309 | 339 | it("skips current live volatile state files while preserving workspace locks", async () => { |
310 | 340 | await withOpenClawTestState( |
311 | 341 | { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -11,6 +11,7 @@ import {
|
11 | 11 | resolveBackupPlanFromDisk, |
12 | 12 | } from "../commands/backup-shared.js"; |
13 | 13 | import { isPathWithin } from "../commands/cleanup-utils.js"; |
| 14 | +import { asDateTimestampMs } from "../shared/number-coercion.js"; |
14 | 15 | import { resolveHomeDir, resolveUserPath } from "../utils.js"; |
15 | 16 | import { resolveRuntimeServiceVersion } from "../version.js"; |
16 | 17 | import { isVolatileBackupPath } from "./backup-volatile-filter.js"; |
@@ -446,7 +447,7 @@ export function buildExtensionsNodeModulesFilter(stateDir: string): (filePath: s
|
446 | 447 | export async function createBackupArchive( |
447 | 448 | opts: BackupCreateOptions = {}, |
448 | 449 | ): Promise<BackupCreateResult> { |
449 | | -const nowMs = opts.nowMs ?? Date.now(); |
| 450 | +const nowMs = asDateTimestampMs(opts.nowMs) ?? Date.now(); |
450 | 451 | const archiveRoot = buildBackupArchiveRoot(nowMs); |
451 | 452 | const onlyConfig = Boolean(opts.onlyConfig); |
452 | 453 | const includeWorkspace = onlyConfig ? false : (opts.includeWorkspace ?? true); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。