build: publish desktop installer via Gitea releases
Some checks failed
Build and tests / test (push) Has been cancelled

This commit is contained in:
237899745
2026-07-27 15:20:09 +08:00
parent f760aa0ae9
commit a736d70d57
12 changed files with 405 additions and 5 deletions

View File

@@ -91,6 +91,25 @@ test('生产部署统一使用 Vite dist 且不会删除 lock 文件', () => {
}
});
test('桌面安装包由 Gitea Release 发布且不会再次提交到 Git', () => {
const gitignore = fs.readFileSync(path.join(projectRoot, '.gitignore'), 'utf8');
const release = JSON.parse(fs.readFileSync(
path.join(projectRoot, 'frontend', 'desktop-release.json'),
'utf8'
));
const installer = fs.readFileSync(path.join(projectRoot, 'install.sh'), 'utf8');
const compose = fs.readFileSync(path.join(projectRoot, 'docker-compose.yml'), 'utf8');
assert.ok(gitignore.split(/\r?\n/).includes('/frontend/downloads/*.exe'));
assert.strictEqual(gitignore.includes('!/frontend/downloads/'), false);
assert.match(release.sha256, /^[a-f0-9]{64}$/);
assert.ok(Number.isSafeInteger(release.size) && release.size > 0);
assert.strictEqual(release.tag, `v${release.version}`);
assert.strictEqual(release.publicPath, `/downloads/${release.asset}`);
assert.ok(installer.includes('sync_desktop_release'));
assert.ok(compose.includes('desktop-release:'));
});
test('Docker 构建上下文排除依赖、环境配置和运行时数据', () => {
const dockerIgnore = fs.readFileSync(path.join(projectRoot, 'backend', '.dockerignore'), 'utf8');
for (const requiredEntry of ['node_modules', '.env', 'data/*', 'storage/*']) {

View File

@@ -0,0 +1,73 @@
const assert = require('assert');
const crypto = require('crypto');
const fs = require('fs');
const os = require('os');
const path = require('path');
const { spawnSync } = require('child_process');
const projectRoot = path.resolve(__dirname, '..', '..');
const syncScript = path.join(projectRoot, 'frontend', 'scripts', 'sync-desktop-release.js');
const results = { passed: 0, failed: 0 };
function test(name, fn) {
try {
fn();
results.passed += 1;
console.log(` [PASS] ${name}`);
} catch (error) {
results.failed += 1;
console.error(` [FAIL] ${name}: ${error.message}`);
}
}
console.log('\n========== 桌面安装包发布同步测试 ==========\n');
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'wanwanyun-release-sync-'));
try {
const destinationDirectory = path.join(tempRoot, 'downloads');
const asset = 'wanwan-cloud-desktop_v9.9.9_x64-setup.exe';
const assetContent = Buffer.from('verified desktop release fixture');
const sha256 = crypto.createHash('sha256').update(assetContent).digest('hex');
const metadataPath = path.join(tempRoot, 'desktop-release.json');
fs.mkdirSync(destinationDirectory, { recursive: true });
fs.writeFileSync(path.join(destinationDirectory, asset), assetContent);
fs.writeFileSync(metadataPath, JSON.stringify({
version: '9.9.9',
tag: 'v9.9.9',
asset,
downloadUrl: `https://example.test/releases/download/v9.9.9/${asset}`,
publicPath: `/downloads/${asset}`,
sha256,
size: assetContent.length
}));
const runCheck = () => spawnSync(process.execPath, [
syncScript,
'--metadata', metadataPath,
'--destination-dir', destinationDirectory,
'--check-only'
], { encoding: 'utf8' });
test('已缓存安装包通过大小与 SHA256 校验', () => {
const result = runCheck();
assert.strictEqual(result.status, 0, result.stderr);
assert.match(result.stdout, /Desktop release verified/);
});
test('损坏的安装包会让只读校验失败', () => {
fs.appendFileSync(path.join(destinationDirectory, asset), 'corrupt');
const result = runCheck();
assert.notStrictEqual(result.status, 0);
assert.match(result.stderr, /Desktop release check failed/);
});
} finally {
fs.rmSync(tempRoot, { recursive: true, force: true });
}
console.log('\n========================================');
console.log('测试总结');
console.log('========================================');
console.log(`通过: ${results.passed}`);
console.log(`失败: ${results.failed}`);
process.exit(results.failed > 0 ? 1 : 0);

View File

@@ -11,6 +11,7 @@ const testFiles = [
'domain-utils-tests.js',
'middleware-tests.js',
'architecture-tests.js',
'release-sync-tests.js',
'archive-tests.js',
'network-concurrent-tests.js',
'state-consistency-tests.js'