Files
tea-sdlc/scripts/wp-list.js
T
jiantw83andClaude Opus 5 03ce382220 refactor(issue-body): 工作包的歸屬判準收成一個函式
wp-extract 與 wp-list 都在問「這顆工作包掛在哪顆需求底下」。規則寫兩份,
某天只會有一邊被改到,而分岔的樣子是「清單裡看得到、抽取卻說不是」。
順手把測試裡兩種取段落的寫法統一,並刪掉沒有人傳過的參數。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 18:19:33 +08:00

88 lines
3.1 KiB
JavaScript

#!/usr/bin/env node
/**
* 列出一顆需求議題底下的工作包。
*
* 使用者手上常常只有需求議題的編號——留言發在那裡、討論也在那裡——但真正要動手的
* 單位是工作包。這一支把「哪幾顆工作包掛在這顆需求底下」答出來,讓他從清單裡挑一顆,
* 而不是自己去 Gitea 網頁上翻。
*
* **判準沿用工作包抽取那一套**:關聯段落裡的 `需求議題:#<編號>`。判準與 wp-extract 的
* `需求議題` 欄位共用 issue-body 的 requirementIndex,不是各寫一份長得像的解析——
* 標籤、標題前綴、相依關係都當得了歸屬判準,但各發明一套就會與抽取契約分岔。
*
* **PR 不算工作包。** 每個 PR 都是議題,而 pr-create 產出的 PR 描述本來就有
* 「需求議題:#N」那一行,只看 body 會把 PR 混進清單裡。
*
* 清單逐頁讀完,讀不完寧可報錯:半份清單會讓使用者從缺了幾顆的清單裡挑,
* 而且他看不出來缺的是哪幾顆。
*
* 用法:
* node scripts/wp-list.js --repo owner/name --requirement 7 [--host <網址>] [--dry-run]
*/
import {
main,
pages,
parseFlags,
parseIndex,
parseRepo,
preflight,
resolveLogin,
} from './lib.js';
import { parseSections, requirementIndex } from './issue-body.js';
main(async () => {
const flags = parseFlags(process.argv.slice(2), {
required: ['repo', 'requirement'],
optional: ['host'],
booleans: ['dry-run'],
});
const repo = parseRepo(flags.repo);
const requirement = parseIndex(flags.requirement, '--requirement');
const issuesPath = `/repos/${repo}/issues`;
if (flags['dry-run']) {
return {
dryRun: true,
repo,
需求議題: requirement,
requests: [{ method: 'GET', path: issuesPath }],
note: '議題清單逐頁讀完,頁數取決於 repo 的議題總數,事前無法列舉。',
};
}
const login = resolveLogin({ host: flags.host });
await preflight(login, repo);
const 工作包 = [];
for await (const issues of pages(login, issuesPath, {
query: { state: 'all' },
limitCode: 'WORK_PACKAGE_LIMIT',
limitHint: `翻不完 ${repo} 的議題,列不出 #${requirement} 底下的完整工作包清單;請直接在 Gitea 上確認`,
})) {
for (const issue of issues) {
if (!belongsTo(issue, requirement)) continue;
工作包.push({
index: issue.number,
title: issue.title,
url: issue.html_url,
state: issue.state,
assignee: issue.assignee?.login ?? null,
});
}
}
// 依編號排序:Gitea 的回傳順序會隨排序設定而變,清單的順序卻是使用者挑選的依據
工作包.sort((a, b) => a.index - b.index);
return { repo, 需求議題: requirement, 工作包, 數量: 工作包.length };
});
/**
* 這顆議題是不是掛在指定需求底下的工作包。
* PR 先擋掉——它的描述也有「需求議題:#N」那一行,但它不是工作包。
*/
function belongsTo(issue, requirement) {
if (issue.pull_request != null) return false;
return requirementIndex(parseSections(issue.body)) === requirement;
}