> For the complete documentation index, see [llms.txt](https://docs.controltheory.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.controltheory.com/controltheory-documentation/dstl8-docs/code-graph/ci.md).

# CI Integration

Push code graphs from GitHub Actions, GitLab CI, or Jenkins

Run the code graph push on every merge to the default branch. The extractor is fast (seconds, even on large repos), the push is skipped when nothing changed, and every integration below is **fail-open** — a graph problem must never break a build.

## Getting a token

CI authenticates with a `dstl8_` API token:

1. In the portal, go to **Org Settings → API Tokens** and create a token (it's shown once — store it immediately in your CI secret store).
2. Or mint a service token via the API (org admin required):

```bash
curl -fsS -X POST "https://acme.app.dstl8.ai/api/tokens/service" \
  -H "Authorization: Bearer <your-access-token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"GitHub Actions CI","service_name":"github-actions","role":"user","expires_in":"365d","scopes":["*"]}'
```

The same token works for the [events action](/controltheory-documentation/dstl8-docs/events.md) — one secret covers both integrations.

Two rules apply everywhere:

* **Default branch only.** The server tracks one lineage per repo. Pushes from other branches are reported as a skip and exit 0, so a mis-wired trigger warns instead of failing.
* **Add a weekly cron.** Snapshot retention follows your log-data retention; a scheduled push keeps low-traffic repos inside the window. When nothing changed it's nearly free — the client skips the upload if the server copy is fresh, and the server just renews an aging identical snapshot.

## GitHub Actions

The `dstl8-codegraph` action installs a pinned CLI release (checksum-verified against the release's `SHA256SUMS`) and runs `dstl8 graph push`.

```yaml
# .github/workflows/codegraph.yml
name: dstl8 code graph
on:
  push:
    branches: [main]        # default branch only — the server rejects others
  schedule:
    - cron: "17 6 * * 1"    # weekly refresh keeps low-traffic repos current
jobs:
  codegraph:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 50    # enough history to diff against the last push
      - uses: control-theory/dstl8/.github/actions/dstl8-codegraph@main
        with:
          api-url: ${{ vars.DSTL8_EVENT_API_URL }}   # e.g. https://acme.app.dstl8.ai
          token: ${{ secrets.DSTL8_EVENT_TOKEN }}
```

**Inputs:**

| Input        | Required | Default  | Description                                                                                                          |
| ------------ | -------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
| `api-url`    | yes      |          | Org API base URL (e.g. `https://acme.app.dstl8.ai`)                                                                  |
| `token`      | yes      |          | `dstl8_` API token                                                                                                   |
| `version`    | no       | `latest` | dstl8 CLI version to pin (e.g. `v1.9.0`); `latest` resolves the newest release                                       |
| `path`       | no       | `.`      | Directory to extract (for monorepos where the graph root isn't the repo root)                                        |
| `extra-args` | no       |          | Extra arguments appended to `dstl8 graph push` (e.g. `--exclude 'gen/**'` or `--service checkout='cmd/checkout/**'`) |

**Fail-open semantics:** every failure mode — unsupported runner architecture, CLI download failure, checksum mismatch, push error — emits a `::warning::` annotation and exits 0. The calling job always succeeds. Check the workflow's annotations if graphs stop arriving.

**Checkout depth:** `fetch-depth: 0` is *not* required. The diff against the previously pushed snapshot needs that snapshot's commit to exist locally, so `fetch-depth: 50` covers typical push cadence. A too-shallow clone degrades gracefully — the snapshot pushes without a diff.

{% hint style="success" %}
Pair it with a deploy marker: `dstl8-codegraph` on merge to main tells Dstl8 *what the code looks like*; a `deploy` [event](/controltheory-documentation/dstl8-docs/events.md) with the commit SHA at deploy time tells it *when that code shipped*. Together they give Möbius the full what-changed picture.
{% endhint %}

## GitLab CI

Plain CLI + env auth. `allow_failure: true` gives you the fail-open behavior; `GIT_DEPTH: "50"` covers the diff.

```yaml
# .gitlab-ci.yml
dstl8-codegraph:
  stage: build
  allow_failure: true
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
  variables:
    GIT_DEPTH: "50"
  script:
    - curl -fsSL https://install.dstl8.ai/script/dstl8-cli | sh
    - dstl8 graph push --json
```

Set `DSTL8_API_TOKEN` (masked) and `DSTL8_API_URL` as CI/CD variables — the CLI authenticates from the environment alone, no profile or login step. Add a [scheduled pipeline](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) on the default branch for the weekly refresh.

## Jenkins

```groovy
stage('dstl8 code graph') {
  when { branch 'main' }
  environment {
    DSTL8_API_TOKEN = credentials('dstl8-api-token')
    DSTL8_API_URL   = 'https://acme.app.dstl8.ai'
  }
  steps {
    // fail-open: never break the build over a graph push
    sh 'curl -fsSL https://install.dstl8.ai/script/dstl8-cli | sh && dstl8 graph push --json || true'
  }
}
```

## Any other CI

The whole integration is one authenticated command from the repo checkout:

```bash
DSTL8_API_TOKEN="dstl8_…" DSTL8_API_URL="https://acme.app.dstl8.ai" dstl8 graph push --json
```

Gate it to the default branch, tolerate failure, and prefer a checkout with \~50 commits of history. In checkouts without a usable `.git` (source exports), pass the identity flags — see [gitless environments](/controltheory-documentation/dstl8-docs/code-graph/cli.md#gitless-environment-exported-tarball-no-git) in the CLI reference.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.controltheory.com/controltheory-documentation/dstl8-docs/code-graph/ci.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
