# izri CI/CD Integration Guide

izri receives GitHub webhooks and runs your Playwright E2E tests in Docker.
This guide explains how to wire your own CI pipeline so it **notifies izri
on every push or PR** and **blocks the build until the tests pass**.

---

## Table of Contents

1. [How it works](#how-it-works)
2. [Get your API token](#get-your-api-token)
3. [GitHub Actions](#github-actions)
4. [GitLab CI](#gitlab-ci)
5. [Jenkins](#jenkins)
6. [CLI helper script](#cli-helper-script)
7. [API reference](#api-reference)
8. [Troubleshooting](#troubleshooting)

---

## How it works

```
Your CI pipeline
      │
      │  POST /api/ci/trigger/:projectId
      │  { commitSha, branch, ref, suitesToRun?, strategy?, notes? }
      ▼
  izri API  ──►  Docker executor  ──►  Playwright tests
      │
      │  GET /api/test-runs/:runId/status
      │  { status: "PENDING" | "RUNNING" | "PASSED" | "FAILED" | "ERROR" }
      ▼
Your CI pipeline (polls every 10 s, fails on FAILED/ERROR)
```

1. Your pipeline sends a POST with commit metadata to the izri CI trigger endpoint.
2. izri returns a `runId`.
3. Your pipeline polls `GET /api/test-runs/:runId/status` until the status is
   terminal (`PASSED`, `FAILED`, or `ERROR`).
4. The pipeline exits 0 on `PASSED`, 1 on `FAILED`/`ERROR`, or 2 on timeout.

---

## Get your API token

1. Log in to your izri dashboard.
2. Navigate to **Settings → API Tokens**.
3. Click **Create token**, give it a name (e.g. `ci-github-actions`), and copy
   the token — it is only shown once.
4. Note your **Project ID** (UUID) from the project's Settings page.

---

## GitHub Actions

Copy [`github-actions.yml`](./github-actions.yml) to
`.github/workflows/izri.yml` in your repository.

### Required secrets

| Secret name               | Description                                   |
|---------------------------|-----------------------------------------------|
| `IZRI_TEST_BASE_URL`      | Base URL of your izri instance, e.g. `https://izri.example.com` |
| `IZRI_TEST_PROJECT_ID`    | Project UUID from the izri dashboard     |
| `IZRI_TEST_API_TOKEN`     | API token (mark as **Secret**)                |

Add them at **Settings → Secrets and variables → Actions** in your GitHub repo.

### What the workflow does

| Job                 | Purpose                                                              |
|---------------------|----------------------------------------------------------------------|
| `notify`            | POSTs commit/PR metadata to izri; outputs `run_id`             |
| `wait-for-results`  | Polls the status endpoint every 10 s; fails the build on test failure |

The `wait-for-results` job has a 30-minute `timeout-minutes` guard; exit code 2
is returned on timeout (treated as a pipeline failure).

---

## GitLab CI

[`gitlab-ci.yml`](./gitlab-ci.yml) provides a hidden `.izri` job template
you can extend in your own pipeline.

### Option A — include from this repo

```yaml
include:
  - project: 'chellahub/izri'
    file: 'docs/ci-cd/gitlab-ci.yml'

izri:
  extends: .izri
  stage: test
```

### Option B — copy the template

Copy the contents of `gitlab-ci.yml` into your own `.gitlab-ci.yml`.

### Required CI/CD variables

Go to **Settings → CI/CD → Variables** in your GitLab project.

| Variable name             | Flags          | Description                              |
|---------------------------|----------------|------------------------------------------|
| `IZRI_TEST_BASE_URL`      | Masked         | Base URL of izri                    |
| `IZRI_TEST_PROJECT_ID`    | —              | Project UUID                             |
| `IZRI_TEST_API_TOKEN`     | Masked, Protected | API token                            |
| `IZRI_TEST_TIMEOUT`       | _(optional)_   | Poll timeout in seconds (default: 1800)  |

The job runs on both `push` and `merge_request_event` pipeline sources by
default. Adjust the `rules:` block if you need different trigger conditions.

---

## Jenkins

Copy [`Jenkinsfile`](./Jenkinsfile) to your repository root (or reference it
from your Multibranch Pipeline configuration).

### Required credentials

Go to **Manage Jenkins → Credentials**.

| Credential ID             | Kind        | Description                              |
|---------------------------|-------------|------------------------------------------|
| `IZRI_TEST_BASE_URL`      | Secret text | Base URL of izri                    |
| `IZRI_TEST_PROJECT_ID`    | Secret text | Project UUID                             |
| `IZRI_TEST_API_TOKEN`     | Secret text | API token                                |

The pipeline uses the `readJSON` step from the **Pipeline Utility Steps** plugin.
Install it from **Manage Jenkins → Plugins** if it is not already present.

### What the pipeline does

| Stage                   | Purpose                                                            |
|-------------------------|--------------------------------------------------------------------|
| `Notify izri`      | POSTs metadata; retries up to 3× on 5xx errors; stores `run_id`   |
| `Wait for E2E results`  | Polls every 10 s; calls `error()` (fails the build) on FAILED/ERROR |

---

## CLI helper script

[`izri-wait.sh`](./izri-wait.sh) is a standalone Bash script that
wraps the polling logic. Use it in any CI system that can run shell commands.

```bash
chmod +x docs/ci-cd/izri-wait.sh

./docs/ci-cd/izri-wait.sh \
  --run-id   "<run-id-from-webhook-response>" \
  --api-token "$IZRI_TEST_API_TOKEN" \
  --base-url  "$IZRI_TEST_BASE_URL" \
  --timeout   1800   # optional, default 1800 s
```

**Exit codes:**

| Code | Meaning           |
|------|-------------------|
| `0`  | PASSED            |
| `1`  | FAILED or ERROR   |
| `2`  | Timeout           |
| `3`  | Usage/config error |

**Dependencies:** `curl`, `jq`

---

## API reference

### Trigger a test run

```
POST /api/ci/trigger/:projectId
Authorization: Bearer <api-token>
Content-Type: application/json

{
  "commitSha":   "<commit-sha>",       // optional
  "branch":      "<branch-name>",      // optional
  "ref":         "<ref>",              // optional
  "suitesToRun": ["suite1", "suite2"], // optional
  "strategy":    "smart|full|critical-only", // optional
  "notes":       "Triggered by CI"    // optional
}
```

**Response `200 OK`:**

```json
{ "runId": "01HXYZ...", "status": "PENDING" }
```

### Poll test run status

```
GET /api/test-runs/:runId/status
Authorization: Bearer <api-token>
```

**Response `200 OK`:**

```json
{
  "runId":        "01HXYZ...",
  "status":       "PENDING" | "RUNNING" | "PASSED" | "FAILED" | "ERROR",
  "createdAt":    "2024-01-15T10:00:00Z",
  "completedAt":  "2024-01-15T10:30:00Z",
  "passedCount":  12,
  "failedCount":  0,
  "totalCount":   12
}
```

---

## Troubleshooting

### `401 Unauthorized`

- Verify the API token is correct and has not expired.
- Ensure the `Authorization: Bearer <token>` header is being sent.
- Check that the token was created for the correct izri instance.

### `404 Project not found`

- Confirm the `IZRI_TEST_PROJECT_ID` matches the **Project UUID** in the
  izri dashboard (not the project slug/name).
- Ensure the API token was created by a user who owns the project.

### Tests never move out of `PENDING`

- Check the izri server logs for Docker executor errors.
- Verify the Docker daemon is running on the izri host.
- Ensure the Playwright Docker image is available or can be pulled.

### Pipeline times out before tests finish

- Increase `IZRI_TEST_TIMEOUT` (GitLab) / `timeout-minutes` (GitHub Actions) /
  `timeout(time: …)` (Jenkins).
- Check if the izri executor is under load — consider scaling out workers.

### Retry logic

All templates retry the initial webhook POST up to 3 times on `5xx` server
errors with a 5-second back-off. The status polling loop retries indefinitely
on non-`200` responses until the timeout is reached.

### Debug mode

Add `-v` to the `curl` commands in any template to see full request/response
headers. In GitHub Actions you can also add
`ACTIONS_STEP_DEBUG: true` to your repository secrets.
