---
component: ROOT
version: "2026.3"
slug: ROOT/integrations/github-actions
canonical_url: "https://docs.develocity.ai/2026.3/integrations/ci/github-actions/"
title: "GitHub Actions"
description: "Integrate Develocity with GitHub Actions using the Gradle GitHub Action to publish a Build Scan without modifying your build scripts."
keywords:
  - "CI"
  - "continuous integration"
  - "Gradle GitHub Action"
  - "Build Scan"
status: current
---

<!-- llms-index: https://docs.develocity.ai/llms.txt -->

# GitHub Actions

<a id="preamble"></a>

> [!NOTE]
> The Develocity plugin or extension is configured in your build. See the documentation for Gradle, Maven, sbt, npm, Python, or Bazel. You have a Develocity server URL and access key.

<a id="use-the-gradle-github-action"></a>

## Use the Gradle GitHub Action

For Gradle builds, the [Gradle GitHub Action](https://github.com/marketplace/actions/build-with-gradle) instruments your CI jobs and publishes a Build Scan without modifying your build scripts. Pass the stored secret to the action via the `develocity-access-key` input so it can authenticate with your Develocity server.

Refer to the [Gradle GitHub Action documentation](https://github.com/marketplace/actions/build-with-gradle) for the complete workflow configuration, including the supported environment variables and configuration options.

<a id="other-build-tools"></a>

## Other Build Tools

For Maven builds, use the `setup-maven` action, and for npm builds, use `setup-npm`, both from the [Develocity GitHub Actions](https://github.com/gradle/develocity-actions). Like the Gradle action, they instrument the build and publish a Build Scan without modifying build scripts, and they exchange the access key passed to `develocity-access-key` for a short-lived token:

```yaml
- uses: gradle/develocity-actions/setup-maven@v2.0
  with:
    develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
```

The `setup-npm` action takes the same input.

For sbt and Python builds there is no Develocity GitHub Action. Expose `DEVELOCITY_ACCESS_KEY` as an environment variable in your workflow step and ensure the Develocity server URL is already configured in your project:

```yaml
- name: Build
  env:
    DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
  run: <build-command>
```

For Bazel builds, authentication uses HTTP headers rather than `DEVELOCITY_ACCESS_KEY`. Configure the authentication headers in your `.bazelrc` file as described in the [Bazel documentation](https://docs.develocity.ai/bazel/bazel-config/#authenticating).

<a id="store-the-access-key-as-a-secret"></a>

## Store the Access Key as a Secret

Store your Develocity access key as a [GitHub Actions secret](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions) named `DEVELOCITY_ACCESS_KEY`.

The access key value uses the format `«server host name»=«access key»`:

```properties
develocity.example.com=7w5kbqqjea4vonghohvuyra5bnvszop4asbqee3m3sm6dbjdudtq
```

<a id="authenticate-with-workload-identity"></a>

## Authenticate With Workload Identity

Instead of the stored secret from [Use the Gradle GitHub Action](#use-the-gradle-github-action), mint a short-lived OIDC token for each run and pass it to the Gradle GitHub Action (`setup-gradle`) through the same `develocity-access-key` input. The action exchanges it for a Develocity access token the same way it exchanges the stored secret.

> [!NOTE]
> Configure a Workload Identity rule in Develocity before using this flow. The audience the workflow passes to getIDToken must match the Audience configured on that rule.

Grant the job `id-token: write` permission, mint the token, and pass it to `setup-gradle` in host-qualified `«server host name»=«token»` form:

```yaml
name: Build
on: push
permissions:
  id-token: write
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Mint the Develocity credential
        id: dv
        uses: actions/github-script@v7
        with:
          script: |
            const token = await core.getIDToken('https://develocity.example.com')
            core.setSecret(token)
            core.setOutput('key', `develocity.example.com=${token}`)
      - uses: gradle/actions/setup-gradle@v4
        with:
          develocity-access-key: ${{ steps.dv.outputs.key }}
      - run: ./gradlew build
```

The Gradle plugin rejects a bare token, so keep the host name prefix.

To mint the token without `actions/github-script`, replace the mint step with a `curl` request to GitHub’s OIDC endpoint, using the `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN` variables that `id-token: write` exposes:

```yaml
- name: Mint the Develocity credential
  id: dv
  run: |
    token=$(curl -sH "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
      "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://develocity.example.com" | jq -r .value)
    echo "::add-mask::$token"
    echo "key=develocity.example.com=$token" >> "$GITHUB_OUTPUT"
```

This step produces the same `steps.dv.outputs.key` value, so the `setup-gradle` step is unchanged.

For Maven and npm builds, pass the minted value to the `develocity-access-key` input of the `setup-maven` or `setup-npm` actions from [Other Build Tools](#other-build-tools) the same way; those actions exchange it just as they exchange an access key. For sbt and Python builds, which have no exchanging action, the build uses the token directly, so it must last the whole build, as described for [Other CI Systems](https://docs.develocity.ai/2026.3/integrations/ci/other-ci/#authenticate-with-workload-identity).

<a id="verify-the-integration"></a>

## Verify the Integration

After your first CI run, open your Develocity server and navigate to Build Scan. Your build should appear there. Install the [Common Custom User Data plugin](https://docs.develocity.ai/2026.3/using-develocity/common-custom-user-data/) to tag builds as CI and enrich each Build Scan with the Git branch, commit SHA, and a link back to the GitHub Actions workflow run.