fix: harden release gate and page delivery
Memind CI / Test, build, and release guards (push) Failing after 12m3s

This commit is contained in:
john
2026-07-26 14:32:01 +08:00
parent d3141a3e91
commit b1577a16e9
61 changed files with 6017 additions and 89 deletions
+49 -5
View File
@@ -75,6 +75,25 @@ function isWithinRoot(root, candidate) {
return candidate === root || candidate.startsWith(`${root}${path.sep}`);
}
function safeSourceDownloadUrl(value) {
const raw = normalizeText(value);
if (!raw) return null;
let parsed;
try {
parsed = new URL(raw, 'http://local.invalid');
} catch {
throw Object.assign(new Error('Excel 原始文件下载地址无效'), { code: 'INVALID_SOURCE_DOWNLOAD_URL' });
}
if (parsed.origin !== 'http://local.invalid'
|| !parsed.pathname.startsWith('/api/mindspace/v1/assets/')
|| !parsed.pathname.endsWith('/download')) {
throw Object.assign(new Error('Excel 原始文件下载地址必须是受保护的站内资产下载路径'), {
code: 'INVALID_SOURCE_DOWNLOAD_URL',
});
}
return `${parsed.pathname}${parsed.search}`;
}
function validateZipBudget(buffer, {
maxUncompressedBytes = DEFAULT_MAX_UNCOMPRESSED_BYTES,
maxEntries = DEFAULT_MAX_ZIP_ENTRIES,
@@ -652,7 +671,15 @@ function buildReportModel(workbook, worksheet, loaded, args = {}) {
const validation = { valid: errors.length === 0, errors, warnings };
return {
schemaVersion: 1,
source: { path: args.path, sheet: worksheet.name, headerRow: loaded.headerRow, rows: loaded.rows.length },
source: {
path: args.path,
sheet: worksheet.name,
headerRow: loaded.headerRow,
rows: loaded.rows.length,
...(args.source_download_url
? { downloadUrl: safeSourceDownloadUrl(args.source_download_url) }
: {}),
},
fields: { metric, profitMetric, quantityMetric, orderId, dimensions },
totals: {
metric: roundNumber(totalMetric),
@@ -699,7 +726,11 @@ export function createExcelAnalysisEngine({ workspaceRoot, maxFileBytes = DEFAUL
const { workbook, source, sizeBytes } = await loadWorkbook(args.path);
const sampleRows = asPositiveInteger(args.sample_rows, DEFAULT_SAMPLE_ROWS, 20);
const sheets = workbook.worksheets.map((worksheet) => {
const loaded = loadRows(worksheet, { headerRow: args.header_row });
const loaded = loadRows(worksheet, {
headerRow: args.header_row,
maxRows: args.max_rows,
maxCells: args.max_cells,
});
const profiles = loaded.headers.map((name) => profileColumn(loaded.rows, name));
return {
name: worksheet.name,
@@ -725,7 +756,11 @@ export function createExcelAnalysisEngine({ workspaceRoot, maxFileBytes = DEFAUL
async analyze(args = {}) {
const { workbook, source } = await loadWorkbook(args.path);
const worksheet = worksheetByName(workbook, args.sheet);
const loaded = loadRows(worksheet, { headerRow: args.header_row });
const loaded = loadRows(worksheet, {
headerRow: args.header_row,
maxRows: args.max_rows,
maxCells: args.max_cells,
});
const operation = normalizeText(args.operation || 'summary').toLowerCase();
let result;
if (operation === 'summary') {
@@ -754,7 +789,11 @@ export function createExcelAnalysisEngine({ workspaceRoot, maxFileBytes = DEFAUL
async chart(args = {}) {
const { workbook, source } = await loadWorkbook(args.path);
const worksheet = worksheetByName(workbook, args.sheet);
const loaded = loadRows(worksheet, { headerRow: args.header_row });
const loaded = loadRows(worksheet, {
headerRow: args.header_row,
maxRows: args.max_rows,
maxCells: args.max_cells,
});
const type = normalizeText(args.type || 'bar').toLowerCase();
if (!['bar', 'line'].includes(type)) {
throw Object.assign(new Error('Phase 1 图表仅支持 bar 或 line'), { code: 'INVALID_CHART_TYPE' });
@@ -784,7 +823,11 @@ export function createExcelAnalysisEngine({ workspaceRoot, maxFileBytes = DEFAUL
async report(args = {}) {
const { workbook, source } = await loadWorkbook(args.path);
const worksheet = worksheetByName(workbook, args.sheet);
const loaded = loadRows(worksheet, { headerRow: args.header_row });
const loaded = loadRows(worksheet, {
headerRow: args.header_row,
maxRows: args.max_rows,
maxCells: args.max_cells,
});
const model = buildReportModel(workbook, worksheet, loaded, { ...args, path: source.relative });
if (!model.validation.valid) {
throw Object.assign(new Error('Excel 报告事实校验失败,未生成报告'), {
@@ -818,6 +861,7 @@ export const excelAnalysisInternals = {
safeRelativeWorkbookPath,
safeChartOutputPath,
safeReportOutputPath,
safeSourceDownloadUrl,
normalizeMainNamespacePrefixes,
validateZipBudget,
};