This Gradle plugin is used to orchestrate DPS Spring Boot projects such that:
- All projects use a common set of plugins at versions that have been tested together
- All projects use a common set of dependencies at versions that have been tested together
- Any common build configuration shared by projects is performed in this plugin and not the project itself (removing duplication and subsequent drift)
- CVEs causing
dependencyCheckAnalyzefailures are mitigated in a single place rather than in each and every project
Currently we recommend 1.1.2 due to issues with Application Insights Agent V3 in 2.0.0
In your build.gradle.kts (or build.gradle for Java) add the following line to the plugin section:
plugins {
...
id("uk.gov.justice.hmpps.gradle-spring-boot") version "1.1.1"
...
}
Where the plugin-version can be found by going to https://plugins.gradle.org/plugin/uk.gov.justice.hmpps.gradle-spring-boot
This plugin provides various build logic that may already exist in your project, and using this plugin may:
- Have no effect - maybe your project's build logic overrides the plugin
- Cause an error - maybe something in the plugin recognises the duplication and complains
Either way you will need to remove some of this duplications from your build.gradle.kts file TODO when we have published our first version, point to a PR that implements the plugin as an example of what to remove
Read the code!
In the main you will probably need to know the following so you don't duplicate in your own build script:
The class DpsSpringBootPlugin contains all 3rd party plugins that are applied by the DPS plugin - check there first. Then look in the file build.gradle.kts in the dependencies/implementation section. There you can find each plugin and its version.
E.g. org.springframework.boot:spring-boot-gradle-plugin is the Spring Boot plugin and its version is part of the configuration
Look in the package uk.gov.justice.digital.hmpps.gradle.pluginmanagers and you should find the class that orchestrates each plugin.
E.g. Class SpringBootPluginManager has a method called setSpringBootInfo which controls the contents of the /info endpoint
Search the package uk.gov.justice.digital.hmpps.gradle for project.dependencies.add. This should list all dependencies this plugin automatically applies.
E.g. Class SpringBootPluginManager applies spring-boot-starter-actuator (amongst others) so you do not need to declare that dependency in your project's build.gradle.kts file.
We no longer exclude JUnit 4 as part of this plugin as it wasn't compatible with Gradle 6.7. If you want to exclude it from your project then add the following to your Gradle build file:
configurations {
testImplementation { exclude(mapOf("group" to "org.junit.vintage", "group" to "junit")) }
}
This will ensure that code that includes junit @Test annotation doesn't compile and also that the junit vintage engine isn't included.
The plugin org.owasp.dependencycheck is applied by this plugin. It has a task dependencyCheckAnalyze which is used to check for vulnerabilities in dependencies.
Any vulnerabilities introduced by this plugin that have been mitigated can be suppressed in file src/main/resources/dps-gradle-spring-boot-suppressions.xml. See the OWASP dependency check plugin's homepage for further details.
If you are using this plugin and need additional suppressions for vulnerabilities introduced by your dependencies then you can specify additional suppression xmls in your Gradle build file:
dependencyCheck {
suppressionFiles.add("<your-suppresion-file>.xml")
}
WARNING
It is possible to overwrite the suppressionFiles list like this:
// This removes the plugin's default suppression file
dependencyCheck {
suppressionFiles = listOf("<your-suppresion-file>.xml")
}
This will remove the suppression file supplied by this plugin which is probably not the intention.
The plugin com.github.ben-manes.versions has task dependencyUpdates which checks the main Gradle build file for out of date versions.
However, we also need to know if dependencies applied by the DPS plugin are up to date.
There is a test in class VersionsPluginManagerTest which:
- builds a sample project
- applies the DPS plugin
- runs the
dependencyUpdatestask against the sample project - copies the reports generated into directory
build/dependencyUpdates/projectsUsingPlugin
You can run the test with command:
./gradlew clean test --tests uk.gov.justice.digital.hmpps.gradle.functional.pluginmanagers.VersionsPluginManagerTest
and check the report generated at build/dependencyUpdates/projectsUsingPlugin/report.txt
- Firstly bump the version of the plugin.
- Then publish the plugin to local maven
./gradlew publishToMavenLocal
- Then change the settings of the dependent project to read plugins from local storage. In settings.gradle.kts
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
Semantic versioning is used for the plugin i.e. MAJOR.MINOR.PATCH. A MAJOR change is a breaking change and will
require changes to any existing projects that wish to adopt the MAJOR change.
At present the version number increment is a manual step in build.gradle.kts. Increment that at the same time
as making changes.
When the plugin is ready to be released and PR approved, merge into main. Then go into circleci at https://app.circleci.com/pipelines/github/ministryofjustice/dps-gradle-spring-boot and approve the publish step. This will publish the plugin to the gradle plugins repository.
./gradlew ktlintApplyToIdea addKtlintFormatGitPreCommitHookwill apply ktlint styles to intellij and also add a pre-commit hook to format all changed kotlin files.
Note that the .editorconfig in the root of this project is for this project only, the one in src/main/resources will be copied to other projects to enforce style.
To setup dependent projects with ktlint:
- (Optional) run the above gradle command to apply to intellij and add the pre commit hook.
- If you don't plan on making changes to .editorconfig (created on first run) then add to .gitignore.
- Ensure that the continuous integration tool runs the
checktask instead oftest.
- Automate incremental version numbers (we could manage this manually but safer if it is impossible overwrite previous versions)