72 lines
2.2 KiB
JavaScript
72 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* 把一顆需求議題抽成下游要用的精簡 JSON。
|
|
*
|
|
* 這是下游(分析、實作)唯一的議題讀取管道,存在的理由是「不必吞下整份議題全文」。
|
|
* 只讀 body,不把留言內容納入輸出;但會回報有幾則留言尚未被整併回描述,
|
|
* 好讓下游知道自己是不是在拿過期的描述做事。
|
|
*
|
|
* 用法:
|
|
* node scripts/issue-extract.js --repo owner/name --index 7 [--host <網址>] [--dry-run]
|
|
*/
|
|
import {
|
|
UNMERGED_COMMENT_NOTE,
|
|
countUnmergedComments,
|
|
fetchIssue,
|
|
main,
|
|
parseFlags,
|
|
parseIndex,
|
|
parseRepo,
|
|
preflight,
|
|
resolveLogin,
|
|
} from './lib.js';
|
|
import { listSection, parseSections, tableSection, textSection } from './issue-body.js';
|
|
|
|
main(async () => {
|
|
const flags = parseFlags(process.argv.slice(2), {
|
|
required: ['repo', 'index'],
|
|
optional: ['host'],
|
|
booleans: ['dry-run'],
|
|
});
|
|
const repo = parseRepo(flags.repo);
|
|
const index = parseIndex(flags.index);
|
|
const issuePath = `/repos/${repo}/issues/${index}`;
|
|
const timelinePath = `${issuePath}/timeline`;
|
|
|
|
if (flags['dry-run']) {
|
|
return {
|
|
dryRun: true,
|
|
repo,
|
|
requests: [
|
|
{ method: 'GET', path: issuePath },
|
|
{ method: 'GET', path: timelinePath },
|
|
],
|
|
note: UNMERGED_COMMENT_NOTE,
|
|
};
|
|
}
|
|
|
|
const login = resolveLogin({ host: flags.host });
|
|
const { user } = await preflight(login, repo);
|
|
|
|
const issue = await fetchIssue(login, repo, index);
|
|
const sections = parseSections(issue.body);
|
|
|
|
return {
|
|
index: issue.number,
|
|
url: issue.html_url,
|
|
title: issue.title,
|
|
labels: (issue.labels ?? []).map((label) => label.name),
|
|
總覽: textSection(sections, '總覽'),
|
|
背景: textSection(sections, '背景'),
|
|
目標: listSection(sections, '目標'),
|
|
非目標: listSection(sections, '非目標'),
|
|
名詞表: tableSection(sections, '領域名詞表'),
|
|
文件: textSection(sections, '文件'),
|
|
驗收標準: listSection(sections, '驗收標準'),
|
|
影響範圍: listSection(sections, '影響範圍'),
|
|
未決事項: listSection(sections, '未決事項'),
|
|
未處理留言數: await countUnmergedComments(login, repo, index, user.login),
|
|
};
|
|
});
|
|
|