The Develocity Gradle plugin enables integration with Develocity and scans.gradle.com.

Prior versions of Develocity were known as “Gradle Enterprise” and used the (Legacy) Gradle Enterprise Gradle plugin. With Develocity 2024.1, that plugin has been deprecated in favor of the one documented in this user manual. Please refer to the Migrating to the Develocity plugin section for details.

Getting set up

Version 3.18.1 is the latest version and is compatible with all Gradle 5.x and later versions. See Gradle 4.x and earlier if you are using an earlier version of Gradle.

The instructions in this section describe applying and configuring the plugin for a single Gradle project. See Integrating your CI tool for help with integrating all projects built within an environment.

Applying the plugin

Gradle 6.x and later

The com.gradle.develocity plugin must be applied in the settings file of the build.

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

develocity {
    // configuration
}
settings.gradle
plugins {
    id "com.gradle.develocity" version "3.18.1"
}

develocity {
    // configuration
}

The plugin is configured via the develocity extension available in the settings script, which is also available via the root project in project build scripts. The same instance is used for the settings extension and root project extension.

Gradle 5.x

The com.gradle.develocity plugin must be applied to the root project of the build.

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

develocity {
    // configuration
}
build.gradle
plugins {
    id "com.gradle.develocity" version "3.18.1"
}

develocity {
    // configuration
}

The plugin is configured via the develocity extension of the root project in project build scripts.

Connecting to Develocity

To connect to a Develocity instance, you must configure the location of the Develocity server.

develocity {
    server.set("https://develocity.mycompany.com")
}
develocity {
    server = "https://develocity.mycompany.com"
}

Allowing untrusted SSL communication

If your Develocity server uses an SSL certificate that is not trusted by your build’s Java runtime, you will not be able to publish Build Scans without explicitly allowing untrusted servers.

To do this, set the allowUntrustedServer option to true:

Disabling SSL certificate checks
develocity {
    server.set("https://develocity.mycompany.com")
    allowUntrustedServer.set(true)
}
Disabling SSL certificate checks
develocity {
    server = "https://develocity.mycompany.com"
    allowUntrustedServer = true
}

Use of this configuration is a security risk as it makes it easier for a third party to intercept your Build Scan data. It should only be used as a short term workaround until the server can be configured with a trusted certificate.

Authenticating

Develocity installations may be configured to require Build Scan publishing to be authenticated. Additionally, installations may be configured to only allow certain users to publish Build Scans.

Develocity access keys should be treated with the same secrecy as passwords. They are used to authorize access to Develocity from a build.

Automated access key provisioning

The easiest way to configure a build environment to authenticate with Develocity is to use the provisionDevelocityAccessKey task.

$ ./gradlew provisionDevelocityAccessKey

When executed, it opens your web browser and asks to confirm provisioning of a new access key. You will be asked to sign in to Develocity in your browser first if you are not already signed in.

When confirmed, a new access key will be generated and stored in the develocity/keys.properties file within the Gradle user home directory (~/.gradle by default).

Any existing access key for the same server will be replaced in the file, but will not be revoked at the server for use elsewhere. To revoke old access keys, sign in to Develocity and access “My settings” via the user menu at the top right of the page.

If your browser cannot be opened automatically at the correct page, you will be asked to manually open a link provided in the build console.

Manual access key configuration

Access keys can also be configured manually for an environment, when automated provisioning is not suitable.

Creating access keys

To create a new access key, sign in to Develocity and access “My settings” via the user menu at the top right of the page. From there, use the “Access keys” section to generate an access key.

The access key value should then be copied and configured in your build environment via file, environment variable or the settings file.

Via file

Develocity access keys are stored inside the Gradle user home directory (~/.gradle by default), at develocity/keys.properties, in a Java properties file. The property name refers to the host name of the server, and the value is the access key.

develocity.mycompany.com=7w5kbqqjea4vonghohvuyra5bnvszop4asbqee3m3sm6dbjdudtq

The file may contain multiple entries. The first entry for a given host value will be used.

Via environment variable

The access key may also be specified via the DEVELOCITY_ACCESS_KEY environment variable. This is typically more suitable for CI build environments.

The environment variable value format is «server host name»=«access key».

$ export DEVELOCITY_ACCESS_KEY=develocity.mycompany.com=7w5kbqqjea4vonghohvuyra5bnvszop4asbqee3m3sm6dbjdudtq && \
  ./gradlew build

The server host name is specified in order to prevent the access key being transmitted to a different server than intended. In the rare case that you require access keys for multiple servers, you can specify multiple entries separated by semicolons.

$ export DEVELOCITY_ACCESS_KEY=ge1.mycompany.com=7w5kbqqjea4vonghohvuyra5bnvszop4asbqee3m3sm6dbjdudtq;ge2.mycompany.com=9y4agfiubqqjea4vonghohvuyra5bnvszop4asbqee3m3sm67w5k && \
  ./gradlew build
Via settings file

The accessKey option of the plugin allows the access key to be set via the settings file.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
    accessKey.set("7w5kbqqjea4vonghohvuyra5bnvszop4asbqee3m3sm6dbjdudtq")
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
    accessKey = "7w5kbqqjea4vonghohvuyra5bnvszop4asbqee3m3sm6dbjdudtq"
}

An access key configured for the server this way will take precedence over an access key set via the environment variable or access key file.

Short-lived access tokens

Develocity access keys are long-lived, creating risks if they are leaked. To avoid this, users can use short-lived access tokens to authenticate with Develocity. Access tokens can be used wherever an access key would be used. Access tokens are only valid for the Develocity instance that created them.

Develocity server version 2024.1+ supports access tokens.
Changing a Develocity instance’s hostname will cause all existing access tokens to become invalid.

To create an access token:

  1. Get an access key or access token for the user you wish to create a token for.

  2. Decide which permissions the new access token should have.

  3. If project-level access control is enabled, decide which projects the new access token should be able to access.

  4. Decide how long the new access token should live.

  5. Make a POST request to /api/auth/token, optionally with the following parameters. The response will be the access token.

    1. A permissions= query parameter with the config values of each permission you wish to grant. By default, all permissions for the credential used to authenticate the token request are granted to the created token.

    2. If project-level access control is enabled, a projectIds= query parameter with the ID of each project you wish to grant access to. By default, all projects for the credential used to authenticate the token request are granted to the created token.

    3. An expiresInHours= query parameter with the token’s intended lifetime in hours, with a maximum of 24. The default is two hours, or the remaining lifetime of the credential used to authenticate the request, whichever is smaller.

The requested permissions and project ids can be specified as comma-seperated lists or repeated parameters. For example, ?projectIds=a,b&projectIds=c is valid and will request projects a, b, and c.

If project-level access control is not enabled, all access tokens will be granted the “Access all data without an associated project” permission even if it is not explicitly requested.

If the user creating the token does not have one of the requested permissions or projects, Develocity will respond with a 403 Forbidden error. If an access token is used to authenticate the creation request, its permissions and projects will be used for this check instead of the user’s. The request will also error if the requested lifetime would cause the new access token to expire after the one used to authenticate the request. Together, this means you cannot create an access token with more access or a later expiration than the credentials used to authenticate the request.

See the API documentation for more details on the /api/auth/token endpoint.

Here is an example using CURL to create an access token:

