Skip to main content

erun review

Review code on a hosted erun platform from a terminal or an Agent — the client for the collaboration API — using the erun-type cloud alias erun cloud init erun and erun cloud login set up. List reviews, open one, comment on a line (or reply to an existing comment), resolve or reopen a comment thread, record a build against a review (or report one MERGED once its promoted environment has gate-built and pushed it), close a review, requeue one stuck at MERGE, assign or remove reviewers, and inspect or advance a target branch's merge queue.

Starting a review needs the source branch to already exist on the remote — push it first with erun exec push.

The desktop app's tenant dashboard has a Reviews tab that covers the same ground from the app: it lists reviews, their builds and their comment threads, opens a review with New review (committing and pushing the environment's branch first), closes one, advances a target branch's merge queue, and starts a new comment thread from a line in the review panel's diff.

Synopsis​

erun review list [flags]
erun review show REVIEW_ID [flags]
erun review create --name <name> --repository <remote> --source-branch <branch> --target-branch <branch> [flags]
erun review comment REVIEW_ID --commit <hash> --file <path> --line <n> [flags]
erun review resolve REVIEW_ID COMMENT_ID [flags]
erun review unresolve REVIEW_ID COMMENT_ID [flags]
erun review close REVIEW_ID [flags]
erun review record-build REVIEW_ID --commit <hash> --version <version> [flags]
erun review report-merged REVIEW_ID --build-id <id> --remote-url <url> [flags]
erun review requeue REVIEW_ID [flags]
erun review reviewers list REVIEW_ID [flags]
erun review reviewers add REVIEW_ID --user-id <id> [flags]
erun review reviewers remove REVIEW_ID --user-id <id> [flags]
erun review queue list --repository <remote> --target-branch <branch> [flags]
erun review queue advance --repository <remote> --target-branch <branch> [flags]
erun review queue override-advance --repository <remote> --target-branch <branch> --reason <text> [flags]

Every subcommand accepts --erun-alias (defaults to the sole configured erun-type alias when only one is set up), --dry-run (trace the resolved HTTP call without sending it), and the global --output json for structured results.

Subcommands​

review list​

Lists reviews visible to the caller's tenant. Every filter is optional and composable.

FlagDescription
--repositoryFilter by repository. Any form git accepts (git remote get-url origin); an SSH remote and its HTTPS form name one repository. Not defaulted from the checkout — a listing is how you find work across every repository your tenant serves.
--target-branch / --source-branchFilter by branch name.
--statusOPEN, CLOSED, FAILED, READY, MERGE, or MERGED; any casing. Anything else is refused rather than listed — see Error behaviour.
--author-user-id / --reviewer-user-idFilter by an explicit user id.
--mineReviews you authored. Resolves your user id via a whoami call first; cannot be combined with --author-user-id.
--waiting-on-meReviews you are a reviewer on. Resolves your user id via a whoami call first; cannot be combined with --reviewer-user-id.

review show​

Fetches one review together with its comment threads and recorded builds.

review create​

Opens a review. --name is the eventual squash-merge message and is unique within a repository among reviews that can still land — a colliding name fails with a conflict, while a CLOSED review's name is free to reuse. --source-branch must already be pushed (see exec push); the review references it by name and the platform can only ever fetch what has actually landed on the remote.

--repository names the repository the branches belong to, defaulting to your checkout's origin. It is what keeps two repositories a tenant serves from sharing one merge queue or colliding on the same branch pair, so a review opened without one is invisible to every repository's queue. A real, immediate write, not a preview, unless --dry-run is set.

review comment​

Comments on a line of a review, or replies to an existing comment with --reply-to. The comment body is read verbatim from stdin — never a shell, so nothing in it is reinterpreted, the same property exec commit uses for its own message input.

FlagDescription
--commitCommit hash the comment is anchored to.
--fileFile path the comment is anchored to.
--lineLine number the comment is anchored to.
--reply-toComment id to reply to, making this a reply in that thread.

review resolve / review unresolve​

Resolve a comment thread by closing its root comment, or reopen one by marking its root comment OPEN again. A thread's status lives entirely on its root comment — COMMENT_ID must be the thread's root (the first comment posted at a file/line, not one made with --reply-to); addressing a reply fails, naming the root comment to retry against. Only that thread's own root-comment author can resolve or reopen it — running this against someone else's thread is refused; ask that author, or see Merge queue § Overriding the gate if it's blocking a merge and the author is unavailable.

review close​

Closes a review without merging it.

review record-build​

Records a build against a review — the only way an erun client transitions a review off OPEN. Recording a successful build moves it to READY (and, if it was already the merge queue's head, on to MERGE); recording a failed one moves it to FAILED. There is no separate command to set a review's status directly to READY or FAILED — only a recorded build result does that. See Builds for the resource shape and validation rules.

FlagDescription
--commitFull 40-character commit hash the build ran against.
--gateRecord the merge queue's own GATE build kind instead of an ordinary build — set by the environment a review's merge queue promoted to MERGE, reporting its own build of the prospective merge. Omit --version when this is set: the gate publishes nothing.
--versionVersion the build minted — from the run's own erun build --output json, or from erun build --dry-run --output json when it failed before printing one. Required even for a failed build. A RECORDED build publishes nothing, so the version is metadata no platform path resolves: a version erun build --release produced is accepted but not required (see Builds § Triggering builds). Omit with --gate.
--failedRecord the build as failed instead of successful.
--failure-detailWhy the build failed. Only meaningful with --failed.

review report-merged​

Reports a review MERGED. The platform does not take this on trust, but which check it applies depends on where the review is sitting — not on what this command claims. Both refusals are 409 Conflict (MERGE_NOT_VERIFIED), so either way the answer is a fact about the repository rather than the caller's word.

A review at MERGE is the merge queue's. This is for the environment the queue promoted, once it has fetched the review's target and source (see exec gate-merge), gate-built the prospective squash merge, recorded that as a successful GATE build (review record-build --gate), and pushed the result — never before the push actually landed. It checks --build-id names an already-recorded, successful GATE build for this review, then fetches --remote-url to confirm that build's commit is really reachable from the target branch's tip with the parent this review was gated against. Either check failing leaves the review at MERGE.

Any other review is one whose work landed without the queue — in practice a GitHub squash merge, where the branch's own commits are deliberately not ancestors of the target and no GATE build exists to name, or a branch that landed by merge commit or fast-forward, which the same fetch confirms by its ancestry. Omit --build-id: the platform confirms against the same remote that everything the review's source branch adds, relative to where it diverged from the target, is already present in the target branch's history — or, where the branch's tip is itself in that history, that it is — and moves the review only if it is. A branch that did not land is refused just as firmly. This is what keeps a squash-landed review from sitting OPEN forever — see Merge queue § Reconciling a review that landed elsewhere.

FlagDescription
--build-idThe successful GATE build's id. Required for a review at MERGE; omit it for work that landed without the queue.
--remote-urlThe git remote the platform fetches to verify the merge. Required either way. Any form git accepts: an SSH remote — what git remote get-url origin returns on an SSH checkout — is read over the same host's HTTPS without credentials, so a public repository verifies either way, and a remote the platform cannot read that way is refused naming the form it needs.

review requeue​

Moves a review stuck at MERGE back to READY, freeing its target branch's merge-queue slot so a different review can be promoted — only one review may be at MERGE per target branch. This is for a review whose gate never reaches a terminal state, or one left at MERGE by a batched exec gate-merge whose other members landed but were never promoted (see Merge queue § When the gate wedges). The requeued review rejoins the queue at the tail, not the head — it is not promoted again immediately.

Refuses, naming the review's actual status, when it is not at MERGE. Takes no --reason: unlike queue override-advance, this bypasses no safety gate — the platform already treats MERGE -> READY as unconditionally valid — so there is nothing to make accountable.

review reviewers list / review reviewers add / review reviewers remove​

Assign or remove reviewers on a review, and list who's currently assigned. reviewers add --user-id must already be enrolled in your own tenant — checked before the network call, not only by the platform's own tenant-scoped refusal — and an already-assigned user is a 409 Conflict. Assigning a reviewer makes erun review list --waiting-on-me return that review for them; it gates no status transition by itself — see merge queue for what actually blocks a merge.

review queue list / review queue advance​

Lists or advances one repository's merge queue for a target branch. A queue belongs to a repository: two repositories a tenant serves both have a main, so --repository names which — defaulting to your checkout's origin, which is the repository this caller would gate. list returns the queue in order; advance promotes the queue's head to MERGE and starts its merge-gate build — a real build of the prospective merge, gating whether it actually lands.

It fails if the queue is empty or its head is not READY (both surface as 404 Not Found), if the queue holds reviews from more than one repository and none was named (409 Conflict, MERGE_QUEUE_AMBIGUOUS, naming them — and any waiting review that records no repository of its own, which naming one cannot reach; see error behaviour), if another review already holds that target branch's single MERGE slot (409 Conflict, naming that review — wait for it, or review requeue it back to READY), or if the head still has unresolved comment threads (409 Conflict). On that last refusal, the command names how many threads and on which review; resolve them with review resolve or use review queue override-advance. See Merge queue for the full mechanics — why the queue exists, what the gate does, and how to recover a wedged gate build with review requeue (see Merge queue § When the gate wedges).

review queue override-advance​

Bypasses review queue advance's unresolved-thread check and advances anyway. --reason is required and is recorded in the platform's audit trail alongside your identity — this is a deliberate, accountable escape hatch for a genuine exception, not a routine way to advance the queue. A tenant can grant this separately from ordinary advance, so it may be unavailable even to operators who can otherwise advance the queue.

Examples​

erun cloud init erun --api-url https://api.erunpaas.com
erun cloud login --alias erun+api.erunpaas.com@erun

erun exec push feature/add-widget
erun review create --name "Add widget" --source-branch feature/add-widget --target-branch main
erun review create --name "Add widget" --repository [email protected]:org/repo.git --source-branch feature/add-widget --target-branch main

erun review list --mine
erun review list --repository [email protected]:org/repo.git --status READY
erun review list --waiting-on-me --status OPEN

echo 'nit: rename this' | erun review comment 018f... --commit abc123 --file main.go --line 42
echo 'good catch, fixed' | erun review comment 018f... --commit abc123 --file main.go --line 42 --reply-to 018g...

erun review show 018f...
erun review resolve 018f... 018h...
erun review unresolve 018f... 018h...
erun review close 018f...

erun review record-build 018f... --commit $(git rev-parse HEAD) --version 1.2.3
erun review record-build 018f... --commit $(git rev-parse HEAD) --version 1.2.3 --failed --failure-detail "image build failed"
erun review record-build 018f... --commit $(git rev-parse HEAD) --gate
erun review report-merged 018f... --build-id 018j... --remote-url https://github.com/org/repo.git

erun review requeue 018f...

erun review reviewers add 018f... --user-id 018i...
erun review reviewers list 018f...
erun review reviewers remove 018f... --user-id 018i...

erun review queue list --repository https://github.com/org/repo.git --target-branch main
erun review queue advance --repository https://github.com/org/repo.git --target-branch main
erun review queue override-advance --repository https://github.com/org/repo.git --target-branch main --reason "hotfix, reviewers unavailable"

Error behaviour​

FailureBehaviour
No erun-type cloud alias configured.Aborts before any network call, naming erun cloud init erun --api-url <url>.
More than one erun-type alias configured, --erun-alias omitted.Aborts asking for an explicit --erun-alias.
--mine/--waiting-on-me combined with the equivalent explicit --author-user-id/--reviewer-user-id (list).Aborts before any network call.
--status names something other than OPEN, CLOSED, FAILED, READY, MERGE, or MERGED (list; any casing).Refused as a bad argument, naming the accepted values, before the alias lookup — a mistyped filter would otherwise return an empty listing, indistinguishable from a review queue that genuinely has nothing in that state. The API refuses the same value with 400 Bad Request and code INVALID_QUERY.
create with a --name that collides with a review in the same repository that can still land or did land.409 Conflict. A CLOSED review reserves nothing, so re-opening work on a rebased branch reuses the name.
create with no --repository and no origin remote in the current checkout.Aborts before any network call: a review whose repository cannot be recorded cannot be placed in any repository's merge queue.
create with a --repository the platform cannot canonicalize (a bare forge, an empty value).400 Bad Request (INVALID_REPOSITORY).
list/queue with a --repository the platform cannot canonicalize.Refused as a bad argument before the alias lookup, like a mistyped --status.
queue advance on a queue holding reviews from more than one repository, with no --repository.409 Conflict (MERGE_QUEUE_AMBIGUOUS), naming the repositories: a target branch alone names one queue only in a tenant that serves one repository, and promoting across the others would gate a branch that need not exist in the checkout driving it. Reviews created before the platform recorded a repository name none, so they are not a second repository and never cause this on their own; when the queue is several repositories' anyway, the refusal lists those rows by id, since naming a repository does not reach them.
report-merged with a --remote-url naming a repository other than the review's own.409 Conflict (MERGE_NOT_VERIFIED); an SSH remote and the HTTPS identity the review recorded are the same repository, so an SSH checkout verifies normally. A review that recorded none adopts the one the report names — and is verified against that same one, so a tenant serving two repositories that share a target branch name never has one repository's merge commit stand in as the other's gated base.
create with a --source-branch that already has a live (non-MERGED/CLOSED) review proposing it onto the same --target-branch.409 Conflict — see branch uniqueness.
show/comment/close on an unknown review id.404 Not Found.
resolve/unresolve addressed to a reply rather than its thread's root comment.Aborts before the status change, naming the root comment id to retry against.
record-build with a --commit that is not 40 lowercase hex characters.400 Bad Request (INVALID_COMMIT_ID).
record-build with a --version that fails the version grammar.400 Bad Request (INVALID_VERSION).
record-build on an unknown review id.404 Not Found.
record-build --gate --failed whose --failure-detail matches a known erun infrastructure-failure signature (a registry or network giving up, not a verdict about the change).Aborts before any network call, naming the matched signature and the remedy: report the gate run inconclusive via exec gate-run report instead of recording a FAILED GATE build.
report-merged on a review at MERGE whose --build-id does not name a recorded, successful GATE build for it.409 Conflict (MERGE_NOT_VERIFIED); the review stays at MERGE.
report-merged on a review at MERGE whose build's commit is not reachable from the target branch's tip, or whose parent does not match the tip this review was gated against.409 Conflict (MERGE_NOT_VERIFIED); the review stays at MERGE.
report-merged on any other review whose source branch's changes are not already in the target branch's history.409 Conflict (MERGE_NOT_VERIFIED); the review's status is unchanged.
report-merged on a CLOSED review.400 Bad Request (INVALID_TRANSITION); CLOSED is terminal.
requeue on a review that is not currently at MERGE.Aborts before the status change, naming the review's actual status; the platform's own refusal does too (409 Conflict, REVIEW_NOT_MERGING).
reviewers add --user-id not enrolled in your own tenant.Aborts before any network call, naming erun platform user list/erun platform user enroll.
reviewers add --user-id already assigned to the review.409 Conflict.
reviewers remove --user-id not currently assigned.404 Not Found.
queue advance on an empty queue, or whose head is not READY.404 Not Found.
queue advance while another review already holds that target branch's MERGE slot.409 Conflict (MERGE_QUEUE_OCCUPIED), naming that review and its source branch. Wait for it, or requeue it back to READY.
queue advance whose head still has unresolved comment threads.409 Conflict, naming the count and the review. Resolve them or use queue override-advance.
queue override-advance with --reason omitted or blank.Aborts before any network call.

One exit code spans every "this machine has no usable platform access" case. No alias configured, several configured with --erun-alias omitted, an alias of the wrong provider type, and an alias whose erun configuration is incomplete all abort before any network call and exit 127. That code is reserved for this condition — an ordinary failure exits 1 — so a caller reading only the exit status can tell "this machine cannot reach the platform at all" apart from "it reached the platform and the call failed", and route the work to a credentialed host instead of retrying. erun-merge and erun-merge-queue-drive use it exactly that way.