mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-02 15:56:59 +08:00
Package production dependencies per architecture for online and offline upgrades. Validate dependencies and isolated backend startup before readiness, repair once when permitted, and preserve service/data through failed preparation or rollback. Publish release bundles with master images and expose an opt-in develop build sharing the development index across Alpine and Debian images.
100 lines
3.8 KiB
JavaScript
100 lines
3.8 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs/promises');
|
|
const path = require('node:path');
|
|
const {
|
|
manualUpgradeFixture,
|
|
} = require('../../../test/helpers/manual-upgrade-fixture.cjs');
|
|
const { createContext } = require('../../dist/internal/runtime/context');
|
|
const { reloadPanel } = require('../../dist/internal/maintenance/upgrade');
|
|
const operator = require('../../dist/internal/maintenance/operator');
|
|
const artifacts = require('../../dist/internal/maintenance/upgradeArtifacts.cjs');
|
|
|
|
for (const status of ['ready', 'failed', 'completed', 'absent'])
|
|
for (const wrongVersion of [false, true])
|
|
test(`CLI validates and records manual reload after ${status}; wrong version=${wrongVersion}`, async (t) => {
|
|
const f = await manualUpgradeFixture(t, wrongVersion);
|
|
await fs.writeFile(
|
|
path.join(f.root, 'package.json'),
|
|
'{"qinglongUpgradeFormat":2}',
|
|
);
|
|
const file = path.join(f.tmp, 'panel-upgrade.json');
|
|
if (status === 'absent') await fs.unlink(file);
|
|
else
|
|
await fs.writeFile(
|
|
file,
|
|
JSON.stringify({
|
|
...(await f.state()),
|
|
status,
|
|
error: 'old error',
|
|
version: '9.9.9',
|
|
sourceCommit: 'f'.repeat(40),
|
|
}),
|
|
);
|
|
t.mock.method(operator, 'stopPanel', async () => {});
|
|
t.mock.method(operator, 'startPanel', async () => ({
|
|
manager: 'fixture',
|
|
}));
|
|
t.mock.method(artifacts, 'waitForHealth', async () => {});
|
|
const operation = reloadPanel(
|
|
createContext({ root: f.root }, f.env),
|
|
'system',
|
|
);
|
|
if (wrongVersion)
|
|
await assert.rejects(operation, /启动版本与更新包不一致/);
|
|
else await operation;
|
|
const state = await f.state();
|
|
assert.equal(state.status, wrongVersion ? 'failed' : 'completed');
|
|
assert.equal(state.sourceCommit, f.expected.sourceCommit);
|
|
assert.equal(state.version, f.expected.version);
|
|
assert.notEqual(state.error, 'old error');
|
|
assert.equal(
|
|
await fs.readFile(path.join(f.root, 'static/build/app.js'), 'utf8'),
|
|
wrongVersion ? 'old backend' : 'new backend',
|
|
);
|
|
assert.equal(
|
|
await fs.readFile(path.join(f.root, 'data/keep'), 'utf8'),
|
|
'preserve data',
|
|
);
|
|
});
|
|
|
|
for (const wrongVersion of [false, true]) {
|
|
test(`operational CLI synchronizes prepared jobs and verifies startup before committing; wrong version=${wrongVersion}`, async (t) => {
|
|
const f = await manualUpgradeFixture(t, wrongVersion);
|
|
const context = createContext({ root: f.root }, f.env);
|
|
const timeouts = [];
|
|
t.mock.method(artifacts, 'waitForHealth', async (_env, timeout) => {
|
|
timeouts.push(timeout);
|
|
});
|
|
t.mock.method(operator, 'stopPanel', async () => {
|
|
assert.equal((await f.state()).status, 'restarting');
|
|
});
|
|
t.mock.method(operator, 'startPanel', async () => ({ manager: 'fixture' }));
|
|
const operation = reloadPanel(context, 'system');
|
|
if (wrongVersion) await assert.rejects(operation, /启动版本与更新包不一致/);
|
|
else await operation;
|
|
assert.ok(timeouts.length > 0);
|
|
assert.ok(
|
|
timeouts.every((timeout) => timeout === undefined),
|
|
'use the shared ARMv6/default startup deadline',
|
|
);
|
|
assert.equal(
|
|
(await f.state()).status,
|
|
wrongVersion ? 'failed' : 'completed',
|
|
);
|
|
assert.equal(
|
|
await fs.readFile(path.join(f.root, 'static/build/app.js'), 'utf8'),
|
|
wrongVersion ? 'old backend' : 'new backend',
|
|
);
|
|
assert.equal(
|
|
await fs.readFile(path.join(f.root, 'data/keep'), 'utf8'),
|
|
'preserve data',
|
|
);
|
|
if (wrongVersion)
|
|
assert.equal(
|
|
await fs.readFile(path.join(f.root, 'node_modules/old'), 'utf8'),
|
|
'old dependency',
|
|
);
|
|
});
|
|
}
|