This Gradle plugin is used to orchestrate HMPPS 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
This plugin targets Spring Boot 4. See the spring-boot-3 branch for the Spring Boot 3 version.
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 "11.0.1"
...
}
Where the plugin-version can be found here
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 duplication from your build.gradle.kts file
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 HmppsSpringBootPlugin contains all 3rd party plugins that are applied by the HMPPS 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.
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 HMPPS plugin are up to date.
There is a test in class VersionsPluginManagerTest which:
- builds a sample project
- applies the HMPPS 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
Note this may suggest some upgrades on transitive dependencies we generally don't override, leaving it to the relevant non-transitive dependency in question to upgrade. This includes:
ktlint-cli,ktlint-cli-reporter-baseline,ktlint-ruleset-standard,sarif4kandkotlin-logging- these come fromorg.jlleitschuh.gradle.ktlint.gradle.plugin
- Bump the version of the plugin.
- Publish the plugin to local maven
./gradlew publishToMavenLocal - If the dependencies have security vulnerabilities, it can be useful to check that locally so you can see the state of
them before and after your changes:
- Run the following Gradle task in the dependent project (not in the plug-in one):
./gradlew dependencyCheckAnalyze - If you are using IntelliJ it can be found by going to Gradle -> hmpps-gradle-spring-boot -> Tasks -> owasp dependency-check -> dependencyCheckAnalyze
- Additional testing can be done with Dependency Update Checks
- Run the following Gradle task in the dependent project (not in the plug-in one):
- 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 github at https://github.com/ministryofjustice/hmpps-gradle-spring-boot/actions 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)
This runbook details how to upgrade the dependencies of this plugin and publish it for others to use.
A new version may be needed for a few different reasons:
- Dependencies have been flagged in #dps_alerts_security as having security vulnerabilities
- See Slack message for guidance on vulnerability patching
- These could also be false positives and can be suppressed. Typically these are raised as issues against the DependencyCheck project
- There is a new major releases of Java, Kotlin or Spring and we want to provide the option for teams to bump to these versions
- Create a Jira ticket
- git clone this repo
- Create a git branch including the Jira ticket in the name
- Open the project in your favourite code editor
- Bump the library version to the next version
- See Releasing the plugin for help on which version to bump
- Upgrade all the dependencies in
build.gradle.ktsby running the following Gradle task:./gradlew useLatestVersions- If you are using IntelliJ it can be found by going to Gradle -> hmpps-gradle-spring-boot -> Tasks -> help -> useLatestVersions
- Run
VersionsPluginManagerTest(see How to check if dependencies applied by the HMPPS plugin are up to date) and apply the suggested dependency updates where relevant - Review the pinned versions in
KotlinPluginManager,AppInsightsConfigManager, and any others- You may need to manually bump, or remove them if they are no longer required
- Follow Testing the plugin locally on other projects
- In the other project you should run all tests including integration and start it locally
- At this stage you may run into issues such as transitive dependency resolution, unexpected test errors, or a new version of a dependency may not play nice with the project
- General advice is to do a bit of Googling to see if other people had the same issue. If it isn't critical to bump that dependency then you can revert that dependency to the previous version and add a note in the build.gradle.kts as to why you didn't upgrade it so the next person knows. Hopefully the issue will be fixed and we'll be able to bump it next time
- In the release-notes directory create a new Markdown file for your version
- Look at previous examples - we list the version upgrades which you can retrieve from the report generated by
useLatestVersions
- Look at previous examples - we list the version upgrades which you can retrieve from the report generated by
- Add a link to the file you just created to Release Notes
- You're now ready to commit these changes and raise a PR 🎉
- Post the PR link on #hmpps_dev for folks to review
- After merging to main it will automatically be published to the Gradle Plugin Portal
If the changes carry a high level of risk, you can add -beta to the end of the version.
We initially release a beta version to indicate to other teams that this version hasn't yet been tested in the wild, i.e. it hasn't been included in a service deployed an environment. We do this to ensure that the new dependencies haven't caused any unexpected issues.
- Pick a non-critical project which is not released to prod very frequently
- The DPS Tech Team used court-register and prison-to-nhs-update
- Update the
uk.gov.justice.hmpps.gradle-spring-bootversion to the beta one which was just published - Raise a PR and once approved deploy it to dev
- Validate that the service has started up and is working as expected
- Leave it running for a day and monitor that no unexpected alerts have been raised
After smoketesting did not surface any issues the plugin is now ready for other teams to use.
- Create a new git branch
- Drop the
-betasuffix from the version number inbuild.gradle.kts - Commit and raise a PR
- Post the PR link on #hmpps_dev for folks to review
- After the new version has been published you can upgrade your remaining projects to the new non-beta version
- A script to do this across a number of projects can be found in HMPPS Tech scripts
- Please also upgrade hmpps-template-kotlin