Build scans are an important tool for developing and maintaining Gradle builds. They provide insights into exactly what your builds are doing, helping you identify problems with the build environment, dependencies, performance, and more. They can also help you understand and improve the build more generally, and make collaborating with others easier.

build scan service overview
Figure 1. An overview of how build scans work

Gradle Cloud Services is hosted by Gradle Inc. and accessed through HTTPS. It can be used by anyone that agrees to the terms of service—see the setup instructions—and has an internet connection. Gradle Enterprise is a commercial product for companies that can be hosted on their own systems and provides some additional features on top of the ones available in Gradle Cloud Services. This manual covers both products and explains the differences between them in the relevant sections.

You can check out the build scan quick start project to get familiar with creating build scans before using them on your own projects.

Getting set up

There are two aspects to working with build scans:

  • Data collection

  • Publishing

You can have data collection without publishing the information, but you usually want to do both.

Here’s an example that enables the data collection—by applying the build scan plugin— and publishes a build scan every time you run the build:

Sample conventional Java build that always publishes build scans to Gradle Cloud Services
plugins {
    id 'com.gradle.build-scan' version '1.10.3'                  (1)
    id 'java'
}

buildScan {
    licenseAgreementUrl = 'https://gradle.com/terms-of-service' (2)
    licenseAgree = 'yes'                                        (2)

    publishAlways()                                             (3)
}
1 Applies the build scan plugin
2 Configures acceptance of the terms of service
3 Publishes a build scan every time a build runs

If that’s exactly what you require, then there’s no need to continue with the rest of the section as you can copy and paste the code from the above example. However, if you want to enable data collection for all your builds without changing their build files, publish to a Gradle Enterprise instance or use Gradle 2.0, then you should read on.

Let’s assume you want to publish build scans, not just collect the data. In that case, you need to:

  • Enable data collection by applying the build scan plugin (for a single build or all your builds)

  • Configure the publication target (Gradle Cloud Services or a Gradle Enterprise instance)

The next sections take you through all the relevant options related to these steps.

Applying the plugin

You can apply the build scan plugin to individual builds, or to all builds on a machine via an init script. Let’s take a look at the configuration you need for each of these scenarios.

For individual builds

You apply the build scan plugin to a build file in the same way that you apply any other plugin. If you’re using version 2.1 or later of Gradle, then we recommend this form:

Preferred option for Gradle 2.1 and above
plugins {
    id 'com.gradle.build-scan' version '1.10.3'
}

As a fallback, for example if you’re using Gradle 2.0, then you can use the older mechanism for applying plugins:

For Gradle 2.0 and above (build scans are unsupported by earlier versions of Gradle)
buildscript {
    repositories {
        maven { url 'https://plugins.gradle.org/m2/' }
    }

    dependencies {
        classpath 'com.gradle:build-scan-plugin:1.10.3'
    }
}

apply plugin: 'com.gradle.build-scan'

We recommend you always use the latest version of the plugin, which you can find on the Gradle Plugin Portal. It is guaranteed that the latest released plugin version always works with all Gradle versions released at that point in time, starting from Gradle 2.0. Please check the Plugin compatibility with Gradle Build Tool appendix for more details. The Gradle Plugin Portal page will also show you what is new in each version of the plugin.

If you are publishing build scans to a Gradle Enterprise instance you must use a compatible version of the plugin. See Plugin compatibility with Gradle Enterprise for details.

Regardless of which syntax you use to apply the plugin, make sure you declare it before any other plugin. This ensures that any relevant configuration data from those plugins is included in the build scans. For example, prefer this:

plugins {
    id 'com.gradle.build-scan' version '1.10.3'
    id 'java'
}

over this

plugins {
    id 'java'
    id 'com.gradle.build-scan' version '1.10.3'
}

The order used by the second example won’t break the build scans that you publish, but they will be missing useful information.

The build scan plugin must be applied to the root project only, not to subprojects.

For all your builds

You may find build scans so useful that you want to enable them always, regardless of which build you are running. If that’s the case, you can create a Gradle init script that automatically applies the build scan plugin to every build. Here’s an example init script that you can use to do just that:

