There are currently no pre-built public releases of the Holy Gradle, and no public release notes for versions before 7.0.0.

Release Overview

Content

The Holy Gradle is released in two main parts which have a weak dependency between them: a Custom Gradle Distribution and a set of Custom Plugins for Gradle.

Upgrading

To use a specific version of the plugins, you should use the highest version of the custom distribution which is less than or equal to the plugin version. Using other versions may work but it is not guaranteed. There is currently no automatic checking of version compatibility between the custom distribution and the plugins.

It is simplest to change the distribution version by replacing your current Gradle wrapper files with those from the ZIP file. Note that different versions of the ZIP file may have a different set of files, so be careful to add any new files to source control in your project, and remove any from source control which are no longer in the ZIP file. The simplest way may be to delete the gradle folder before unzipping.

Gradle Plugins

See the section on the Version Number Convention if you want to know how the version numbers are assigned.

Before version 6.0.0, each plugin could be (and was) published independently with its own version number. From 6.0.0 onwards, all plugins are published together with the same version number, any time any of them changes. This simplifies things for users, and also for plugin developers.

7.x

7.12.x

7.12.0

(01356a342715 at 2017-12-01 16:21:13 UTC)

Intrepid
  • Transitive packed dependencies can now appear in the workspace (as links or unpack folders) in more than one location. Previously, if a transitive dependency was expected to appear in multiple locations (because it came from multiple packed dependencies which were configured to appear in different folders) it would only appear in one of those locations, and the location was not predictable.

    • To prevent multiple versions of the same transitive dependency targeting the same location, this change introduces the restriction that any packed dependency can only appear in one location per configuration. In other words, each configuration must all its dependencies in one folder. This may require breaking changes to the dependency paths in your packedDependencies block. See Dependency Locations for more details.

    • Also as part of this, removed support for packedDependenciesSettings.useRelativePathFromIvyXmle, which was introduced in 7.4.0 as a temporary way to re-enable that deprecated feature.

CustomGradleCorePlugin
DevEnv
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.11.x

7.11.0

(4ec3faf09545 at 2017-10-12 15:56:06 UTC)

Intrepid
  • Major new feature: added support for "source overrides", which allow developers to replace the links for packed dependencies with links to a local checkout of corresponding source code. This allows you to modify the source, for example to help debug a problem. See sourceOverrides for more details.

    • Multiple packed dependencies can be replaced.

    • If the source of the replaced dependencies itself uses a new enough version of the Holy Gradle, then multiple levels of source override are possible.

    • The Holy Gradle can ensure that the transitive dependencies of the replaced source are consistent with the dependencies of the main build and any other source overrides.

    • A module with source overrides cannot be published, because Gradle cannot know the published version of the overridden dependency.

CustomGradleCorePlugin
DevEnv
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.10.x

7.10.3

(62ee2a1a8eaf at 2017-09-27 12:12:57 UTC)

DevEnv
  • Improve support for choosing a Visual Studio version. See version for more details.

    • For a version of Visual Studio before 2017, try to use the VSnnnCOMNTOOLS environment variable before trying to run vswhere.exe, because some early versions of vswhere.exe don’t detect older versions of Visual Studio.

    • For versions of Visual Studio from 2017 onwards, allow specifying an exact update version (such as 15.0 or 15.35) or the latest minor version (using 15.+).

CustomGradleCorePlugin
Intrepid
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.10.2

(bcbdabef989b at 2017-08-11 12:05:12 UTC)

CredentialStore
  • Change credential-store.exe to compare usernames case-insensitively.