$ curl -X POST https://ge.mycompany.com/api/auth/token?permissions=publishScan,writeCache,accessDataWithoutAssociatedProject&projectIds=project-a,project-b&expiresInHours=1 \
    -H "Authorization: Bearer 7asejatf24zun43yshqufp7qi4ovcefxpykbwzqbzilcpwzb52ja"

eyJraWQiOiJ0ZXN0LWtleSIsImFsZyI6IlJTMjU2IiwidHlwIjoiSldUIn0.eyJpc19hbm9ueW1vdXMiOmZhbHNlLCJwZXJtaXNzaW9ucyI6WyJSRUFEX1ZFUlNJT04iLCJFWFBPUlRfREFUQSIsIkFDQ0VTU19EQVRBX1dJVEhPVVRfQVNTT0NJQVRFRF9QUk9KRUNUIl0sInByb2plY3RzIjp7ImEiOjEsImIiOjJ9LCJ1c2VyX2lkIjoic29tZS1pZCIsInVzZXJuYW1lIjoidGVzdCIsImZpcnN0X25hbWUiOiJhIiwibGFzdF9uYW1lIjoidXNlciIsImVtYWlsIjoiYkBncmFkbGUuY29tIiwic3ViIjoidGVzdCIsImV4cCI6NzIwMCwibmJmIjowLCJpYXQiOjAsImF1ZCI6ImV4YW1wbGUuZ3JhZGxlLmNvbSIsImlzcyI6ImV4YW1wbGUuZ3JhZGxlLmNvbSIsInRva2VuX3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.H1_NEG1xuleP-WIAY_uvSmdd2o7i_-Ko3qhlo04zvCgrElJe7_F5jNuqsyDfnb5hvKlOe5UKG_7QPTgY9-3pFQ

The resulting token would have the following permissions:

  • “Publish Build Scans”

  • “Read and write Build Cache data”

  • “Access all data without an associated project”

And it would have access to these projects:

  • “project-a”

  • “project-b”

The token would only be usable for one hour.

Connecting to scans.gradle.com

If the location of a Develocity server is not specified, Build Scans will be published to scans.gradle.com. This requires agreeing the terms of service, which can be found at https://gradle.com/terms-of-service.

You can agree to the terms of service by adding the following configuration to your build.

Agreeing to the terms of service
develocity {
    buildScan {
        termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use")
        termsOfUseAgree.set("yes")
    }
}
Agreeing to the terms of service
develocity {
    buildScan {
        termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use"
        termsOfUseAgree = "yes"
    }
}

If you do not agree to the terms of service in your build, you will be asked interactively when trying to publish a Build Scan to scans.gradle.com each time you try to publish.

Be careful not to commit agreement to the terms of service into a project that may be built by others.

Using Build Scans

Controlling when Build Scans are published

Once you’ve gone through the initial setup of the previous section, you are ready to start publishing Build Scans. But when should you publish them? Every time you run a build? Only when the build fails? It’s up to you. The Develocity Gradle plugin has several options that allow you to use whatever approach works best.

Publishing every build

This is the default. There are many advantages to publishing Build Scans regularly, such as being able to track the behavior and performance of a build over time. It makes no sense relying on ad-hoc publishing of scans in such a situation as it’s easy to forget on the command line. Should you decide to explicitly enforce this default option, you can do this as follows:

Publishing a Build Scan for every build execution
develocity {
    buildScan {
        publishing.onlyIf { true }
    }
}
Publishing a Build Scan for every build execution
develocity {
    buildScan {
        publishing.onlyIf { true }
    }
}

If you want to skip publishing a particular build, you can then add the --no-scan argument to any Gradle build.

$ ./gradlew assemble --no-scan

Publishing on demand

We imagine that when you first start experimenting with Build Scans, you won’t want to publish them all the time until you become familiar with the implications. Even then, you may have good reason not to go all-in and automate the process. That’s where one-off Build Scans come in.

If you only want to publish Build Scans when explicitly requested, use the following option:

Publishing a Build Scan on demand
develocity {
    buildScan {
        publishing.onlyIf { false }
    }
}
Publishing a Build Scan on demand
develocity {
    buildScan {
        publishing.onlyIf { false }
    }
}

You can then add the --scan argument to any Gradle build to publish a Build Scan.

$ ./gradlew assemble --scan
Interoperability with Gradle 8.4 and older

If the build does not apply the plugin, Gradle will automatically apply the most recent version available at the time that version of Gradle was released.

Gradle versions older than 8.4 do not recognize the Develocity plugin as the replacement for deprecated Gradle Enterprise and Build Scan plugins. When --scan argument is used, Gradle attempts to apply its version of the plugin which may conflict with the Develocity plugin explicitly applied to your project. If the plugin applied by Gradle wins, the new functionality provided by the Develocity plugin will not be available.

This case will be highlighted using the following message:

WARNING: Deprecated Gradle Enterprise plugin [version: 3.16.2] was applied alongside Develocity plugin.
If your build uses the latest Develocity functionality, it may fail or not run as expected since the deprecated plugin may not support requested features.
The simultaneous application of Develocity and Gradle Enterprise plugins will cause the build to fail in a future release of the Develocity plugin.

To resolve the issue, upgrade to a newer Gradle version or configure on-demand publication using one of the options described in Publishing based on criteria section.

You can also publish a Build Scan for the most recently run build by invoking the buildScanPublishPrevious task added by the plugin.

$ ./gradlew buildScanPublishPrevious

Since the task name is quite long, it’s worth taking advantage of Gradle’s abbreviated command line notation for tasks:

$ ./gradlew bSPP

Publishing based on criteria

Many of you will want a bit more control over exactly when Build Scans are published without resorting to using --scan each time. You may want to publish Build Scans only under the following conditions:

  1. When the build fails

  2. When the user running the build is authenticated with Develocity

  3. If the build is running on CI

Such scenarios are covered by configuring a custom predicate.

Restricting Build Scans to failed builds
develocity {
    buildScan {
        publishing.onlyIf { it.buildResult.failures.isNotEmpty() }
    }
}
Restricting Build Scans to failed builds
develocity {
    buildScan {
        publishing.onlyIf { !it.buildResult.failures.empty }
    }
}
Restricting Build Scans to authenticated users
develocity {
    buildScan {
        publishing.onlyIf { it.authenticated }
    }
}
Restricting Build Scans to authenticated users
develocity {
    buildScan {
        publishing.onlyIf { it.authenticated }
    }
}
Restricting Build Scans to CI builds
develocity {
    buildScan {
        publishing.onlyIf { !System.getenv("CI").isNullOrEmpty() }
    }
}
Restricting Build Scans to CI builds
develocity {
    buildScan {
        publishing.onlyIf { System.getenv("CI") }
    }
}

You can use the other options in the same way. If you want to configure several things based on a set of criteria, you can use an if condition instead:

Encapsulating several settings based on some criteria
develocity {
    buildScan {
        if (!System.getenv("CI").isNullOrEmpty()) {
            publishing.onlyIf { true }
            tag("CI")
        }
    }
}
Encapsulating several settings based on some criteria
develocity {
    buildScan {
        if (System.getenv("CI")) {
            publishing.onlyIf { true }
            tag "CI"
        }
    }
}

Configuring background uploading

By default, Build Scans are uploaded in the background after the build has finished. This allows the build to finish sooner, but can be problematic in build environments (e.g. ephemeral CI agents) that terminate as soon as the build is finished, as the upload may be terminated before it completes. Background uploading should be disabled for such environments.

Disabling programmatically

The develocity.buildScan.uploadInBackground property can be set to false.

