ci: 무결성 검증 통합(권장 플로우)
- scripts/make-verify-json.js: 산출물 폴더 → extras/assets JSON 생성 - scripts/verify.js: JSON 입력으로 무결성 검증(종료코드 반영) - package.json: verify 스크립트 추가 - .gitea/workflows/ci.yml: ./artifacts/export 존재 시 검증 스텝 실행
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
Generate verify inputs from an export folder
|
||||
Usage: node scripts/make-verify-json.js --root <export_folder> --extras <out_extras.json> --assets <out_assets.json>
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const fsp = require('fs/promises');
|
||||
const path = require('path');
|
||||
|
||||
function parseArgs(argv) {
|
||||
const out = { root: '', extras: '', assets: '' };
|
||||
for (let i = 2; i < argv.length; i++) {
|
||||
const a = argv[i];
|
||||
if (a === '--root') out.root = argv[++i];
|
||||
else if (a === '--extras') out.extras = argv[++i];
|
||||
else if (a === '--assets') out.assets = argv[++i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function toB64(buf) { return Buffer.from(buf).toString('base64'); }
|
||||
|
||||
async function readFileB64(p) { const b = await fsp.readFile(p); return toB64(b); }
|
||||
|
||||
async function walk(dir) {
|
||||
const out = [];
|
||||
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
||||
for (const ent of entries) {
|
||||
const abs = path.join(dir, ent.name);
|
||||
if (ent.isDirectory()) {
|
||||
const sub = await walk(abs);
|
||||
out.push(...sub);
|
||||
} else if (ent.isFile()) {
|
||||
out.push(abs);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const { root, extras, assets } = parseArgs(process.argv);
|
||||
if (!root || !extras || !assets) {
|
||||
console.log('Usage: node scripts/make-verify-json.js --root <export_folder> --extras <out_extras.json> --assets <out_assets.json>');
|
||||
process.exit(2);
|
||||
}
|
||||
const rootAbs = path.resolve(process.cwd(), root);
|
||||
const files = await walk(rootAbs);
|
||||
const norm = (p) => p.split(path.sep).join('/');
|
||||
const rootNorm = norm(rootAbs).replace(/\/$/, '');
|
||||
const rel = (p) => {
|
||||
const pn = norm(p);
|
||||
return pn.startsWith(rootNorm + '/') ? pn.slice(rootNorm.length + 1) : pn;
|
||||
};
|
||||
|
||||
const extrasMap = {};
|
||||
const assetsMap = {};
|
||||
|
||||
// integrity index
|
||||
const idx = files.find((p) => rel(p) === 'assets.integrity.index.json');
|
||||
if (idx) {
|
||||
extrasMap['assets.integrity.index.json'] = await readFileB64(idx);
|
||||
}
|
||||
|
||||
// assets/**/*
|
||||
for (const abs of files) {
|
||||
const r = rel(abs);
|
||||
if (!r.startsWith('assets/')) continue;
|
||||
const b64 = await readFileB64(abs);
|
||||
assetsMap[r] = b64;
|
||||
}
|
||||
|
||||
await fsp.mkdir(path.dirname(path.resolve(process.cwd(), extras)), { recursive: true });
|
||||
await fsp.mkdir(path.dirname(path.resolve(process.cwd(), assets)), { recursive: true });
|
||||
await fsp.writeFile(extras, JSON.stringify(extrasMap));
|
||||
await fsp.writeFile(assets, JSON.stringify(assetsMap));
|
||||
console.log(`Wrote ${extras} and ${assets}`);
|
||||
} catch (e) {
|
||||
console.error(e && e.stack || String(e));
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user