Merge pull request #1530 from pikasTech/fix/issue-1529-gh-comments

fix: add bounded gh issue comments command
This commit is contained in:
Lyon
2026-07-04 20:14:41 +08:00
committed by GitHub
9 changed files with 152 additions and 14 deletions
+1
View File
@@ -26,6 +26,7 @@ bun scripts/cli.ts gh auth status --repo pikasTech/unidesk
bun scripts/cli.ts gh issue list --repo pikasTech/unidesk --state open --limit 30
bun scripts/cli.ts gh issue view <number> --repo pikasTech/unidesk
bun scripts/cli.ts gh issue view <number> --repo pikasTech/unidesk --json body,title,state
bun scripts/cli.ts gh issue comments <number> --repo pikasTech/unidesk --limit 8
bun scripts/cli.ts gh issue create --repo pikasTech/unidesk --title "标题" --body-stdin
bun scripts/cli.ts gh pr list --repo pikasTech/unidesk --state all --limit 10
bun scripts/cli.ts gh pr review-plan <number> --repo pikasTech/unidesk
@@ -3,6 +3,7 @@
Issue writes use `bun scripts/cli.ts gh ...` or the `trans gh:` virtual filesystem.
- Body and comments default to Chinese.
- Recent issue comment progress should prefer `bun scripts/cli.ts gh issue comments <number> --repo owner/name [--limit N] [--full|--raw]`; structured output is stable at `.data.comments`.
- New issues include `目标合并分支`.
- Multi-stage architecture/API/platform issues begin with `P0 SPEC 先行`.
- Long body text uses `--body-stdin`.
+4 -3
View File
@@ -362,10 +362,11 @@ export function issueBodyReadCommands(repo: string, issueNumber: number): Record
export function issueCommentReadCommands(repo: string, issueNumber: number): Record<string, string> {
return {
comments: `bun scripts/cli.ts gh issue view ${issueNumber} --repo ${repo} --json comments`,
comments: `bun scripts/cli.ts gh issue comments ${issueNumber} --repo ${repo}`,
comment: `bun scripts/cli.ts gh issue comment view <commentId> --repo ${repo} --full`,
full: `bun scripts/cli.ts gh issue view ${issueNumber} --repo ${repo} --full`,
raw: `bun scripts/cli.ts gh issue view ${issueNumber} --repo ${repo} --raw`,
full: `bun scripts/cli.ts gh issue comments ${issueNumber} --repo ${repo} --full`,
raw: `bun scripts/cli.ts gh issue comments ${issueNumber} --repo ${repo} --raw`,
issue: `bun scripts/cli.ts gh issue view ${issueNumber} --repo ${repo}`,
};
}
+35
View File
@@ -47,6 +47,7 @@ function renderGhDefaultText(result: GitHubCommandResult): string {
if (result.ok === false) return renderGhError(result);
const command = result.command;
if (isIssueReadResult(result)) return renderIssueView(result);
if (command === "issue comments") return renderIssueComments(result);
if (isPrReadResult(result)) return renderPrView(result);
if (command === "pr list") return renderPrList(result);
if (command === "pr files" || command === "pr diff --stat") return renderPrFiles(result);
@@ -138,6 +139,7 @@ function renderIssueView(result: GitHubCommandResult): string {
` author=${ghText(issue.author)} bodySha=${ghText(issue.bodySha)} bodyPreview=${body.preview}`,
"",
"Next:",
` ${ghText(readCommands.comments ?? `bun scripts/cli.ts gh issue comments ${number} --repo ${result.repo}`)}`,
` ${ghText(readCommands.body ?? `bun scripts/cli.ts gh issue view ${number} --repo ${result.repo} --json body`)}`,
` ${ghText(readCommands.full ?? `bun scripts/cli.ts gh issue view ${number} --repo ${result.repo} --full`)}`,
"",
@@ -147,6 +149,39 @@ function renderIssueView(result: GitHubCommandResult): string {
return lines.join("\n");
}
function renderIssueComments(result: GitHubCommandResult): string {
const issue = record(result.issue);
const comments = arrayOfRecords(result.comments);
const commentRange = record(result.commentRange);
const readCommands = record(result.readCommands);
const rows = comments.slice(0, 40).map((comment) => [
ghText(comment.id),
ghText(comment.author),
shortDate(comment.createdAt),
ghShort(ghText(comment.url), 40),
ghShort(previewFrom(comment), 72),
]);
const lines = [
"gh issue comments (observed)",
"",
rows.length > 0
? ghTable(["COMMENT", "AUTHOR", "CREATED", "URL", "PREVIEW"], rows)
: "No comments found.",
"",
"Summary:",
` repo=${ghText(result.repo)} issue=#${ghText(issue.number ?? result.issueNumber)} total=${ghText(result.totalComments)} returned=${ghText(result.returned)} omitted=${ghText(result.omitted)}`,
` range=${ghText(commentRange.from)}..${ghText(commentRange.to)} title=${ghShort(ghText(issue.title), 96)}`,
"",
"Next:",
` ${ghText(readCommands.full ?? `bun scripts/cli.ts gh issue comments ${ghText(issue.number ?? result.issueNumber)} --repo ${result.repo} --full`)}`,
` ${ghText(readCommands.comment ?? `bun scripts/cli.ts gh issue comment view <commentId> --repo ${result.repo} --full`)}`,
"",
"Disclosure:",
" default comments output is a bounded recent-comment table with body preview; use --full/--raw for structured full bodies.",
];
return lines.join("\n");
}
function renderPrView(result: GitHubCommandResult): string {
const pr = record(result.pullRequest);
const number = ghText(pr.number);
+7 -3
View File
@@ -15,6 +15,7 @@ export function ghHelp(): unknown {
"bun scripts/cli.ts gh issue list [owner/repo] [--state open|closed|all] [--limit N] [--search text] [--title-prefix text] [--label label[,label...]]... [--repo owner/name] [--json number,title,state,closed,closedAt,url,updatedAt,createdAt,author,labels] [--raw|--full]",
"bun scripts/cli.ts gh issue view <number|url|owner/repo#number> [--repo owner/name] [--number N compat] [--json body,title,state,closed,closedAt,comments,commentCount] [--raw|--full]",
"bun scripts/cli.ts gh issue read <number|url|owner/repo#number> [--repo owner/name] [--number N compat] [--raw|--full] [compatibility alias for issue view]",
"bun scripts/cli.ts gh issue comments <number|url|owner/repo#number> [--repo owner/name] [--number N compat] [--limit N] [--full|--raw] [bounded recent comment progress path]",
"bun scripts/cli.ts gh issue attachment list <number|url|owner/repo#number> [--repo owner/name] [--number N compat]",
"bun scripts/cli.ts gh issue attachment download <number|url|owner/repo#number> [--repo owner/name] [--number N compat] [--attachment index|assetId|url] [--output path] [--dry-run]",
"bun scripts/cli.ts gh issue create --title <title> (--body-stdin|--body-file <file|->) [--label label[,label...]]... [--repo owner/name] [--dry-run]",
@@ -72,9 +73,9 @@ export function ghHelp(): unknown {
"issue list and pr list accept a single positional owner/repo as a compatibility alias for --repo owner/name. The positional repo and --repo must match if both are supplied; non-repo positionals fail structurally instead of falling back to the default repo.",
"issue list defaults to --state open and bounded --limit 30; it paginates GitHub REST/Search pages internally when --limit exceeds GitHub's per-page cap and discloses pagination/rawCount/hasMore so operators do not mistake a single page for the full repository. --search uses GitHub Search Issues API with repo/type/state qualifiers for low-friction dedupe lookup before creating a new issue. --title-prefix filters the bounded listed issues locally by exact title startsWith, useful for [FEEDBACK] dedupe, and reports titleFilter input/output counts. Supported --json fields are number,title,state,closed,closedAt,url,updatedAt,createdAt,author,labels and unknown fields fail structurally.",
"PR list defaults to --state all for compatibility with earlier UniDesk CLI behavior; supported states are open, closed, and all.",
"issue view is the canonical GitHub CLI-compatible read path; read remains a UniDesk compatibility alias. View/read accept positional numbers, GitHub issue URLs, and owner/repo#number shorthand, deriving --repo unless an explicit conflicting --repo is supplied. --number is accepted on single issue/comment numeric target commands for low-friction compatibility and returns a standard syntax hint; list/create/scan-escape/cleanup-plan/board-audit/board-row list do not accept it. Comment view/read/update/edit/delete treat --number as commentId, not an issue number. View supports lifecycle fields closed/closedAt plus legacy --json field selection; explicit --json fields limit output even with --raw/--full; full issue body is included only when requested with --json body or when --json is omitted and --full/--raw requests all fields. Comment lists always stay bounded except --raw; use gh issue comment view <commentId> --full for a single full comment body. Unsupported fields fail structurally.",
"issue view is the canonical GitHub CLI-compatible read path; read remains a UniDesk compatibility alias. View/read accept positional numbers, GitHub issue URLs, and owner/repo#number shorthand, deriving --repo unless an explicit conflicting --repo is supplied. --number is accepted on single issue/comment numeric target commands for low-friction compatibility and returns a standard syntax hint; list/create/scan-escape/cleanup-plan/board-audit/board-row list do not accept it. Comment view/read/update/edit/delete treat --number as commentId, not an issue number. View supports lifecycle fields closed/closedAt plus legacy --json field selection; explicit --json fields limit output even with --raw/--full; full issue body is included only when requested with --json body or when --json is omitted and --full/--raw requests all fields. For recent comment progress, prefer `gh issue comments <number>`: it defaults to a bounded recent-comment table and structured output lives at `.data.comments` instead of `.data.json.comments`. `gh issue view --json comments` remains the compatibility path. Use gh issue comment view <commentId> --full for one full comment body. Unsupported fields fail structurally.",
"issue attachment list/download scan issue body and comments for GitHub user attachment URLs (`https://github.com/user-attachments/assets/...`). list is read-only and returns bounded attachment metadata. download writes the selected attachment to --output or /tmp/unidesk-gh-attachments, returns bytes/SHA-256/content-type/path, redacts redirected signed URL query parameters, and never prints binary bytes.",
"--raw and --full are explicit full-disclosure aliases for gh issue list/read/view/update/edit/patch/comment view, gh pr list/read/view/comment view, and gh pr diff --file. For issue read/view commands, --full expands issue fields but keeps comment lists bounded; --raw is the explicit all-comment-body escape hatch. Use issue comment view <commentId> --full for a single full comment body. For issue writes, default success output omits full issue.body and returns bodyChars/bodySha/bodyPreview plus readCommands; --full|--raw includes the full returned issue body only on commands that explicitly support full disclosure.",
"--raw and --full are explicit full-disclosure aliases for gh issue list/read/view/comments/update/edit/patch/comment view, gh pr list/read/view/comment view, and gh pr diff --file. For issue read/view commands, --full expands issue fields but keeps comment lists bounded; --raw is the explicit all-comment-body escape hatch. For `gh issue comments`, both --full and --raw keep the list bounded to recent comments and include full comment bodies in structured output. Use issue comment view <commentId> --full for a single full comment body. For issue writes, default success output omits full issue.body and returns bodyChars/bodySha/bodyPreview plus readCommands; --full|--raw includes the full returned issue body only on commands that explicitly support full disclosure.",
"CLI output larger than config/unidesk-cli.yaml output.maxStdoutBytes is automatically written to /tmp/unidesk-cli-output; stdout stays bounded with outputTruncated=true, warning text, dump file metadata, and drill-down read commands.",
"issue create accepts --body-stdin or --body-file <file|-> plus repeatable --label values and comma-separated labels; inline --body is intentionally unsupported for issue creation. Dry-run prints the parsed labels and non-dry-run sends them in the GitHub REST create-issue payload.",
"--body-stdin is the first-class heredoc/stdin source for Markdown bodies. Use quoted heredoc syntax such as bun scripts/cli.ts gh issue comment create 1 --body-stdin <<'EOF' so real newlines, backticks, and tables are read as stdin bytes instead of shell arguments.",
@@ -157,8 +158,11 @@ export function ghScopedHelpNotes(tokens: string[]): string[] {
];
if (key === "issue comment" || key.startsWith("issue comment ")) {
notes.push("Issue comments use `--body-stdin` or `--body-file <file|->` for Markdown bodies; inline `--body` is only for short single-line comments.");
notes.push("Use `issue comment view <commentId> --full` to read one full comment body; issue-level `--json comments --full` keeps the comment list bounded.");
notes.push("Use `issue comment view <commentId> --full` to read one full comment body; use `issue comments <number>` for the bounded recent-comment issue view.");
notes.push("Use `issue comment update/edit` for wording fixes, `issue comment patch` for apply_patch-style local edits, and `issue comment delete` only for intentional removal.");
} else if (key === "issue comments") {
notes.push("Use `issue comments <number>` as the low-friction recent-progress path; default output is bounded and structured output is at `.data.comments`.");
notes.push("`--full` or `--raw` includes full bodies for the bounded recent list without changing the stable top-level `comments` path.");
} else if (key === "issue close" || key === "issue reopen") {
notes.push("Issue close/reopen can post a lifecycle comment with `--comment`, `--comment-stdin`, or `--comment-file <file|->` before changing state.");
notes.push("For long closeout evidence, prefer `--comment-stdin` with a quoted heredoc.");
+12 -3
View File
@@ -11,7 +11,7 @@ import { commentDelete, commentPatch, commentUpdate, commentView, issueComment,
import { issueScanEscape } from "./escape-scan";
import { ghHelp, ghScopedHelp } from "./help";
import { issueList } from "./issue-list";
import { issueRead, issueView } from "./issue-read";
import { issueComments, issueRead, issueView } from "./issue-read";
import { repoCreate, repoView } from "./issue-summary";
import { issueCreate, issueEdit, issuePatch } from "./issue-write";
import { allowsNumberTargetAlias, isIssueReadCommand, isPrReadCommand, optionValue, optionWasProvided, parseOptions } from "./options";
@@ -57,12 +57,13 @@ export async function runGhCommand(args: string[]): Promise<GitHubCommandResult
const isIssueCommentReadCommand = top === "issue" && sub === "comment" && (third === "view" || third === "read");
const isPrCommentReadCommand = top === "pr" && sub === "comment" && (third === "view" || third === "read");
const isPrDiffFileCommand = top === "pr" && sub === "diff" && optionWasProvided(args, "--file");
if ((optionWasProvided(args, "--raw") || optionWasProvided(args, "--full")) && !((top === "issue" && (isIssueReadCommand(sub) || sub === "list" || sub === "update" || sub === "edit" || sub === "patch")) || isIssueCommentReadCommand || top === "preflight" || (top === "pr" && (isPrReadCommand(sub) || sub === "list" || sub === "preflight" || sub === "closeout")) || isPrCommentReadCommand || isPrDiffFileCommand)) {
if ((optionWasProvided(args, "--raw") || optionWasProvided(args, "--full")) && !((top === "issue" && (isIssueReadCommand(sub) || sub === "comments" || sub === "list" || sub === "update" || sub === "edit" || sub === "patch")) || isIssueCommentReadCommand || top === "preflight" || (top === "pr" && (isPrReadCommand(sub) || sub === "list" || sub === "preflight" || sub === "closeout")) || isPrCommentReadCommand || isPrDiffFileCommand)) {
const command = [top, sub].filter((value): value is string => value !== undefined).join(" ") || "gh";
return validationError(command, options.repo, "--raw and --full are explicit full-disclosure aliases only for gh issue list/read/view/update/edit/patch/comment view, gh pr list/read/view/comment view, gh pr preflight/closeout, and gh pr diff --file.", {
return validationError(command, options.repo, "--raw and --full are explicit full-disclosure aliases only for gh issue list/read/view/comments/update/edit/patch/comment view, gh pr list/read/view/comment view, gh pr preflight/closeout, and gh pr diff --file.", {
supportedCommands: [
"bun scripts/cli.ts gh issue list --repo owner/name --limit 200 --full",
"bun scripts/cli.ts gh issue view owner/name#<number> --raw",
"bun scripts/cli.ts gh issue comments <number> --repo owner/name --limit 8 --full",
"bun scripts/cli.ts gh issue view <number> --repo owner/name --json body,title,state,comments",
"bun scripts/cli.ts gh issue comment view <commentId> --repo owner/name --full",
"bun scripts/cli.ts gh issue update <number> --repo owner/name --body-stdin --full <<'EOF'\n<reviewed body>\nEOF",
@@ -306,6 +307,14 @@ export async function runGhCommand(args: string[]): Promise<GitHubCommandResult
if (missing !== null || token === null) return missing ?? authRequired(options.repo, "issue comment create", { present: false, source: null, ghFallbackAttempted: true });
return withNumberOptionHint(issueComment(resolved.repo, token, issueNumber, { ...options, repo: resolved.repo }), resolved);
}
if (sub === "comments") {
const resolved = resolvePositionalIssueReference(args, 2, "issue comments", options);
if (isGitHubCommandResult(resolved)) return resolved;
const { token, probe } = resolveToken(true);
const missing = authRequired(resolved.repo, "issue comments", probe);
if (missing !== null || token === null) return missing ?? authRequired(resolved.repo, "issue comments", { present: false, source: null, ghFallbackAttempted: true });
return withNumberOptionHint(issueComments(resolved.repo, token, resolved.number, options.limit, { includeFullCommentBodies: options.full || options.raw }), resolved);
}
if (sub === "scan-escape" || sub === "cleanup-plan") {
const { token, probe } = resolveToken(true);
const commandName = sub === "cleanup-plan" ? "issue cleanup-plan" : "issue scan-escape";
+76 -2
View File
@@ -10,9 +10,13 @@ import { commentSummary, compactCommentSummary, compactIssueViewCommentSummary }
import { GITHUB_REST_PAGE_SIZE } from "./types";
import type { GitHubCommandResult, GitHubComment, GitHubErrorPayload, GitHubIssue, GitHubIssueListPage, GitHubIssueListResult, GitHubIssueSearchResponse, IssueListState, IssueViewJsonField } from "./types";
export async function listIssueComments(token: string, repo: string, issueNumber: number): Promise<GitHubComment[] | GitHubErrorPayload> {
export async function listIssueComments(token: string, repo: string, issueNumber: number, options: { page?: number; perPage?: number } = {}): Promise<GitHubComment[] | GitHubErrorPayload> {
const { owner, name } = repoParts(repo);
return githubRequest<GitHubComment[]>(token, "GET", `/repos/${owner}/${name}/issues/${issueNumber}/comments?per_page=100`);
const params = new URLSearchParams({
per_page: String(options.perPage ?? GITHUB_REST_PAGE_SIZE),
page: String(options.page ?? 1),
});
return githubRequest<GitHubComment[]>(token, "GET", `/repos/${owner}/${name}/issues/${issueNumber}/comments?${params.toString()}`);
}
export function githubSearchLabelQualifier(label: string): string {
@@ -99,6 +103,22 @@ export async function getIssueComment(token: string, repo: string, commentId: nu
return githubRequest<GitHubComment>(token, "GET", `/repos/${owner}/${name}/issues/comments/${commentId}`);
}
async function listRecentIssueComments(token: string, repo: string, issueNumber: number, totalComments: number, limit: number): Promise<GitHubComment[] | GitHubErrorPayload> {
if (totalComments <= 0 || limit <= 0) return [];
const boundedLimit = Math.min(limit, GITHUB_REST_PAGE_SIZE);
const pages: GitHubComment[][] = [];
let collected = 0;
let page = Math.max(1, Math.ceil(totalComments / GITHUB_REST_PAGE_SIZE));
while (page >= 1 && collected < boundedLimit) {
const pageComments = await listIssueComments(token, repo, issueNumber, { page, perPage: GITHUB_REST_PAGE_SIZE });
if (isGitHubError(pageComments)) return pageComments;
pages.unshift(pageComments);
collected += pageComments.length;
page -= 1;
}
return pages.flat().slice(-boundedLimit);
}
export function selectedIssueJson(issue: GitHubIssue, comments: GitHubComment[] | null, fields: IssueViewJsonField[] | undefined, options: { includeFullCommentBodies?: boolean } = {}): Record<string, unknown> | null {
if (fields === undefined) return null;
const summary = issueSummary(issue);
@@ -151,3 +171,57 @@ export async function issueRead(repo: string, token: string, issueNumber: number
export async function issueView(repo: string, token: string, issueNumber: number, jsonFields: IssueViewJsonField[] | undefined, disclosure: Record<string, unknown> | null = null, options: { includeFullCommentBodies?: boolean } = {}): Promise<GitHubCommandResult> {
return issueRead(repo, token, issueNumber, jsonFields, "issue view", disclosure, options);
}
export async function issueComments(repo: string, token: string, issueNumber: number, limit: number, options: { includeFullCommentBodies?: boolean } = {}): Promise<GitHubCommandResult> {
const issue = await getIssue(token, repo, issueNumber);
if (isGitHubError(issue)) return commandError("issue comments", repo, issue, { issueNumber });
const totalComments = Math.max(0, issue.comments ?? 0);
const boundedLimit = Math.min(limit, GITHUB_REST_PAGE_SIZE);
const includeFullCommentBodies = options.includeFullCommentBodies === true;
const comments = await listRecentIssueComments(token, repo, issueNumber, totalComments, boundedLimit);
if (isGitHubError(comments)) return commandError("issue comments", repo, comments, {
issueNumber,
issue: issueSummary(issue, { includeBody: false, includePreview: false }),
});
const shownFrom = comments.length === 0 ? 0 : Math.max(1, totalComments - comments.length + 1);
return {
ok: true,
command: "issue comments",
repo,
issue: issueSummary(issue, { includeBody: false, includePreview: false }),
issueNumber,
limit: boundedLimit,
totalComments,
returned: comments.length,
omitted: Math.max(0, totalComments - comments.length),
commentRange: {
from: shownFrom,
to: comments.length === 0 ? 0 : shownFrom + comments.length - 1,
total: totalComments,
},
comments: comments.map(includeFullCommentBodies ? commentSummary : compactCommentSummary),
disclosure: {
boundedRecentComments: true,
fullCommentBodiesIncluded: includeFullCommentBodies,
bodyOmitted: !includeFullCommentBodies,
note: includeFullCommentBodies
? "issue comments returns a bounded recent-comment list with full bodies because --full or --raw was explicitly requested."
: "issue comments defaults to bounded recent-comment previews; use --full or --raw for full bodies, or issue comment view <commentId> --full for a single comment.",
},
compatibility: {
commentsPath: ".data.comments",
issuePath: ".data.issue",
authorField: "string|null",
previewField: includeFullCommentBodies ? null : "bodyPreview",
fullBodyField: includeFullCommentBodies ? "body" : null,
nestedIssueViewCommentsPath: ".data.json.comments",
},
readCommands: {
self: `bun scripts/cli.ts gh issue comments ${issueNumber} --repo ${repo}`,
full: `bun scripts/cli.ts gh issue comments ${issueNumber} --repo ${repo} --limit ${boundedLimit} --full`,
raw: `bun scripts/cli.ts gh issue comments ${issueNumber} --repo ${repo} --limit ${boundedLimit} --raw`,
comment: `bun scripts/cli.ts gh issue comment view <commentId> --repo ${repo} --full`,
issue: `bun scripts/cli.ts gh issue view ${issueNumber} --repo ${repo}`,
},
};
}
+14 -3
View File
@@ -1,7 +1,7 @@
// SPEC: PJ2026-010606 GitHub入口 draft-2026-06-25-gh-split
// Moved mechanically from scripts/src/gh.ts:614-978.
import { BOARD_GITHUB_STATUSES, BOARD_MUTATION_SECTIONS, BOARD_ROW_FIELDS, BODY_UPDATE_MODES, CODE_QUEUE_BOARD_TARGET_ISSUE, DEFAULT_REPO, DEFAULT_STALE_CLOSE_INACTIVE_HOURS, GH_FLAG_OPTIONS, GH_VALUE_OPTIONS, ISSUE_LIST_JSON_FIELDS, ISSUE_LIST_STATES, ISSUE_VIEW_JSON_FIELDS, MAX_ISSUE_LIST_LIMIT, MAX_PR_FILES_LIMIT, MAX_STALE_CLOSE_INACTIVE_HOURS, PR_CLOSEOUT_JSON_FIELDS, PR_CLOSEOUT_VIEW_JSON, PR_LIST_JSON_FIELDS, PR_READ_JSON_FIELDS } from "./types";
import { BOARD_GITHUB_STATUSES, BOARD_MUTATION_SECTIONS, BOARD_ROW_FIELDS, BODY_UPDATE_MODES, CODE_QUEUE_BOARD_TARGET_ISSUE, DEFAULT_ISSUE_COMMENTS_LIMIT, DEFAULT_REPO, DEFAULT_STALE_CLOSE_INACTIVE_HOURS, GH_FLAG_OPTIONS, GH_VALUE_OPTIONS, ISSUE_LIST_JSON_FIELDS, ISSUE_LIST_STATES, ISSUE_VIEW_JSON_FIELDS, MAX_ISSUE_LIST_LIMIT, MAX_PR_FILES_LIMIT, MAX_STALE_CLOSE_INACTIVE_HOURS, PR_CLOSEOUT_JSON_FIELDS, PR_CLOSEOUT_VIEW_JSON, PR_LIST_JSON_FIELDS, PR_READ_JSON_FIELDS } from "./types";
import type { BoardGithubStatus, BoardMutationSection, BoardRowField, BoardRowUpsertValues, BodyUpdateMode, GitHubOptions, IssueBodyProfileOption, IssueListJsonField, IssueListState, IssueViewJsonField, PrListJsonField, PrListState, PrReadJsonField, PullRequestMergeMethod, RepoVisibility } from "./types";
export function optionValue(args: string[], name: string): string | undefined {
@@ -158,7 +158,7 @@ export function isPrReadCommand(sub: string | undefined): boolean {
export function allowsNumberTargetAlias(top: string | undefined, sub: string | undefined, third: string | undefined): boolean {
if (top === "preflight") return true;
if (top === "issue") {
if (sub === "read" || sub === "view" || sub === "edit" || sub === "update" || sub === "patch" || sub === "close" || sub === "reopen" || sub === "delete") return true;
if (sub === "read" || sub === "view" || sub === "comments" || sub === "edit" || sub === "update" || sub === "patch" || sub === "close" || sub === "reopen" || sub === "delete") return true;
if (sub === "comment") return true;
if (sub === "attachment" && (third === "list" || third === "download")) return true;
if (sub === "board-row" && ["get", "update", "add", "move", "delete", "upsert"].includes(third ?? "")) return true;
@@ -335,7 +335,18 @@ export function parseOptions(args: string[]): GitHubOptions {
dryRun: hasFlag(args, "--dry-run"),
raw: hasFlag(args, "--raw"),
full: hasFlag(args, "--full"),
limit: positiveIntegerOption(args, "--limit", top === "issue" && sub === "board-audit" ? 100 : top === "issue" && sub === "stale-close" ? MAX_ISSUE_LIST_LIMIT : 30, limitMax),
limit: positiveIntegerOption(
args,
"--limit",
top === "issue" && sub === "board-audit"
? 100
: top === "issue" && sub === "stale-close"
? MAX_ISSUE_LIST_LIMIT
: top === "issue" && sub === "comments"
? DEFAULT_ISSUE_COMMENTS_LIMIT
: 30,
limitMax,
),
inactiveHours: positiveNumberOption(args, "--inactive-hours", DEFAULT_STALE_CLOSE_INACTIVE_HOURS, MAX_STALE_CLOSE_INACTIVE_HOURS),
boardIssue: positiveIntegerSingleOption(args, "--board-issue", CODE_QUEUE_BOARD_TARGET_ISSUE),
knownMetaIssues: positiveIntegerValuesOption(args, "--known-meta-issue"),
+2
View File
@@ -25,6 +25,8 @@ export const GITHUB_REST_PAGE_SIZE = 100;
export const MAX_ISSUE_LIST_LIMIT = 1000;
export const DEFAULT_ISSUE_COMMENTS_LIMIT = 8;
export const DEFAULT_STALE_CLOSE_INACTIVE_HOURS = 48;
export const MAX_STALE_CLOSE_INACTIVE_HOURS = 24 * 365 * 10;