Which PRs get reviewed
One filename, and the repository holding it decides what it governs. Each review then covers only the commits since the last one.
Two rules decide what gets reviewed. There is one pipeline filename, code_review.yaml, and which repository you commit it to decides whether it governs that repository or the whole organization. And every review covers only the commits since the last review, never the whole pull request again.
Where the file lives is what it governs
Where you commit code_review.yaml | Governs |
|---|---|
| Any repository, at its root | That repository. |
Your .ellipsis repository, at its root | Every repository in the organization. |
.ellipsis/code_review.yaml works too, in any repository, and governs that repository. When a repository holds both, the root file wins.
Ellipsis takes the first one that exists: the repository's own file, else the organization-wide one, else the built-in pipeline. Consequences:
- The
.ellipsisrepository is never itself reviewed. It is pure configuration, which is what keeps one filename unambiguous. - A repository's own file replaces the organization-wide one, rather than layering onto it. A repository file that sets only
pull_requests:runs the built-in reviewers, not the ones your organization-wide file declares, so copy across whatever you meant to keep. - The organization-wide file's filters scope its own reach, not the organization's. A repository it excludes reviews itself the moment it commits its own
code_review.yaml. - Whichever file wins is still an overlay onto the built-in pipeline. Fields it leaves unset inherit the built-in ones. See the pipeline file.
ellipsis.enabled: falsemakes the file inactive, so Ellipsis reads it as no policy at all and continues to the next rung. Use it to park a draft, not to opt a repository out.- A pipeline at any other path is a configuration error, reported on the file when it syncs.
- If Ellipsis cannot read your
.ellipsisrepository (the App was removed from it, or it was renamed or deleted), the organization-wide rung drops and reviews continue on the built-in pipeline.
Only a file on the default branch is live. A code_review.yaml added on a pull request branch does not govern that pull request.
To turn reviews off in one repository, commit a file there whose pull_requests: matches nothing. Its filters are authoritative for that repository, so nothing falls through:
# code_review.yaml: no reviews in this repository
ellipsis:
version: v1
kind: code_review
name: Review disabled
pull_requests:
for:
users: false
bots: falseNew commits only
The first review of a pull request covers everything on it, including commits pushed before it was opened. Every review after that covers only the commits since the last review that posted:
base ── A ── B ── C ── D ── E commits on the PR branch
└─────────┘
review 1: base...C the PR is opened at C; the first
review reads the whole PR (A, B, C)
└────┘
review 2: C...E D and E are pushed later; the next
review reads only D and E, and never
re-comments on A, B, or C- A review that fails does not count as coverage. If a review errors or hits its budget, the commits it was reading stay unreviewed, and the next review covers everything since the last one that posted.
- A clean review still counts. A review that finds nothing posts a one-line summary, and the commits it read are covered.
- Coverage belongs to the pull request, not to the pipeline. Adopting, editing, or deleting a pipeline file mid-pull-request picks up where the last review left off.
Each review anchors to the exact commit it reviewed. The dashboard shows the commits each review covered, and the API reports the range as scope.watermark (the last reviewed commit) and scope.head.
Repo scoping
Two fields name repositories, and they answer different questions:
pull_requests.repositoriesis the watch set: which repositories' pull requests this file reviews. Valid only in the.ellipsisrepository's copy; declaring it anywhere else is a configuration error.environment.repositoriesis the context set: extra repositories cloned into every stage sandbox. The pull request's own repository is always cloned. Valid in either file.
# code_review.yaml in your .ellipsis repository
ellipsis:
version: v1
kind: code_review
name: API review with web context
pull_requests:
repositories: [api-repo]
environment:
repositories:
- name: web-repoOnly api-repo pull requests are reviewed, and web-repo is on disk while reviewing, so a change to an API response shape is judged against the client that consumes it.
The watch set is include-minus-exclude. A bare list is shorthand for include; an omitted include means every repository, so an exclude-only filter reviews everything except the listed repositories and stays correct as repositories are added later:
pull_requests:
repositories:
exclude: [sandbox-experiments, docs-repo]The watch set is authoritative for this file. Scoping the organization-wide file to api-repo means a pull request in mobile-repo gets no review, rather than the built-in pipeline. Ellipsis never reviews, or bills you for, something your file excluded.
Per-repository filters
paths globs are relative to one repository, and branch conventions differ between repositories, so one top-level filter set rarely fits an organization. An include entry may carry its own base, head, draft, labels, and paths, which replace the top-level values for that repository. A key the entry leaves out inherits the top-level one; an explicit [] overrides it to "all". for stays organization-wide.
pull_requests:
base: [default]
repositories:
include:
- name: api-repo
paths: [api/**, sql/**]
- name: docs-repo
base: [docs]
- web-repoapi-repo is reviewed only when a pull request into its default branch touches api/ or sql/; docs-repo is reviewed on pull requests into docs; web-repo inherits the top-level filters. A repository named twice, or listed under both include and exclude, is a configuration error.
Pull request filters
Beside repositories, the pull_requests: block filters on branch, draft status, labels, changed paths, and author. All declared filters must pass; an omitted filter passes everything.
ellipsis:
version: v1
kind: code_review
name: API release review
pull_requests:
repositories: [api-repo]
base: [main, "release/*"]
draft: false
paths: [src/**, sql/**]
for:
users: true
bots: falseAgainst that file, a change into main touching src/trades.py is reviewed. The same change opened as a draft is not, until it is marked ready and the next push lands. A Dependabot bump is not (bots: false). A README-only change is not (no changed file matches paths).
baseandheadmatch the target and source branch: an exact name, a prefix glob likerelease/*, or the literaldefaultfor the repository's default branch.draftunset reviews drafts and non-drafts alike;trueorfalserequires that state.labelspasses a pull request carrying at least one listed label, matched exactly including case. Labels are read when the review triggers; adding a label to an open pull request does not trigger a review by itself.pathsare include-only globs over the pull request's full changed-file set; any matching file passes. A pattern with a slash is repository-root-relative,**crosses directories, a slashless pattern matches at any depth, and a leading/anchors to the root. Negated patterns (!foo) are a validation error.forgates on the pull request's author, for the pull request's whole life.usersandbotseach taketrue, a list of logins,false, or an include-minus-exclude mapping, and a side you omit insidefor:isfalse. Logins match exactly, and bots carry their suffix:bots: ["renovate[bot]"]reviews Renovate's pull requests and no other bot's. Apull_requests:block with nofor:reviews humans and every bot, including the two the built-in pipeline excludes; write the exclusion back if you want it.
Every field, type, and default is in the reference.
Per-reviewer filters
The pipeline's pull_requests: decides which pull requests get reviewed at all. Each reviewer can carry its own pull_requests: block, with paths, base, and head only, deciding which of those it reads. A specialist scoped to paths: ["**/migrations/**"] never starts on a pull request that touches no migration: no sandbox, no model call, and its share of the run budget goes to the reviewers that did run. The worked example is under custom reviewers.
When reviews are skipped
A push produces no review when:
- Code review is off. The organization-wide setting gates every path in, including the API.
- The governing pipeline does not match the pull request. Its filters are authoritative, so a non-matching pull request gets nothing rather than the built-in pipeline.
- There is nothing new. A push whose head was already covered by the last posted review is skipped before anything starts or costs anything.
- The pipeline is over its trailing budget.
budget.dayandbudget.weekare checked before a review starts; reviews resume when the window rolls. See budgets. - A review of the pull request is already running. When it finishes, Ellipsis re-checks the pull request and immediately reviews anything that landed in the meantime.
- Every reviewer's own filters excluded the pull request. That shows as a cancelled review on the dashboard, and the commits stay uncovered until a later push matches.
In every case the incremental rule holds: commits nothing reviewed stay unreviewed, and the next review covers all of them. The one exception is a pre_review agent you configured cancelling a review: that is a judgment that the range needs no review, so it counts as coverage.
Reviewing on demand
POST /v1/reviews reviews an open pull request without waiting for a push. Which pipeline runs is not a parameter: it resolves from the repository's files exactly as above, so an on-demand review can never disagree with the automatic one. The request names owner, repo, and pull_request_number, plus an optional scope (pin a historical range by watermark and head, or kind: full to re-review the whole pull request) and post: false, which returns the findings without writing anything to GitHub. When nothing is new the response is status: skipped, not an error. See Reviews.
The CLI wraps the same route. From a checkout of the repository:
agent review 123It streams the review and prints each finding as path:line [severity/5 category] with its claim. --full re-reviews the whole pull request, --no-post keeps the findings in your terminal, and --repo owner/name targets a repository you are not inside.