Disabling background uploading
develocity {
    buildScan {
        uploadInBackground.set(false)
    }
}
Disabling background uploading
develocity {
    buildScan {
        uploadInBackground = false
    }
}

It may be desirable to conditionally set the value based on the environment.

Conditionally set background uploading
develocity {
    buildScan {
        uploadInBackground.set(System.getenv("CI") == null)
    }
}
Conditionally set background uploading
develocity {
    buildScan {
        uploadInBackground = System.getenv("CI") == null
    }
}

Disabling via system property

Background uploading can be disabled by setting the scan.uploadInBackground system property to false. The system property setting always takes precedence over the programmatic setting.

The system property may be specified when invoking the build:

$ ./gradlew build -Dscan.uploadInBackground=false

Or, can be set as part of the environment with the JAVA_OPTS or GRADLE_OPTS environment variables:

$ export GRADLE_OPTS=-Dscan.uploadInBackground=false

Or, can be set in the user’s gradle.properties file (i.e. ~/.gradle/gradle.properties).

systemProp.scan.uploadInBackground=false

Configuring project identifier

Detailed information regarding project-level access control can be found here.

Setting programmatically

The develocity.projectId property can be set to a necessary value.

Specifying project identifier
develocity {
    projectId.set("myProject")
}
Specifying project identifier
develocity {
    projectId = "myProject"
}

Setting via system property

Project identifier can be also set using the develocity.projectId system property. The system property setting always takes precedence over the programmatic setting.

The system property may be specified when invoking the build:

$ ./gradlew build -Ddevelocity.projectId=myProject

Or, can be set as part of the environment with the JAVA_OPTS or GRADLE_OPTS environment variables:

$ export GRADLE_OPTS=-Ddevelocity.projectId=myProject

Or, can be set in the user’s gradle.properties file (i.e. ~/.gradle/gradle.properties).

systemProp.develocity.projectId=myProject

Capturing file fingerprints

Build Scans capture hashes of inputs of tasks (and other units of work), to enable identifying changes to inputs when comparing builds, among other features. The overall hash value of each input property enables identifying which properties changed for a task (e.g. the source or the classpath for Java compilation). In addition, the paths and content hashes of individual input files of each property are captured by default. They allow identifying which individual files changed for a task when comparing two builds.

When to disable

Capturing file fingerprints increases the amount of data transmitted to the Build Scan server at the end of the build. If the network connection to the Build Scan server is poor, it may increase the time required to transmit. Additionally, it may also increase the data storage requirements for a Build Scan server. In such cases, capturing file fingerprints can be disabled.

However, if you are using Develocity and utilising its Build Cache to accelerate your builds, it is strongly recommended to keep it enabled as identifying which files have changed between builds with build comparison is extremely effective for diagnosing unexpected Build Cache misses.

If you are using Develocity for Predictive Test Selection enabling capture of file fingerprints is a prerequisite.

How to disable

Capture of file fingerprints can be enabled/disabled programmatically via the buildScan extension, or via a system property.

Programmatically

To enable/disable programmatically, use the buildScan extension added by the Develocity Gradle plugin.

Disabling file fingerprints capturing
develocity {
    buildScan {
        capture {
            fileFingerprints.set(false)
        }
    }
}
Disabling file fingerprints capturing
develocity {
    buildScan {
        capture {
            fileFingerprints = false
        }
    }
}
Via system property

To enable/disable without modifying the build script, supply a scan.capture-file-fingerprints system property to the build. If the property is set to false, capture is disabled. Otherwise, capture is enabled. The environmental setting always takes precedence over the programmatic setting.

The system property may be specified when invoking the build:

$ ./gradlew build -Dscan.capture-file-fingerprints=false

Or, can be set as part of the environment with the JAVA_OPTS or GRADLE_OPTS environment variables:

$ export GRADLE_OPTS=-Dscan.capture-file-fingerprints=false

Or, can be set in the project’s gradle.properties file, or the user’s gradle.properties file (i.e. ~/.gradle/gradle.properties).

systemProp.scan.capture-file-fingerprints=false

See the Build Environment chapter of the Gradle User Manual for more information on specifying system properties.

Capturing build and test outputs

By default, outputs generated during the build are captured and displayed in Build Scans.

Note that when disabling test output capturing, test failures will still be captured.

When to disable

You may want to skip capturing build or test outputs for security/privacy reasons (i.e., some outputs may leak sensitive data), or performance/storage reasons (i.e., some tasks/tests may produce a lot of outputs that are irrelevant for your usage of Build Scans).

How to disable

Output capture can be enabled/disabled programmatically via the buildScan extension, or via a system property.

Programmatically

To enable/disable programmatically, use the buildScan extension added by the Develocity Gradle plugin.

Disabling build or test output logging
develocity {
    buildScan {
        capture {
            buildLogging.set(false)
            testLogging.set(false)
        }
    }
}
Disabling build or test output logging
develocity {
    buildScan {
        capture {
            buildLogging = false
            testLogging = false
        }
    }
}
Via system property

To enable/disable without modifying the build script, supply the scan.capture-build-logging and/or scan.capture-test-logging system properties to the build. If the property is set to false, capture is disabled. Otherwise, capture is enabled. The environmental setting always takes precedence over the programmatic setting.

The system property may be specified when invoking the build:

$ ./gradlew build -Dscan.capture-build-logging=false -Dscan.capture-test-logging=false

Or, can be set as part of the environment with the JAVA_OPTS or GRADLE_OPTS environment variables:

$ export GRADLE_OPTS="-Dscan.capture-build-logging=false -Dscan.capture-test-logging=false"

Or, can be set in the project’s gradle.properties file, or the user’s gradle.properties file (i.e. ~/.gradle/gradle.properties).

systemProp.scan.capture-build-logging=false
systemProp.scan.capture-test-logging=false

See the Build Environment chapter of the Gradle User Manual for more information on specifying system properties.

Capturing resource usage

(plugin 3.18+)

Build Scans capture information on key resources of the machine executing the build. This includes CPU load, memory, disk usage, network activity, and the names of the most CPU-intensive processes. This data can help analyze poor build performance, whether due to the build needing too many resources or factors external to the build. It can also help understand if the machine is underutilized and if it could do more work.

By default, resource usage is captured and displayed in Build Scans.

Users of Gradle’s configuration cache feature must use version 7.6 of Gradle or later to benefit from resource usage capturing. When using plugin 3.18+ with earlier versions of Gradle and configuration caching turned on, resource usage capturing will be automatically disabled, and a warning message will be printed.

When to disable

You may want to skip capturing resource usage for security/privacy reasons. Note that the names of processes external to the build (i.e. not the build process nor its descendants) can be obfuscated.

How to disable

Resource usage capture can be enabled/disabled programmatically via the buildScan extension, or via a system property.

Programmatically

To enable/disable programmatically, use the buildScan extension added by the Develocity Gradle plugin.

Disabling resource usage capturing
develocity {
    buildScan {
        capture {
            resourceUsage.set(false)
        }
    }
}
Disabling resource usage capturing
develocity {
    buildScan {
        capture {
            resourceUsage = false
        }
    }
}
Via system property

To enable/disable without modifying the build script, supply the scan.capture-resource-usage system properties to the build. If the property is set to false, capture is disabled. Otherwise, capture is enabled. The environmental setting always takes precedence over the programmatic setting.

The system property may be specified when invoking the build:

$ ./gradlew build -Dscan.capture-resource-usage=false