~/.gradle/init.d/buildScan.gradle
initscript {
    repositories {
        maven { url 'https://plugins.gradle.org/m2' }
    }

    dependencies {
        classpath 'com.gradle:build-scan-plugin:1.10.3'
    }
}

rootProject {
    apply plugin: com.gradle.scan.plugin.BuildScanPlugin
}

Note The ~ in the file path for the init script represents the absolute path to your user home directory. This is the same as the %UserProfile% environment variable on Windows.

Applying the plugin enables the data collection, but you won’t be able to publish build scans until you’ve added some extra configuration. What that configuration looks like depends on where you want to publish those build scans.

Enabling publication of build scans

The last bit of configuration you need depends on whether you are publishing to Gradle Cloud Services or a Gradle Enterprise instance. In the case of the former, you need to accept the terms of service. The latter requires you to specify the service’s location.

Accept the terms of service

There is no interactive option to accept the terms of service when you attempt to publish a build scan to Gradle Cloud Services. Instead, you have to do indicate your acceptance in advance by setting the appropriate build scan plugin options.

To accept the terms of service, add the following configuration to the build script—or the rootProject {} block of the init script if you’re using that approach—ensuring that it appears after the plugin is declared/applied:

Accepting the GCS license agreement in your build or init script
buildScan {
    licenseAgreementUrl = 'https://gradle.com/terms-of-service'
    licenseAgree = 'yes'
}

Before committing to this, be sure to check the terms of service at the URL shown in the above code fragment. Note that if you don’t accept the terms of service, you won’t be able to publish build scans to Gradle Cloud Services.

Once your build file or init script contains these two lines, you’re ready and can start publishing build scans to Gradle Cloud Services.

Set the location of your Gradle Enterprise instance

When you publish build scans to a Gradle Enterprise instance, you don’t need to include the license agreement settings. Instead, you must tell the build scan plugin where to publish the build scans.

Add the following configuration to the build script—or the rootProject {} block of the init script if you’re using that approach—ensuring that it appears after the plugin is declared or applied:

Specifying a custom server for build scans
buildScan {
  server = 'https://gradle.my-company.com'
}

The precise URL you need depends on the hostname your Gradle Enterprise instance has been configured with. If in doubt, be sure to ask whomever manages that instance.

You may encounter a warning about an untrusted certificate every time you try to publish a build scan to an HTTPS URL. The ideal solution is for someone to add a valid SSL certificate to the Gradle Enterprise instance, but we recognise that you may not be able to do that. In which case, set the allowUntrustedServer option to true:

Disabling SSL certificate checks
buildScan {
    server = '...'
    allowUntrustedServer = true
}

This is a convenient workaround, but you shouldn’t use it as a long-term solution.

Controlling when build scans are published

Once you’ve gone through the initial setup of the previous section, you’re 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 build scan plugin has several options that allow you to use whatever approach works best.

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, or ad-hoc, build scans come in.

As long as build scans are enabled for a build, you can publish one by passing the --scan option to Gradle. For example, each of the following will result in a published build scan:

$ gradle assemble --scan
$ gradle clean build --scan
If you are using a Gradle version older than 3.4 or a build scan plugin version older than 1.6, you have to publish build scans using the -Dscan system property instead of --scan.

Behind the scenes, Gradle captures information about the build while it runs and then publishes the data to the configured Gradle Build Scan Service at the end.

There may be occasions when you want to publish a build scan for the previous run. Perhaps you noticed something interesting about the build from its output and would like to review a build scan for it. The build scan plugin supports this situation by providing a buildScanPublishPrevious task that publishes the data that was collected from the previous run:

$ gradle buildScanPublishPrevious

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

$ gradle bSPP

Be aware that the task only works for the previous build execution, so if you remember too late and want to publish the build scan for three builds ago, you’ll need to run the build again. At that point, you should consider automating the publication of build scans.

Publishing every build run

There are 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 the --scan option in such a situation as it’s easy to forget this little tweak to the command line.

When you want to publish every build run, you can use the publishAlways setting:

