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

# GitHub Integration (Advanced)

> Manage tests in GitHub and run them via Actions using loadforge-cli.

This guide shows how to manage LoadForge tests and run them automatically from GitHub using the CLI. It covers repo layout, required secrets, and sample workflows.

## Repo layout

Tests live under `tests/<slug>/`:

```text theme={null}
tests/<slug>/
  locustfile.py
  config.json
```

`config.json` fields managed by the CLI:

```json theme={null}
{
  "users": 200,
  "rate": 1,
  "servers": 2,
  "host": "https://example.com:443",
  "apdex_target": 300,
  "p95_target": 600,
  "error_perc_target": 0,
  "region_servers": { "nyc3": 1, "sfo3": 1 }
}
```

Notes:

* Slug is the unique test name.
* `host` is protocol+hostname+port; the CLI resolves/creates the Host and sends `host_id`.
* New tests require `region` present on create; for updates, `region` defaults to remote if omitted.
* Only `test_type = "load"` is supported for pull/push currently.

## Required secret

Add to your repo or org secrets:

* `API_KEY`: your LoadForge API key (used as env var `API_KEY`).

References: [Introduction](/api-reference/introduction), [List Hosts](/api-reference/endpoint/hosts-list), [List Tests](/api-reference/endpoint/tests-list), [Update Test](/api-reference/endpoint/tests-update), [Start Run](/api-reference/endpoint/run-start), [Get Result](/api-reference/endpoint/result-get)

## Install method in CI

Use npx (no install step needed; both aliases work):

```bash theme={null}
npx loadforge-cli --help
# or
npx lf-cli --help
```

Or cache node\_modules and install once:

```bash theme={null}
npm ci
npx loadforge-cli --help
```

## Workflow: sync configs on push to main

Sync local configs and locustfiles to LoadForge when PRs are merged. Creates new tests and updates existing ones by slug; optionally prunes remote tests not present locally.

```yaml theme={null}
name: Sync LoadForge tests

on:
  push:
    branches: [ main ]

jobs:
  sync:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Push tests to LoadForge
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          npx loadforge-cli push --dir tests --dry-run=false --allow-create --allow-delete
```

Behavior:

* Intersection (same slug) → PATCH
* Local-only → create (with `--allow-create`)
* Remote-only → delete/prune (with `--allow-delete`)
* Extended fields are attempted; if rejected, the CLI falls back to base fields.

## Workflow: drift check (no changes)

Detect drift between main and LoadForge without making changes.

```yaml theme={null}
name: LoadForge drift check

on:
  pull_request:
    branches: [ main ]

jobs:
  check:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Dry run push (no changes)
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          npx loadforge-cli push --dir tests --dry-run
```

## Workflow: run tests on demand (matrix by slug)

Start runs and wait for completion. The `wait` command exits with:

* 0: run\_status=3 and run\_passed=true
* 2: run\_status=3 and run\_passed=false (explanation printed)
* 1: run\_status>=4 (failure reason printed)

```yaml theme={null}
name: LoadForge run (matrix)

on:
  workflow_dispatch:
    inputs:
      duration:
        description: Minutes (>=2)
        required: true
        default: '5'

jobs:
  run:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        slug: [ lf-website ] # add more slugs here
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Start run
        id: start
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          RUN_ID=$(npx loadforge-cli start "${{ matrix.slug }}" -d "${{ github.event.inputs.duration }}")
          echo "RUN_ID=$RUN_ID" >> $GITHUB_OUTPUT

      - name: Wait for result
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          npx loadforge-cli wait "${{ steps.start.outputs.RUN_ID }}"
```

Use the exit code to fail the job if the run failed to execute or if it completed but did not pass thresholds (apdex/error%/p95).

## Workflow: nightly scheduled runs

```yaml theme={null}
name: Nightly LoadForge runs

on:
  schedule:
    - cron: '0 2 * * *' # 02:00 UTC daily

jobs:
  nightly:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        slug: [ lf-website ] # extend as needed
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Start and wait
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          RUN_ID=$(npx loadforge-cli start "${{ matrix.slug }}" -d 5)
          npx loadforge-cli wait "$RUN_ID"
```

## Hosts management via config.host

* Specify a host string in `config.json`, e.g., `"host": "https://example.com:443"`.
* On push, the CLI resolves to an existing Host (protocol/url/port match) or creates one if missing, and sends `host_id` automatically.
* No need to store host IDs in git.

## Pulling from LoadForge

To bootstrap or refresh local files:

```bash theme={null}
npx loadforge-cli pull --out tests
```

This writes `tests/<slug>/locustfile.py` and `tests/<slug>/config.json` for all load tests. It writes `host` strings by resolving `host_id` via the Hosts API.

## Creating new tests (local scaffold)

Create a new test folder (interactive or via flags). Then push with `--allow-create` to create it remotely.

```bash theme={null}
# Interactive
npx loadforge-cli create

# Non-interactive
npx loadforge-cli create --name my-test --users 50 --host https://example.com:443
npx loadforge-cli push --allow-create
```

## References

* Intro/Auth: /api-reference/introduction
* Hosts (list): /api-reference/endpoint/hosts-list
* Tests (list): /api-reference/endpoint/tests-list
* Tests (update): /api-reference/endpoint/tests-update
* Run (start): /api-reference/endpoint/run-start
* Result (get): /api-reference/endpoint/result-get