Or, can be set as part of the environment with the JAVA_OPTS or GRADLE_OPTS environment variables:

$ export GRADLE_OPTS="-Dscan.capture-resource-usage=false"

Or, can be set in the project’s gradle.properties file, or the user’s gradle.properties file (i.e. ~/.gradle/gradle.properties).

systemProp.scan.capture-resource-usage=false

See the Build Environment chapter of the Gradle User Manual for more information on specifying system properties.

Extending Build Scans

You can easily include extra custom information in your Build Scans in the form of tags, links and values. This is a very powerful mechanism for capturing and sharing information that is important to your build and development process.

This information can be anything you like. You can tag all builds run by your continuous integration tool with a CI tag. You can capture the name of the environment that the build published to as a value. You can link to the source revision for the build in an online tool such as GitHub. The possibilities are endless.

You can see how the custom data appears in figures 1 and 2:

scan with custom data 1
Figure 1. A Build Scan containing tags and links
scan with custom data 2
Figure 2. A Build Scan containing custom values

Develocity allows listing and searching across all of the Build Scans in the system. You can find and filter Build Scans by tags and custom values, in addition to project name, outcome and other properties. In figure 3, for example, we are filtering for all Build Scans that have the tag "CI" and a git branch name of "master":

build scan filtered list
Figure 3. A filtered list of Build Scans in Develocity

Adding tags

Tags are typically used to indicate the type or class of a build, or a key characteristic. They are prominent in the user interface and quickly inform a user about the nature of a build. A build can have zero or more tags.

They can be added at build time via the tag() method:

Adding tags to a build’s Build Scans
develocity {
    buildScan {
        tag(if (System.getenv("CI").isNullOrEmpty()) "Local" else "CI")
        tag(System.getProperty("os.name"))
    }
}
Adding tags to a build’s Build Scans
develocity {
    buildScan {
        if (System.getenv("CI")) {
            tag "CI"
        } else {
            tag "Local"
        }

        tag System.getProperty("os.name")
    }
}

As demonstrated by the example above, tags are typically applied either as fixed strings within a condition or evaluated at runtime from the environment. But there are no set rules that you need to follow—these are only suggestions.

The syntax for adding a tag is:

tag(<tag>)

where the <tag> is a string.

Note that the order in which you declare the tags doesn’t affect the Build Scan view. They are displayed in alphabetical order, with any all-caps labels displayed before the rest.

The plugin imposes the following limits on captured tags:

  • maximum tag count: 50

  • maximum tag length: 200 characters

Builds rarely live in isolation. Where does the project source live? Is there online documentation for the project? Where can you find the project"s issue tracker? If these exist and have a URL, you can add them to the Build Scan.

They can be added at build time via the link() method:

Adding a VCS URL to a build’s Build Scans
develocity {
    buildScan {
        link("VCS", "https://github.com/myorg/sample/tree/${System.getProperty("vcs.branch")}")
    }
}
Adding a VCS URL to a build’s Build Scans
develocity {
    buildScan {
        link "VCS", "https://github.com/myorg/sample/tree/${System.getProperty("vcs.branch")}"
    }
}

The above example demonstrates how you can attach a link to an online VCS repository that points to a specific branch provided as a system property.

The syntax for adding a link is:

link(<label>, <URL>)

The <label> is simply a string identifier that you choose and that means something to you.

You can see the effect of a custom link in figure 1, which shows how a label Source becomes a hyperlink that anyone viewing the Build Scan can follow.

The plugin imposes the following limits on captured links:

  • maximum link count: 20

  • maximum link label length: 100 characters

  • maximum link url length: 100,000 characters

Adding custom values

Some information just isn’t useful without context. What does "1G" mean? You might guess that it represents 1 gigabyte, but of what? It’s only when you attach the label "Max heap size for build" that it makes sense. The same applies to git commit IDs, for example, which could be interpreted as some other checksum without a suitable label.

Custom values are designed for these cases that require context. They’re standard key-value pairs, in which the key is a string label of your choosing and the values are also strings, often evaluated from the build environment.

They can be added at build time via the value() method:

Adding custom values to a build’s Build Scans
develocity {
    buildScan {
        value("Build Number", project.buildNumber)
    }
}
Adding custom values to a build’s Build Scans
develocity {
    buildScan {
        value "Build Number", project.buildNumber
    }
}

The above example demonstrates how you can read the build number from a project property—assuming you have your build set up for this—and attach it to the Build Scans as a custom value.

The syntax for adding a value is:

value(<key>, <value>)

where both the <key> and the <value> are strings.

As with tags, you can filter Build Scans by custom values in Develocity.

The plugin imposes the following limits on captured custom values:

  • maximum custom value count: 1,000

  • maximum custom value key length: 1,000 characters

  • maximum custom value value length: 100,000 characters

Adding data at the end of the build

The examples you have seen so far work well if when the custom data is available at the beginning of the build. But what if you want to attach data that’s only available later? For example, you might want to label a build as "built-from-clean" if the clean task was run. But you don’t know if that’s the case until the task execution graph is ready.

The Develocity Gradle plugin provides a buildFinished() hook that you can use for these situations. It defers attaching custom data until the build has finished running. As an example, imagine you want to report how much disk space was taken up by the output build directory. The build doesn’t know this until it’s finished, so the solution is to calculate the disk space and attach it to a custom value in the buildFinished() hook:

Adding a custom disk usage value at the end of the build
develocity {
    buildScan {
        buildFinished {
            value("Disk usage (output dir)", buildDir.walkTopDown().map { it.length() }.sum().toString())
        }
    }
}
Adding a custom disk usage value at the end of the build
develocity {
    buildScan {
        buildFinished {
            value "Disk usage (output dir)", buildDir.directorySize().toString()
        }
    }
}

The buildFinished() action has access to the rest of the build, including the Project instance, so it can extract all sorts of information. It also has access to a BuildResult instance that you can use to determine whether the build failed or not, like so:

Checking build status from buildFinished()
develocity {
    buildScan {
        buildFinished {
            if (this.failures.isNotEmpty()) {
                value("Failed with", this.failure.message)
            }
        }
    }
}
Checking build status from buildFinished()
import com.gradle.scan.plugin.BuildResult

develocity {
    buildScan {
        buildFinished { BuildResult result ->
            if (result.failures) {
                value "Failed with", result.failure.message
            }
        }
    }
}

The Gradle build tool has a BuildListener interface that also contains a buildFinished() hook. However, you cannot use this to attach custom data because it is triggered too late. You can use hooks like project.afterEvaluate() or the buildStarted() method of BuildListener because they are executed early enough.

Adding expensive data

Some data that you may wish to add to your Build Scan can be expensive to capture. For example, capturing the Git commit ID may require executing the git command as an external process, which is expensive. To do this without slowing your build down, you can use the buildScan.background() method:

Using background() to capture an expensive custom value with Gradle 6.2+ and Configuration Cache compatibility.
import org.gradle.kotlin.dsl.support.serviceOf
import java.io.ByteArrayOutputStream
...

