---
name: glab-mr-approve
description: >
  Approve a GitLab merge request via the glab CLI, optionally gating a manual-testing confirmation
  and a Slack visibility post after approval. Use when the user says /glab-mr-approve,
  'approuve la MR', 'approuve cette MR', 'valide la MR', 'approuve !42', 'donne ton approbation',
  'approuve la merge request', 'approve the MR', 'approve this MR', 'sign off on the MR',
  'give your approval', 'approve !123', or when delegated from /code-review after an APPROVED
  verdict. Distinct from /glab-mr-merge (which merges the MR) — this only records the approval and
  never merges. In CI it never approves: approval must come from a human.
argument-hint: "[optional: MR !IID — defaults to the MR for the current branch] [optional: --ask=false|true|auto — gate the manual-testing confirmation; default 'auto' asks in local mode and never in CI] [optional: --notify=true|false — gate the Slack notification after approve; default 'true'. Callers that merge immediately afterwards (e.g. /code-autopilot --merge=auto) pass 'false' and post their own post-merge summary instead]"
allowed-tools:
  - Read
  - Bash
  - Skill
  - AskUserQuestion
---

Approve a GitLab merge request using the `glab` CLI.

## Required tools

- `glab`
- `jq`

Run `pysae-ai-tools tools require <tools>` before starting; if it exits non-zero, abort and report the install command from stderr to the user.

## Mode detection

Detect the execution context using `detect_context` (pass `$ARGUMENTS` refs for automatic parsing of `!IID`, URLs):
```bash
CTX=$(pysae-ai-tools internal detect-context $ARGUMENTS_REFS)
IS_CI=$(echo "$CTX" | jq -r '.is_ci')
MR_IID=$(echo "$CTX" | jq -r '.mr_iid // empty')
MR_URL=$(echo "$CTX" | jq -r '.mr_url // empty')

# Parse the --ask flag (default: auto).
ASK_MODE=$(echo "$ARGUMENTS" | grep -oE -- "--ask=(false|true|auto)" | sed 's/--ask=//' | tail -n1)
[ -z "$ASK_MODE" ] && ASK_MODE="auto"

# Parse the --notify flag (default: true). 'false' suppresses every
# /slack-ask-review call from this skill — used by callers that merge the MR
# immediately afterwards and post their own post-merge summary.
NOTIFY_MODE=$(echo "$ARGUMENTS" | grep -oE -- "--notify=(false|true)" | sed 's/--notify=//' | tail -n1)
[ -z "$NOTIFY_MODE" ] && NOTIFY_MODE="true"
```

In CI mode (`IS_CI` is `true`):
- **Never approve the MR** — exit immediately without error. Approval must come from a human.
- **Never use `AskUserQuestion`**
- **Never invoke `/slack-ask-review`**

## Process

1. **Resolve MR IID** — use `MR_IID` from detect_context above (refs in `$ARGUMENTS` are parsed automatically).
   If `MR_IID` is empty, inform the user and stop.

