GitHub PR Reviewer
An AI first pass on pull requests, posted as inline comments
A GitHub Action in development that sends a pull request's diff to OpenAI and posts each finding as an inline review comment with a severity.
Solo build
The problem
A pull request often waits for a reviewer, and the first pass is the same every time: look for obvious bugs, risky code and style slips. I wanted that first pass to be there before a person opens the PR, as normal review comments on the lines in question, without the tool taking any decision away from the reviewer.
What I built
A GitHub Action written in TypeScript. When a pull request event fires, it fetches the PR's diff, asks an OpenAI
model to review it, and posts the result as one review with inline comments. Each comment starts with a severity
label ([INFO], [WARNING] or [CRITICAL]) and sits on the file and line the model points at. It only comments:
approving, requesting changes and merging stay with people.
See it running
A recorded walkthrough of GitHub PR Reviewer is on the way. Until then, the write-up and the diagram below show how it works.
How it fits together
From pull request to inline review comments
- Pull requestOpened or updated on GitHubpull_request eventpull_request event
- GitHub ActionTypeScript on GitHub's runner (node20)Fetches the full diffOctokitfull diff
- OpenAI, JSON modeOne Chat Completions call, default gpt-4ofile, line, commentinfo, warning, criticalfindings as JSON
- Inline commentsOne review, event COMMENTSeverity prefixNo approve or block
How it works
The action reads four inputs: openai_key, github_token, model (default gpt-4o) and include_severity. It
takes the PR number from the event payload and skips with a warning if there is none. It then fetches the unified
diff through Octokit and sends the whole diff to the OpenAI Chat Completions API in JSON mode. The system prompt
asks for bugs, security vulnerabilities and major code-style issues, each as {file, lineNumber, comment, severity}.
The findings become one review with event: 'COMMENT':
const githubComments = comments.map(c => ({
path: c.file,
line: c.lineNumber,
body: `**[${c.severity.toUpperCase()}]** ${c.comment}`,
}));
Full file: src/github.ts. The prompt sees only the diff, with no wider repository context, and the whole diff goes in one request.
Stack: TypeScript, a node20 JavaScript action, @actions/core and @actions/github, the OpenAI SDK, and three Jest
tests with mocked GitHub and OpenAI clients.
Status and links
In development. The code is public on GitHub with a v1.0.0 pre-release, but it is not ready to drop into a
workflow yet: action.yml points at a build file the build doesn't produce, so the action can't start as
committed. What it still needs before it works: a fixed entry point, the include_severity filter applied (it is
read but not used yet), committed tests that pass cleanly, and large diffs handled in parts instead of one request. There is no demo
video yet; the repo link above is the place to read the code.
Need something like this built?
I build AI automations, agents and Salesforce solutions for teams. Tell me what you want to automate and I’ll tell you honestly whether it’s a fit.
Comments
Loading comments...