develocity {
  buildScan {
    val execOps = serviceOf<ExecOperations>()
    background {
      val os = ByteArrayOutputStream()
      execOps.exec {
        commandLine("git", "rev-parse", "--verify", "HEAD")
        standardOutput = os
      }
      value("Git Commit ID", os.toString())
    }
  }
}
Using background() to capture an expensive custom value with Gradle 5.x
import java.io.ByteArrayOutputStream
...
develocity {
    buildScan {
        background {
            val os = ByteArrayOutputStream()
            exec {
                commandLine("git", "rev-parse", "--verify", "HEAD")
                standardOutput = os
            }
            value("Git Commit ID", os.toString())
        }
    }
}
Using background() to capture an expensive custom value
develocity {
    buildScan {
        background {
            def commitId = "git rev-parse --verify HEAD".execute().text.trim()
            value "Git Commit ID", commitId
        }
    }
}

This method takes a function that will be executed on a separate thread, which allows Gradle to continue without waiting for the expensive work to complete.

All background work will be completed before finishing the build and publishing the Build Scan.

Any errors that are thrown by the background action will be logged and captured in the Build Scan.

See the buildScan.background() API reference for more information.

Providing custom data via system properties

The examples up to this point have shown how your build file or init script can pull information from the environment, via environment variables and system properties. The Develocity Gradle plugin also allows you to inject any form of custom data through the use of specially named system properties. This can help you keep your build files clean of too much environment-specific information that may not be relevant to most of the users of the build.

These system properties take the following forms, depending on whether you want to inject a link, a tag or a custom value:

-Dscan.tag.<tag>
-Dscan.link.<label>=<URL>
-Dscan.value.<key>=<value>

Here are some concrete examples, which assume that the build has been configured to publish Build Scans automatically:

$ ./gradlew build -Dscan.tag.CI
$ ./gradlew build -Dscan.link.VCS=https://github.com/myorg/my-super-project/tree/my-new-feature
$ ./gradlew build "-Dscan.value.CIBuildType=QA_Build"

This feature is particularly useful for continuous integration builds as you can typically easily configure your CI tool to specify system properties for a build. It’s even common for CI tools to be able to inject system properties into a build that are interpolated with information from the CI system, such as build number.

$ ./gradlew build "-Dscan.value.buildNumber=$CI_BUILD_NUMBER"

Capturing the Build Scan ID or address

The address of the Build Scan is included in the output at the end of the build. However, you may wish to record the ID or URL of the Build Scan in some other way. The Develocity Gradle plugin allows you to register a callback that will receive this information. The callback is invoked after a Build Scan has been successfully published.

The example build script snippet below shows this feature being used to maintain a journal of created Build Scans.

Develocity provides the ability to search for Build Scans created by a certain user and/or from a particular host (along with other search criteria).

Creating a log of published Build Scans
import java.util.Date

develocity {
    buildScan {
        buildScanPublished {
            file("scan-journal.log").appendText("${Date()} - ${this.buildScanId} - ${this.buildScanUri}\n")
        }
    }
}
Creating a log of published Build Scans
import com.gradle.scan.plugin.PublishedBuildScan

develocity {
    buildScan {
        buildScanPublished { PublishedBuildScan scan ->
            file("scan-journal.log") << "${new Date()} - ${scan.buildScanId} - ${scan.buildScanUri}\n"
        }
    }
}

Please see the buildScan.buildScanPublished() method for API details.

Obfuscating identifying data

Build Scans capture certain identifying information such as the operating system username, hostname, network addresses, and CPU-intensive process names. You may choose to obfuscate this data so that it is not decipherable in Build Scans when viewed, by registering obfuscation functions as part of the Build Scan configuration.

The following examples show registering obfuscation functions for the different identifying data.

Obfuscating the username
develocity {
    buildScan {
        obfuscation {
            username { name -> name.reversed() }
        }
    }
}
Obfuscating the username
develocity {
    buildScan {
        obfuscation {
            username { name -> name.reverse() }
        }
    }
}
Obfuscating the hostnames
develocity {
    buildScan {
        obfuscation {
            hostname { host -> host.toCharArray().map { character -> Character.getNumericValue(character) }.joinToString("-") }
        }
    }
}
Obfuscating the hostnames
develocity {
    buildScan {
        obfuscation {
            hostname { host -> host.collect { character -> Character.getNumericValue(character as char) }.join("-") }
        }
    }
}
Obfuscating the IP addresses
develocity {
    buildScan {
        obfuscation {
            ipAddresses { addresses -> addresses.map { _ -> "0.0.0.0" } }
        }
    }
}
Obfuscating the IP addresses
develocity {
    buildScan {
        obfuscation {
            ipAddresses { addresses -> addresses.collect { address -> "0.0.0.0" } }
        }
    }
}
Obfuscating the non-build-related process names (plugin 3.18+)
develocity {
    buildScan {
        obfuscation {
            externalProcessName { processName -> "non-build-process" }
        }
    }
}
Obfuscating the non-build-related process names (plugin 3.18+)
develocity {
    buildScan {
        obfuscation {
            externalProcessName { processName -> 'non-build-process' }
        }
    }
}

Integrating your CI tool

Jenkins

The Gradle Jenkins plugin prominently displays links to the Build Scan for any Gradle or Maven build that produce Build Scans, which makes it convenient to access the Build Scans. See the following screenshot for an example:

jenkins

Besides that, the plugin allows you to instrument all CI jobs and to publish a Build Scan without modifying the underlying projects. This eases the adoption of Build Scans within the company and allows configuring the Develocity Gradle plugin or Develocity Maven extension in a central place. For more information please read the documentation here.

TeamCity

The TeamCity Build Scan plugin prominently displays links to the Build Scan for any Gradle or Maven build that produce Build Scans, which makes it convenient to access the Build Scans. See the following screenshot for an example:

teamcity

Besides that, the plugin allows you to instrument all CI jobs and to publish a Build Scan without modifying the underlying projects. This eases the adoption of Build Scans within the company and allows configuring the Develocity Gradle plugin or Develocity Maven extension in a central place. For more information please read the documentation here.

Bamboo

The Develocity Bamboo plugin prominently displays links to the Build Scan for any Gradle or Maven build that produce Build Scans, which makes it convenient to access the Build Scans. See the following screenshot for an example:

bamboo

Besides that, the plugin allows you to instrument all CI jobs and to publish a Build Scan without modifying the underlying projects. This eases the adoption of Build Scans within the company and allows configuring the Develocity Gradle plugin or Develocity Maven extension in a central place. For more information please read the documentation here.

GitLab templates

The Develocity GitLab templates allow you to instrument CI jobs and to publish a Build Scan without modifying the project’s build scripts. This eases the adoption of Build Scans within the company and allows configuring the Develocity Gradle plugin or Develocity Maven extension at the CI level. For more information please read the documentation here.

GitHub Actions

The Gradle GitHub Action prominently displays links to the Build Scan for any Gradle build that produces Build Scans, which makes them convenient to access. See the following screenshot for an example:

githubactions

Besides that, the plugin allows you to instrument all CI jobs and to publish a Build Scan without modifying the underlying Gradle build, via environment variables defined in your GitHub Actions workflow. This eases the adoption of Build Scans within the company and allows configuring the Develocity Gradle plugin at the CI level. For more information please read the documentation here.

Viewing test results

The Develocity plugin will capture test execution results and publish them to the Develocity server. After your Build Scan® is ready, you can view and analyze the results.

Any test framework that is supported by Gradle’s Test task and based on JUnit Platform should work with Develocity without requiring any change. Contact us at support.gradle.com if the results are not correctly displayed for the test framework that you are using.

The Test overview page

The Test overview page shows a high level overview of all the tests that were executed as part of the build. The test results are displayed hierarchically: they are grouped by task, test suite and finally test case. Next to each task, test suite and test case, the outcome and the total time are displayed.

