# Precompiled Script Plugin Sample

version 6.5-milestone-1

- Groovy DSL

- Kotlin DSL

| You can open this sample inside an IDE using the IntelliJ native importer or Eclipse Buildship.

This sample shows how precompiled script plugins can be used to compose build logic using built-in Gradle plugins, external Gradle plugins and other utility classes.

## Use case

As an example, let’s say an organization produces two types of Java software - services and libraries. We want to apply a set of code quality checking rules to both types of projects and configure some aspects specific to each type.

This is achieved by layering three separate plugins:

- `com.example.java-convention` - configures conventions that are generic for any Java project in the organization.

- `com.example.library` - adds publishing configuration to publish to the organization’s repository.

- `com.example.service` - adds integration tests and checks for mandatory content in a README.

We’ve put the plugins in the `plugins` directory in the sample. All plugins created in this sample contain functional tests that use TestKit to verify their behavior.

This root of this sample contains a consumer project that demonstrates how the plugins can be consumed using a composite build:

settings.gradle

    rootProject.name = 'consumer-service'

    includeBuild('plugin')

build.gradle

    plugins {
        id 'com.example.service' version '1.0'
    }

settings.gradle.kts

    rootProject.name = "consumer-service"

    includeBuild("plugin")

build.gradle.kts

    plugins {
        id("com.example.service") version "1.0"
    }

## Things to note

### Applying an external plugin in precompiled script plugin

The `com.example.java-convention` plugin uses SpotBugs plugin to perform static code analysis.

SpotBugs is an external plugin - external plugins need to be added as implementation dependencies before they can be applied in a precompiled script plugin:

plugin/build.gradle

    repositories {
        gradlePluginPortal() // so that external plugins can be resolved in dependencies section
    }

    dependencies {
        implementation 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.0.5'
        testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
    }

plugin/build.gradle.kts

    repositories {
        gradlePluginPortal() // so that external plugins can be resolved in dependencies section
    }

    dependencies {
        implementation("gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.0.5")
        testImplementation("junit:junit:4.13")
    }

- The dependency artifact coordinates (GAV) for a plugin can be different from the plugin id.

- The Gradle Plugin Portal (`gradlePluginPortal()`) is added as a repository for plugin dependencies.

- The plugin version is determined from the dependency version. Precompiled script plugins cannot supply a different version for now.

Once the dependency is added, the external plugin can be applied in precompiled script plugin by id:

plugin/src/main/groovy/com.example.java-convention.gradle

    plugins {
        id 'java'
        id 'checkstyle'

        // NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
        id 'com.github.spotbugs'
    }

plugin/src/main/kotlin/com.example.java-convention.gradle.kts

    plugins {
        java
        checkstyle

        // NOTE: external plugin version is specified in implementation dependency artifact of the project's build file
        id("com.github.spotbugs")
    }

### Applying other precompiled script plugins

Precompiled script plugins can apply other precompiled script plugins.

The `com.example.library` and `com.example.service` plugins both apply the `com.example.java-convention` plugin:

plugin/src/main/groovy/com.example.library.gradle

    plugins {
        id 'java-library'
        id 'maven-publish'
        id 'com.example.java-convention'
    }

plugin/src/main/groovy/com.example.service.gradle

    plugins {
        id 'com.example.java-convention'
    }

plugin/src/main/kotlin/com.example.library.gradle.kts

    plugins {
        `java-library`
        `maven-publish`
        id("com.example.java-convention")
    }

plugin/src/main/kotlin/com.example.service.gradle.kts

    plugins {
        id("com.example.java-convention")
    }

### Using classes from the main source set

Precompiled script plugins can use classes defined in the main source set of the plugins project.

In this sample, `com.example.service` plugin uses a custom task class from `src/main/java` to configure service README checks:

plugin/src/main/groovy/com.example.service.gradle

    def readmeCheck = tasks.register('readmeCheck', com.example.ReadmeVerificationTask) {
        // Expect the README in the project directory
        readme = layout.projectDirectory.file("README.md")
        // README must contain a Service API header
        readmePatterns = ['^## Service API$']
    }

plugin/src/main/kotlin/com.example.service.gradle.kts

    val readmeCheck by tasks.registering(com.example.ReadmeVerificationTask::class) {
        readme.set(layout.projectDirectory.file("README.md"))
        readmePatterns.set(listOf("^## Service API$"))
    }

For more details on authoring custom Gradle plugins, consult the user manual.