Kotlin-based Custom Gradle Plugin for Build Automation
Build a Gradle plugin in Kotlin that any project can apply to automate releases. It reads the project's Git history, decides the next version number following semantic versioning (a fix bumps the patch number, a new feature the minor number, a breaking change the major number) based on Conventional Commit messages like feat: or fix:, and generates a CHANGELOG.md entry grouped by type. Projects configure it with a small Kotlin DSL block in their build file. You'll learn how Gradle plugins, tasks and extensions work, how to write configuration-cache-friendly tasks with lazy properties, how to parse commit messages, and how to test plugins with Gradle TestKit and publish them to a Maven repository.
- Estimate
- ~13h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
Gradle Plugin API · Kotlin DSL
Project roadmap
- 01
Set up the plugin project
~1.5hCreate a Gradle project using the Kotlin DSL with the java-gradle-plugin and kotlin-jvm plugins. Declare your plugin in the gradlePlugin block with an id (such as com.example.release) and an implementation class that implements Plugin<Project>. Its apply method registers a placeholder task. Done when: ./gradlew build succeeds and a test project can apply the plugin by id.
- 02
Read commits and tags
~2hWrite a GitHistory class that finds the latest tag matching v<major>.<minor>.<patch> and lists the commit messages since that tag, running git commands with ProcessBuilder (or using JGit). With no tags yet, start from 0.0.0 and use all commits. Report a clear error when the directory isn't a Git repository. Done when: in a test repository, GitHistory returns the last version and the new commits.
- 03
Calculate the next version
~2hParse each message as a Conventional Commit: type, optional scope, optional ! and description. A BREAKING CHANGE footer or ! means major, feat means minor, and fix or perf means patch; other types don't change the version. Before 1.0.0, treat breaking changes as minor. Put this logic in plain Kotlin classes, separate from Gradle. Done when: unit tests cover each bump rule and pre-1.0 behavior.
- 04
Generate the changelog
~2hGenerate a Markdown entry for the new version with today's date and sections for Breaking changes, Features and Bug fixes, each listing commit descriptions with their scope in bold. Prepend it to CHANGELOG.md, creating the file if it doesn't exist, and skip commits that don't match the format. Done when: running it in a test repository adds a correctly formatted entry at the top of CHANGELOG.md.
- 05
Add the DSL extension and tasks
~2hCreate a ReleaseExtension with Property and ListProperty fields: changelogFile, versionFile (such as gradle.properties), tagPrefix and the list of commit types to include. Register tasks nextVersion (prints the version), updateChangelog and bumpVersion (writes the version file), wiring them to the extension with lazy providers so they work with Gradle's configuration cache. Done when: a project can configure release { ... } in build.gradle.kts and run the three tasks.
- 06
Test with Gradle TestKit
~2.5hWrite functional tests with GradleRunner that create a temporary project with a Git repository and example commits, apply the plugin, and run the tasks. Check the calculated version, the changelog content and the updated version file. Also run once with --configuration-cache. Done when: ./gradlew test passes, including the functional tests.
- 07
Publish the plugin
~1hAdd the maven-publish plugin and publish to your local Maven repository with ./gradlew publishToMavenLocal. Write a README explaining how to apply and configure the plugin, with a full example. Done when: a separate sample project applies the plugin from mavenLocal() and runs its tasks successfully.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack