Skip to content
Fallow home
All docs pages

fallow ci: post PR and MR feedback from CI

Reference for fallow ci: post or update the sticky PR comment, post inline reviews, resolve fixed review threads, and post GitHub Check Runs from rendered fallow output.

fallow ci posts fallow feedback to a pull request (GitHub) or a merge request (GitLab). The GitHub Action and the GitLab CI template call these commands for you. Use them directly when you build your own CI integration.

Each command reads a file that an earlier fallow run rendered. It does not analyze the project.

SubcommandWhat it doesProviders
plan-pr-commentComputes the action for a sticky summary comment. It does not call an API.Both
post-pr-commentCreates, updates, or skips the sticky summary comment.GitHub, GitLab
post-reviewPosts the new findings of a review envelope as inline review comments, and resolves the fallow threads of fixed findings.GitHub, GitLab
reconcile-reviewResolves the fallow review threads of findings that went away.GitHub, GitLab
post-check-runPosts a GitHub Check Run from a PR decision file.GitHub
fallow dead-code --format pr-comment-github --quiet > fallow-comment.md
fallow ci post-pr-comment --provider github --pr 42 \
  --body fallow-comment.md --marker-id fallow-results

Input files

FileHow to make it
PR comment bodyRun an analysis with --format pr-comment-github or --format pr-comment-gitlab. The body has a <!-- fallow-id: <marker> --> line. The default marker is fallow-results.
PR comment envelopeSet FALLOW_PR_COMMENT_ENVELOPE_FILE to a path when you render the comment body. Fallow then also writes the typed envelope to that path.
PR decision fileSet FALLOW_PR_DECISION_FILE to a path when you render the comment body. Fallow then writes a fallow-pr-decision/v1 JSON file to that path.
Review envelopeRun an analysis with --format review-github or --format review-gitlab.

Authentication

ProviderTokenRepository or project
GitHubGH_TOKEN, else GITHUB_TOKEN--repo <owner/name>, else GH_REPO, else GITHUB_REPOSITORY
GitLabGITLAB_TOKEN, a project access token or a personal access token with api scope--project-id, else CI_PROJECT_ID

The API base URL is --api-url. The GitHub default is github.com. The GitLab default is CI_API_V4_URL, else https://gitlab.com/api/v4. The GitLab CI_JOB_TOKEN cannot create or update MR notes, so fallow does not use it.

These environment variables also change the behavior:

VariableEffect
FALLOW_BOT_LOGINThe user name that fallow treats as its own when it finds an existing comment. Set it when you post with a personal access token.
FALLOW_API_RETRIESThe maximum number of HTTP attempts (default 3).
FALLOW_API_RETRY_DELAYThe minimum delay in seconds between retries (default 2). A Retry-After header overrides it.
FALLOW_CONSOLIDATED_STATUSWith post-check-run --split-gates, set it to 1, true, yes, or on to also post one aggregate check.

ci plan-pr-comment

Computes what to do with a sticky summary comment. It does not call a provider API. Use it when your own script posts the comment.

FlagDescription
--body <BODY>Required. The path of the rendered comment body.
--marker-id <MARKER_ID>Required. The sticky marker id in the body.
--cleanTreat the body as a clean result with no findings.
--existing-comment-id <ID>The id of the existing sticky comment, when one exists.
--existing-body <PATH>The path of the body of the existing comment. With this flag, the plan can skip an unchanged comment.

The output is JSON with an action: create, update, or skip. A skip has a skip_reason: clean_no_existing_comment (a clean run with no comment to update) or unchanged (the body did not change).

{
  "action": "create",
  "marker_id": "fallow-results",
  "body": "<!-- fallow-id: fallow-results -->\n### Fallow codebase report\n..."
}

ci post-pr-comment

Finds the existing sticky comment, then creates, updates, or skips it. The rules are the same as in plan-pr-comment.

FlagDescription
--provider <PROVIDER>Required. github or gitlab.
--pr <PR>The pull request number (GitHub).
--mr <MR>The merge request IID (GitLab).
--body <BODY>Required. The path of the rendered comment body.
--envelope <ENVELOPE>The path of the typed PR comment envelope, when you have one.
--marker-id <MARKER_ID>Required. The sticky marker id in the body.
--cleanTreat the body as a clean result with no findings.
--repo <REPO>The GitHub repository, in owner/name form.
--project-id <PROJECT_ID>The GitLab project id or path.
--api-url <API_URL>The provider API base URL.
--dry-runCompute the plan. Do not create or update the comment.

The command prints the plan as JSON on stdout.

ci post-review

Posts a review envelope to the pull request or merge request. On GitHub, the comments go into one review. On GitLab, each comment is a discussion on the diff. The command posts only the comments whose fingerprint is not in an open fallow thread. It also resolves the fallow threads of findings that are not in the envelope any more, as reconcile-review does.

FlagDescription
--provider <PROVIDER>Required. github or gitlab.
--pr <PR>The pull request number (GitHub).
--mr <MR>The merge request IID (GitLab).
--envelope <ENVELOPE>Required. The path of a review-github or review-gitlab JSON envelope.
--repo <REPO>The GitHub repository, in owner/name form.
--project-id <PROJECT_ID>The GitLab project id or path.
--api-url <API_URL>The provider API base URL.
--dry-runCompute the plan. Do not create comments.

The JSON result gives comments_posted, comments_skipped, stale_fingerprints, and threads_resolved. A comment that the provider rejects goes into post_errors, and the command still exits 0. See CI integration for the fingerprint markers.

ci reconcile-review

Checks a review envelope and computes a stable plan. Then it resolves the fallow threads of findings that are not in the envelope any more.

FlagDescription
--provider <PROVIDER>Required. github or gitlab.
--pr <PR>The pull request number (GitHub).
--mr <MR>The merge request IID (GitLab).
--envelope <ENVELOPE>Required. The path of a review-github or review-gitlab JSON envelope.
--repo <REPO>The GitHub repository, in owner/name form.
--project-id <PROJECT_ID>The GitLab project id or path.
--api-url <API_URL>The provider API base URL.
--dry-runCompute the plan. Do not post resolution notes or resolve threads.

ci post-check-run

Posts a GitHub Check Run from a PR decision file. Only GitHub is supported. --provider gitlab exits with code 2.

FlagDescription
--provider <PROVIDER>Required. Use github.
--decision <DECISION>Required. The path of a fallow-pr-decision/v1 JSON file.
--repo <REPO>Required. The GitHub repository, in owner/name form.
--head-sha <HEAD_SHA>Required. The commit that the check run attaches to.
--api-url <API_URL>The GitHub API base URL.
--split-gatesPost one check run for each gate, named Fallow / <gate>, in place of one Fallow check.
--dry-runPrint the check run payload. Do not post it.
FALLOW_PR_DECISION_FILE=fallow-pr-decision.json \
  fallow dead-code --format pr-comment-github --quiet > fallow-comment.md
fallow ci post-check-run --provider github --decision fallow-pr-decision.json \
  --repo acme/app --head-sha "$GITHUB_SHA" --split-gates

Use --split-gates to make each gate a separate required check. See Gates.

Exit codes

CodeMeaning
0The command ran. A skipped post is a success. Errors for single comments or threads are in the post_errors and apply_errors arrays of the JSON result.
2Invalid input, for example a file that fallow cannot read, an invalid envelope, or a missing --repo.
7A network or provider API failure, for example a missing token or a failed API request.

With --format json, an error is a JSON object with "error": true on stdout.

See also