所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
修改原因:远端 b140269 已删除 #5216/#5262 两个非法旧文件名,遗留 alias 配置会令 source 测试失败。 修改内容:移除指向已删除物理文件的 repository alias;保留临时 fixture 对 alias 解析、状态同步和安全校验的覆盖,并更新仓库清单回归断言。 实际验证:source npm test 46 项、check:path-aliases 与 git diff --check 通过。Changelog:#5216、#5262 路径兼容清理。
133 行
4.3 KiB
JavaScript
133 行
4.3 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
import {
|
|
loadPathAliasManifest,
|
|
parsePathAliasManifest,
|
|
resolveChangelogPath,
|
|
transitionAliasedFrontendState,
|
|
validatePathAliases,
|
|
} from '../scripts/changelog-path-aliases.mjs';
|
|
import { parseFrontmatter } from '../scripts/validate-changelog-frontmatter.mjs';
|
|
|
|
const OLD_5216 = 'changelogs-v2/2026-07/24_5216_派车看板补充槽位接送路线与就绪摘要-修改接口-前端待处理-管理后台.md';
|
|
const CURRENT_5216 = 'changelogs-v2/2026-07/24_5216_派车看板补充槽位接送路线与就绪摘要-修改接口-管理后台.md';
|
|
|
|
function document({ canonicalPath = '', status = 'claimed', owner = 'frontend-team', frontendRef = '' } = {}) {
|
|
const canonicalLine = canonicalPath ? `canonical_path: "${canonicalPath}"\n` : '';
|
|
return `---
|
|
schema: "hl-changelog/v2"
|
|
ticket: "5216"
|
|
title: "路径兼容测试"
|
|
consumer: "admin"
|
|
change_type: "修改接口"
|
|
backend_status: "deployed"
|
|
gateway_status: "verified"
|
|
frontend_status: "${status}"
|
|
frontend_owner: "${owner}"
|
|
frontend_ref: "${frontendRef}"
|
|
target_release: ""
|
|
verified_at: ""
|
|
${canonicalLine}updated_at: "2026-07-26"
|
|
base: "dev-v3"
|
|
---
|
|
|
|
# 路径兼容测试
|
|
|
|
## 变更接口
|
|
|
|
- 无业务接口变化。
|
|
|
|
## 验证证据
|
|
|
|
- 自动化测试。
|
|
`;
|
|
}
|
|
|
|
function createFixture() {
|
|
const root = mkdtempSync(path.join(tmpdir(), 'hl-changelog-alias-'));
|
|
const manifest = {
|
|
schema: 'hl-changelog-path-aliases/v1',
|
|
aliases: [{
|
|
ticket: '5216',
|
|
alias: OLD_5216,
|
|
canonical: CURRENT_5216,
|
|
reason: '测试旧路径兼容',
|
|
}],
|
|
};
|
|
writeFileSync(path.join(root, 'changelog-path-aliases.json'), JSON.stringify(manifest, null, 2));
|
|
for (const repoPath of [OLD_5216, CURRENT_5216]) {
|
|
const absolute = path.join(root, ...repoPath.split('/'));
|
|
mkdirSync(path.dirname(absolute), { recursive: true });
|
|
writeFileSync(absolute, document({
|
|
canonicalPath: repoPath === OLD_5216 ? CURRENT_5216 : '',
|
|
}));
|
|
}
|
|
return root;
|
|
}
|
|
|
|
test('repository manifest has no dangling aliases after illegal legacy paths are removed', () => {
|
|
const manifest = loadPathAliasManifest();
|
|
assert.equal(resolveChangelogPath(OLD_5216, manifest), OLD_5216);
|
|
assert.equal(resolveChangelogPath(CURRENT_5216, manifest), CURRENT_5216);
|
|
assert.deepEqual(validatePathAliases().errors, []);
|
|
});
|
|
|
|
test('rejects unsafe paths, duplicate aliases and alias chains', () => {
|
|
assert.throws(() => parsePathAliasManifest(JSON.stringify({
|
|
schema: 'hl-changelog-path-aliases/v1',
|
|
aliases: [{
|
|
ticket: '5216',
|
|
alias: '../outside.md',
|
|
canonical: CURRENT_5216,
|
|
reason: 'unsafe',
|
|
}],
|
|
})), /POSIX|规范路径/);
|
|
assert.throws(() => parsePathAliasManifest(JSON.stringify({
|
|
schema: 'hl-changelog-path-aliases/v1',
|
|
aliases: [
|
|
{ ticket: '5216', alias: OLD_5216, canonical: CURRENT_5216, reason: 'one' },
|
|
{ ticket: '5216', alias: OLD_5216, canonical: CURRENT_5216, reason: 'two' },
|
|
],
|
|
})), /重复/);
|
|
});
|
|
|
|
test('frontend status transition updates alias group once and is idempotent', () => {
|
|
const root = createFixture();
|
|
try {
|
|
const first = transitionAliasedFrontendState(root, OLD_5216, {
|
|
status: 'implemented',
|
|
owner: 'frontend-team',
|
|
frontendRef: 'mmg/hl-ui@abc1234',
|
|
}, {
|
|
now: new Date('2026-07-26T04:00:00Z'),
|
|
write: true,
|
|
});
|
|
assert.deepEqual(new Set(first.changedPaths), new Set([OLD_5216, CURRENT_5216]));
|
|
assert.deepEqual(validatePathAliases(root).errors, []);
|
|
|
|
for (const repoPath of [OLD_5216, CURRENT_5216]) {
|
|
const text = readFileSync(path.join(root, ...repoPath.split('/')), 'utf8');
|
|
const { metadata } = parseFrontmatter(text);
|
|
assert.equal(metadata.frontend_status, 'implemented');
|
|
assert.equal(metadata.frontend_owner, 'frontend-team');
|
|
assert.equal(metadata.frontend_ref, 'mmg/hl-ui@abc1234');
|
|
}
|
|
|
|
const second = transitionAliasedFrontendState(root, OLD_5216, {
|
|
status: 'implemented',
|
|
owner: 'frontend-team',
|
|
frontendRef: 'mmg/hl-ui@abc1234',
|
|
}, {
|
|
now: new Date('2026-07-26T04:00:00Z'),
|
|
write: true,
|
|
});
|
|
assert.deepEqual(second.changedPaths, []);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|