Kotlin Poet Gradle Plugin CI/CD
Now that we have the core plugin and skeleton build out. We want to ensure a prompt quick feed back loop for ensuring that changes are indeed working.
This example will be using GitLab CI/CD.
We will be focusing on building a simple pipe line. With three stages.
- Build the plugin
- Integration test against the plugin
- Publish the plugin.

If you're not familiar with the GitLab CI/CD system. It takes a YAML
file at the root of the repository to define the pipe line. Each stage is executed in a docker container. Each stage may define a custom image, or a top level image.
Front Matter
image: registry.gitlab.com/animusdesign/kotlin-mp-build:latest
stages:
- build
- test
- integration_test
- publish
- pages
cache:
paths:
- ./.m2/repository
- .gradle/wrapper
- .gradle/caches
key: "$CI_BUILD_REF_NAME"
- image Defines the docker build image. This is a custom one I maintain for building multi platform images.
- stages Defines the respective pages of the pipe line.
- cache Defines what to cache, downloaded dependencies, etc.
As we define the front matter. We want to think about repetitive tasks to expedite the build. That's why I built a custom docker image. It includes additional debugging tools that can help me if a build steps. You can also limit time by re-using dependencies.
The Tricky Part
Building gradle plugins requires some extra work up front. The problem is we need to manipulate settings.gradle.kts
. Disabling and enabling the example project that consumes the plugin. The example project will throw an error if the plugin is not present.
Enable
sed -i 's/\/\/include(":example:")/include\(":example:"\)/g' settings.gradle.kts
Disable
sed -i 's/include(":example:")/\/\/include\(":example:"\)/g'
Both commands are sed inserting into the settings.gradle.kts
file.
- Look for a line
//include(":example:")
if present change toinclude(":example:")
- Look for a line
include(":example:")
if present change to //include(":example:")
It's not the cleanest but it works.
Build
During the build stage prior to running tests, we want to ensure that the plugin builds. There is no point in running tests if there is a compile error on the plugin.
Integration Tests

While this is a very simple example, a one property class. We still want to set up the scaffolding for easing testing. Above is a screen capture of the test running, and it's status.
The integration tests, use the gradle plugin. Generating the expected types. Then runs tests against them. This is a full dog food run.
Publish

We now publish the artifact so that it can be consumed / used. This is done after testing and validation. We don't want to publish an artifact without validating that it works as anticipated.
Note: There is a bug regarding gradle and snapshots not working right now with GitLab packages.
Full Yaml
image: registry.gitlab.com/animusdesign/kotlin-mp-build:latest
stages:
- build
- test
- integration_test
- publish
- pages
cache:
paths:
- ./.m2/repository
- .gradle/wrapper
- .gradle/caches
key: "$CI_BUILD_REF_NAME"
build:typeprovider_plugin:
stage: build
script:
- ./scripts/publish-local.sh
artifacts:
paths:
- plugin/build
expire_in: 60 mins
integration_test:example:
stage: integration_test
script:
- sh ./scripts/publish-local.sh
- tree ~/.m2/repository
- sed -i 's/\/\/include(":example:")/include\(":example:"\)/g' settings.gradle.kts
- ./gradlew :example:generateTypes
- ./gradlew :example:test
artifacts:
reports:
junit: example/build/test-results/test/*.xml
publish:typeprovider_plugin:
stage: publish
except:
refs:
- release/.*
- master
script:
- sed -i 's/include(":example:")/\/\/include\(":example:"\)/g' settings.gradle.kts
- ./gradlew :plugin:publish
artifacts:
paths:
- plugin/build/libs/*.jar
expire_in: 1 week
Source Code