test overview

Test outcomes

Every task, test suite and test case has an outcome. For a task, the outcome is either SUCCESS, indicating that the task was successful, FLAKY, which means that at least one test suite was flaky, or FAILED, if a test suite has failed.

For test suites, the outcome can be SUCCESS, meaning that all executed test cases were successful, FAILED, indicating that at least one test case failed, FLAKY, meaning that at least one test case was successful only after retry, or SKIPPED, meaning that the test suite was not executed.

For test cases, the outcome can be SKIPPED, meaning that the test case was not executed, SUCCESS, meaning that the test case was successful, FAILED indicating that the test case was failed, or FLAKY, meaning that the test case was successful only after retry.

Test timings

On a task, the total time corresponds to the total amount of wall clock time the task took to execute.

On a test suite, the total time corresponds to the total amount of wall clock time the test suite took to execute.

On a test case, the total time corresponds to the total amount of wall clock time the test case took to execute. Clicking on a test task will open the details for this test task, which will display the results of the test suites which ran as part of this test task.

Test task details page

The Test task details page displays the results of the test suites which ran as part of the selected test task.

test task details

At the top of the page, it also shows relevant configuration values, and performance statistics. Clicking on a test suite will open the details for this test suite, which will display the results of the test cases which ran as part of this test suite.

Test suite details page

The Test suite details page displays the results of the test cases which ran as part of the selected test suite.

test suite details

Errors that may have happened during the setup or cleanup phase of the test suite execution are reported in this page.

The suite’s overall outcome is broken down into Class setup/cleanup and Test execution outcomes. Class setup/cleanup tracks whether a failure occurred in the suite’s setup / teardown callbacks, and Test execution whether it was a test case that caused the test suite to fail.

At the bottom of the page, the test cases that were executed as part of this test suite are listed, along with the time and outcome of each execution. A test case may be run more than once in case of retries.

Clicking on a test case will open the details for this test case, which will display the results of the executions of this test case.

Test case details page

The Test case details page displays the results of the executions of the selected test case.

test case details

The total time and outcome of each execution of the selected test case are displayed on the page. If an execution failed with an exception, then the exception is displayed under the corresponding execution.

Using Build Caching

The Develocity Gradle plugin provides a build cache connector that can be used to leverage the build cache provided by Develocity. Gradle’s out-of-the-box support for generic HTTP build cache servers is also compatible with the build cache provided by Develocity, and can be used when the Develocity specific connector can not be used.

The Develocity specific connector should be preferred, and can be used whenever all of the following conditions are met:

  • You are using Gradle version >= 6.0

  • You are using Develocity Build Cache Nodes of version >= 13

Using the Develocity connector

(Gradle 6+)

Users of Gradle’s configuration cache feature must use version 7.5.1 of Gradle or later when using the Develocity build cache connector. Earlier versions of Gradle will fail with an error message stating “Could not create service of type BuildCacheController”.

The Develocity build cache connector can be used by registering the connector with Gradle and configuring it:

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(develocity.buildCache) {
        // configure
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(develocity.buildCache) {
        // configure
    }
}

The buildCache {} method is provided by Gradle, with the develocity.buildCache method being provided by the Develocity configuration.

Without further configuration, the build will now attempt to read entries from the built-in build cache of the specified Develocity server. The connector of type DevelocityBuildCache can be configured inside the configuration block.

Credentials

If an access key has been configured for the specified Develocity server (see Authenticating), it will be used. Otherwise, requests will be sent anonymously.

Develocity also allows build caches to be configured with username and password credentials separate to access-key-based access control. To connect with a username and password credential, use the usernameAndPassword() method. The username and password will be used instead of any configured access key.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(develocity.buildCache) {
        usernameAndPassword("user", "pass")
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(develocity.buildCache) {
        usernameAndPassword("user", "pass")
    }
}

Writing to the build cache

By default, Gradle will only attempt to read from the build cache. To also write to the build cache, the push property of the connector must be configured to true.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(develocity.buildCache) {
        isPush = true
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(develocity.buildCache) {
        push = true
    }
}

The write attempt may be rejected due to insufficient permissions depending on the Develocity server’s access control settings.

Using Expect-Continue

The Develocity Build Cache client allows opt-in use of HTTP Expect-Continue. This causes PUT requests to happen in two parts: first a check whether a body would be accepted, then transmission of the body if the server indicates it will accept it. This is particularly suitable for Build Cache servers that routinely redirect or reject PUT requests, as it avoids transmitting the cache entry just to have it rejected (e.g. the cache entry is larger than the Build Cache will allow). This additional check incurs extra latency when the server accepts the request, but reduces latency when the request is rejected or redirected.

While the Develocity Build Cache Node supports Expect-Continue, not all HTTP servers and proxies reliably do. Be sure to check that your Build Cache server does support it before enabling.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(develocity.buildCache) {
        useExpectContinue = true
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(develocity.buildCache) {
        useExpectContinue = true
    }
}

Using a non-built-in cache

Develocity provides a built-in build cache, but can also leverage separately deployed build cache nodes for geographical distribution and horizontal scaling. If you are using such a non-built-in node, you must configure its address with the build cache connector.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(develocity.buildCache) {
        server = "https://develocity-cache-1.mycompany.com"
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(develocity.buildCache) {
        server = "https://develocity-cache-1.mycompany.com"
    }
}

Note that the server address should be specified without any request path component.

If using access-key-based authentication, the given build cache server must be of version 13 or later and be connected with the Develocity server specified by the develocity {} extension.

Similar to the Develocity server configuration, the remote Build Cache server configuration also provides an allowUntrustedServer option to circumvent certificate warnings:

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(develocity.buildCache) {
        server = "https://develocity-cache-1.mycompany.com"
        allowUntrustedServer = true
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(develocity.buildCache) {
        server = "https://develocity-cache-1.mycompany.com"
        allowUntrustedServer = true
    }
}
This is a convenient workaround during the initial evaluation, but it is a serious security issue and should not be used in production.

Using Gradle’s built-in HTTP connector

Gradle’s out-of-the-box support for generic HTTP build cache servers is also compatible with the build cache provided by Develocity, and can be used when the Develocity specific connector can not be used.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
}

