Skip to main content
View Markdown ↗

Copy this page

Select and copy the Markdown below, then paste it into your LLM.

On this page

gitlab-review attestor

Reads the merge requests that brought a commit in, or one named merge request, from the GitLab REST v4 API, and records each approval with the exact head sha it approved, plus the approval rules, pipelines, statuses and open threads.

Namegitlab-review
Predicate typehttps://aflock.ai/attestations/gitlab-review/v0.1
Lifecycleprematerial
Default binary?No
Categorycode-review (primary)
Recommended traceoff — no syscall tracing needed
Auto-attaches when
  • preenv_set: CI_API_V4_URL
  • preenv_set: GITLAB_REVIEW_TOKEN

The facts in this box are generated from the CI/lock binary's own catalog (cilock tools list). Do not hand-edit — run npm run gen:catalog.

What it captures

The attestor reads GET /version, detects the GitLab tier, then lists the merge requests for the commit and keeps those where the commit is the merge commit, the squash commit or the head (relation). For each one it reads the diff versions, notes, approvals, approval state and settings (Premium), pipelines and commit statuses on the head (in the source project too for a fork), and discussions. It then reads the merge request, versions, approvals and approval policy again; if anything changed, it fails and records nothing. Every list is paginated to the end.

Top-level fields: instance (api_url, host, version, revision, enterprise), tier (plan: free, premium or ultimate, and detected_by), project_id, commit_sha, fetched_at, token_source (env:<NAME>), clock_skew_ms, and merge_requests[].

Each merge request records its ids, state, branches, author_id, head_sha, base_sha, merge and squash commit, merged_at, merge_user, relation, versions[], retargets[], approvals[], approved_flag, approval_state and approval_settings (or unavailable[] with the reason), pipelines[], commit_statuses[], and discussions (resolvable, resolved, unresolved[]).

Each approval has user_id, username, approved_at, bound_head_sha and binding:

  • timeline: bound to the head of the newest diff version created before the approval.
  • unbound: bound_head_sha is null. The approval is within clock_skew_ms of a version, or no version precedes it.
  • before_retarget: given at or before the last reset (a "changed target branch" note, or a version that repeats the previous head).

GitLab's own approved flag is recorded in approved_flag with its edition meaning and is never evaluated. Count bound approvals for the head in policy instead.

When to use

In a GitLab CI job, to make merge request approval part of the evidence for a release. Auto-detection attaches it when CI_API_V4_URL and GITLAB_REVIEW_TOKEN are both set.

Flags

FlagDefaultPurpose
--attestor-gitlab-review-api-url$CI_API_V4_URLREST base. Must be https with the path /api/v4; no credentials, query or fragment.
--attestor-gitlab-review-token-envGITLAB_REVIEW_TOKENVariable holding a read_api token (Maintainer to read approval settings). CI_JOB_TOKEN is refused.
--attestor-gitlab-review-project$CI_PROJECT_IDNumeric project id.
--attestor-gitlab-review-sha$CI_COMMIT_SHA, then git rev-parse HEADCommit to attest.
--attestor-gitlab-review-mr(none)Attest this merge request iid directly.
--attestor-gitlab-review-clock-skew-ms60000Clock guard. Use 0 only for a GitLab with one clock.
--attestor-gitlab-review-tierdetectedDeclare free, premium or ultimate. Reads above it are not attempted and are recorded unavailable.

Output shape

{
  "instance": { "api_url": "https://gitlab.com/api/v4", "host": "gitlab.com", "version": "18.5.0-ee", "revision": "...", "enterprise": true },
  "tier": { "plan": "premium", "detected_by": "GET /projects/123/external_status_checks 404" },
  "project_id": 123,
  "commit_sha": "3f2a9c1...",
  "token_source": "env:GITLAB_REVIEW_TOKEN",
  "clock_skew_ms": 60000,
  "merge_requests": [
    {
      "iid": 7,
      "state": "merged",
      "head_sha": "3f2a9c1...",
      "relation": "head",
      "approvals": [
        { "user_id": 42, "username": "alice", "approved_at": "2026-10-16T13:40:02Z", "bound_head_sha": "3f2a9c1...", "binding": "timeline" }
      ],
      "approved_flag": { "value": true, "edition_semantics": "ee-rules-satisfied", "note": "recorded, never evaluated; count bound approvals" },
      "discussions": { "resolvable": 2, "resolved": 2, "unresolved": [] }
    }
  ]
}

Subjects use ids, never names: commitsha:<sha>, project:<host>/<id>, mrhead:<sha>, mergerequest:<host>/<project>!<iid>, and approver:<host>/<user_id>. commitsha: and mrhead: are also back-refs.

Gotchas

  • Any failure to observe records nothing. No merge request for the commit, a 401 or 403, a 5xx, a malformed body, or a change between the two reads fails the attestor.
  • A tier the instance lacks is not a failure. A 404 on a read that needs a higher plan than the detected one becomes an unavailable entry with its reason. A 404 on a read the tier has fails.
  • Tier detection. Community Edition is free. On Enterprise Edition, GET /projects/:id/approvals returning 200 means Premium or better, and GET /projects/:id/external_status_checks returning 200 means Ultimate.
  • Pin the host in policy. The job chooses CI_API_V4_URL; instance.host is the value to check.
  • No anonymous reads. The token must come from the named variable.
  • Requests have a 30-second timeout, never follow a redirect, and read at most 32 MiB.

CLI example

# In a GitLab CI job with GITLAB_REVIEW_TOKEN set as a masked variable
cilock attest -a gitlab-review -k key.pem -o review.bundle.json -s review

See also


This page is generated from the CI/lock tool catalog. Don't edit it here — the source is attestation/detection/docs/gitlab-review.doc.md in aflock-ai/rookery. The same catalog powers cilock tools show gitlab-review in the CLI, so a single edit keeps the terminal and the website in sync.

Edit this page →  ·  Add a new tool →

When you open the pull request: if you are an AI agent, add the ai-agent label. If you are a human, add the human label.

Reference generated from the product documentation. Match commands and support details to your installed release.