Publishing a build scan for every build execution
buildScan {
    publishAlways()
}

This approach means that you get a build scan for every successful and failed build that runs, including from your continuous integration infrastructure and your developers. That may work for you, but if you find it overwhelming or simply not useful, add some publication criteria as demonstrated in the following section.

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. Perhaps you only want to publish build scans when the build fails, or if the build is running on your continuous integration infrastructure. Such scenarios are covered by the options in the following table.

Table 1. Options for automatic publishing based on criteria
Option Description

publishAlwaysIf(boolean)

Publish a build scan if the given condition is true, regardless of whether the build succeeds or fails.

publishOnFailure()

Publish a build scan only when the build fails.

publishOnFailureIf(boolean)

Publish a build scan only if the condition is true and the build fails.

For example, let’s say you only want to publish build scans from your CI system, which is identified by having a CI environment variable. This configuration will do the trick:

Restricting build scans to a CI system
buildScan {
    publishAlwaysIf(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:

buildScan {
    if (System.getenv('CI')) {
        publishAlways()
        tag 'CI'
    }
}

Extending build scans

(build scan plugin v1.1+)

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 figure 2:

scan with custom data
Figure 2. A build scan containing the different types of custom data

Gradle Enterprise 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 Gradle Enterprise

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
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.

Build scan plugin v1.9.1+ impose 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
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 2, which shows how a label Source becomes a hyperlink that anyone viewing the build scan can follow.

Build scan plugin v1.9.1+ impose limits on captured links:

  • maximum link count: 20

  • maximum link label length: 100 characters

  • maximum link url length: 1,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
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 Gradle Enterprise.

Build scan plugin v1.9.1+ impose 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

(build scan plugin v1.2+)

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 build scan 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
buildScan {
    buildFinished {
        value 'Disk usage (output dir)', buildDir.directorySize()
    }
}

The buildFinished() closure 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()
import com.gradle.scan.plugin.BuildResult
...
buildScan {
    buildFinished { BuildResult result ->
        if (result.failure) {
            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.

Providing custom data via system properties

(build scan plugin v1.3+)

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 build scan 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:

$ gradle build -Dscan.tag.CI
$ gradle build -Dscan.link.VCS=https://github.com/myorg/my-super-project/tree/my-new-feature
$ gradle build "-Dscan.value.CI Build Type=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.

$ gradle build "-Dscan.value.buildNumber=$CI_BUILD_NUMBER"

Capturing the build scan ID or address

(build scan plugin v1.9+)

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 build scan 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.

Gradle Enterprise 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 com.gradle.scan.plugin.PublishedBuildScan
...
buildScan {
    buildScanPublished { PublishedBuildScan scan ->
        file('scan-journal.log') << "${new Date()} - ${scan.buildScanId} - ${scan.buildScanUri}\n"
    }
}

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

Troubleshooting

Slow build startup in MacOS Sierra after applying build scan plugin

An issue with resolving localhost affecting MacOS Sierra can cause a 5 second delay after applying the build scan plugin to your build. Until the issue is fixed, there is a workaround that you can apply 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 Javadoc.

Appendix B: Captured information

The build scan 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 build scan plugin and transmitted in a build scan.

  • Environment

    • Build Java Virtual Machine

    • Username (system property 'user.name')

    • Local hostname (environment variable 'COMPUTERNAME' / 'HOSTNAME')

    • Public hostname

    • IP addresses

    • Operating System

    • Hardware

  • Build

    • Gradle command-line and invocation options (e.g. requested tasks, switches)

    • Executed task names and outcomes (e.g. FAILED, UP-TO-DATE)

    • Build console output

    • Build failure exception messages and stacktraces

    • Project names and structure

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

    • Applied plugins

    • Resolved dependencies

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

    • Network downloads (performed by Gradle)

Access

Build scans published to a Gradle Enterprise installation are viewable by all users that can reach the server. Gradle Enterprise 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: Plugin release history

1.10.3 - 23th Nov 2017
Fix incompatibility with Android Plugin for Gradle 3.0.0

1.10.2 - 7th Nov 2017
Fix incompatibility with development builds of Gradle 4.4.

1.10.1 - 27th Oct 2017
Fix incompatibility with development builds of Gradle 4.4.

1.10 - 17th Oct 2017
Detect when build was run by a single-use daemon.
Capture default charset of the JVM that executed the build.
Capture build path of each project.

1.9.1 - 10th Oct 2017
Prompt user for license agreement acceptance, if needed.
Capture console output and network activity until closer to the end of the build.
Limit the number and length of captured custom tags, custom links, and custom values.

1.9 - 15th Aug 2017
Capture task graph calculation.
Capture more fine-grained project configuration.
Capture build cache interactions including artifact packing and unpacking.

1.8 - 15th June 2017
Capture resolved requested tasks.
Capture build cache configuration when build cache is enabled.
Capture task inputs for each task when build cache is enabled.
Capture origin build invocation id for tasks with up-to-date and from-cache outcome.
Capture reasons why a task was not up-to-date.
Capture GC and peak heap memory statistics.
Capture more network download activities.
Get notified after successful build scan publication via buildScan.buildScanPublished().
Build scan plugin logs at quiet level.

1.7.4 - 29th May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7.3 - 19th May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7.2 - 17th May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7.1 - 3rd May 2017
Fix incompatibility with development builds of Gradle 4.0.

1.7 - 24th April 2017
Fix NPE when specifying buildScan 'server' URL without schema or host.
Overlapping output is captured as a non-cacheable reason for a task.

1.6 - 10th February 2017
Capture whether task outputs are cacheable and the reason if they are not.
Capture network download activities.

1.5 - 11st January 2017
Capture whether tasks were skipped due to having no source.
Capture whether tasks are lifecycle tasks (i.e. no actions).
Add 'mailto:' link as custom build scan links.

1.4 - 21st December 2016
Performance improvements when executing many tests.

1.3 - 15th November 2016
Capture tags, links and/or values via conventional system properties.
Reduced payload size when publishing large dependency graphs.

1.2 - 12th October 2016
Capture tags, links and/or values at the end of the build via buildScan.buildFinished().

1.1.1 - 20th September 2016
Fixed issues with creating build scans for some projects via Android Studio.

1.1 - 17th September 2016
Capture user-defined tags, links and arbitrary values.
Create a build scan for every build, or every failed build.
Create a build scan for the immediately previous build.
Publishing a build scan is implicitly disabled when build with --offline.
Publish a build scan over an untrusted HTTPS connection, if explicitly configured.
Several fixes for creating build scans when executing a build through an IDE.

1.0 - 23rd June 2016
Initial release.

Appendix D: Plugin compatibility with Gradle Build Tool

Upgrading your Gradle version may require updating the build scan plugin version. At all times, the latest version of the build scan plugin is compatible with all Gradle versions later than Gradle 2.0.

Using the latest plugin version is strongly recommended as it will produce the most useful build scans.

Table 2. Gradle Build Tool compatibility with the build scan plugin
Gradle Build Tool versions Minimum plugin version Maximum plugin version

4.0 - 4.3.1

1.7.4

1.10.3

2.0 - 3.5

1.0

1.10.3

< 2.0

build scan plugin not supported

build scan plugin not supported

Latest plugin version: 1.10.3

Please see the above section on applying the plugin for guidance on using the latest version.

Appendix E: Plugin compatibility with Gradle Enterprise

When using the build scan plugin in conjunction with a Gradle Enterprise instance you must ensure you are using a compatible plugin version. Scans created using a plugin version later than the maximum version supported by your Gradle Enterprise instance will be rejected.

Table 3. Gradle Enterprise compatibility with the build scan plugin
Gradle Enterprise versions Minimum plugin version Maximum plugin version

2017.6

1.0

1.10.3

2017.5

1.0

1.9.1

2017.4

1.0

1.8

2017.3

1.0

1.7.4

2017.2

1.0

1.6

2017.1

1.0

1.6

2016.4

1.0

1.3

2016.3

1.0

1.1.1

2016.2

1.0

1.0

2016.1

1.0

1.0

2016.0

1.0

1.0