2. **Confirm manual testing** — gated by `ASK_MODE` (resolved in Mode detection):

   - `ASK_MODE == "false"`: **skip this step entirely** and proceed to step 3. Typical callers: re-approval after an automatic rebase, `/code-autopilot` delegating an autonomous approve.
   - `ASK_MODE == "auto"` (default): **skip in CI** (proceed to step 3), **ask in local mode** (next paragraph).
   - `ASK_MODE == "true"`: **always ask** — but in CI mode, `AskUserQuestion` is forbidden, so log a warning to stderr and skip (effectively collapses to `false` in CI).

   In local mode (when asking), display the MR link (`$MR_URL`) and ask in **two steps**.

   **Step 2a — single-select** (`AskUserQuestion`, header « Approbation »). Question: « La MR !<MR_IID> (<MR_URL>) est prête. As-tu testé manuellement les changements ? ». Two options:
   - **« J'ai testé — approuver directement »** → proceed to step 3.
   - **« Je ne suis pas encore sûr, laisse-moi choisir »** → go to step 2b.

   **Step 2b — multi-select** (`AskUserQuestion`, `multiSelect: true`, header « Avant d'approuver »), only when 2a returned the second option. Question: « Que veux-tu faire avant d'approuver ? ». Options:
   - **« Lancer les tests en CI »**
   - **« Ouvrir la MR dans le navigateur »**
   - **« Déployer en review pour tester »**

   Run the selected preparatory actions as follows:
   1. **Ouvrir la MR dans le navigateur** — first, synchronously: run `glab mr view <MR_IID> --web`. In a headless context this exits non-zero (no browser / `BROWSER` unset or invalid) — don't propagate the failure: display `$MR_URL` in clear instead.
   2. Then run **Lancer les tests en CI** and **Déployer en review pour tester** **in parallel** (whichever are selected):
      - **Lancer les tests en CI** → invoke the `/ci-run` skill with `tests` to trigger the CI test job on the MR branch (`/ci-run` reads `.gitlab-ci.yml` to resolve the project's test job name); surface the pipeline/job link.
      - **Déployer en review pour tester** → run the **review-deploy flow** below; surface the review URL (and the pipeline link it spawns).

   Then **stop and wait**: recap the relevant links (pipeline, review URL, MR) and tell the user to re-run `/glab-mr-approve` once ready to approve. **Never approve in this branch** — the user chose to test first.

   **Review-deploy flow**:
   1. Invoke the `/ci-deploy-status` skill with `review` to check the review environment
   2. If verdict is `DEPLOYED` → display the review URL so the user can test
   3. If verdict is `NOT_DEPLOYED`, `NO_DEPLOY_JOB`, or `NO_PIPELINE` → invoke `/ci-deploy` with `review` to trigger the deployment, then display the URL once deployed
   4. If verdict is `DEPLOYING` → inform the user the deploy is in progress, provide the pipeline link
   5. If verdict is `DEPLOY_FAILED` or `DEPLOYED_UNHEALTHY` → report the issue, suggest `/ci-debug`

3. **Approve the MR**:
   ```bash
   glab mr approve <MR_IID>
   ```
   On **success in local mode with `NOTIFY_MODE == "true"`**, notify the team that the AI validated the MR: invoke the `/slack-ask-review` skill with `--approved-by-ai`. It posts the standard review message with an extra `:white_check_mark: *Validée par IA*` line under the title (same content as a review request, just flagged as AI-validated). **Never** do this in CI mode — the MR is never approved there anyway (see Mode detection).

   > ⚠️ **This notification is NOT a review request — it is a visibility post.** Its purpose is to give the team visibility on the work the AI just validated, on Slack. Do **not** skip it on your own rationale ("the user will merge soon", "asking for a review would be counter-productive"): the **only** sanctioned ways to skip it are CI mode, the approval-failure fallback below, and an explicit `--notify=false` from the caller. `--notify=false` exists precisely for flows that merge immediately after approving (e.g. `/code-autopilot --merge=auto`): a pre-merge "review" message would be incoherent noise there, and the caller posts a single post-merge summary instead.

4. **Handle an approval failure** — **never assume anything about the project's approval configuration** (whether the author is allowed to approve, whether a pipeline must pass first, how many approvals are required, …). Do **not** pre-check it: always run the approve (step 3) and react to the actual result. The error, if any, depends entirely on that config.
   - **Success** → continue (the Slack `--approved-by-ai` notification in step 3, gated by `NOTIFY_MODE`).
   - **Any failure** (401, 403, 405, 409, « already approved », rule denied, etc.) in **local mode with `NOTIFY_MODE == "true"`** → fall back to the `/slack-ask-review` skill (without `--approved-by-ai`) to request a manual review on Slack. Do not interpret the specific cause — just surface that the approval didn't go through and a human review is requested. With `NOTIFY_MODE == "false"`, log the failure and let the caller decide (an auto-merge caller will surface it in its own summary).
   - **Any failure in CI mode** → log the error to stderr and continue — **never invoke `/slack-ask-review` in CI**.
   - If `glab` itself is not available, report the error to the user.

$ARGUMENTS
