@pourkit/cli 0.0.0-next-20260529095319
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +7877 -0
- package/dist/cli.js.map +1 -0
- package/dist/e2e/run-live-e2e.js +5581 -0
- package/dist/e2e/run-live-e2e.js.map +1 -0
- package/dist/issues/close-issues-on-merge.js +842 -0
- package/dist/issues/close-issues-on-merge.js.map +1 -0
- package/dist/issues/unblock.js +685 -0
- package/dist/issues/unblock.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../common/logger/src/index.ts","../../shared/common.ts","../../issues/unblock.ts","../../issues/blocked-issue.ts","../../issues/issue-transitions.ts","../../providers/github-client.ts"],"sourcesContent":["import { createWriteStream } from \"node:fs\";\nimport { mkdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { styleText } from \"node:util\";\n\nexport interface PourkitLogger {\n line(msg: string): void;\n raw(msg: string): void;\n step(step: string, msg: string): void;\n status(status: string): void;\n kv(key: string, value: string): void;\n close(): Promise<void>;\n}\n\nexport function createLogger(name: string, filePath?: string): PourkitLogger {\n let fileStream: import(\"fs\").WriteStream | undefined;\n\n if (filePath) {\n mkdirSync(path.dirname(filePath), { recursive: true });\n fileStream = createWriteStream(filePath, { flags: \"a\" });\n }\n\n const write = (terminal: string, plain = terminal) => {\n process.stdout.write(`${terminal}\\n`);\n if (fileStream) {\n fileStream.write(`${plain}\\n`);\n }\n };\n\n return {\n line(msg: string) {\n const ts = timestamp();\n write(`${ts.terminal} ${msg}`, `${ts.plain} ${msg}`);\n },\n\n raw(msg: string) {\n write(msg);\n },\n\n step(step: string, msg: string) {\n const ts = timestamp();\n write(\n `${ts.terminal} ${formatStep(step)} ${formatStepMessage(step, msg)}`,\n `${ts.plain} [${step}] ${msg}`\n );\n },\n\n status(status: string) {\n const ts = timestamp();\n write(\n `${ts.terminal} ${color([\"bold\", \"cyan\"], \"POURKIT\")} ${color(\"cyan\", status)}`,\n `${ts.plain} POURKIT ${status}`\n );\n },\n\n kv(key: string, value: string) {\n const ts = timestamp();\n write(\n `${ts.terminal} ${color(\"dim\", key)}=${formatValue(key, value)}`,\n `${ts.plain} ${key}=${value}`\n );\n },\n\n async close() {\n await new Promise<void>((resolve) => {\n if (!fileStream) {\n resolve();\n return;\n }\n\n const timer = setTimeout(() => {\n if (!fileStream.destroyed) {\n fileStream.destroy();\n }\n resolve();\n }, 2000);\n\n fileStream.end(() => {\n clearTimeout(timer);\n resolve();\n });\n });\n },\n };\n}\n\nfunction timestamp() {\n const now = new Date();\n const time = now.toTimeString().slice(0, 8);\n const ms = String(now.getMilliseconds()).padStart(3, \"0\");\n const plain = `${time}.${ms}`;\n return { terminal: color(\"dim\", plain), plain };\n}\n\nfunction formatStep(step: string) {\n return color(stepStyle(step), `[${step}]`);\n}\n\nfunction formatStepMessage(step: string, msg: string) {\n if (step === \"error\") {\n return color(\"red\", msg);\n }\n if (step === \"warn\") {\n return color(\"yellow\", msg);\n }\n return msg;\n}\n\nfunction formatValue(key: string, value: string) {\n if (/SUCCESS|CREATED|COMMITS/.test(key)) {\n return color(\"green\", value);\n }\n if (/BRANCH|PATH|FILE|URL/.test(key)) {\n return color(\"cyan\", value);\n }\n return color(\"bold\", value);\n}\n\nfunction stepStyle(step: string): Parameters<typeof styleText>[0] {\n switch (step) {\n case \"sandcastle\":\n return [\"bold\", \"cyan\"];\n case \"git\":\n return [\"bold\", \"magenta\"];\n case \"review\":\n case \"reviewer\":\n return [\"bold\", \"blue\"];\n case \"cleanup\":\n return [\"bold\", \"yellow\"];\n case \"error\":\n return [\"bold\", \"red\"];\n case \"warn\":\n return [\"bold\", \"yellow\"];\n case \"info\":\n return \"cyan\";\n default:\n return \"green\";\n }\n}\n\nfunction color(format: Parameters<typeof styleText>[0], text: string) {\n if (process.env.NO_COLOR) {\n return text;\n }\n\n try {\n return styleText(format, text);\n } catch {\n return text;\n }\n}\n","import { mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execFile, spawnSync } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { type PourkitLogger, createLogger } from \"@pourkit/logger\";\n\nconst execFileAsync = promisify(execFile);\n\ntype RunResult = {\n code: number;\n stdout: string;\n stderr: string;\n};\n\nexport type { PourkitLogger };\nexport { createLogger };\n\nexport async function ensureDir(dir: string) {\n await mkdir(dir, { recursive: true });\n}\n\nexport function repoRoot(explicitRoot = process.env.POURKIT_ROOT) {\n if (explicitRoot?.trim()) {\n const root = explicitRoot.trim();\n\n const insideResult = spawnSync(\n \"git\",\n [\"-C\", root, \"rev-parse\", \"--is-inside-work-tree\"],\n { encoding: \"utf8\" }\n );\n\n if (insideResult.status !== 0 || insideResult.stdout.trim() !== \"true\") {\n throw new Error(\n `POURKIT_ROOT is not a valid Git worktree: ${root}\\n${insideResult.stderr || insideResult.stdout}`\n );\n }\n\n const topLevelResult = spawnSync(\n \"git\",\n [\"-C\", root, \"rev-parse\", \"--show-toplevel\"],\n { encoding: \"utf8\" }\n );\n\n if (topLevelResult.status !== 0) {\n throw new Error(\n `Failed to validate POURKIT_ROOT as a Git worktree: ${root}\\n${topLevelResult.stderr || topLevelResult.stdout}`\n );\n }\n\n return topLevelResult.stdout.trim();\n }\n\n const result = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n encoding: \"utf8\",\n });\n\n if (result.status !== 0) {\n throw new Error(\n `Failed to resolve repo root: ${result.stderr || result.stdout}`\n );\n }\n\n return result.stdout.trim();\n}\n\nexport function repoRelative(root: string, ...segments: string[]) {\n return path.join(root, ...segments);\n}\n\nexport function slugify(value: string) {\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"-\")\n .replace(/--+/g, \"-\")\n .replace(/^-+/, \"\")\n .replace(/-+$/, \"\")\n .slice(0, 50);\n\n return slug || \"issue\";\n}\n\nfunction formatCommand(command: string, args: string[]) {\n return [command, ...args]\n .map((part) => {\n if (/^[A-Za-z0-9_\\/.=:,@+-]+$/.test(part)) {\n return part;\n }\n\n return `'${part.replace(/'/g, \"'\\\\''\")}'`;\n })\n .join(\" \");\n}\n\nexport function readMaybeEnvInt(value: string | undefined, fallback: number) {\n const parsed = Number(value ?? fallback);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\nexport async function execCapture(\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n logger?: PourkitLogger;\n label?: string;\n } = {}\n) {\n if (options.logger && options.label) {\n options.logger.step(\n options.label,\n `running ${formatCommand(command, args)}`\n );\n }\n\n let stdout = \"\";\n let stderr = \"\";\n let code = 0;\n\n try {\n const result = await execFileAsync(command, args, {\n cwd: options.cwd,\n env: options.env,\n encoding: \"utf8\",\n maxBuffer: 20 * 1024 * 1024,\n });\n\n stdout =\n typeof result.stdout === \"string\"\n ? result.stdout\n : String(result.stdout ?? \"\");\n stderr =\n typeof result.stderr === \"string\"\n ? result.stderr\n : String(result.stderr ?? \"\");\n } catch (error) {\n const err = error as NodeJS.ErrnoException & {\n stdout?: string;\n stderr?: string;\n code?: number | string;\n };\n stdout = typeof err.stdout === \"string\" ? err.stdout : \"\";\n stderr = typeof err.stderr === \"string\" ? err.stderr : \"\";\n code = typeof err.code === \"number\" ? err.code : 1;\n }\n\n if (code !== 0) {\n throw new Error(\n [\n `command failed: ${formatCommand(command, args)}`,\n `exit code: ${code}`,\n stdout ? `stdout:\\n${stdout}` : \"\",\n stderr ? `stderr:\\n${stderr}` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n );\n }\n\n return { code, stdout, stderr } satisfies RunResult;\n}\n\nexport async function execJson<T>(\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n logger?: PourkitLogger;\n label?: string;\n } = {}\n) {\n const result = await execCapture(command, args, options);\n return JSON.parse(result.stdout) as T;\n}\n\nexport function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst TRANSIENT_GH_ERROR =\n /HTTP (502|503|504)\\b|Could not close the issue|GraphQL:.*closeIssue/;\n\nexport async function execCaptureWithRetry(\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n logger?: PourkitLogger;\n label?: string;\n retries?: number;\n backoffMs?: number;\n } = {}\n) {\n const retries = options.retries ?? 3;\n const backoffMs = options.backoffMs ?? 2000;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n return await execCapture(command, args, options);\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (!TRANSIENT_GH_ERROR.test(lastError.message)) {\n throw lastError;\n }\n if (options.logger) {\n options.logger.step(\n options.label ?? command,\n `transient failure (attempt ${attempt}/${retries}), retrying`\n );\n }\n if (attempt < retries) {\n await sleep(backoffMs * Math.pow(2, attempt - 1));\n }\n }\n }\n\n throw lastError!;\n}\n\nexport async function execJsonWithRetry<T>(\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n logger?: PourkitLogger;\n label?: string;\n retries?: number;\n backoffMs?: number;\n } = {}\n) {\n const result = await execCaptureWithRetry(command, args, options);\n return JSON.parse(result.stdout) as T;\n}\n\nexport const TYPE_LABELS = [\n \"type:bugfix\",\n \"type:infra\",\n \"type:feature\",\n \"type:polish\",\n \"type:refactor\",\n] as const;\n\n/**\n * Parse `git worktree list --porcelain` output and find the worktree\n * path for a given branch.\n *\n * Returns null if no worktree is registered for that branch.\n */\nexport function parseWorktreeListPorcelain(\n text: string,\n branch: string\n): string | null {\n const entries = text.trim().split(\"\\n\\n\");\n for (const entry of entries) {\n const lines = entry.trim().split(\"\\n\");\n let path = \"\";\n let entryBranch = \"\";\n for (const line of lines) {\n if (line.startsWith(\"worktree \")) {\n path = line.slice(\"worktree \".length);\n } else if (line.startsWith(\"branch refs/heads/\")) {\n entryBranch = line.slice(\"branch refs/heads/\".length);\n }\n }\n if (entryBranch === branch && path) {\n return path;\n }\n }\n return null;\n}\n","import { repoRoot, repoRelative, createLogger } from \"../shared/common\";\nimport { fileURLToPath } from \"node:url\";\nimport { TYPE_LABELS } from \"../shared/common\";\nimport { reconcileBlockedIssues } from \"./blocked-issue\";\nimport { createIssueTransitions } from \"./issue-transitions\";\nimport type { IssueTransitionDeps } from \"./issue-transitions\";\nimport type { GitHubClient } from \"../providers/github-client\";\nimport { requireGitHubClient } from \"../providers/github-client\";\n\nconst ROOT = repoRoot();\nprocess.chdir(ROOT);\n\nconst LOG_DIR = repoRelative(ROOT, \"pourkit\", \"logs\");\nconst RUN_ID = new Date().toISOString().replace(/[:.]/g, \"-\");\nconst LOG_PATH = repoRelative(LOG_DIR, `unblock-${RUN_ID}.log`);\nconst logger = createLogger(\"unblock\", LOG_PATH);\nconst __filename = fileURLToPath(import.meta.url);\n\ntype Issue = {\n number: number;\n title: string;\n body: string | null;\n labels: Array<{ name: string }>;\n};\n\nasync function main() {\n try {\n logger.status(\"starting\");\n const client = await requireGitHubClient();\n await unblock(client);\n logger.status(\"completed\");\n } catch (error) {\n logger.status(\"failed\");\n logger.line(\n error instanceof Error ? (error.stack ?? error.message) : String(error)\n );\n process.exitCode = 1;\n } finally {\n await logger.close();\n }\n}\n\nasync function withRetryOnTransient<T>(\n fn: () => Promise<T>,\n maxAttempts: number = 2\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n const isTransient =\n (error instanceof Error &&\n /HTTP (502|503|504)\\b/.test(error.message)) ||\n (typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n ((error as { status: number }).status === 502 ||\n (error as { status: number }).status === 503 ||\n (error as { status: number }).status === 504));\n if (!isTransient || attempt === maxAttempts) {\n throw error;\n }\n await new Promise((r) => setTimeout(r, 2000 * Math.pow(2, attempt - 1)));\n }\n }\n throw lastError as Error;\n}\n\nasync function unblock(client: GitHubClient) {\n const issues = await listBlockedIssues(client);\n logger.kv(\"POURKIT_BLOCKED_COUNT\", String(issues.length));\n\n const issueTitles = new Map(issues.map((i) => [i.number, i.title]));\n\n const transitionDeps: IssueTransitionDeps = {\n fetchIssue: async (issueNumber: number) => {\n const { data } = await client.octokit.rest.issues.get({\n owner: client.owner,\n repo: client.repo,\n issue_number: issueNumber,\n });\n return {\n labels: data.labels.map((l) =>\n typeof l === \"string\" ? l : (l.name ?? \"\")\n ),\n };\n },\n addLabels: async (issueNumber, labels) => {\n await withRetryOnTransient(() =>\n client.octokit.rest.issues.addLabels({\n owner: client.owner,\n repo: client.repo,\n issue_number: issueNumber,\n labels,\n })\n );\n },\n removeLabel: async (issueNumber, label) => {\n try {\n await withRetryOnTransient(() =>\n client.octokit.rest.issues.removeLabel({\n owner: client.owner,\n repo: client.repo,\n issue_number: issueNumber,\n name: label,\n })\n );\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n (error as { status: number }).status === 404\n ) {\n // Label may not exist\n } else {\n throw error;\n }\n }\n },\n updateLabels: async (issueNumber, removes, adds) => {\n for (const label of removes) {\n try {\n await withRetryOnTransient(() =>\n client.octokit.rest.issues.removeLabel({\n owner: client.owner,\n repo: client.repo,\n issue_number: issueNumber,\n name: label,\n })\n );\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n (error as { status: number }).status === 404\n ) {\n // Label may not exist\n } else {\n throw error;\n }\n }\n }\n if (adds.length > 0) {\n await withRetryOnTransient(() =>\n client.octokit.rest.issues.addLabels({\n owner: client.owner,\n repo: client.repo,\n issue_number: issueNumber,\n labels: adds,\n })\n );\n }\n },\n };\n\n const transitions = createIssueTransitions(transitionDeps, {\n blocked: \"blocked\",\n readyForAgent: \"ready-for-agent\",\n needsTriage: \"needs-triage\",\n agentInProgress: \"agent-in-progress\",\n readyForHuman: \"ready-for-human\",\n prOpenAwaitingMerge: \"pr-open-awaiting-merge\",\n });\n\n const results = await reconcileBlockedIssues(issues, {\n getIssueState: async (issueNumber: number) => {\n const { data } = await client.octokit.rest.issues.get({\n owner: client.owner,\n repo: client.repo,\n issue_number: issueNumber,\n });\n return (data.state as string).toUpperCase();\n },\n transitions,\n typeLabels: TYPE_LABELS,\n readyLabel: \"ready-for-agent\",\n });\n\n for (const { issueNumber, result } of results) {\n const title = issueTitles.get(issueNumber) ?? `#${issueNumber}`;\n logger.step(\"process\", `#${issueNumber}: ${title}`);\n\n if (result === \"still-blocked\") {\n logger.step(\"skip\", `#${issueNumber}: still blocked`);\n continue;\n }\n\n logger.step(\"unblock\", `#${issueNumber}: all blockers resolved`);\n\n if (result === \"unblocked\") {\n logger.step(\"done\", `#${issueNumber}: unblocked and ready`);\n continue;\n }\n\n logger.step(\n \"needs_triage\",\n `#${issueNumber}: moved to needs-triage (missing or conflicting type labels)`\n );\n }\n}\n\nasync function listBlockedIssues(client: GitHubClient): Promise<Issue[]> {\n const { data } = await client.octokit.rest.issues.listForRepo({\n owner: client.owner,\n repo: client.repo,\n state: \"open\",\n per_page: 100,\n labels: \"blocked\",\n });\n\n return data\n .filter((issue) => !issue.pull_request)\n .map((issue) => ({\n number: issue.number,\n title: issue.title,\n body: issue.body ?? null,\n labels: issue.labels.map((l) => ({\n name: typeof l === \"string\" ? l : (l.name ?? \"\"),\n })),\n }));\n}\n\nif (process.argv[1] === __filename) {\n void main();\n}\n\nexport { main };\n","export type BlockedIssue = {\n number: number;\n body: string | null;\n labels?: Array<{ name: string }>;\n};\n\nimport type { IssueTransitionsContract } from \"./issue-transitions\";\n\nexport type ReconcileDependencies = {\n getIssueState: (issueNumber: number) => Promise<string>;\n transitions: IssueTransitionsContract;\n typeLabels: readonly string[];\n readyLabel: string;\n};\n\nexport type ReconcileResult = \"still-blocked\" | \"unblocked\" | \"needs-triage\";\n\nexport type ReconcileBlockedIssuesResult = {\n issueNumber: number;\n result: ReconcileResult;\n};\n\nexport function parseBlockedBy(body: string | null): number[] {\n if (!body) return [];\n\n const bm = body.match(/## Blocked by\\s*\\n([\\s\\S]*?)(?=\\n## |$)/i);\n if (!bm) return [];\n\n const refs: number[] = [];\n const re = /#(\\d+)/g;\n let m;\n while ((m = re.exec(bm[1])) !== null) {\n refs.push(Number(m[1]));\n }\n return refs;\n}\n\nexport async function reconcileBlockedIssue(\n issue: BlockedIssue,\n deps: ReconcileDependencies\n): Promise<ReconcileResult> {\n const blockers = parseBlockedBy(issue.body);\n\n if (blockers.length === 0) {\n await deps.transitions.moveToNeedsTriage(issue.number);\n return \"needs-triage\";\n }\n\n const stillBlocked = await anyBlockerStillOpen(blockers, deps.getIssueState);\n if (stillBlocked) {\n return \"still-blocked\";\n }\n\n const labels = issue.labels ?? [];\n const typeLabels = labels.filter((l) => deps.typeLabels.includes(l.name));\n\n if (typeLabels.length === 1) {\n await deps.transitions.removeBlocked(issue.number);\n const alreadyReady = labels.some((l) => l.name === deps.readyLabel);\n if (!alreadyReady) {\n await deps.transitions.addReadyForAgent(issue.number);\n }\n return \"unblocked\";\n }\n\n await deps.transitions.moveToNeedsTriage(issue.number);\n return \"needs-triage\";\n}\n\nexport async function reconcileBlockedIssues(\n issues: BlockedIssue[],\n deps: ReconcileDependencies\n): Promise<ReconcileBlockedIssuesResult[]> {\n const results: ReconcileBlockedIssuesResult[] = [];\n\n for (const issue of issues) {\n const result = await reconcileBlockedIssue(issue, deps);\n results.push({ issueNumber: issue.number, result });\n }\n\n return results;\n}\n\nasync function anyBlockerStillOpen(\n refs: number[],\n getIssueState: (issueNumber: number) => Promise<string>\n): Promise<boolean> {\n for (const ref of refs) {\n const state = await getIssueState(ref);\n if (state !== \"CLOSED\") {\n return true;\n }\n }\n\n return false;\n}\n","export interface IssueTransitionLabels {\n blocked: string;\n readyForAgent: string;\n needsTriage: string;\n agentInProgress: string;\n readyForHuman: string;\n prOpenAwaitingMerge: string;\n}\n\nexport interface IssueTransitionsContract {\n removeBlocked(issueNumber: number): Promise<void>;\n addReadyForAgent(issueNumber: number): Promise<void>;\n moveToNeedsTriage(issueNumber: number): Promise<void>;\n moveToReadyForHuman(issueNumber: number): Promise<void>;\n closeCompleted(issueNumber: number): Promise<void>;\n}\n\nexport interface IssueTransitionDeps {\n fetchIssue(issueNumber: number): Promise<{ labels: string[] }>;\n addLabels(issueNumber: number, labels: string[]): Promise<void>;\n removeLabel(issueNumber: number, label: string): Promise<void>;\n closeIssue?(issueNumber: number): Promise<void>;\n updateLabels?(\n issueNumber: number,\n removes: string[],\n adds: string[]\n ): Promise<void>;\n}\n\nexport function createIssueTransitions(\n deps: IssueTransitionDeps,\n labels: IssueTransitionLabels\n): IssueTransitionsContract {\n return {\n async removeBlocked(issueNumber: number): Promise<void> {\n await deps.removeLabel(issueNumber, labels.blocked);\n },\n async addReadyForAgent(issueNumber: number): Promise<void> {\n const issue = await deps.fetchIssue(issueNumber);\n if (!issue.labels.includes(labels.readyForAgent)) {\n await deps.addLabels(issueNumber, [labels.readyForAgent]);\n }\n },\n async moveToNeedsTriage(issueNumber: number): Promise<void> {\n if (deps.updateLabels) {\n await deps.updateLabels(\n issueNumber,\n [labels.blocked, labels.readyForAgent],\n [labels.needsTriage]\n );\n } else {\n await deps.removeLabel(issueNumber, labels.blocked);\n const issue = await deps.fetchIssue(issueNumber);\n if (issue.labels.includes(labels.readyForAgent)) {\n await deps.removeLabel(issueNumber, labels.readyForAgent);\n }\n await deps.addLabels(issueNumber, [labels.needsTriage]);\n }\n },\n async moveToReadyForHuman(issueNumber: number): Promise<void> {\n try {\n await deps.removeLabel(issueNumber, labels.agentInProgress);\n } catch {\n // Ignore - label may not exist\n }\n try {\n await deps.removeLabel(issueNumber, labels.readyForAgent);\n } catch {\n // Ignore - label may not exist\n }\n await deps.addLabels(issueNumber, [labels.readyForHuman]);\n },\n async closeCompleted(issueNumber: number): Promise<void> {\n try {\n await deps.removeLabel(issueNumber, labels.agentInProgress);\n } catch {\n // Ignore - label may not exist\n }\n try {\n await deps.removeLabel(issueNumber, labels.prOpenAwaitingMerge);\n } catch {\n // Ignore - label may not exist\n }\n if (!deps.closeIssue) {\n throw new Error(\"closeIssue is required for closeCompleted\");\n }\n await deps.closeIssue(issueNumber);\n },\n };\n}\n","import { Octokit } from \"octokit\";\n\nexport interface GitHubClient {\n octokit: Octokit;\n owner: string;\n repo: string;\n}\n\nexport interface GitHubClientOptions {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n repository?: string;\n}\n\nconst REMOTE_PATTERN = /github\\.com[:/]([^/]+)\\/([^/]+?)(?:\\.git)?$/;\n\nexport function resolveGitHubToken(env: NodeJS.ProcessEnv): string {\n const token = env.POURKIT_GITHUB_TOKEN ?? env.GH_TOKEN ?? env.GITHUB_TOKEN;\n if (!token) {\n throw new Error(\n \"GitHub token is required. Set POURKIT_GITHUB_TOKEN, GH_TOKEN, or GITHUB_TOKEN.\"\n );\n }\n return token;\n}\n\nexport async function resolveGitHubRepository(\n options?: GitHubClientOptions\n): Promise<{ owner: string; repo: string }> {\n if (options?.repository) {\n const parts = options.repository.split(\"/\");\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new Error(\n `Invalid repository format: \"${options.repository}\". Expected \"owner/repo\".`\n );\n }\n return { owner: parts[0], repo: parts[1] };\n }\n\n const env = options?.env ?? process.env;\n const envRepo = env.GITHUB_REPOSITORY;\n if (envRepo) {\n const parts = envRepo.split(\"/\");\n if (parts.length === 2 && parts[0] && parts[1]) {\n return { owner: parts[0], repo: parts[1] };\n }\n throw new Error(\n `Invalid repository format: \"${envRepo}\". Expected \"owner/repo\".`\n );\n }\n\n const { execCapture } = await import(\"../shared/common\");\n const cwd = options?.cwd;\n try {\n const result = await execCapture(\"git\", [\"remote\", \"get-url\", \"origin\"], {\n cwd,\n });\n const remote = result.stdout.trim();\n const match = remote.match(REMOTE_PATTERN);\n if (match) {\n return { owner: match[1], repo: match[2] };\n }\n } catch {\n // fall through to error\n }\n\n throw new Error(\n \"Could not resolve GitHub repository. Set GITHUB_REPOSITORY env var or ensure a valid 'origin' remote exists.\"\n );\n}\n\nexport async function requireGitHubClient(\n options?: GitHubClientOptions\n): Promise<GitHubClient> {\n const env = options?.env ?? process.env;\n const token = resolveGitHubToken(env);\n const repo = await resolveGitHubRepository(options);\n\n const octokit = new Octokit({ auth: token });\n\n return { octokit, ...repo };\n}\n\nexport async function tryCreateGitHubClient(\n options?: GitHubClientOptions\n): Promise<\n | { ok: true; client: GitHubClient }\n | {\n ok: false;\n reason: \"missing-token\" | \"missing-repository\" | \"invalid-repository\";\n message: string;\n }\n> {\n const env = options?.env ?? process.env;\n\n let token: string;\n try {\n token = resolveGitHubToken(env);\n } catch {\n return {\n ok: false,\n reason: \"missing-token\",\n message: \"GitHub token is not configured.\",\n };\n }\n\n let repo: { owner: string; repo: string };\n try {\n repo = await resolveGitHubRepository(options);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n if (message.includes(\"Invalid repository format\")) {\n return { ok: false, reason: \"invalid-repository\", message };\n }\n return { ok: false, reason: \"missing-repository\", message };\n }\n\n const octokit = new Octokit({ auth: token });\n\n return { ok: true, client: { octokit, ...repo } };\n}\n"],"mappings":"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","names":["path","execCapture"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pourkit/cli",
|
|
3
|
+
"version": "0.0.0-next-20260529095319",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/pourkit-ai/pourkit.git"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"bin": {
|
|
14
|
+
"pourkit": "dist/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup --config tsup.config.ts",
|
|
21
|
+
"postbuild": "chmod +x dist/cli.js dist/e2e/run-live-e2e.js dist/issues/unblock.js dist/issues/close-issues-on-merge.js",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.json --noEmit --pretty false"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@pourkit/logger": "*"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@clack/prompts": "^0.10.1",
|
|
29
|
+
"commander": "^14.0.3",
|
|
30
|
+
"octokit": "^5.0.5",
|
|
31
|
+
"zod": "^3.24.5"
|
|
32
|
+
}
|
|
33
|
+
}
|