Stamper
  • GR #6718 Add support for reading/writing files with a non-default charset, e.g., UTF-8 on Windows 7.

    stamping {
        charsetName = "UTF-8" // New in 7.10.2
    
        def commas = nextVersionNumber.replaceAll("\\.", ",")
        files(".rc") {
            replaceRegex ~/(FILEVERSION )[\d,]+(.*)/, commas
            replaceRegex ~/(PRODUCTVERSION )[\d,]+(.*)/, commas
            replaceRegex ~/(VALUE \"FileVersion\", \")[\d\.]+(\\0\")/, nextVersionNumber
            replaceRegex ~/(VALUE \"ProductVersion\", \")[\d\.]+(\\0\")/, nextVersionNumber
        }
    }
CustomGradleCorePlugin
Intrepid
DevEnv
UnitTest
ArtifactoryManager
MyCredentials
Utils
  • No changes.

7.10.1

(d61afb3c0e6d at 2017-07-20 16:18:17 UTC)

CredentialStore
  • GR #6716 Fix bugs in the changes to credential-store.exe in 7.10.0

    • credential-store for-default would update all credentials, not just those not associated with any basis.

    • credential-store.exe would fail without an error message if environment variable GRADLE_USER_HOME was not set.

DevEnv
  • Support Visual Studio 2017. (Instead of using environment variables, this version has a new mechanism for locating devenv.com, namely by running vswhere.exe. This allows installing multiple "flavours" of VS but needs changes to the Holy Gradle.)

CustomGradleCorePlugin
Intrepid
UnitTest
ArtifactoryManager
MyCredentials
Stamper
Utils
  • No changes.

7.10.0

(238dac7222d6 at 2017-04-04 08:40:10 UTC)

CustomGradleCorePlugin
CredentialStore
Intrepid
MyCredentials
  • GR #6715 Allow source dependency credentials to be derived from a user-named "basis" credential. This supports having source dependencies on repos hosted at different sites, which need different credentials.

    • To use this, add credentialBasis = "AnyStringYouLike" to a sourceDependency block. The default basis string is "Domain Credentials" for backward compatibility.

    • credential-store.exe has been modified to allow users to separately update credentials for a given basis, or to update credentials not associated with any basis (for backward compatibility and for use with credentials supplied from my.credentials to binary dependency repositories such as Artifactory). This relies on a file holygradle/credential-bases.txt which is written into the user’s Gradle Home directory by the Intrepid plugin and read by credential-store.exe.

DevEnv
UnitTest
ArtifactoryManager
Stamper
Utils
  • No changes.

7.9.x

7.9.2

(6de1381c9dba at 2017-03-28 10:09:55 UTC)

CustomGradleCorePlugin
  • GR #6714 Fix: ensure an exception is thrown to stop the build if Git/Hg/Svn processes have a non-zero exit value.

Intrepid
  • GR #6714 Various fixes related to Git (and Hg) source dependencies:

    • The existing Git support was specific to the now-outdated "wincred" Git credential helper. Support was changed to also cover the newer "winstore" and "manager" helpers. The Holy Gradle will always cache credentials for "http(s):" URLs for Git source dependencies, even if they aren’t actually needed, otherwise the newer helpers may show a modal dialog which never times out which can cause problems on continuous integration build machines.

    • If a source dependency was not fetched correctly, Gradle would still treat the fetch task as "up to date", so running it again would do nothing unless you deleted your ".gradle" build state cache folder.

DevEnv
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.9.1

(3e6fe3d1f432 at 2016-07-26 13:35:49 UTC)

CustomGradleCorePlugin
  • GR #5985 Extend the auto-detection of the current domain (to set the default Artifactory plugin repo URL) so that it checks all network interfaces, not just the default one.

Intrepid
DevEnv
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.9.0

(11be4c326e36 at 2016-06-30 09:58:34 UTC)

Intrepid
  • GR #6692 Git support. Git repos can now be source dependencies, by using the git method instead of hg or svn. This includes recording the source URL, revision, and branch in the build_info folder in packaged artifacts.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.8.x

7.8.1

(311b92b40032 at 2016-06-29 16:53:08 UTC)

CustomGradleCorePlugin
  • Fixed a bug in gw.bat which forced you to set the HOLY_GRADLE_REPOSITORY_BASE_URL environment variable even if the file .\gradle\base-url-lookup.txt existed. When that file exists, the base URL should be set from that file. This bug was introduced in 7.6.0. As well as upgrading the version of the plugins, you should upgrade the gradle wrapper (for example, from the wrapper-starter-kit).

Intrepid
DevEnv
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.8.0

(adb85b78fe9b at 2016-04-19 15:03:19 UTC)

CustomGradleCorePlugin
Intrepid
  • GR #6570 Create directory junctions instead of directory symbolic links by default. On Windows 7, if you have local Administrator rights, you need to turn UAC down or off to be able to create symlinks, which is somewhat annoying and unsafe. On Windows 8 and above you also need to run from an elevated (Administrator) Command Prompt, which is even more so. This release uses directory junctions instead, for symlinks to the unpack cache and for the links DSL (renamed from symlinks).

    • This is a Windows security restriction, apparently related to the fact that the target of a network share can be changed by the server, so a symlink to a network share might be an unexpected security risk. Directory junctions cannot point to network shares and so processes do not need special permissions to create them.

    • If your unpack cache or other link targets are on a network share it will use symlinks for those, and then you still may need to run from an elevated Command Prompt.

DevEnv
UnitTest
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.7.x

7.7.6

(14b9d6237fb2 at 2016-04-19 12:00:20 UTC)

Intrepid
  • GR #6588 Fix for upgrading from Artifactory 3.3.0 to 4.7.1. The checkPackedDependencies command was sending the wrong content type in the "Accept" header when checking for which module versions exist. The older Artifactory version ignored it but 4.7.1 complained with "406 Not Acceptable".

UnitTest
  • GR #6675 Bug fix and further improvements to the unit-test plugin. Deprecated the behaviour that test tasks would look for the executable relative to the root project’s projectDir. It now only looks in the current project’s projectDir or on the system PATH, similar to the default behaviour for Exec and project.exec.

Utils
  • GR #6588 Fix for upgrading from Artifactory 3.3.0 to 4.7.1. Fixes for the replicationVersionCheck Artifactory plugin; should still be compatible with 3.3.0 but that wasn’t tested.

    • We now need to explicitly use the proxy for a remote repo to connect to the remote server to find out its version.

    • The comparison logic was flawed.

    • Artifactory 3.3.0 passes the name of the remote repo to the beforeReplicateXxx hooks, but 4.7.1 passes the "-cache" repo name; so we now strip off that suffix if it exists.

DevEnv
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
  • No changes.

7.7.5

(76dfef3c465a at 2016-04-11 13:35:09 UTC)

CustomGradleCorePlugin
  • In gw.bat the JAVA_HOME and GRADLE_HOME environment variables are now copied from HOLY_GRADLE_JAVA_HOME and HOLY_GRADLE_GRADLE_HOME if they exist. This allows you to run other apps with a different version of Java, even though the Holy Gradle requires Java 1.7. As well as upgrading the version of the plugins, you should upgrade the gradle wrapper (for example, from the wrapper-starter-kit).

Intrepid
  • GR #6664 Move the "everything" configuration behind a property flag. Added an error message for the unlikely case of trying to explicitly put the same packed dependency at two different locations, which is not supported.

UnitTest
  • GR #6675 Bug fix and further improvements to the unit-test plugin:

    • The previous changes for #6675 always re-created empty test output files on every build (that is, when the task was configured) even if that build didn’t involve running the tests. That meant that test results from previous runs would be lost when you ran any other task. Now the output files are not overwritten until the test tasks run.

    • You can now choose to send test "standard error" output to just a file, or to both a file and standard output, in the same way as "standard output". See setErrorOutput and setErrorOutputTee for details.

DevEnv
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.7.4

(a5902c826e99 at 2016-03-23 09:57:55 UTC)

Intrepid
  • GR #6664 Move the "everything" configuration behind a property flag. Fixed a bug where, if the same module was both a direct and a transitive dependency, it could cause packed dependency resolution to fail, depending on the order in which they were found.

  • GR #4126 Bug fix for recording source version info for unpublished source dependencies. Info for transitive source dependencies was only included for the root project; for other projects (including all source dependencies reachable from the root project), only info on immediate source dependencies was included. Now each project’s build_info folder includes source version info for its complete set of transitive source dependecies.

  • GR #6585 Internal change to make sure that the configurations returned by a configuration set’s methods are always returned in the same order.

UnitTest
  • GR #6675 Convenience improvements to the unit-test plugin:

    • You can now set the workingDir for the tasks which are generated, in the same way as ExecSpec#workingDir.

    • You can now choose to send test output either just to a file (using standardOutput = <String, File, etc.>), or to both a file and standard output (using standardOutputTee = <String, File, etc.>). These methods replace redirectOutputFilePath which is deprecated (but still works, for now). Note that these new methods don’t take strings, only File objects, and they are not automatically interpreted relative to the projectDir. See setStandardOutput and setStandardOutputTee for details.

Utils
  • GR #5818, GR #4104 These Artifactory plugins need to make REST calls to the local server’s API. This release parameterises the URL for the local server, since it may not be on the default of "http://localhost:8081/".

DevEnv
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
  • No changes.

7.7.3

(9bb5a2f764ff at 2016-03-09 11:30:32 UTC)

Intrepid
  • GR #6664 Move the "everything" configuration behind a property flag

    • Make the everything configuration not created unless the property createEverythingConfiguration is set.

    • Packed dependencies are more aware of configurations. This allows different versions of modules to exist in one project so long as they are in different configurations.

    • Transitive dependencies that are also specified as a direct packed dependency will now use the location of the packed dependency even if the transitive dependency is evaluated first.

Utils
  • GR #5818 New Artifactory plugin — fail replication if source server is different version (and send email notifications).

  • GR #4104 Add email notifications to existing checkCaseInsensitiveNameClash Artifactory plugin.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
  • No changes.

7.7.2

(4b7e7f25280b at 2016-02-04 15:14:32 UTC)

Intrepid
  • GR #6585 Further bugfixes and improvements.

    • Make the "private build configuration" mechanism work for DefaultConfigurationSetType, not just for the WindowsConfigurationSetType subclass, so that "web libraries" can also choose not to re-export things they import.

    • Create the "private build configuration" automatically if it doesn’t already exist.

    • Add automatically-generated descriptions for the configurations generated by configuration sets.

    • In the default Visual Studio and Web configuration set types, change the names of some axes, so that they map the variables used in Visual Studio (configurations to Configuration, and platforms to Platform).

    • In the default Web configuration set type, change to have "_common" configurations for all stages, not just "import", because web projects are more likely to have files in each stage which don’t differ between Release and Debug.

    • Add a getAxes method to DefaultConfigurationSet so that scripts can easily iterate over one of the axes, for example in the pacakgeArtifacts block. See the example build scripts.

    • The ConfigurationSet interface had methods called getConfigurations and getConfigurationNames which returned a mapping from axis bindings to the corresponding configurations (or names). These methods now just return a list, and new methods getConfigurationsMap and getConfigurationNamesMap have been added to the DefaultConfigurationSet implementation class.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.7.1

(186454651bba at 2015-11-30 13:55:03 UTC)

Intrepid
  • GR #6585 Fixed mistake in overall design of configuration mapping. If module A is mapping to module B, and doesn’t want to export B’s "import" configurations in its own "import" configurations, it usually still needs to have a mapping to the import configurations of module B, otherwise headers/etc. will be missing (if the unpack cache is clean). The fix is to map from a private configuration "build" in A to the "import" configurations of B.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.7.0

(aee70bdfbd29 at 2015-11-27 13:02:35 UTC)

Intrepid
  • GR #6585 Further bugfixes and improvements based on use in practice.

    • Renamed mapConfigurationSet to just configurationSet (similar to the existing confguration method).

    • For mapping from a single configuration to a configuration set (or type), require a Configuration object instead of just a String. Using a String could mislead users into thinking they can map from "a configuration set by name".

    • Changed default configuration set types only have a "…_common" configuration for stage "import", rather than also for the "runtime" and "debugging" stages.

    • Bugfix: Referring to "configurations.foo" inside a SourceDependencyHandler was intended to refer to the project configuration called "foo", but instead indexed into an internal "configurations" property on the handler. Renamed the internal property to allow this to work.

    • Replaced DefaultConfigurationSetType.withPrefix with a more general method makeSet, which creates a new set and takes a closure to configure it.

    • In DefaultConfigurationSetType, changed how overriding of "mappings from" is done, to make it more obvious how to override, and more consistent with "mappings to".

  • GR #2693 Deprecated the ".publishing" level of the sourceDependencies DSL, because the configuration inside it is relevant for dependency resolution when building, not only when publishing. The configuration mapping methods inside it are now available one level up, directly in the SourceDependencyHandler.

  • GR #4676 Removed the never-used option in SourceDependencyHandler to override the group or version of a published source dependency, because it never really made sense. Also removed the sourceDepdendency.usePublishedVersion property. What these were trying to achieve will be provided by the "GR #6279 source overrides" work when it’s merged to default.

  • A source dependency will no longer automatically have a mapping between the "everything" configurations of the originating module and the dependency. This mapping is only added when some other mapping is added. This means that you can now have a source dependency with no Gradle project and no published dependency, for example, to include source or documents from a different source repository in the current module. See configuration.

  • GR #5847 By default the "relativePath" attribute is no longer added to generated ivy.xml files. GR #5845 and GR #5846 changed the behaviour on read so that, by default, this value is ignored anyway. The Ivy files therefore now validate, which will allow us to upgrade to Gradle 1.8 or higher.

DevEnv
  • GR #5823 Changed DevEnvHandler so it no longer assumes (the now rather outdated) Visual Studio 2010 by default. Now you must specify the version.

UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.6.x

7.6.2

(a18a258bee8a at 2015-11-18 17:49:32 UTC)

Intrepid
  • Fixed new bug introduced by previous bugfix (for deleting files with long paths), that read-only files could not be deleted.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.6.1

(5e8a66eb0f71 at 2015-11-16 14:54:00 UTC)

Intrepid
  • GR #6585 Bugfixes and improvements based on use in practice.

    • Fix a bug introduced in refactoring, which meant that use of packageArtifacts.includeBuildScript would throw an exception.

    • Added a withPrefix method to ConfigurationSetTypes to make it easy for one module to refer to prefixed configurationSets in another module. See [TODO: link to doc].

    • Added overloads of mapConfigurationSet for mapping a single configuration to a target configuration set (not just to a target configuration set type).

    • Add a simplistic configuration type for "web libraries". May change this in future. See WEB_LIB.

  • Internal bugfix for deleting test output files with paths longer than the Windows maximum.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.6.0

(c4befcca049a at 2015-10-30 17:38:34 UTC)

Intrepid
  • Bugfix for symlink creation: Symlinks were testing whether the link target existed before creating but for relative links this was being done relative to the working directory rather than the link itself (which is the behaviour Windows uses when creating the link).

  • Made gw.bat cope properly with paths with spaces in them (though other parts of the Holy Gradle may not).

  • GR #6585 Add support for creating and mapping sets of related configurations. Unlike JVM-based code, native applications often vary by platform, build setup (Debug or Release), etc., as reflected in the "model" in newer versions of Gradle, and it is natural to map these to separate Gradle configurations. This new DSL makes this easier. See configurationSetTypes and configurationSets.

DevEnv
UnitTest
CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.5.x

7.5.1

(267f84a42508 at 2015-08-20 11:43:46 UTC)

Intrepid
  • GR #6391. Added a zipDependencies task which is like collectDependencies but collects files straight to a UTC-time-stamped ZIP file.

  • GR #6355. Can’t republish with holygradle 7.5.0. The changes in 7.3.0 for GR #5759 (not entirely overwriting the settings.gradle file) clashed with the createSettingsFileForPackedDependencies task which is only used as part of the "republish" task. For now I’ve merged the logic, in a slightly hacky way, but the real fix is to replace the current republish mechanism with something much simpler.

  • GR #2297, GR #4677. Configurations with a naming starting with "private" used to be removed from the ivy.xml. They are now just marked as visible=false in Gradle terms (visibility="private" in the ivy.xml). This means it’s easier to find the version number of non-public dependencies: previously you had to look at the build scripts. It also means that, if you use a floating version number (which we don’t recommend) for a private dependency, the ivy.xml will record the version actually used.

  • GR #1962. (Shouldn’t affect anyone.) Removed the "_confict" mechanism, which was added in the very early days in an attempt to make the ivy.xml "look neater" when conflicting versions of dependencies were used in different configurations of one module. However, the resulting ivy.xml would be incorrect and unusable, so it was pointless.

  • Fixed minor bug where pacakgeArtifacts.includeBuildScript.addPackedDependency could be called more than once for the same dependency and would only use the last call. Now it fails if called more than once.

  • Fixed minor bug where a unit test would fail if the folder for the test output didn’t already exist. Now it’s created.

  • Fixed minor bug where a packedDependency could be declared more than once with a different dependency string, which doesn’t make sense, and would break symlink generation. Now it fails immediately with a sensible error message.

DevEnv
UnitTest
  • GR #5714. Replace TaskDependencies with Gradle’s built-in mechanism. Previous implementation of "build/test for this project only, ignoring dependencies" (in 7.3.0) didn’t actually work, and always ran dependencies as well.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
MyCredentials
Stamper
Utils
  • No changes.

7.5.0

(1db4b7a566e1 at 2015-07-14 09:41:15 UTC)

Intrepid
  • GR #6072. local_artifacts folder now contains build_info so that the person who receives it can tell which version of the source it matches.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.4.x

7.4.3

(ae78078ada2a at 2015-07-10 11:03:13 UTC)

Intrepid
  • GR #5845, GR #5846. Bug fixes.

    • If there was a pre-existing settings file in which the last line did not have a line ending character sequence, the text inserted by the Holy Gradle would be inserted at the end of that line; then on later runs, it would fail to find the BEGIN marker, and so add the text again.

    • The inserted code removes any source dependencies from the subproject list if they have no build file. However, the code to do this removal made the classic mistake of trying to remove from collection while iterating over it, so it would cause a ConcurrentModificationException if there were any further projects after one which was removed.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.4.2

(328affd15303 at 2015-06-11 16:16:08 UTC)

Intrepid
  • Bug fix. Using resolutionStrategy.force with packed dependencies would cause intrepid to fail to find the ivy.xml files (needed for the relativePath and for collectDependencies) for those modules (if the forced version was lexicographically less than the original version), and so fail the build.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.4.1

(c2f77e448810 at 2015-05-18 10:42:16 UTC)

Note
This version adds the changes in 7.3.3 and 7.3.2.
Intrepid
  • A minor change to how collectDependencies works. Previously there was one such task per project, with no task dependencies between them. This made it tricky to have another task depending on collectDependencies. Now there is just one such task, in the root project, which collects the dependency artifacts and metadata for all projects.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.4.0

(9284cf3153b2 at 2015-04-24 14:56:49 UTC)

Warning
This version does not include the changes in 7.3.3 or 7.3.2.
Intrepid
  • GR #5845, GR #5846. Make default relative path for transitive packed deps be "../name" instead of "./name". This is the first of several changes to simplify dependency symlinks. This change means that libraries which don’t have relativePath in their ivy.xml will all be symlinked next to each other, rather than some appearing inside others. Any projects which have worked around this lack of relativePath, by adding direct dependencies on things they really only indirectly depend on, can now remove those workaround dependencies.

    This change also means that indirect dependencies will appear under symlinks which exactly match the module name. You can deal with that in several ways.

    • Change your include and link paths in your projects.

    • Explicitly add a symlink from the old location to the new one (using the holygradle symlinks block, for example).

    • Add an explicit dependency on that module at the path you want it to have. You only have to supply the path and the module ID — not any configuration mapping.

    • Temporarily disable this new behaviour by adding packedDependenciesSettings.useRelativePathFromIvyXml = true to your script. This mechanism will be removed in future.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.3.x

7.3.3

(33cebe1933a1 at 2015-05-13 12:15:43 UTC)

Intrepid
  • GR #5759 Bug fix. When a settings.gradle file was created by 7.3.2, 7.3.1, or 7.3.0, it would work for the developer who first created it and committed it to source control, but fail for another developer who checked it out. This is because it required the "settings-subprojects.txt" to exist. A workaround is to create an empty file of that name. This release fixes the bug properly: if the file does not exist, the code added to settings.gradle will assume there are no subprojects. If you already have a settings.gradle with this bug then, to upgrade, you must first either delete the section "holygradle source dependencies" from it, or create an empty "settings-subprojects.txt", Then upgrade your plugin versions and run "gw fAD".

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.3.2

(1a3f9b5d967b at 2015-04-30 10:34:28 UTC)

Intrepid
  • GR #5759, GR #5912 Fix two exceptions which could occur in error cases. These were introduced in the changes for not overwriting the settings file (#5759) and for removing the embedded Mercurial and Subversion code (#5912).

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.3.1

(defef8336345 at 2015-04-24 11:55:41 UTC)

Intrepid
  • GR #5759 Intrepid will now include the settings file (settings.gradle) in the "buildScript" artifact ZIP file when publishing, as well as the build script (build.gradle). Now that intrepid does not always overwrite the settings file, users may modify it, so it should be kept for traceability. This is particularly useful for simple packaging of third-party libraries, where the build file may not be committed to source control.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.3.0

(1d9f497cefb2 at 2015-04-22 12:27:58 UTC)

CustomGradleCorePlugin
Intrepid
DevEnv
  • GR #5714 Replace TaskDependencies with Gradle’s built-in mechanism. Tasks like buildDebugIndependently have been replaced with the standard Gradle way of saying "run just for this project, not for other source dependency projects": gw -a buildDebug.

  • GR #5912 Use installed Mercurial and/or Subversion to process source dependencies, instead of using an embedded version. Before this release, the intrepid plugin would use a pre-packed version of Mercurial pulled from Artifactory, and used a Java library svnkit for Subversion access. This was convenient in some ways but has caused problems (a) where user configuration of their installed tools was not shared with the "embedded" versions; and (b) that some users' installed version of Subversion now creates a working copy format which the embedded version can’t read. So from now on the plugin will rely on hg.exe and/or svn.exe being on the path, to access source dependencies.

  • GR #2618 Reduce the visibility of warnings about source dependencies, when they are still to be fetched. These warnings are usually false positives, so now they’re only shown at the info logging level.

  • GR #2394 Intrepid could previously record the wrong source version in the build_info folder, if the project dir was both an SVN and Hg working copy. This isn’t really a sensible thing to do, and it only every happened on one build machine a long time ago, but the plugins will now just fail if the project is under both kinds of source control.

  • GR #5759 Intrepid will no longer completely overwrite the settings file each time it runs. Previously it did this to add source dependency projects to the build. Now it injects a fixed code section and keeps the varying part (a list of source dependency folders) in a separate file. This means that you can use the settings.gradle file for its intended purposes, which includes setting the name of the a project, rather than inferring it from the name of the containing folder. See the Gradle Settings documentation for details. For example, you could write

    rootProject.name = "MyModule"
    

    Currently you can only change the name of the root project. Changing the name of subprojects causes problems with the part of intrepid which handles source dependencies. This could be fixed easily enough if necessary.

ArtifactoryManager
CredentialStore
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.2.x

7.2.5

(c2d491236925 at 2015-01-30 16:40:18 UTC)

Intrepid
  • GR #5660 Fix for checkPackedDependencies task failing after checking an unavailable dependency.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.2.4

(fbaa4be26917 at 2014-12-05 11:08:30 UTC)

Intrepid
  • GR #5346 If a meta-package has a generated build script (using includeBuildScript), it will now also have a default settings.gradle added, unless (a) one is added explicitly with includeSettingsFile; or (b) createDefaultSettingsFile = false is called. This avoids the unpacked meta-package accidentally picking up a settings file from an ancestor directory when run, which almost certainly won’t be what its creator intended.

  • This release also includes a small breaking change to a method used only by one team, but it’s an internal, not-officially-supported method, so I still regard this as a micro version change.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.2.3

(82b038d4b721 at 2014-11-24 16:37:18 UTC)

Intrepid
  • GR #4546 Added error-checking/-reporting to addPackedDependency and addPinnedSourceDependency, so they fail if the script tries to add a dependency which doesn’t exist.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
Utils
  • No changes.

7.2.2

(991ce16b079f at 2014-08-21 14:47:30 UTC)

Intrepid
  • GR #4071 Using dependencySettings.defaultFailOnVersionConflict = false didn’t actually do anything; fixed.

  • GR #4125 Add always-visible logging of ZIP files extracted by extractPackedDependencies simlar to what Gradle normally does for downloading of artifacts.

  • GR #4546 Simplified the code behind packageArtifacts.config>.includeBuildScript.addPackedDependency, by making two changes. In theory these are breaking changes but in practice we know they won’t affect any of our users.

    • includeSymlinks is removed. This never really made sense anyway: a module could have symlinks into folders belonging to dependencies which were not present in the set of configurations pulled in by the generated build script (typically because they were private), in which case creating the symlinks would fail when using the module (even though it worked when building it).

    • addPinnedSourceDependency doesn’t support wildcards any more. This was only ever used for "include all source deps from all projects", which can now be done like this:

      gradle.projectsEvaluated { allprojects { sourceDependencies.each {
          addPinnedSourceDependency it
      } } }
  • GR #3080 packageArtifacts.includeBuildScript used to work only if you included at least one packed or source dependency; now it always works.

  • GR #5099 Since the fix for GR #4126 in 7.2.1, the republish task would delete the build_info folder and re-create it with only versions.txt. This is now fixed, although running the packageFoo tasks will still re-create the build_info.

Utils
  • GR #4104 Added an Artifactory plugin to work around https://www.jfrog.com/jira/browse/RTFACT-6377.

  • GR #4570 Added an Artifactory plugin to provide a per-repo storage usage summary, showing details only for repos visible to the authenticated user (or anonymous).

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.2.1

(991ce16b079f at 2014-08-21 14:47:30 UTC)

Intrepid
  • GR #4125 Using PackedDependenyHandler#noCreateSymlinkToCache() (unless the dependency has unpackToCache = false) will now prevent the containing module from publishing (because we can’t be sure which version of the dependency was used).

  • GR #4126 The build_info folder created during publishing now also records source information for the transitive set of source dependencies, in case some of them are not published.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.2.0

(633551bc9a87 at 2014-08-19 09:25:51 UTC)

CustomGradleCorePlugin
Intrepid
  • GR #2151, #4125 For large projects, the start-up time of intrepid was dominated by dependency resolution (for the project itself, rather than for the plugins), which was used to build the list of tasks (one extract and one symlink task per dependency), so it happened every time, even if you just ran gw tasks. Now, intrepid avoids doing anything which requires dependency resolution unless you run a task which requires it (fetching or collecting dependencies, rebuilding symlnks, etc.). For a multi-project build with around 10 sub-projects, with an average of 10 source or packed dependencies each, this reduced the start-up time from about 60s to about 20s.

  • GR #3719, #4559 Previously, if a symlink target did not already exist, the symlink would be created anyway and a warning printed. This seems to have been done because the dependencies between unpacking and symlink tasks were not strictly correct. However, it led to confusion in genuine error cases. Now it fails in such cases (or if there is a non-symlink at the link source location). Some teams had taken advantage of the previous behaviour to swap in a "built from source" version of a packed dependency on their development PC; I’ve added a new method noCreateSymlinkToCache() to allow this pattern in an intentional, rather than accidental, way.

DevEnv
  • GR #4125 To speed up builds, the beforeBuild task no longer depends on the rebuildSymlinks task. This means that building the solution doesn’t automatically force time-consuming dependency resolution. Projects can still add beforeBuild.dependsOn rebuildSymlinks if they prefer the previous arrangement.

ArtifactoryManager
CredentialStore
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.x

7.1.7

(ccd9abb1c942 at 2014-08-06 15:24:26 UTC)

Intrepid
  • GR #4577 A previous bug-fix exposed a bug which was only observed by the one team: the createPublishNotes task needs hg.exe, but doesn’t depend on extractMercurial. If you try to publish when you have a clean cache and haven’t fetched any Mercurial source dependecies (e.g., as on an autobuild machine), this will fail. This release fixes that bug.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.6

(fbbe79848f3f at 2014-07-23 13:22:50 UTC)

CustomGradleCorePlugin
Intrepid
  • GR #4546 Release 7.1.5 fixed addPackedDependency but broke addPinnedSourceDependency — the latter was supposed to use wildcard matching, but 7.1.5 changed it to exact matching. This release makes both work as documented.

ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.5

(7aee2487c6d7 at 2014-07-25 12:40:53 UTC)

BROKEN, DO NOT USE

Intrepid
  • GR #4546 The DSL for adding packed dependencies to a generated build script (packageArtifacts.config.includeBuildScript.addPackedDependency) was broken. It was using wildcard matching instead of the intended exact matching, so it could add the wrong packed dependency, if the name of one were a substring of the other.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.4

(66f47c9c5737 at 2014-07-23 13:22:50 UTC)

Intrepid
  • GR #4088 Fix a bug in 7.1.3 which meant that collectDependencies would try to copy ZIP file artifacts and metadata files for source dependencies, which don’t exist (and aren’t needed anyway), because those dependencies are being built from source.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.3

(be97073caa47 at 2014-07-16 11:01:12 UTC)

Intrepid
  • GR #4088 Previously, if a dependency was referenced in terms of a configuration which had no artifacts, intrepid would silently fail to fetch or otherwise consider any dependencies from that empty configuration. 7.1.0 fixed this for all cases except the collectDependencies task; 7.1.3 fixes that as well.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.2

(f55df7416c24 at 2014-07-08 16:05:15 UTC)

Intrepid
  • GR #3813, GR #4071 Fixed a further which could cause an error "Some dependencies had no ivy.xml file" when running gw fetchAllDependencies. This could happen if the same dependency appeared at multiple levels in the graph (e.g., boost), but only in some cases (depending on the order in which Gradle visited dependencies).

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.1

(f35c15b2126d at 2014-07-04 09:30:20 UTC)

Intrepid
  • GR #3813, GR #4071 Fixed a bug I introduced in 7.1.0, which could cause a crash, rather than useful information, if multiple versions of the same module were specified.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.1.0

(cc70f8bc88da at 2014-07-01 10:47:27 UTC)

Intrepid
  • GR #3813, GR #4071 Previously, if a dependency was referenced in terms of a configuration which had no artifacts, intrepid would silently fail to fetch or otherwise consider any dependencies from that empty configuration. This is now fixed, except for the collectDependencies task.

CustomGradleCorePlugin
ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.0.x

7.0.2

(0a066299ca84 at 2014-06-18 14:19:11 UTC)

Make gw.bat work without the repository environment variable, when the local_artifacts folder is being used.

This release also contains all the changes in 7.0.1, without broken references between parts of the release.

CustomGradleCorePlugin
  • GR #4116 Change gw.bat so it doesn’t require HOLY_GRADLE_REPOSITORY_BASE_URL (nor generate/overwrite gradle-wrapper.properties) if the local_artifacts folder exists.

  • GR #4116 Since the init script doesn’t have the server hard-coded into it, we don’t need to depend on the gradle.properties file (of the holy-gradle-plugins build itself).

  • Put source back-reference into gw.bat.

Intrepid
  • Fix bug: If on a new machine you run fetchFirstLevelSourceDependencies before fethAllDependencies, then hg.exe would not be downloaded and the command would fail.

ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.0.1

(7364cdcf19be at 2014-06-10 09:22:14 UTC)

BROKEN, DO NOT USE

Parts of this release were published with references to SNAPSHOT versions of other parts. so its behaviour could change in future.

Re-adding changes which were made in 6.3.2, but removed in 7.0.0 due to a merge error (while backing out changes in 6.3.3, 6.4.0, 6.4.1).

ArtifactoryManager
  • GR #3554 Allow more fine-grained deletion periods (i.e., days).

Intrepid
  • GR #2584 Work-around for occasional race condition creating "build_info" folder.

CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

7.0.0

(b99d0858efcf at 2014-06-05 12:18:51 UTC)

CustomGradleCorePlugin
  • GR #4116 The createWrapper task now generates a wrapper which doesn’t hard-code the server URL. Normally only the plugin developers will need to run this task, to publish a new wrapper-starter-kit.

Intrepid
  • GR #4106 As a workaround for a Gradle 1.4 bug (fixed in later versions), fail with a clear message if a dependency is given as something->*.

  • Make it easier to debug conflicting dependencies. By default, intrepid turns on failOnVersionConflict for all configurations. It now turns this off if:

ArtifactoryManager
CredentialStore
DevEnv
MyCredentials
UnitTest
Stamper
  • No changes.

Note
This version of the plugins has a matching change to the custom distribution. You can update your Gradle wrapper independently from upgrading the rest of the plugins; see 7.0.0 for upgrade instructions. Similarly, upgrading to version 7.0.0 of the plugins does not require an upgrade to the new wrapper version.

Gradle Custom Distribution

History for versions before 3.0.0 is not recorded, because there was no back-reference from the published distribution to the source code.

A pre-packaged Gradle wrapper can be downloaded from your nearest server; see Setting up a Gradle Wrapper for details.

7.x

7.5.x

7.5.1

(267f84a42508 at 2015-08-20 11:43:46 UTC)

  • GR #6266. If certificates can’t be imported for some reason, the user is now directed to read the error log. Previously it would fail silently and Gradle wouldn’t run.

  • GR #6382. Improvements for offline builds using local_artifacts

    • Previous versions of the Holy Gradle required a modification to the gradle/gradle-wrapper.properties file in order to use the local_artifacts folder (for running without an Artifactory or similar server). This change was made when collectDependencies was run to generate local_artifacts. Now, gw.bat automatically detects that folder and generates gradle/gradle-wrapper.properties appropriately. This means that the same source can be built with or without the local_artifacts folder, without needing a change to committed source files.

    • The local_artifacts folder can now be in the project folder or any folder above it. This means the same artifacts can be shared across multiple projects.

7.5.0

(1db4b7a566e1 at 2015-07-14 09:41:15 UTC)

This version adds a number of small improvements for using the Holy Gradle at multiple sites which each have their own Artifactory server (or no such server). It involves a change to the Gradle wrapper, so you will have to commit new files to your project’s source code to use it.

  • GR #5985. Attempt to auto-detect which site-specific Artifactory server to use, so users don’t have to set HOLY_GRADLE_REPOSITORY_BASE_URL. See Setting up a Gradle Wrapper and Setup of Base URL for details.

  • GR #6266. Auto-import site-specific HTTPS root certs. If a gradle\certs folder exists in your project’s source, gw.bat will combine all SSL certificate files in that folder with the Java built-in ones in JRE/lib/security/cacerts , and the combined "trust store" file will be passed to the Gradle process. This means you do not need any special setup to access Artifactory servers which are signed with these certificates. (Mercurial has its own seperate configuration, so you still need to do that, if you are accessing Mercurial servers which use self-signed certificates.)

    • This release adds some new files which should be put under source control, and generates some new files which should not. So, as usual for a wrapper upgrade, you should unzip the new wrapper-starter-kit in place, don’t run it, commit the new files, and only after that run it.

7.2.x

7.2.0

(633551bc9a87 at 2014-08-19 09:25:51 UTC)

Expose project property project.holyGradleRepositoryBase to build scripts. This normally contains the value of environment variable HOLY_GRADLE_REPOSITORY_BASE_URL, guaranteed to have a single trailing ‘/’. If that environment variable is not set, an exception will be thrown. If the local_artifacts folder exists, meaning all artifacts will be fetched from there, then this property has the value "__using_local_artifacts".

7.1.x

7.1.5

(7aee2487c6d7+ at 2014-07-25 12:40:53 UTC)

No changes; published in error.

7.1.1

(f35c15b2126d at 2014-07-04 09:30:20 UTC)

No changes; published in error.

7.1.0

(cc70f8bc88da at 2014-07-01 10:47:27 UTC)

No changes. Re-published to check improvements to the publishing process.

7.0.x

7.0.2

(0a066299ca84 at 2014-06-18 14:19:11 UTC)

New distribution and new wrapper-starter-kit. Make gw.bat work without the repository environment variable, when the local_artifacts folder is being used.

This release also contains all the changes in 7.0.1, without broken references between parts of the release.

7.0.1

(7a20b9b361a6 at 2014-06-17 15:06:19 UTC)

BROKEN, DO NOT USE

Parts of this release were published with references to SNAPSHOT versions of other parts. so its behaviour could change in future. The wrapper-starter-kit was removed because of this, but the plugins were left, so as not to immediately break builds for any teams.

New distribution and new wrapper-starter-kit. The change is in gw.bat: if a local_artifacts folder exists in the root of the project, it doesn’t require HOLY_GRADLE_REPOSITORY_BASE_URL to be set and doesn’t overwrite gradle/gradle-wrapper.properties. (The local_artifacts folder is present in zipped releases which teams can sent to other sites which do not have their own Artifactory or similar repository server.)

Note
the wrapper-starter-kit was removed because parts of the release were published with references to SNAPSHOT versions of other modules.
  • GR #4116 Make it possible to use the same "Holy Gradle wrapper" from any site.

7.0.0

(b99d0858efcf at 2014-06-05 12:18:51 UTC for custom-gradle and wrapper-starter-kit)
(5143be21823d at 2014-06-16 16:02:26 UTC for https-setup-kit)

Additional component, https-setup-kit. This ZIP file has a plain Gradle wrapper plus a build script which makes it easy to install a new CA Certificate into the same installation of Java which Gradle uses. Instructions are included in the ZIP file.

New distribution and new wrapper-starter-kit. Main change is site-independence. Previously the local Artifactory server URL was hard-coded when these files were published.

  • GR #1875 Use HTTPS for Artifactory server

  • GR #2219 Added a comment to gw.bat, warning people against editing it.

  • GR #4116 Make it possible to use the same "Holy Gradle wrapper" from any site. The server URL is now set in an environment variable, and injected into gradle-wrapper.properties by gw.bat. The custom init script in the downloaded distribution no longer hard-codes the server part of the URL for fetching the plugins.

    To change your wrapper from previous versions to this one, follow these steps.

    1. Download https://artifact-server.example-corp.com/artifactory/plugins-release-local/holygradle/wrapper-starter-kit/7.0.0/wrapper-starter-kit-7.0.0.zip and unzip it in the root folder of your project.

    2. Delete gradle/gradle-wrapper.properties from source control (because it’s now generated on the fly) and add the new files (gradle/gradle-wrapper.properties.in, gradle/distributionPath.txt), then commit that.

    3. Add .hgignore entries for gradle/gradle-wrapper.properties (not the .in version), because they’re now generated, and gradle/distributionUrlBase.txt), then commit that. (Separate commit because trying to delete and ignore a file in the same commit is liable to cause problems.)

    4. Set environment variable HOLY_GRADLE_REPOSITORY_BASE_URL to https://artifact-server.example-corp.com/artifactory/ (or other appropriate URL for your server). Remember to do this on your autobuild machines, too.

    5. If you have any hard-coded URLs in your build.gradle or gradle.properties, you’ll have to initialise them from the environment variable, in your build.gradle, as follows. Instead of gradle.properties having

      myTeamDependenciesRepo=https://artifact-server.example-corp.com/artifactory/teamA-integration/
      myTeamPublishRepo=https://artifact-server.example-corp.com/artifactory/teamA-integration-local/

      change to build.gradle having

      // We don't need to check that this variable is non-null because, if the environment
      // variable isn't set, "gw.bat" won't run.
      String repoBaseUrl = System.getenv("HOLY_GRADLE_REPOSITORY_BASE_URL")
      if (!repoBaseUrl.endsWith("/")) {
          repoBaseUrl += "/"
      }
      project.ext.myTeamDependenciesRepo = repoBaseUrl + "teamA-integration/"
      project.ext.myTeamPublishRepo = repoBaseUrl + "teamA-integration-local/"
      
Note
You can update your Gradle wrapper independently from upgrading the rest of the plugins. Similarly, upgrading to version 7.0.0 of the plugins does not require an upgrade to the new wrapper version. See 7.0.0 for details.

Version Number Convention

All releases will follow the version numbering convention: a.b.c

  • a - major release - Significant change/addition/removal, assume API and functional changes.

  • b - minor release - Incremental improvement/addition, assume API changes.

  • c - build id - Bug-fixes, should be no API changes, should be safe to pick up latest.

For reproducibility of builds, we recommended specifying plugin versions exactly, e.g., "1.2.3".