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

# CI Recipes

> Wire Roboticks into GitHub Actions, Jenkins, CircleCI, and BuildKite. Minimal working snippets and the CLI-in-CI pattern for non-GitHub systems.

# CI recipes

The Roboticks GitHub App is the canonical CI integration. For everything else there is `rbtk` — a single Go binary you call from any CI system.

| CI system          | Mechanism                                                                                      |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| **GitHub Actions** | GitHub App (Check Runs) — zero YAML needed; optional `upload-action` for richer artifact paths |
| **Jenkins**        | `rbtk` CLI inside a freestyle or pipeline stage                                                |
| **CircleCI**       | `rbtk` CLI inside an orb job                                                                   |
| **BuildKite**      | `rbtk` CLI inside a pipeline step                                                              |
| **GitLab CI**      | `rbtk` CLI inside a `.gitlab-ci.yml` job (GitLab App planned post-MVP)                         |

## GitHub Actions

The GitHub App handles webhooks, Check Runs, and result upload automatically. If you want to *also* run your tests in Actions (because you already do, and you don't want to move them), use the optional `upload-action`:

```yaml theme={null}
# .github/workflows/ros2-tests.yml
name: ROS2 tests
on: [pull_request]

jobs:
  test:
    runs-on: ubuntu-22.04
    container: ros:humble
    steps:
      - uses: actions/checkout@v4

      - name: Install SDK
        run: pip install 'roboticks[mcap]' pytest-cov

      - name: Run pytest
        run: |
          pytest --cov=src --cov-report=xml:coverage.xml \
                 --junit-xml=test_results/junit.xml \
                 tests/

      - name: Upload to Roboticks
        uses: roboticks-io/upload-action@v1
        if: always()
        with:
          junit: 'test_results/**/*.xml'
          coverage: 'coverage.xml'
```

The action posts results to the Roboticks platform; the GitHub App writes them back as the Check Run. You can skip the action and let the App's own runner execute the suite — see [Self-hosted runners](/runners/installation) for the routing-label pattern that keeps the suite on your hardware.

## Jenkins

```groovy theme={null}
// Jenkinsfile
pipeline {
  agent any
  stages {
    stage('test') {
      steps {
        sh '''
          pip install 'roboticks[mcap]' pytest-cov
          pytest --cov=src --cov-report=xml:coverage.xml \
                 --junit-xml=test_results/junit.xml \
                 tests/
        '''
      }
    }
    stage('upload') {
      environment {
        ROBOTICKS_TOKEN = credentials('roboticks-token')
      }
      steps {
        sh '''
          rbtk test results upload \
            --junit 'test_results/**/*.xml' \
            --coverage coverage.xml \
            --commit "$GIT_COMMIT" \
            --branch "$BRANCH_NAME"
        '''
      }
    }
  }
}
```

The `ROBOTICKS_TOKEN` is a project-scoped API token created at **Settings → API tokens** in the dashboard.

## CircleCI

```yaml theme={null}
# .circleci/config.yml
version: 2.1
jobs:
  test:
    docker:
      - image: ros:humble
    steps:
      - checkout
      - run:
          name: Install
          command: pip install 'roboticks[mcap]' pytest-cov
      - run:
          name: Test
          command: |
            pytest --cov=src --cov-report=xml:coverage.xml \
                   --junit-xml=test_results/junit.xml tests/
      - run:
          name: Upload
          command: |
            curl -L https://github.com/roboticks-io/rbtk/releases/latest/download/rbtk-linux-amd64 -o /usr/local/bin/rbtk
            chmod +x /usr/local/bin/rbtk
            rbtk test results upload \
              --junit 'test_results/**/*.xml' \
              --coverage coverage.xml \
              --commit "$CIRCLE_SHA1" \
              --branch "$CIRCLE_BRANCH"
          environment:
            ROBOTICKS_TOKEN: $ROBOTICKS_TOKEN

workflows:
  pr:
    jobs:
      - test
```

## BuildKite

```yaml theme={null}
# .buildkite/pipeline.yml
steps:
  - label: "Test"
    command: |
      pip install 'roboticks[mcap]' pytest-cov
      pytest --cov=src --cov-report=xml:coverage.xml \
             --junit-xml=test_results/junit.xml tests/
      rbtk test results upload \
        --junit 'test_results/**/*.xml' \
        --coverage coverage.xml \
        --commit "$BUILDKITE_COMMIT" \
        --branch "$BUILDKITE_BRANCH"
    plugins:
      - docker#v5.10.0:
          image: "ros:humble"
          environment:
            - ROBOTICKS_TOKEN
```

## The CLI-in-CI pattern

For any system not listed: install `rbtk`, run your tests, upload.

```bash theme={null}
# Install (or cache)
curl -L https://github.com/roboticks-io/rbtk/releases/latest/download/rbtk-linux-amd64 -o rbtk
chmod +x rbtk

# Run your tests as usual
pytest --junit-xml=test_results/junit.xml ...

# Upload
./rbtk test results upload \
  --junit 'test_results/**/*.xml' \
  --coverage coverage.xml \
  --commit "$CI_COMMIT_SHA" \
  --branch "$CI_BRANCH"
```

The `--commit` and `--branch` flags are required so the platform can join the upload to the right traceability node. The platform does not infer them from git context — your CI may have detached HEADs, custom merge refs, or arbitrary checkout depths.

## Auth in CI

`rbtk` reads `ROBOTICKS_TOKEN` from the environment in CI mode. Create the token at:

```
app.roboticks.io → Settings → API tokens → New (scope: project)
```

Tokens are project-scoped and revocable. Rotate per the schedule your security policy demands; the platform records every upload's token ID so revocation is forensically clean.

## What you don't need

* A YAML schema for the Roboticks suite. Tests are discovered via pytest / colcon, not enumerated in CI YAML.
* A custom runner per CI system. `rbtk` is the same binary everywhere.
* A separate "report results" step beyond `test results upload`. JUnit + coverage is the entire payload.

## Next

<CardGroup cols={2}>
  <Card title="GitHub App" icon="github" href="/github-app/installation">
    The zero-YAML path. Strongly recommended over Actions+CLI.
  </Card>

  <Card title="CLI: test commands" icon="terminal" href="/cli/test-commands">
    Full `rbtk` surface.
  </Card>

  <Card title="Coverage" icon="percent" href="/testing/coverage">
    How to produce the coverage files referenced above.
  </Card>

  <Card title="Wire contract" icon="file-code" href="/testing/wire-contract">
    What the upload command actually sends.
  </Card>
</CardGroup>
