Files
ftb-project-management/scripts/ops-scripts.test.mjs
2161970543 feat(ops): 添加生产备份恢复脚本
- 新增 PostgreSQL 备份、fresh DB 恢复和 server_data volume 备份脚本\n- 恢复默认拒绝覆盖,必须显式 --confirm-overwrite\n- 补充 package scripts、deploy verify 校验和部署文档\n\nCo-Authored-By: GPT-5 Codex <codex@openai.com>
2026-07-08 16:10:15 +08:00

86 lines
2.7 KiB
JavaScript

import { spawnSync } from 'node:child_process';
import { mkdtempSync, writeFileSync, existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
const root = resolve(import.meta.dirname, '..');
function runScript(script, args) {
return spawnSync(process.execPath, [join(root, script), ...args], {
cwd: root,
encoding: 'utf8',
});
}
describe('production ops scripts', () => {
it('prints a pg_dump command in dry-run mode without writing the target file', () => {
const dir = mkdtempSync(join(tmpdir(), 'ftb-pg-backup-'));
const output = join(dir, 'backup.dump');
const result = runScript('scripts/backup-postgres.mjs', [
'--dry-run',
'--env-file',
'.env.production.example',
'--output',
output,
]);
assert.equal(result.status, 0, result.stderr);
assert.match(result.stdout, /docker compose/);
assert.match(result.stdout, /pg_dump/);
assert.match(result.stdout, /backup\.dump/);
assert.equal(existsSync(output), false);
});
it('refuses restore by default unless --confirm-overwrite is supplied', () => {
const dir = mkdtempSync(join(tmpdir(), 'ftb-pg-restore-'));
const input = join(dir, 'backup.dump');
writeFileSync(input, 'not-a-real-dump');
const result = runScript('scripts/restore-postgres.mjs', [
'--env-file',
'.env.production.example',
'--input',
input,
]);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /--confirm-overwrite/);
});
it('prints fresh database restore steps in dry-run mode after explicit overwrite confirmation', () => {
const dir = mkdtempSync(join(tmpdir(), 'ftb-pg-restore-dry-'));
const input = join(dir, 'backup.dump');
writeFileSync(input, 'not-a-real-dump');
const result = runScript('scripts/restore-postgres.mjs', [
'--dry-run',
'--confirm-overwrite',
'--env-file',
'.env.production.example',
'--input',
input,
]);
assert.equal(result.status, 0, result.stderr);
assert.match(result.stdout, /dropdb/);
assert.match(result.stdout, /createdb/);
assert.match(result.stdout, /pg_restore/);
});
it('prints a server_data volume tar backup command in dry-run mode', () => {
const result = runScript('scripts/backup-server-data.mjs', [
'--dry-run',
'--env-file',
'.env.production.example',
]);
assert.equal(result.status, 0, result.stderr);
assert.match(result.stdout, /docker run/);
assert.match(result.stdout, /ftb_pm_server_data/);
assert.match(result.stdout, /tar -czf/);
});
});