feat: add CLI for fetching PR comments and launching Codex#11
feat: add CLI for fetching PR comments and launching Codex#11valuecodes merged 3 commits intomainfrom
Conversation
- Implement `run:fix-pr-comments` script in package.json - Create main logic for fetching comments and formatting output - Add README with usage instructions and argument details
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b599f64973
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const repo = await ghClient.getRepo(options.repo); | ||
| const pr = await ghClient.getPrNumber(options.pr); |
There was a problem hiding this comment.
Use repo override when auto-detecting PR number
When --repo is supplied but --pr is omitted, the code resolves repo from the override but still calls getPrNumber without that override. This means gh pr view is executed in the current repository, so the detected PR number can come from a different repo and then be used against the overridden repo, leading to fetching the wrong PR’s comments or a 404. Consider passing the repo override into PR detection (or requiring --pr whenever --repo is provided) to keep repo/PR in sync.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a new CLI workflow to fetch GitHub PR conversation + review comments, write them to a markdown file, and optionally invoke codex to address the feedback.
Changes:
- Introduces
run:fix-pr-commentsscript and a newsrc/cli/fix-pr-commentscommand entrypoint. - Implements a small pipeline (
FixPrPipeline+GhClient) to resolve repo/PR and fetch comments viagh api. - Adds markdown formatting/output helpers and CLI-specific documentation.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/cli/fix-pr-comments/types/schemas.ts | Adds Zod schemas for CLI args and GitHub comment payloads |
| src/cli/fix-pr-comments/main.ts | CLI entrypoint wiring args → pipeline execution |
| src/cli/fix-pr-comments/constants.ts | Output path helpers and Codex prompt template |
| src/cli/fix-pr-comments/clients/gh-client.ts | Wraps gh calls for auth, repo/PR resolution, and comment fetching |
| src/cli/fix-pr-comments/clients/fix-pr-pipeline.ts | Orchestrates fetch → format → write → optional Codex launch |
| src/cli/fix-pr-comments/clients/comment-formatter.ts | Produces markdown output for comments |
| src/cli/fix-pr-comments/README.md | Adds command-specific usage documentation |
| package.json | Registers run:fix-pr-comments script |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| this.logger.error( | ||
| "No PR found for current branch. Use --pr=<number> to specify." | ||
| ); | ||
| process.exit(1); |
There was a problem hiding this comment.
getPrNumber() calls process.exit(1) when it can't resolve a PR. Similar to checkAuth(), this should throw an error and let main() handle exiting, so callers can reuse FixPrPipeline/GhClient programmatically and tests can assert error conditions.
| this.logger.error( | |
| "No PR found for current branch. Use --pr=<number> to specify." | |
| ); | |
| process.exit(1); | |
| const message = | |
| "No PR found for current branch. Use --pr=<number> to specify."; | |
| this.logger.error(message); | |
| throw new Error(message); |
| comment.line ?? comment.original_line ?? comment.position ?? 0; | ||
| return `— ${comment.created_at} ${comment.user.login}\n ${comment.path}:${line}\n ${comment.body}\n ${comment.html_url}\n`; |
There was a problem hiding this comment.
For review comment replies, GitHub can return null for line/original_line/position; defaulting to 0 produces misleading locations like path:0. Prefer omitting the line suffix when no line info exists, or render a clearer placeholder (e.g., path:(no line info)).
| comment.line ?? comment.original_line ?? comment.position ?? 0; | |
| return `— ${comment.created_at} ${comment.user.login}\n ${comment.path}:${line}\n ${comment.body}\n ${comment.html_url}\n`; | |
| comment.line ?? comment.original_line ?? comment.position; | |
| const location = | |
| line != null ? `${comment.path}:${line}` : `${comment.path}:(no line info)`; | |
| return `— ${comment.created_at} ${comment.user.login}\n ${location}\n ${comment.body}\n ${comment.html_url}\n`; |
| # Fix PR Comments CLI | ||
|
|
||
| Fetch all comments from a GitHub PR, write them to a markdown file, and optionally launch Codex to address review feedback. | ||
|
|
There was a problem hiding this comment.
PR description says "Added usage instructions in the README", but this change adds a new README under src/cli/fix-pr-comments/README.md without updating the repo root README.md. Either update the root README (if that's the intent) or adjust the PR description to avoid confusion.
src/cli/fix-pr-comments/constants.ts
Outdated
| export const OUTPUT_BASE_DIR = "tmp/pr-comments"; | ||
| export const OUTPUT_FILENAME = "all-comments.md"; |
There was a problem hiding this comment.
OUTPUT_BASE_DIR is defined as a single string with a forward slash ("tmp/pr-comments"). When combined with path.join on Windows this can produce mixed separators (e.g., "tmp\pr-comments"). Prefer building this path from separate segments (e.g., "tmp", "pr-comments") or exporting OUTPUT_BASE_DIR as a path.join(...) result, consistent with other code (e.g., src/cli/scrape-publications/main.ts:35-40).
| } catch { | ||
| this.logger.error("gh CLI not authenticated. Run 'gh auth login' first."); |
There was a problem hiding this comment.
checkAuth() treats any failure from gh auth status as an auth problem and logs "gh CLI not authenticated". If gh is not installed / not on PATH, this message is misleading. Consider checking the error (e.g., ENOENT) and emitting a more accurate message (or a generic "Failed to run gh" with the underlying error).
| } catch { | |
| this.logger.error("gh CLI not authenticated. Run 'gh auth login' first."); | |
| } catch (error: unknown) { | |
| if ( | |
| typeof error === "object" && | |
| error !== null && | |
| "code" in error && | |
| (error as { code?: unknown }).code === "ENOENT" | |
| ) { | |
| const message = | |
| (error as { message?: unknown }).message ?? | |
| "Executable not found (ENOENT)"; | |
| this.logger.error( | |
| `Failed to run 'gh'. Make sure the GitHub CLI is installed and on your PATH. Underlying error: ${String( | |
| message, | |
| )}`, | |
| ); | |
| } else { | |
| this.logger.error("gh CLI not authenticated. Run 'gh auth login' first."); | |
| } |
| } catch { | ||
| this.logger.error("gh CLI not authenticated. Run 'gh auth login' first."); | ||
| process.exit(1); | ||
| } |
There was a problem hiding this comment.
Avoid calling process.exit() inside GhClient methods. Exiting from a lower-level client makes the code hard to reuse/test and bypasses main()'s centralized error handling. Prefer throwing an Error (with a clear message) and let the CLI entrypoint decide exit codes.
| * Exits process if no PR found and no override provided. | ||
| */ | ||
| async getPrNumber(prOverride?: number): Promise<number> { | ||
| if (prOverride) { |
There was a problem hiding this comment.
if (prOverride) { ... } ignores valid numeric values like 0 because it relies on truthiness. Use an explicit undefined check (e.g., prOverride !== undefined) so the override is always respected, and let the downstream API call fail naturally for invalid PR numbers.
| if (prOverride) { | |
| if (prOverride !== undefined) { |
There was a problem hiding this comment.
Confirmed getPrNumber already uses an explicit undefined check for prOverride, so 0 is respected; no code change needed.
- Implemented writing review and conversation comments to separate JSON files - Updated constants for file paths in the FixPrPipeline class
- Implement `fix-pr-comments` CLI to fetch GitHub PR comments - Write markdown/JSON artifacts and optionally launch Codex for fixes - Add tests for comment formatting and enhance error handling
What
Introduce a new CLI command to fetch comments from GitHub pull requests and optionally launch Codex to address review feedback. This feature enhances the workflow for developers by automating the retrieval of PR comments and formatting them into a markdown file. The implementation includes a new script in
package.json, a dedicated pipeline for fetching comments, and a formatter for output.Added
run:fix-pr-commentsscript topackage.json.Implemented
FixPrPipelineto handle fetching and formatting comments.Created
CommentFormatterfor markdown output.Added usage instructions in the README.
How to test
Run
pnpm run:fix-pr-commentsto auto-detect the PR from the current branch.Use
pnpm run:fix-pr-comments -- --pr=<number>to specify a PR number.Check the output markdown file in
tmp/pr-comments/pr-{number}/all-comments.mdfor the formatted comments.Expected results include a markdown file containing all conversation and review comments from the specified PR.
Security review
Secrets / env vars: not changed.
Auth / session: changed. (Requires
gh auth loginfor GitHub CLI.)Network / API calls: changed. (New calls to GitHub API for fetching comments.)
Data handling / PII: not changed.
Dependencies: not changed.
No security-impacting changes identified.
No new dependencies and no network calls beyond existing GitHub API usage.
No env var changes and no auth/session logic touched.