---
name: ci-run-local
description: >
  Run a GitLab CI job locally by reconstructing its environment (predefined CI_* vars,
  group + project CI/CD variables, .gitlab-ci.yml variables), downloading its input
  artifacts, generating a temporary script, and executing it — in the job's Docker image
  by default. Use when the user says /ci-run-local, 'rejoue ce job en local',
  'run this job locally', 'exécute le job en local', 'reproduis le job CI en local',
  'debug ce job localement', 'teste mon script CI en local', 'lance le job <name> en local',
  or wants to reproduce/debug a CI job on their machine without pushing to the pipeline.
argument-hint: "<job name, e.g. 'unit-tests', or 'rejoue le job lint en local'>"
allowed-tools:
  - Read
  - Glob
  - Grep
  - Bash
  - Skill
---

Run a GitLab CI job **locally**: reconstruct an environment equivalent to the real pipeline and execute the job's script, by default inside the job's Docker image.

All heavy lifting is done by `pysae-ai-tools ci run-local` — it parses `.gitlab-ci.yml` (following `include:`, `extends:`, `default:`, anchors and `!reference`), resolves the effective `image`/`before_script`/`script`/`after_script`, builds the full variable set (predefined `CI_*` + group + project + YAML, with GitLab precedence and `$VAR` expansion), downloads `needs:`/`dependencies:` artifacts, generates `runner.sh` + a `0600` `env.sh`, and runs it.

Use it to debug a failing job, replay a job locally, or develop a script destined for the pipeline without pushing on every iteration.

## Required tools

- `glab`
- `docker`

Run `pysae-ai-tools tools require glab docker` before starting; if it exits non-zero, abort and report the install command from stderr to the user. (When the user explicitly asks for `--no-docker`, `glab` alone is enough — `pysae-ai-tools tools require glab`.)

## Security

The generated scripts go in `.ci/local/<job-name>/` by default (under the current directory; override with `--out-dir`), and `.ci/local/` is automatically added to the repo `.gitignore`. The `env.sh` inside holds **resolved secrets** (group/project CI/CD variables) and is written with `chmod 600`. **Never** print `env.sh`'s contents, `cat` it, paste it into the conversation, or commit it. Only ever surface the *keys* (via `inspect`), never values.

## Workflow

1. **Interpret `$ARGUMENTS`** to find the target job name. If it's natural language ("rejoue le lint", "le job de tests unitaires"), map it to the real job name — read `.gitlab-ci.yml` or run `pysae-ai-tools ci run-local inspect <guess>` (it lists available jobs on a miss).

2. **Inspect first** — show the user what will run, without side effects:
   ```bash
   pysae-ai-tools ci run-local inspect <job_name>
   ```
   This prints the resolved image, stage, flattened `before_script`/`script`/`after_script`, `needs`/`dependencies`, and the variable **keys** with their source (never the values). Use it to confirm the resolution looks right.

3. **Run the job** (foreground, so the user sees the live output):
   ```bash
   pysae-ai-tools ci run-local run <job_name>
   ```
   By default this runs **inside the job's Docker image**, fetches input artifacts, and reconstructs group + project variables. The final line of stdout is a JSON summary:
   ```json
   {"job": "unit-tests", "backend": "docker", "image": "…", "script_path": "…",
    "env_path": "…", "exit_code": 0, "downloaded_artifacts": ["build"], "warnings": []}
   ```
   The process exit code equals the job's exit code.

4. **Report in French**: the backend used, the image, the exit code, and any warnings. If the job failed, read the streamed output to explain why, and propose a fix or delegate to `/ci-debug` for deeper analysis.

## Useful flags

- `--no-docker` — run on the **host shell** instead of the image (fast for iterating on a script; environment may diverge from CI).
- `--generate-only` — write `runner.sh` + `env.sh` and print their paths **without executing** (inspect/develop the generated script).
- `--no-remote-vars` — skip group/project UI variables (no secrets pulled locally; only `CI_*` + `.gitlab-ci.yml` vars). Jobs needing a token will fail.
- `--no-artifacts` — don't download `needs:`/`dependencies:` artifacts.
- `--var KEY=VALUE` — inject/override a variable (highest precedence) — e.g. supply a token manually with `--no-remote-vars`.
- `--image <ref>` — override the job image, or supply it when the job declares none (it would otherwise use the **runner's default image**, which isn't in the repo).
- `--no-pull` — don't `docker pull` the image (use the local copy).
- `--scope <env>` — filter UI variables by `environment_scope` (default `*`).
- `--out-dir <path>` — write the generated scripts elsewhere (default `.ci/local/<job-name>/`; skips the `.gitignore` edit).

## Rules

- **Always `inspect` before `run`** the first time on a job, so the user can confirm the resolved image and script.
- **Never reveal `env.sh` contents** — keys only.
- If `--docker` (default) but the job has no `image:` or the Docker daemon is down, the command errors and suggests `--no-docker` — relay that to the user.
- If a private image fails to pull, the command tries a `glab`-token `docker login`; if that fails, tell the user to run `docker login registry.gitlab.com` manually.
- **French** for communication, English for commands.

$ARGUMENTS
