diff --git a/deploy/package.mjs b/deploy/package.mjs index e223e63..8bf989f 100644 --- a/deploy/package.mjs +++ b/deploy/package.mjs @@ -1,4 +1,5 @@ -import { access, copyFile, mkdir, writeFile } from 'node:fs/promises' +import { createHash } from 'node:crypto' +import { access, copyFile, mkdir, readFile, stat, writeFile } from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' import { buildPlan, root, targets } from './build-plugins.mjs' @@ -17,6 +18,12 @@ export function packagePlan(target) { ] } +async function digestFile(filename) { + const [bytes, info] = await Promise.all([readFile(filename), stat(filename)]) + if (!info.isFile() || info.size === 0) throw new Error(`发布产物无效:${filename}`) + return { bytes: info.size, sha256: createHash('sha256').update(bytes).digest('hex') } +} + export async function packageRelease(selectedTargets = targets) { const plan = selectedTargets.flatMap(packagePlan) // 所有输入齐备后才写发布目录,不把旧的或其他平台插件混入发布包。 @@ -28,9 +35,17 @@ export async function packageRelease(selectedTargets = targets) { for (const target of selectedTargets) { for (const name of ['config', 'ssl', 'data', 'log']) await mkdir(path.join(root, 'out', 'package', target, name), { recursive: true }) await mkdir(path.join(root, 'out', 'release-receipts'), { recursive: true }) + const directory = path.join(root, 'out', 'package', target) + const files = await Promise.all(plan + .filter(item => path.dirname(item.target) === directory) + .map(async item => ({ + name: path.basename(item.target), + ...await digestFile(item.target) + }))) await writeFile(path.join(root, 'out', 'release-receipts', `${target}.json`), JSON.stringify({ version: process.env.SMAIL_VERSION || 'dev', gitHash: process.env.GIT_HASH || '', - protocolVersion: 1, target, plugins: buildPlan({ target }).map(item => item.id), createdAt: new Date().toISOString() + protocolVersion: 1, target, plugins: buildPlan({ target }).map(item => item.id), files, + createdAt: new Date().toISOString() }, null, 2) + '\n') } console.log(`发布包已生成:${selectedTargets.map(target => `out/package/${target}`).join('、')}`) diff --git a/test/frontend/output-paths.test.mjs b/test/frontend/output-paths.test.mjs index 89c09b5..a915c00 100644 --- a/test/frontend/output-paths.test.mjs +++ b/test/frontend/output-paths.test.mjs @@ -95,6 +95,8 @@ test('六个平台默认包含三个插件,构建和发布名称与后端目 assert.match(await read('deploy/build.ps1'), /build-plugins\.mjs'\) --dev/) assert.match(await read('Makefile'), /package: build_server plugin/) assert.match(await read('.github/workflows/release.yml'), /node deploy\/build-plugins\.mjs --target=/) + assert.match(await read('deploy/package.mjs'), /sha256: createHash\('sha256'\)/) + assert.match(await read('deploy/package.mjs'), /files,\n createdAt/) }) test('安全工作流必须先构建嵌入资源再执行 Go 测试', async () => {