buildCache {
    remote(HttpBuildCache::class) {
        url = uri("https://develocity.mycompany.com/cache/")
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
}

buildCache {
    remote(HttpBuildCache) {
        url = 'https://develocity.mycompany.com/cache/'
    }
}

When using this connector, access-key-based access control cannot be used. Instead, username and password based access control must be used which is also supported by the Develocity build cache and can be configured by administrators.

Using Predictive Test Selection

Develocity Predictive Test Selection allows developers to get faster feedback by running only tests that are likely to provide useful feedback on a particular code change using a probabilistic machine learning model.

For information on how to use Predictive Test Selection, please consult the Predictive Test Selection User Manual.

Using Test Distribution

Develocity Test Distribution takes your existing test suites and distributes them across remote agents to execute them faster.

For information on how to use Test Distribution, please consult the Test Distribution User Manual.

Using Test Retry

When test retry is enabled, any failed tests are retried after all the tests have been executed. The process repeats with tests that continue to fail until the maximum specified number of retries has been attempted, or there are no more failing tests.

By default, the test task does not fail when all failed tests pass after a retry. This setting can be changed so that tests that pass on retry cause the task to fail.

Tests that initially fail but pass on retry are considered “flaky” by Develocity. For information on how to detect flaky tests with test retry, please consult the Develocity Flaky Test Detection Guide.

Configuration

Test retry is not enabled by default. It can be enabled and configured via the retry extension added to each Test task by the plugin.

build.gradle.kts
tasks.test {
    develocity.testRetry {
        maxRetries.set(3) (1)
        maxFailures.set(20) (2)
        failOnPassedAfterRetry.set(true)(3)
    }
}
build.gradle
tasks.named('test', Test) {
    develocity.testRetry {
        maxRetries = 3  (1)
        maxFailures = 20  (2)
        failOnPassedAfterRetry = true  (3)
    }
}
1 The maximum number of times to retry an individual test.
2 The maximum number of test failures allowed before retrying is disabled for the current test run.
3 Whether tests that initially fail and then pass on retry should fail the task.

Retrying only some tests

By default, all tests are eligible for retrying. The filter component of the test retry extension can be used to control which tests should be retried and which should not.

The decision to retry a test or not is based on the tests reported class name, regardless of the name of the test case or method. The annotations present or not on this class can also be used as the criteria.

build.gradle.kts
tasks.test {
    develocity.testRetry {
        maxRetries.set(3)
        filter {
            // filter by qualified class name (* matches zero or more of any character)
            includeClasses.add("*IntegrationTest")
            excludeClasses.add("*DatabaseTest")

            // filter by class level annotations
            // Note: @Inherited annotations are respected
            includeAnnotationClasses.add("*Retryable")
            excludeAnnotationClasses.add("*NonRetryable")
        }
    }
}
build.gradle
tasks.named('test', Test) {
    develocity.testRetry {
        maxRetries = 3
        filter {
            // filter by qualified class name (* matches zero or more of any character)
            includeClasses.add("*IntegrationTest")
            excludeClasses.add("*DatabaseTest")

            // filter by class level annotations
            // Note: @Inherited annotations are respected
            includeAnnotationClasses.add("*Retryable")
            excludeAnnotationClasses.add("*NonRetryable")
        }
    }
}

Retrying on class-level

By default, individual tests are retried. The classRetry component of the test retry extension can be used to control which test classes must be retried as a whole unit. To retry a class as a whole, the class must also satisfy the configured filter.

build.gradle.kts
tasks.test {
    develocity.testRetry {
        maxRetries.set(3)
        classRetry {
            // configure by qualified class name (* matches zero or more of any character)
            includeClasses.add("*StepWiseIntegrationTest")

            // configure by class level annotations
            // Note: @Inherited annotations are respected
            includeAnnotationClasses.add("*ClassRetry")
        }
    }
}
build.gradle
tasks.named('test', Test) {
    develocity.testRetry {
        maxRetries.set(3)
        classRetry {
            // configure by qualified class name (* matches zero or more of any character)
            includeClasses.add("*StepWiseIntegrationTest")

            // configure by class level annotations
            // Note: @Inherited annotations are respected
            includeAnnotationClasses.add("*ClassRetry")
        }
    }
}
You can also use the ClassRetry annotation from the develocity-testing-annotations project without any additional configuration other than the dependency.

Retrying only for CI builds

You may find that local developer builds do not benefit much from retry behaviour, particularly when those tests are invoked via your IDE. In that case we recommend enabling retry only for CI builds.

build.gradle.kts
val isCiServer = System.getenv().containsKey("CI")
tasks.test {
    develocity.testRetry {
        if (isCiServer) { (1)
            maxRetries.set(3)
            maxFailures.set(20)
            failOnPassedAfterRetry.set(true)
        }
    }
}
build.gradle
boolean isCiServer = System.getenv().containsKey("CI")
tasks.named('test', Test) {
    develocity.testRetry {
        if (isCiServer) {
            maxRetries = 3
            maxFailures = 20
            failOnPassedAfterRetry = true
        }
    }
}
1 Only configure retrying tests, when running on CI

Migrating from Test Retry Gradle plugin

Prior to version 3.12 of this plugin, enabling test retries required the org.gradle.test-retry plugin. It is recommended that Develocity users adopt the Develocity plugin’s retry functionality for ensured future compatibility and easier adoption of future Develocity specific features.

This plugin offers effectively the same API as the org.gradle.test-retry plugin, making migrating simple:

  • Builds using Groovy build scripts need to just remove reference to the org.gradle.test-retry plugin.

  • Builds using Kotlin DSL build scripts need to remove reference to the org.gradle.test-retry plugin and add an import of com.gradle.enterprise.gradleplugin.testretry.retry.

If you cannot easily remove the org.gradle.test-retry plugin from your build, you can disable the test retry functionality provided by the Gradle Enterprise Gradle plugin by setting the system property develocity.testretry.enabled to false.

The system property can be specified in the user’s or build’s gradle.properties file (i.e. ~/.gradle/gradle.properties).

systemProp.develocity.testretry.enabled=false

See the Build Environment chapter of the Gradle User Manual for more information on specifying system properties.

Upgrading to Gradle 6

Starting with Gradle 6, the Develocity plugin needs to be applied to the settings file of the build rather than the root project.

To upgrade, first locate where the plugin is being applied and remove it. This is likely to be in the root build.gradle or build.gradle.kts file, and will look similar to the following:

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

Then, add the following to the settings.gradle or settings.gradle.kts file for the build:

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

Any buildScan {} configuration should be enclosed in a develocity {} block, or be moved to the settings file inside a develocity {} block. Please see the Gradle 6.x section above for more information.

settings.gradle.kts
develocity {
    server.set("https://develocity.mycompany.com")
    buildScan {
        // tags and other settings
    }
}
settings.gradle
develocity {
    server = "https://develocity.mycompany.com"
    buildScan {
        // tags and other settings
    }
}

Gradle 4.x and earlier

Gradle versions earlier than 5.0 are not compatible with the Develocity Gradle plugin. Please refer to the (Legacy) Gradle Enterprise Gradle Plugin User Manual for information on using the “Build Scan” plugin with Gradle 4.x and earlier.

Troubleshooting

Failed background Build Scan uploads

When using background Build Scan uploading (default behaviour, see this section for configuration options) upload failures are not visible in the build logging due to occurring in a background process after the build has finished. Instead, errors are logged to a file located at ~/.gradle/build-scan-data/upload-failure.log. If this additional information does not help to resolve the failure, please contact technical support and include the contents of this log file.

If the background upload process fails to start, a warning is shown in the build console and uploading is performed in the build process. If this occurs, please contact technical support with the log files located at ~/.gradle/build-scan-data/<<plugin-version>>/pending-uploads/*.log.

Slow resolution of host name

Build Scans attempt to determine the host name of the machine. An issue affecting macOS can cause a delay when doing this in some environments.

If you see a warning during your build that resolving the local host name is slow, you can workaround the problem by adding a host name mapping to your /etc/hosts file.

Add these lines to your /etc/hosts file, substituting your computer name for 'mbpro' in the below snippet:

/etc/hosts
127.0.0.1   localhost mbpro.local
::1         localhost mbpro.local

Appendix A: API reference

Please see the API reference for more details about programmatic configuration of the Develocity Gradle plugin.

The Common Custom User Data Gradle Plugin provided by Gradle Inc. provides an example. This plugin can be applied directly to your project, or can serve as a template project for your own plugin implementation.

Appendix B: Captured information

The Develocity Gradle plugin captures information while the build is running and transmits it to a server after the build has completed.

Most of the information captured can be considered to be build data. This includes the name of the projects in your build, the tasks, plugins, dependencies, names and results of tests and other things of this nature. Some more general environmental information is also captured. This includes your Java version, operating system, hardware, country, timezone and other things of this nature.

Notably, the actual source code being built and the output artifacts are not captured. However, error messages emitted by compilers or errors in tests may reveal aspects of the source code.

Listing

The list below details the notable information captured by the Develocity Gradle plugin and transmitted in a Build Scan.

  • Environment

    • User home (system property 'user.home')

    • Username (system property 'user.name') (Can be obfuscated)

    • Local hostname (environment variable 'COMPUTERNAME' / 'HOSTNAME') (Can be obfuscated)

    • Public hostname (Can be obfuscated)

    • Local IP addresses (Can be obfuscated)

    • Build Java Virtual Machine

    • Operating System

    • Hardware

  • Build

    • Build invocation options (e.g. requested tasks, switches)

    • Build console output

    • Build failure exception messages and stacktraces

    • Build deprecation

    • Project names and structure

    • Executed tasks

    • Executed tests (using Gradle’s JVM Test task)

    • Artifact transforms

    • Applied plugins

    • Resolved dependencies

    • Network downloads (performed by Gradle)

    • Build Cache configuration

    • Background Build Scan publication

    • Gradle Daemon operational data (e.g. start time, build count)

    • Gradle lifecycle callbacks

    • File system watching

    • Configuration cache

    • Java toolchains

Access

Build scans published to a Develocity installation are viewable by all users that can reach the server. Develocity provides a search interface for discovering and finding individual Build Scans.

Build Scans published to scans.gradle.com are viewable by anyone with the link assigned when publishing the Build Scan. Links to individual Build Scans are not discoverable and cannot be guessed, but may be shared.

Appendix C: Release history

Please refer to the (Legacy) Gradle Enterprise Gradle Plugin User Manual for the release history prior to version 3.17.

3.18.1

10th September 2024
  • [NEW] Build Cache: Increase parallel remote build cache operation limit

  • [FIX] Build Scan: Resource usage capturing causes excessive logging on Linux when udev is absent

  • [FIX] Build Scan: Display name extraction for Java commands with multiple -jar arguments fails when resource usage capturing is enabled

Compatible with scans.gradle.com and Develocity 2024.2 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.18

19th August 2024
  • [NEW] Build Scan: Resource usage observability in Build Scan

  • [NEW] Build Scan: Configuration cache miss reason is captured

Compatible with scans.gradle.com and Develocity 2024.2 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17.6

22nd July 2024
  • [FIX] Test Retry: Retry TestNG tests with dependencies when using JUnit TestNG engine

  • [FIX] Test Retry: Retry failures in TestNG lifecycle methods when using JUnit TestNG engine

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17.5

12th June 2024
  • [NEW] Build Scan: Capture timestamped version of unique Maven snapshot dependencies

  • [FIX] Predictive Test Selection: Tests may be retried in different JVM when only using Predictive Test Selection

  • [FIX] Test Distribution: When a remote executor disconnects unexpectedly, the plugin might generate invalid executor events in the Build Scan event stream

  • [FIX] Test Distribution: Proxy configuration evaluation may fail in a multi-module project

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17.4

17th May 2024
  • [FIX] Test Distribution/Predictive Test Selection: Test acceleration uses wrong protocol when communicating with a proxy

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17.3

8th May 2024
  • [NEW] Show the origin of the deprecated Gradle Enterprise API usage on demand

  • [NEW] Test Distribution/Predictive Test Selection: Test acceleration requests respect proxy settings

  • [FIX] Test Distribution: Remote execution is sometimes not properly terminated

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17.2

17th April 2024
  • [NEW] Build Scan: Capturing problems are only logged when the Build Scan is published or dumped

  • [FIX] Build may fail if both Gradle Enterprise and Develocity plugins are applied

  • [FIX] Predictive Test Selection: Deprecation warnings are shown for the "mode" and "profile" properties, although the properties are not set by the user

  • [FIX] Test Distribution: Improve resiliency against connection issues

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17.1

9th April 2024
  • [NEW] Support muting Gradle Enterprise deprecation warnings coming from transitive dependencies

  • [FIX] Build Scan: Task for provisioning access key fails if the Develocity server is overwritten

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

3.17

2nd April 2024
  • [NEW] Test Distribution/Predictive Test Selection: Test Distribution and Predictive Test Selection are compatible with Gradle’s Isolated Projects

  • [NEW] Rename plugin from Gradle Enterprise to Develocity, along with new configuration DSLs, system properties, and APIs

  • [NEW] Build Scan: Insights into Gradle’s configuration caching - origin build navigation, entry size, and failure

  • [NEW] Build Scan: Develocity reliably detects when Gradle disables the remote build cache due to failures

  • [NEW] Build Scan: Develocity displays avoidance savings and a link to the origin Build Scan for all up-to-date Gradle artifact transform executions

  • [NEW] Test Distribution: Add support for debugging tests executed remotely on Test Distribution agents

  • [NEW] Test Distribution: Add support for relational operators in build requirements

  • [FIX] Build Scan: Cancelling a Gradle build may result in an incomplete Build Scan

  • [FIX] Build cache cannot be used when publishing a Build Scan® to scans.gradle.com

  • [FIX] Predictive Test Selection: Gradle displays a "no test executed" deprecation warning when no tests are selected on Gradle 8.3 and later

  • [FIX] Test Distribution: Running test tasks is incompatible with IntelliJ’s "Run with coverage" feature

  • [FIX] Test Distribution: Builds may succeed despite unsuccessful retries of location-restricted tests

Compatible with scans.gradle.com and Develocity 2024.1 or later.

When upgrading from the Gradle Enterprise Gradle plugin, refer to the Migrating to the Develocity plugin section.

Appendix D: Compatibility with Gradle Build Tool and Develocity

Compatibility between versions of Gradle, Develocity, and the Develocity Gradle plugin can be found here.

Appendix E: Verifying the signature of the plugin jar

The plugin jar is published to plugins.gradle.org alongside its signature. The public key is published to https://keys.openpgp.org. You can verify the signature as follows:

$ curl -OL https://plugins.gradle.org/m2/com/gradle/develocity-gradle-plugin/3.18.1/develocity-gradle-plugin-3.18.1.jar && \
  curl -OL https://plugins.gradle.org/m2/com/gradle/develocity-gradle-plugin/3.18.1/develocity-gradle-plugin-3.18.1.jar.asc && \
  gpg --keyserver keys.openpgp.org --recv-key 7B79ADD11F8A779FE90FD3D0893A028475557671 && \
  gpg --verify develocity-gradle-plugin-3.18.1.jar.asc develocity-gradle-plugin-3.18.1.jar

The output of the last command should look similar to the following:

gpg: Signature made Thu Sep 28 16:17:46 2023 CEST
gpg:                using RSA key 893A028475557671
gpg: Good signature from "Gradle Inc. <info@gradle.com>" [unknown]
gpg:                 aka "Gradle Inc. <maven-publishing@gradle.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 7B79 ADD1 1F8A 779F E90F  D3D0 893A 0284 7555 7671

This verifies that the artifact was signed with the private key that corresponds to the imported public key. The warning is emitted because you haven’t explicitly trusted the imported key (hence [unknown]). One way of establishing trust is to verify the fingerprint over a secure channel. Please contact technical support should you wish to do so.