{"id":49296857,"url":"https://github.com/misospace/pr-reviewer-action","last_synced_at":"2026-04-26T04:04:23.865Z","repository":{"id":351593691,"uuid":"1211621353","full_name":"misospace/pr-reviewer-action","owner":"misospace","description":"Reusable GitHub Action for AI-assisted pull request review with self-hosted and cloud OpenAI-compatible models","archived":false,"fork":false,"pushed_at":"2026-04-16T20:44:29.000Z","size":52,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-16T22:35:14.060Z","etag":null,"topics":["ai","code-review","github-action","pull-request"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/misospace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-15T15:19:11.000Z","updated_at":"2026-04-16T20:44:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/misospace/pr-reviewer-action","commit_stats":null,"previous_names":["joryirving/pr-reviewer-action","misospace/pr-reviewer-action"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/misospace/pr-reviewer-action","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/misospace%2Fpr-reviewer-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/misospace%2Fpr-reviewer-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/misospace%2Fpr-reviewer-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/misospace%2Fpr-reviewer-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/misospace","download_url":"https://codeload.github.com/misospace/pr-reviewer-action/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/misospace%2Fpr-reviewer-action/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32285283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"online","status_checked_at":"2026-04-26T02:00:05.962Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","code-review","github-action","pull-request"],"created_at":"2026-04-26T04:04:23.130Z","updated_at":"2026-04-26T04:04:23.860Z","avatar_url":"https://github.com/misospace.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pr-reviewer-action\n\nAnalyze pull requests with a self-hosted or cloud OpenAI-compatible model.\n\n[![CI](https://github.com/joryirving/pr-reviewer-action/actions/workflows/ci.yaml/badge.svg)](https://github.com/joryirving/pr-reviewer-action/actions/workflows/ci.yaml)\n\nThe action gathers PR metadata, diff context, linked issue context from PR-closing references, linked sources, optional evidence provider output, image digest provenance, basic repository impact/history, and an optional standards file such as `CLAUDE.md`. It returns a structured verdict and markdown review body, and it can also publish or update a sticky PR comment.\n\n## What it supports\n\n- self-hosted OpenAI-compatible endpoints\n- cloud OpenAI-compatible subscriptions with bearer auth\n- optional fallback model/endpoint\n- optional evidence providers for repo-specific checks\n- optional managed PR comment publishing\n- automatic skip when the effective PR diff is unchanged since the last managed review\n- linked issue body ingestion from `Fixes #123`, `Closes owner/repo#456`, and similar PR-body references\n- repo-provided rules via `CLAUDE.md`, `AGENTS.md`, or a custom file\n- full prompt override via inline text or a file in the destination repo\n\n## Requirements\n\n- The repository under review must already be checked out.\n- The runner must have `gh`, `jq`, `curl`, `git`, and `python3`.\n- The workflow should run on `pull_request` events, or pass explicit `repo` and `pr_number` inputs.\n\n## Inputs\n\n| Input | Description | Required | Default |\n|-------|-------------|----------|---------|\n| `github_token` | GitHub token for PR and API access | Yes | - |\n| `repo` | Repository in `owner/name` format | No | current repository |\n| `pr_number` | Pull request number | No | current `pull_request` number |\n| `ai_base_url` | Base URL of the primary OpenAI-compatible API | Yes | - |\n| `ai_model` | Model name for the primary analysis pass | Yes | - |\n| `ai_api_key` | Optional bearer token for the primary AI endpoint | No | `\"\"` |\n| `ai_fallback_base_url` | Optional fallback OpenAI-compatible API base URL | No | `\"\"` |\n| `ai_fallback_model` | Optional fallback model name | No | `\"\"` |\n| `ai_fallback_api_key` | Optional bearer token for the fallback AI endpoint | No | `\"\"` |\n| `ai_primary_retries` | Number of retries for the primary model | No | `8` |\n| `ai_primary_retry_delay_sec` | Delay between retries in seconds | No | `15` |\n| `allowed_source_hosts` | Comma-separated allowlist for linked URL fetching | No | `github.com,api.github.com,gitlab.com,registry.terraform.io,artifacthub.io` |\n| `system_prompt` | Optional system prompt override | No | bundled prompt |\n| `system_prompt_file` | File in the reviewed repo to use as the full system prompt | No | `\"\"` |\n| `standards_file` | Explicit standards file path; takes priority over candidates | No | `\"\"` |\n| `standards_file_candidates` | Candidate files checked in order; first found is used | No | `AGENTS.md,agents.md,CLAUDE.md,claude.md,.github/ai-review-rules.md,.github/ai-review-rules.txt` |\n| `publish_review_comment` | Publish or update a managed PR comment | No | `false` |\n| `context_limit_mode` | Context budget mode: `normal` (140k/70k/220k), `low` (80k/40k/120k), `minimal` (40k/20k/60k) | No | `normal` |\n| `evidence_providers_file` | Optional JSON file in the reviewed repo defining evidence provider commands | No | `\"\"` |\n| `evidence_provider_timeout_sec` | Default timeout in seconds for each evidence provider command | No | `30` |\n| `evidence_provider_max_output_bytes` | Max stdout or stderr bytes captured per provider command | No | `20000` |\n| `evidence_blocker_enforcement` | Force `request_changes` when any provider reports blocker severity | No | `false` |\n| `skip_if_diff_unchanged` | Skip the LLM review when the current PR patch matches the last managed review fingerprint | No | `true` |\n| `comment_marker` | HTML marker for the managed PR comment | No | `\u003c!-- ai-pr-reviewer --\u003e` |\n\n## Outputs\n\n| Output | Description |\n|--------|-------------|\n| `verdict` | `approve` or `request_changes` |\n| `review_markdown` | Full markdown review body |\n| `analysis_engine` | Model and endpoint that produced the final result |\n| `should_review` | `true` when a new LLM review was run |\n| `skip_reason` | Skip reason such as `diff-unchanged` |\n| `diff_fingerprint` | Stable fingerprint of the current PR patch |\n\n## Usage\n\n### Self-hosted model\n\n```yaml\nname: AI PR Review\n\non:\n  pull_request:\n    types: [opened, reopened, synchronize, ready_for_review]\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  review:\n    if: ${{ !github.event.pull_request.draft }}\n    runs-on: self-hosted\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          ref: ${{ github.event.pull_request.head.sha }}\n\n      - uses: joryirving/pr-reviewer-action@v1\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          ai_base_url: http://llama-server.internal:8080/v1\n          ai_model: qwen3-32b\n          publish_review_comment: \"true\"\n```\n\n### Cloud model subscription\n\n```yaml\nname: AI PR Review\n\non:\n  pull_request:\n    types: [opened, reopened, synchronize, ready_for_review]\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  review:\n    if: ${{ !github.event.pull_request.draft }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          ref: ${{ github.event.pull_request.head.sha }}\n\n      - uses: joryirving/pr-reviewer-action@v1\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          ai_base_url: https://api.openai.com/v1\n          ai_model: gpt-4.1\n          ai_api_key: ${{ secrets.OPENAI_API_KEY }}\n          standards_file: CLAUDE.md\n          publish_review_comment: \"true\"\n```\n\n### With a fallback model\n\n```yaml\n- uses: joryirving/pr-reviewer-action@v1\n  id: review\n  with:\n    github_token: ${{ secrets.GITHUB_TOKEN }}\n    ai_base_url: http://llama-server.internal:8080/v1\n    ai_model: qwen3-32b\n    ai_fallback_base_url: https://api.openai.com/v1\n    ai_fallback_model: gpt-4.1-mini\n    ai_fallback_api_key: ${{ secrets.OPENAI_API_KEY }}\n```\n\n### With evidence providers\n\n```yaml\n- uses: joryirving/pr-reviewer-action@v1\n  with:\n    github_token: ${{ secrets.GITHUB_TOKEN }}\n    ai_base_url: http://llama-server.internal:8080/v1\n    ai_model: qwen3-32b\n    evidence_providers_file: .github/pr-review-providers.json\n    evidence_provider_timeout_sec: \"30\"\n    evidence_provider_max_output_bytes: \"20000\"\n    evidence_blocker_enforcement: \"true\"\n```\n\nExample provider config (`.github/pr-review-providers.json`):\n\n```json\n{\n  \"providers\": [\n    {\n      \"id\": \"version-compat\",\n      \"command\": [\"python3\", \"scripts/check_version_compat.py\"],\n      \"timeout_sec\": 45,\n      \"max_output_bytes\": 15000\n    }\n  ]\n}\n```\n\nProvider commands can print plain text, or JSON with fields such as `severity` and `findings`. If `evidence_blocker_enforcement` is `true`, any provider output with blocker severity forces a `request_changes` verdict.\n\n### Use repo-local review rules\n\nIf the destination repo has a `CLAUDE.md`, `claude.md`, `AGENTS.md`, or `.github/ai-review-rules.md`, the action can use that as review policy context.\n\n```yaml\n- uses: joryirving/pr-reviewer-action@v1\n  with:\n    github_token: ${{ secrets.GITHUB_TOKEN }}\n    ai_base_url: https://api.openai.com/v1\n    ai_model: gpt-4.1\n    ai_api_key: ${{ secrets.OPENAI_API_KEY }}\n    standards_file: \"\"\n```\n\nYou can also pin a specific rules file:\n\n```yaml\n- uses: joryirving/pr-reviewer-action@v1\n  with:\n    github_token: ${{ secrets.GITHUB_TOKEN }}\n    ai_base_url: https://api.openai.com/v1\n    ai_model: gpt-4.1\n    ai_api_key: ${{ secrets.OPENAI_API_KEY }}\n    standards_file: .github/review-rules.md\n```\n\n### Issue-first review workflows\n\nIf PRs are driven by detailed GitHub issues, include closing references such as `Fixes #40` or `Closes owner/repo#12` in the PR body. The action will fetch those issue bodies and include them in the review corpus so the model can compare the implementation against issue guidance and acceptance criteria.\n\n### Use a repo-local prompt file\n\nIf a repo wants more than policy context and needs to fully control the reviewer behavior, it can provide a prompt file:\n\n```yaml\n- uses: joryirving/pr-reviewer-action@v1\n  with:\n    github_token: ${{ secrets.GITHUB_TOKEN }}\n    ai_base_url: https://api.openai.com/v1\n    ai_model: gpt-4.1\n    ai_api_key: ${{ secrets.OPENAI_API_KEY }}\n    system_prompt_file: .github/pr-review-prompt.md\n```\n\n## Notes\n\n- The action expects an OpenAI-compatible `POST /chat/completions` API.\n- `system_prompt` takes precedence over `system_prompt_file`.\n- `system_prompt_file` takes precedence over the bundled generic prompt.\n- `standards_file` is optional; if blank, the action checks `standards_file_candidates` in order and uses the first file found. `AGENTS.md` is checked first by default, then `CLAUDE.md`, making the action compatible with both Claude Code and non-Claude Code setups.\n- By default, the action computes a stable patch fingerprint with `git patch-id --stable` and skips the LLM call when that fingerprint matches the most recent managed review comment. This avoids token spend on rebases and other history-only changes.\n- `publish_review_comment` uses `gh pr comment --edit-last --create-if-none`, so the comment is managed by the token identity used in the workflow.\n- `context_limit_mode` reduces the amount of PR data sent to the LLM. Use `minimal` for models with very small context windows. This skips nothing but truncates more aggressively.\n- `evidence_providers_file` accepts JSON only. It can be either an object with `providers: []` or a top-level provider array.\n- Provider `command` may be a shell string or an argument array. Each provider can override `timeout_sec` and `max_output_bytes`.\n- Provider output is appended to the review corpus under an `Evidence Providers` section.\n\n## Validation\n\nThis repo includes a local smoke test that exercises the action logic against a real GitHub pull request while using a mock OpenAI-compatible API server.\n\nRun it with a specific PR:\n\n```bash\nPR_NUMBER=6757 tests/smoke_test.sh\n```\n\nOr let it pick the most recent open PR in `joryirving/home-ops`:\n\n```bash\ntests/smoke_test.sh\n```\n\nThe smoke test validates:\n\n- GitHub PR data collection through `gh`\n- review corpus assembly\n- OpenAI-compatible `chat/completions` request formatting\n- output parsing and action output generation\n\n## Examples\n\nCopyable workflows are included here:\n\n- `examples/workflow-self-hosted.yml`\n- `examples/workflow-cloud.yml`\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmisospace%2Fpr-reviewer-action","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmisospace%2Fpr-reviewer-action","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmisospace%2Fpr-reviewer-action/lists"}