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

# CircleCI pipelines

> Configure a CircleCI pipeline to run on Aspect Workflows CI runners: target a runner group, keep your existing bazel steps, and optionally adopt Aspect CLI tasks.

export const gatedAccess = (user, group) => {
  const loggedIn = !!(user && user.loggedIn);
  const groups = user && user.tenantMetadata && user.tenantMetadata.docsGroups || [];
  if (loggedIn && (!group || groups.indexOf(group) >= 0)) {
    return "entitled";
  }
  return loggedIn ? "signed-in" : "anonymous";
};

export const GatedLink = ({access, href, group, children}) => {
  const note = group ? "Aspect Enterprise customers" : "free Aspect account";
  const muted = {
    fontSize: "0.85em",
    opacity: 0.7,
    whiteSpace: "nowrap"
  };
  if (access === "entitled") {
    return <a href={href}>{children}</a>;
  }
  if (access !== "signed-in") {
    return <span>
        <a href={"/login?redirect=" + encodeURIComponent(href)}>{children}</a>
        <span style={muted}> (sign in: {note})</span>
      </span>;
  }
  return <span>
      {children}
      <span style={muted}> ({note})</span>
    </span>;
};

Your CircleCI pipeline runs on Aspect Workflows CI runners by targeting a runner group with `resource_class:`. Your existing `bazel` steps keep working unchanged: the [setup step](/docs/aspect-workflows/enterprise/connect/ci-setup#the-setup-step) wires the runner's remote cache, build event service and NVMe-backed output base into every invocation.

<Note>
  Registering the runners with CircleCI is covered in <GatedLink access={gatedAccess(user, "workflows-subscriber")} href="/docs/aspect-workflows/enterprise/self-hosted/runner-registration/circleci" group="workflows-subscriber">runner registration</GatedLink>.
</Note>

## Configure `.circleci/config.yml`

Point each job's `resource_class:` at your Workflows resource class and keep your existing `bazel` steps.

Every job runs the [`aspect-build/setup-aspect`](https://circleci.com/developer/orbs/orb/aspect-build/setup-aspect) orb's `setup` command after `checkout`. [The setup step](/docs/aspect-workflows/enterprise/connect/ci-setup#the-setup-step) covers what it does and the parameters it takes.

The `when` clause keeps the pipeline off scheduled triggers, which run the [warming](/docs/aspect-workflows/enterprise/ci-runners/warming) job instead.

```yaml title=.circleci/config.yml theme={null}
version: 2.1

orbs:
  setup-aspect: aspect-build/setup-aspect@2026.38.2

workflows:
  aspect-workflows:
    jobs:
      - build
      - test
    when:
      not:
        equal:
          - scheduled_pipeline
          - << pipeline.trigger_source >>

jobs:
  build:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Build
          command: bazel build //...

  test:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Test
          command: bazel test //...
```

<Note>
  Keep the <code>setup-aspect/setup</code> step on every job that runs <code>bazel</code>, so your calls pick up the runner's cache and build event service.
</Note>

## Non-Bazel jobs

Jobs that don't call Bazel need no setup step. Target the runner group and run your commands:

```yaml title=.circleci/config.yml theme={null}
jobs:
  custom-job:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - run: npm install && npm test
```

## Aspect CLI tasks (optional)

Swap a `bazel` step for the matching `aspect <task>` from the open-source [Aspect CLI](/docs/cli/overview) to add status checks, inline PR comments with one-click suggested fixes, retries on transient Bazel errors and [selective delivery](/docs/aspect-workflows/platform/features/selective-delivery).

The CLI's platform integrations (status checks, PR comments) authenticate with an `ASPECT_API_TOKEN`. Expose it as a CircleCI environment variable (via a [context](https://circleci.com/docs/contexts/) or project setting) so the setup step can authenticate the `aspect <task>` steps.

```yaml title=.circleci/config.yml theme={null}
version: 2.1

orbs:
  setup-aspect: aspect-build/setup-aspect@2026.38.2

parameters:
  force_targets:
    type: string
    default: ""

workflows:
  aspect-workflows:
    jobs:
      - build
      - test
      - format
      - lint
      - delivery:
          requires: [test]
          filters:
            branches:
              only: main
    when:
      not:
        equal:
          - scheduled_pipeline
          - << pipeline.trigger_source >>

jobs:
  build:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Build
          command: aspect build --task:name build -- //...

  test:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Test
          command: aspect test --task:name test -- //...

  format:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Format
          command: aspect format --task:name format

  lint:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Lint
          command: aspect lint --task:name lint -- //...

  delivery:
    machine: true
    resource_class: YOUR-ORG/aspect-default
    working_directory: /mnt/ephemeral/workdir
    environment:
      ASPECT_WORKFLOWS_DELIVERY_FORCE_TARGETS: << pipeline.parameters.force_targets >>
    steps:
      - checkout
      - setup-aspect/setup
      - run:
          name: Delivery
          command: aspect delivery --task:name delivery --ci-host=circle --query='attr(tags, deliverable, //...)'
```

The `delivery` job runs only on `main`. `--query` selects the targets to deliver; without it or positional targets, `aspect delivery` delivers nothing. You can set the query once in `.aspect/config.axl` instead (`ctx.tasks["delivery"].args.query`).

The `force_targets` pipeline parameter feeds `ASPECT_WORKFLOWS_DELIVERY_FORCE_TARGETS`, so a manually triggered pipeline can re-deliver named targets that delivery already resolved. See [`aspect delivery`](/docs/cli/tasks/delivery) for `--force-target`.

See [Running tasks in CI](/docs/cli/tasks-ci) for the full task reference and examples for all CI providers.

<Tip>
  See [Aspect Bazel Examples](https://app.circleci.com/pipelines/github/aspect-build/bazel-examples) for a complete working example of a CircleCI config.
</Tip>
