MR Auto Approver

The MR Auto Approver is a RabbitMQ consumer that listens for GitLab merge_request webhook events and automatically approves MRs that match configurable rules. It is primarily used to auto-approve Renovate/Mintmaker dependency update MRs.

How it works

  1. GitLab sends merge_request webhooks to the CKI receiver Lambda
  2. Events flow through SQS → amqp-bridge → RabbitMQ exchange
  3. The auto-approver consumes events from its queue
  4. For each MR event (action: open or update):
    • Look up the project in config
    • Evaluate ordered rules (first match wins)
    • If a rule matches with action approve: call GitLab’s approve API
    • If a rule matches with action deny: log and skip

Security

  • User identity is matched by user_id (immutable integer), not by username. This prevents spoofing via GitLab username changes.
  • Per-project access tokens: each supported project has its own GitLab project access token (Maintainer role, api scope). Tokens are resolved via cki_lib.gitlab’s longest-prefix matching on MR_APPROVER_GITLAB_TOKENS.
  • Fork MRs are always skipped (source_project_id != target_project_id).

Configuration

The config file is mounted from deployment-all as a ConfigMap at /config/config.yaml (configurable via MR_APPROVER_CONFIG_PATH).

settings:
  gitlab_tokens_env: MR_APPROVER_GITLAB_TOKENS

projects:
  cki-project/kernel-ark:
    rules:
      - user_ids: [12345678]          # renovate-bot's GitLab user ID
        branch_regexes: ["renovate/.*", "mintmaker/.*"]
        action: approve

Rule semantics

  • First match wins: rules are evaluated in order; the first matching rule determines the action.
  • AND across fields: both user_ids and branch_regexes must match (if specified) for a rule to fire.
  • OR within a field: any user_id in the list OR any branch_regex matching is sufficient for that field.
  • Empty field = no constraint: omitting user_ids means any user matches for that dimension.
  • action: approve (default) or deny.

Finding a user’s GitLab ID

curl -s "https://gitlab.com/api/v4/users?username=renovate-bot" | jq '.[0].id'

Environment variables

Variable Required Description
MR_APPROVER_CONFIG_PATH no Path to config YAML (default: /config/config.yaml)
MR_APPROVER_GITLAB_TOKENS yes JSON map: project URL prefix → token env var name
GITLAB_APPROVAL_TOKEN_* yes Per-project GitLab access tokens (referenced by the map)
MR_AUTO_APPROVER_ROUTING_KEYS yes Space-separated RabbitMQ routing keys
MR_AUTO_APPROVER_QUEUE no Queue name (default: auto-generated)
WEBHOOK_RECEIVER_EXCHANGE no Exchange name (default: cki.exchange.webhooks)
RABBITMQ_USER yes RabbitMQ credentials
RABBITMQ_PASSWORD yes RabbitMQ credentials
RABBITMQ_HOST yes RabbitMQ host
RABBITMQ_PORT yes RabbitMQ port
RABBITMQ_VIRTUAL_HOST yes RabbitMQ vhost
SENTRY_DSN no Sentry error reporting

Metrics

Prometheus metrics are exposed on port 8765 at /metrics:

  • cki_mr_auto_approver_messages_total{result}: counter with labels:
    • approved: MR was successfully approved
    • denied: rule matched with action=deny
    • no_match: no rule matched for the project
    • approval_failed: approve API call failed
    • ignored_not_gitlab: non-GitLab message
    • ignored_not_mr: non-merge_request event
    • ignored_action: MR action not in {open, update}
    • ignored_fork: fork MR skipped
    • ignored_incomplete: incomplete webhook payload
    • ignored_no_config: project not in config