This page is a reference for integrating Gradle with CircleCI.

CircleCI provides a Gradle orb (circleci/gradle) that simplifies building and testing Gradle projects. The orb wraps common tasks — running Gradle with dependency caching, publishing test results, and selecting a JDK — into reusable configuration blocks.

The Gradle orb

The circleci/gradle orb (current version 4.x) provides a job and a command.

Element Purpose

Job: gradle/run

A ready-made job that checks out code, restores the Gradle dependency cache, runs a Gradle command, saves the cache, and optionally stores test results. Suitable for most single-step builds.

Command: gradle/run_with_cache

A reusable command you can embed in your own job definition. Performs the same cache-restore → Gradle invocation → cache-save cycle, giving you control over the executor and surrounding steps.

Minimal configuration

Using the orb job

The simplest way to build a Gradle project on CircleCI. Add a .circleci/config.yml to your repository:

version: 2.1

orbs:
  gradle: circleci/gradle@4.1

workflows:
  build:
    jobs:
      - gradle/run:
          command: build

This checks out the project, restores cached dependencies, runs ./gradlew build, and saves the updated cache.

Manual configuration (no orb)

If you prefer full control over each step, use the Gradle Wrapper directly:

version: 2.1

jobs:
  build:
    docker:
      - image: cimg/openjdk:21.0
    steps:
      - checkout

      - restore_cache:
          keys:
            - gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "build.gradle.kts" }}
            - gradle-

      - run:
          name: Build
          command: ./gradlew build --no-daemon

      - save_cache:
          key: gradle-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "build.gradle.kts" }}
          paths:
            - ~/.gradle/caches
            - ~/.gradle/wrapper

      - store_test_results:
          path: build/test-results

workflows:
  build:
    jobs:
      - build
  • cimg/openjdk:21.0 is CircleCI’s convenience image for JDK 21. The Gradle Wrapper supplies the Gradle distribution.

  • --no-daemon avoids daemon startup overhead in short-lived containers.

  • store_test_results parses JUnit XML reports so test counts and failures appear in the CircleCI UI.

Orb job parameters

The gradle/run job accepts several parameters to customize the build:

Parameter Default Description

command

build

Gradle tasks to execute (e.g. clean build, check, assemble).

executor

gradle/default (cimg/openjdk)

The executor to run the job on. Override to use a different JDK or a machine executor.

app_src_directory

.

Path to the Gradle project root, relative to the repository root. Useful for monorepos.

cache_key

(generated)

Override the default cache key. The default incorporates build.gradle*, settings.gradle*, and gradle-wrapper.properties.

deps_checksum_file

build.gradle

File used in the cache checksum. Set to build.gradle.kts for Kotlin DSL projects.

test_results_path

build/test-results

Path to JUnit XML reports, relative to app_src_directory.

reports_path

build/reports

Path to HTML reports, stored as CircleCI artifacts.

wrapper

true

When true, invokes ./gradlew. Set to false to use a Gradle installation on the executor.

Choosing an executor

The orb’s default executor uses cimg/openjdk, which provides common JDK versions on an Ubuntu base. Override it when you need a different JDK or an Android SDK:

version: 2.1

orbs:
  gradle: circleci/gradle@4.1

executors:
  jdk17:
    docker:
      - image: cimg/openjdk:17.0

workflows:
  build:
    jobs:
      - gradle/run:
          executor: jdk17
          command: build

For Android projects, use the circleci/android orb or the cimg/android image, which bundles the Android SDK alongside a JDK.

Caching and performance

CircleCI containers are ephemeral — the filesystem is discarded after every job. There are two layers of caching to consider: the CI cache (managed by CircleCI) and the Gradle build cache (managed by Gradle).

CI dependency cache

The Gradle orb’s run_with_cache command automatically saves and restores ~/.gradle/caches and ~/.gradle/wrapper. The default cache key incorporates the Gradle Wrapper properties and your build files, so the cache is invalidated when dependencies or the Gradle version change.

If you are not using the orb, replicate this with save_cache / restore_cache as shown in the manual configuration above.

Keep the cache focused on downloaded dependencies and the Wrapper distribution. Avoid caching the entire ~/.gradle directory — it includes daemon logs, lock files, and other transient data that bloat the archive without improving build speed.

Gradle build cache

The CI dependency cache stores downloaded artifacts. The Gradle build cache stores task outputs — compiled classes, test results, processed resources — and can skip tasks entirely when inputs have not changed.

For a single CircleCI job, the local build cache has limited value because each container starts clean. A remote build cache (either a Develocity instance or an HTTP build cache node) provides the biggest speedup by sharing outputs across jobs, branches, and developers.

Enable the build cache in gradle.properties:

org.gradle.caching=true

Configure a remote cache in settings.gradle[.kts]. A common pattern is to let CI push to the remote cache while developers and feature-branch jobs only pull:

buildCache {
    local {
        isEnabled = true
    }
    remote<HttpBuildCache> {
        url = uri("https://my-cache-node.example.com/cache/")
        isPush = System.getenv("CI") != null
    }
}

CircleCI sets CI=true automatically.

Publishing Build Scans

To publish a Build Scan® for every CI build, apply the Develocity plugin in settings.gradle[.kts] and accept the terms of use:

plugins {
    id("com.gradle.develocity") version "3.18.1"
}

develocity {
    buildScan {
        termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use"
        termsOfUseAgree = "yes"
        publishing.onlyIf { true }
    }
}

The Build Scan URL is printed in the CircleCI job log.

Build Scans are especially valuable on CircleCI because the ephemeral container environment makes it difficult to inspect build outputs after the job completes. A Build Scan preserves full details — task execution timeline, dependency resolution, test results, and environment info — in a shareable link.

Test reporting

CircleCI can parse JUnit XML reports to display test counts, durations, and failure details in the job UI. Gradle produces these reports by default under build/test-results/.

When using the orb, set test_results_path if your reports are in a non-default location. When configuring manually, add a store_test_results step:

- store_test_results:
    path: build/test-results

For multi-project builds, use a glob path to capture reports from all subprojects:

- store_test_results:
    path: .

CircleCI recursively searches for TEST-*.xml files under the given path.

Parallelism and workflows

CircleCI workflows allow you to run jobs in parallel or in sequence. A common pattern for Gradle projects splits the build and test stages:

version: 2.1

orbs:
  gradle: circleci/gradle@4.1

workflows:
  build-and-test:
    jobs:
      - gradle/run:
          name: compile
          command: classes testClasses

      - gradle/run:
          name: unit-tests
          command: test
          requires:
            - compile

      - gradle/run:
          name: integration-tests
          command: integrationTest
          requires:
            - compile

The compile job runs first; unit-tests and integration-tests run in parallel once compilation succeeds.

For CPU-intensive builds, CircleCI’s parallelism feature splits work across multiple containers. Combine it with Gradle’s --parallel flag to maximize throughput:

- run:
    name: Build
    command: ./gradlew build --parallel --no-daemon

Managing credentials

Store publishing tokens, signing keys, and other secrets as CircleCI environment variables (project-level or context-level).

Access them in build.gradle[.kts] with System.getenv("VAR_NAME") or providers.environmentVariable("VAR_NAME").

publishing {
    repositories {
        maven {
            url = uri("https://repo.example.com/releases")
            credentials {
                username = System.getenv("REPO_USER")
                password = System.getenv("REPO_TOKEN")
            }
        }
    }
}

Use contexts to share credentials across multiple projects while restricting access to specific teams.