> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raigal.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# CI/CD pipelines

> Integrate Raigal into GitHub Actions, GitLab CI, and Bitbucket Pipelines.

Configure Raigal to evaluate pull requests in CI, enforce quality gates, and report live metrics to your dashboard at [app.raigal.dev](https://app.raigal.dev).

Running `raigal init` automatically detects your repository's CI provider and scaffolds your workflow file without guesswork.

## Environment variables

Provide these variables in your CI runner environment:

| Variable | Required | Description | Example |
| - | - | - | - |
| `RAIGAL_TOKEN` | Recommended\* | Organization API key (`rgl_live_...`) | `rgl_live_8f3a9b...` |
| `RAIGAL_ORG_ID` | Conditional | Organization ID (`org_...`), required if repository owner belongs to multiple Raigal organizations | `org_2tQ...` |
| `RAIGAL_API_URL` | Optional | Custom backend URL (defaults to `https://app.raigal.dev`) | `https://app.raigal.dev` |

*Note: In GitHub Actions jobs configured with `permissions: id-token: write`, static tokens can be omitted because Raigal validates the runner using zero-token cryptographic GitHub OIDC directly. Configuring `RAIGAL_TOKEN` as a repository secret is still recommended for multi-platform consistency.*

## GitHub Actions

### 1. Hardened pull request check

Create `.github/workflows/raigal.yml` to evaluate pull requests, report results to your dashboard, and optionally generate SARIF annotations:

```yaml theme={null}
name: Raigal quality gate

on:
  push:
    branches: [main, master, develop]
  pull_request:
    branches: [main, master, develop]

permissions:
  contents: read
  id-token: write        # Enables zero-token cryptographic OIDC authentication
  security-events: write # Required for GitHub Code Scanning SARIF upload

jobs:
  quality-gate:
    name: Code quality gate
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Full git history required for base diff resolution

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Run Raigal quality gate
        env:
          RAIGAL_TOKEN: ${{ secrets.RAIGAL_TOKEN }}
          # RAIGAL_ORG_ID: ${{ vars.RAIGAL_ORG_ID }} # Required only if account owner is bound to multiple organizations
        run: |
          if [ "${{ github.event_name }}" = "pull_request" ]; then
            git fetch origin ${{ github.base_ref }} --depth=1
            npx --yes @methiu/raigal@latest ci --changes --base origin/${{ github.base_ref }}
          else
            npx --yes @methiu/raigal@latest ci .
          fi

      - name: Generate SARIF security report (optional)
        if: always()
        run: npx --yes @methiu/raigal@latest scan . --sarif > raigal-results.sarif

      - name: Upload SARIF to GitHub Code Scanning (optional)
        if: always() && github.event.pull_request.head.repo.full_name == github.repository
        uses: github/codeql-action/upload-sarif@v3
        continue-on-error: true
        with:
          sarif_file: raigal-results.sarif
          category: raigal
```

> [!NOTE]
>
> Uploading SARIF reports to GitHub Code Scanning on private repositories requires GitHub Advanced Security (GHAS) enabled on your GitHub enterprise account. On public repositories, GitHub Code Scanning is provided at no additional cost by GitHub.

### 2. Pull request close and merge sync

> [!NOTE]
>
> If you use the official **Raigal GitHub App**, this step is unnecessary. The app receives `pull_request.closed` webhook events directly from GitHub and updates your remediation board automatically.

For standalone CI environments without the GitHub App, synchronize card status when pull requests merge or close:

```yaml theme={null}
name: Raigal PR lifecycle

on:
  pull_request:
    types: [closed]

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Synchronize PR with Raigal Cloud
        env:
          RAIGAL_TOKEN: ${{ secrets.RAIGAL_TOKEN }}
        run: |
          npx --yes @methiu/raigal@latest report-pr-closed --pr ${{ github.event.pull_request.number }} ${{ github.event.pull_request.merged && '--merged' || '' }}
```

## GitLab CI

In `.gitlab-ci.yml` (auto-generated by `raigal init`):

```yaml theme={null}
raigal_quality_gate:
  image: node:22
  stage: test
  script:
    - if [ -n "$CI_MERGE_REQUEST_IID" ]; then npx --yes @methiu/raigal@latest ci --changes --base "$CI_MERGE_REQUEST_DIFF_BASE_SHA"; else npx --yes @methiu/raigal@latest ci .; fi
  variables:
    RAIGAL_TOKEN: $RAIGAL_TOKEN
    # RAIGAL_ORG_ID: $RAIGAL_ORG_ID # Required only if repository owner belongs to multiple Raigal orgs
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```

Configure `RAIGAL_TOKEN` in GitLab under **Settings > CI/CD > Variables**.

## Bitbucket Pipelines

In `bitbucket-pipelines.yml` (auto-generated by `raigal init`):

```yaml theme={null}
pipelines:
  default:
    - step:
        name: raigal quality gate
        image: node:22
        script:
          - npx --yes @methiu/raigal@latest ci .
        secrets:
          - RAIGAL_TOKEN
          # - RAIGAL_ORG_ID
  pull-requests:
    "**":
      - step:
          name: raigal quality gate
          image: node:22
          clone:
            depth: full   # branch diffs need full history
          script:
            - git fetch origin "$BITBUCKET_PR_DESTINATION_BRANCH"
            - npx --yes @methiu/raigal@latest ci --changes --base FETCH_HEAD
          secrets:
            - RAIGAL_TOKEN
            # - RAIGAL_ORG_ID
```

Configure `RAIGAL_TOKEN` in Bitbucket under **Repository settings > Repository variables**.

## Quality gate exit codes and thresholds

In all CI providers, `raigal ci` behaves deterministically:

* **Exit code 0 (Pass)**: The overall repository score is at or above `ci.failBelow` (default: 70), and zero `error`-severity findings are present.
* **Exit code 1 (Block)**: The score dropped below `ci.failBelow`, or one or more `error`-severity findings (security risks, syntax errors, or prompt injections) were detected.
* **Exit code 2 (Licensing lapse)**: Occurs only if `licensing.onLapse` is configured as `"fail-closed"` and offline lease verification has expired without network access.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.