Slide 1

Slide 1 text

Crash Course Building Gradle Plugins @iurysza iurysouza.dev

Slide 2

Slide 2 text

● Senior Engineer @ Klarna ● Currently building a browser ● Working with android since 2016 @iurysza iurysouza.dev About me

Slide 3

Slide 3 text

〉Section Title What is this about?

Slide 4

Slide 4 text

〉Section Title What is this about? A quick starter guide on how to approach building gradle plugins.

Slide 5

Slide 5 text

〉Section Title What is this NOT about?

Slide 6

Slide 6 text

〉Section Title What is this NOT about? An exhaustive Gradle API tutorial.

Slide 7

Slide 7 text

*record scratch* *freeze frame* "Yup, that's me. You're probably wondering how I ended up in this situation…" Background Story

Slide 8

Slide 8 text

Another project, another task copy/paste Background Story

Slide 9

Slide 9 text

A plugin is born Background Story

Slide 10

Slide 10 text

A plugin is born Background Story

Slide 11

Slide 11 text

〉Gradle Plugins Overview Gradle Plugin Overview

Slide 12

Slide 12 text

What It’s an add-on for your build, which you can apply using the Gradle plugin DSL

Slide 13

Slide 13 text

plugins { id("com.android.application") } For example, we have the android application plugin What

Slide 14

Slide 14 text

How

Slide 15

Slide 15 text

How There's basically two ways to do this

Slide 16

Slide 16 text

Performing some behavior when the plugin is applied How

Slide 17

Slide 17 text

For example, the android plugin configures the main, test and androidTest source sets. How

Slide 18

Slide 18 text

Build tasks ----------- assemble - Assemble main outputs for all the variants. build - Assembles and tests this project. clean - Deletes the build directory. Exposing tasks that allow you to run some specific action How

Slide 19

Slide 19 text

〉Getting started The Gradle Plugin Puzzle

Slide 20

Slide 20 text

〉Getting started

Slide 21

Slide 21 text

〉Getting started

Slide 22

Slide 22 text

〉Getting started

Slide 23

Slide 23 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 24

Slide 24 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 25

Slide 25 text

What do you need to do to configure a gradle plugin project. Setup

Slide 26

Slide 26 text

The project's folder structure Setup

Slide 27

Slide 27 text

$ tree ├── build.gradle.kts ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── myplugin │ ├── build.gradle.kts │ └── src │ ├── main │ │ └── kotlin │ │ └── dev │ │ └── iurysouza │ │ └── myplugin │ └── test │ └── kotlin │ └── dev │ └── iurysouza │ └── myplugin └── settings.gradle.kts The project's folder structure Setup

Slide 28

Slide 28 text

$ tree ├── build.gradle.kts ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── myplugin │ ├── build.gradle.kts │ └── src │ ├── main │ │ └── kotlin │ │ └── dev │ │ └── iurysouza │ │ └── myplugin │ └── test │ └── kotlin │ └── dev │ └── iurysouza │ └── myplugin └── settings.gradle.kts Pretty standard Setup

Slide 29

Slide 29 text

$ tree ├── build.gradle.kts ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── myplugin │ ├── build.gradle.kts │ └── src │ ├── main │ │ └── kotlin │ │ └── dev │ │ └── iurysouza │ │ └── myplugin │ └── test │ └── kotlin │ └── dev │ └── iurysouza │ └── myplugin └── settings.gradle.kts Pretty standard Setup

Slide 30

Slide 30 text

$ tree ├── build.gradle.kts ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── app │ ├── build.gradle.kts │ └── src │ ├── main │ │ └── kotlin │ │ └── dev │ │ └── iurysouza │ │ └── app │ └── test │ └── kotlin │ └── dev │ └── iurysouza │ └── app └── settings.gradle.kts Pretty standard Setup

Slide 31

Slide 31 text

〉myplugin 〉build.gradle.kts Build configuration Setup

Slide 32

Slide 32 text

plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) } Build configuration Setup

Slide 33

Slide 33 text

plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) } A plugin for building plugins Setup

Slide 34

Slide 34 text

plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) } A plugin for building plugins Setup

Slide 35

Slide 35 text

plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) } A plugin for building plugins Setup

Slide 36

Slide 36 text

gradlePlugin { plugins { create("myplugin") { id = "dev.iurysouza.myplugin" implementationClass = "dev.iurysouza.myplugin.MyPlugin" version = "0.0.1" description = "My plugin description" displayName = "My plugin name" } } } Defining the plugin Setup

Slide 37

Slide 37 text

gradlePlugin { plugins { create("myplugin") { id = "dev.iurysouza.myplugin" implementationClass = "dev.iurysouza.myplugin.MyPlugin" version = "0.0.1" description = "My plugin description" displayName = "My plugin name" } } } Defining the plugin Setup

Slide 38

Slide 38 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 39

Slide 39 text

Implementation

Slide 40

Slide 40 text

The basic building blocks Implementation

Slide 41

Slide 41 text

The basic building blocks Implementation

Slide 42

Slide 42 text

The Extension Class is a glorified data object. It helps us pass in configuration to the plugin. Implementation

Slide 43

Slide 43 text

import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.provider.Property abstract class MyPluginExtension @Inject constructor( project: Project, ) { val shouldDoSomething: Property = project.objects.property(Boolean-:class.java) } Implementing an Extension Class Implementation

Slide 44

Slide 44 text

import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.provider.Property abstract class MyPluginExtension @Inject constructor( project: Project, ) { val shouldDoSomething: Property = project.objects.property(Boolean-:class.java) } Implementing an Extension Class Implementation

Slide 45

Slide 45 text

import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.provider.Property abstract class MyPluginExtension @Inject constructor( project: Project, ) { val shouldDoSomething: Property = project.objects.property(Boolean-:class.java) } Implementing an Extension Class Implementation

Slide 46

Slide 46 text

import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.provider.Property abstract class MyPluginExtension @Inject constructor( project: Project, ) { val shouldDoSomething: Property = project.objects.property(Boolean-:class.java) } Implementing an Extension Class Implementation

Slide 47

Slide 47 text

import javax.inject.Inject import org.gradle.api.Project import org.gradle.api.provider.Property abstract class MyPluginExtension @Inject constructor( project: Project, ) { val shouldDoSomething: Property = project.objects.property(Boolean-:class.java) } Implementing an Extension Class Implementation

Slide 48

Slide 48 text

The basic building blocks Implementation

Slide 49

Slide 49 text

The basic building blocks Implementation

Slide 50

Slide 50 text

The Task encapsulates an action Implementation

Slide 51

Slide 51 text

Defining our plugin's Task Class Implementation

Slide 52

Slide 52 text

import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction abstract class MyPluginTask : DefaultTask() { @get:Input abstract val shouldDoSomething: Property @TaskAction fun execute() { if (shouldDoSomething.get()) { println("Did something") } else { println("Did something else") } } } Defining our plugin's Task Class Implementation

Slide 53

Slide 53 text

import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction abstract class MyPluginTask : DefaultTask() { @get:Input abstract val shouldDoSomething: Property @TaskAction fun execute() { if (shouldDoSomething.get()) { println("Did something") } else { println("Did something else") } } } Defining our plugin's Task Class Implementation

Slide 54

Slide 54 text

import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction abstract class MyPluginTask : DefaultTask() { @get:Input abstract val shouldDoSomething: Property @TaskAction fun execute() { if (shouldDoSomething.get()) { println("Did something") } else { println("Did something else") } } } Defining our plugin's Task Class Implementation

Slide 55

Slide 55 text

import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction abstract class MyPluginTask : DefaultTask() { @get:Input abstract val shouldDoSomething: Property @TaskAction fun execute() { if (shouldDoSomething.get()) { println("Did something") } else { println("Did something else") } } } Defining our plugin's Task Class Implementation

Slide 56

Slide 56 text

import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction abstract class MyPluginTask : DefaultTask() { @get:Input abstract val shouldDoSomething: Property @TaskAction fun execute() { if (shouldDoSomething.get()) { println("Did something") } else { println("Did something else") } } } Defining our plugin's Task Class Implementation

Slide 57

Slide 57 text

The basic building blocks Implementation

Slide 58

Slide 58 text

The basic building blocks Implementation

Slide 59

Slide 59 text

The plugin, finally! Implementation

Slide 60

Slide 60 text

gradlePlugin { plugins { create("myplugin") { id = "dev.iurysouza.myplugin" implementationClass = "dev.iurysouza.myplugin.MyPlugin" version = "0.0.1" description = "My plugin description" displayName = "My plugin name" } } } Remember this? Implementation

Slide 61

Slide 61 text

It's our entry point. It defines what happens when we the plugin is applied. Implementation

Slide 62

Slide 62 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { println("MyPlugin was applied!") } } Implementation Defining our Plugin Class

Slide 63

Slide 63 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { println("MyPlugin was applied!") } } Implementation Defining our Plugin Class

Slide 64

Slide 64 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { println("MyPlugin was applied!") } } Implementation Defining our Plugin Class

Slide 65

Slide 65 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { println("MyPlugin was applied!") } } Implementation Defining our Plugin Class

Slide 66

Slide 66 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { println("MyPlugin was applied!") } } Implementation Defining our Plugin Class

Slide 67

Slide 67 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { val extension = project.extensions.create( "myPluginConfig", MyPluginExtension-:class.java, project ) project.tasks.register( "myPluginTask", MyPluginTask-:class.java ) { task -> task.shouldDoSomething.set( extension.shouldDoSomething ) } } } Implementation Putting things together

Slide 68

Slide 68 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { val extension = project.extensions.create( "myPluginConfig", MyPluginExtension-:class.java, project ) project.tasks.register( “myPluginTask”, MyPluginTask-:class.java ) { task -> task.shouldDoSomething.set( extension.shouldDoSomething ) } } } Implementation Putting things together

Slide 69

Slide 69 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { val extension = project.extensions.create( "myPluginConfig", MyPluginExtension-:class.java, project ) project.tasks.register( "myPluginTask", MyPluginTask-:class.java ) { task -> task.shouldDoSomething.set( extension.shouldDoSomething ) } } } Implementation Putting things together

Slide 70

Slide 70 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 71

Slide 71 text

Testing Because we're pros, right?

Slide 72

Slide 72 text

Testing A bit of setup first 〉myplugin 〉build.gradle.kts

Slide 73

Slide 73 text

Testing A bit of setup first plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) }

Slide 74

Slide 74 text

Testing A bit of setup first plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) testRuntimeOnly(libs.junit5Engine) testImplementation(libs.junit5Api) } tasks.test { useJUnitPlatform() }

Slide 75

Slide 75 text

Testing Just add your tests here $ tree ├── build.gradle.kts ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── myplugin │ ├── build.gradle.kts │ └── src │ │── main │ │ └── kotlin │ │ └── dev │ │ └── iurysouza │ │ └── myplugin │ └── test │ └── kotlin │ └── dev │ └── iurysouza │ └── myplugin └── settings.gradle.kts

Slide 76

Slide 76 text

Testing Gradle offers support for writing both unit and functional tests.

Slide 77

Slide 77 text

Testing Unit Tests with the ProjectBuilder org.gradle.testfixtures.ProjectBuilder

Slide 78

Slide 78 text

class MyPluginTest { @Test fun `When plugin is applied, the task is added to the build`() { val project = ProjectBuilder.builder().build() project.pluginManager.apply("myPlugin") assert(project.tasks.getByName("myPluginTask") is MyPluginTask) } } Testing Unit tests with ProjectBuilder

Slide 79

Slide 79 text

Testing Fast & lightweight. Great for sanity checks. org.gradle.testfixtures.ProjectBuilder

Slide 80

Slide 80 text

org.gradle.testkit.runner.GradleRunner Testing Functional Tests with testKit

Slide 81

Slide 81 text

plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) testImplementation(libs.junit5Api) testRuntimeOnly(libs.junit5Engine) testImplementation(gradleTestKit()) } tasks.test { useJUnitPlatform() } Testing Setting up

Slide 82

Slide 82 text

class MyPluginFunctionalTest { @TempDir lateinit var projDir: File private lateinit var settingsFile: File private lateinit var buildFile: File @BeforeEach fun setup() { settingsFile = File(projDir, "settings.gradle.kts") buildFile = File(projDir, "build.gradle.kts") } } Testing Functional Tests with testKit

Slide 83

Slide 83 text

class MyPluginFunctionalTest { @TempDir lateinit var projDir: File private lateinit var settingsFile: File private lateinit var buildFile: File @BeforeEach fun setup() { settingsFile = File(projDir, "settings.gradle.kts") buildFile = File(projDir, "build.gradle.kts") } } Testing Functional Tests with testKit

Slide 84

Slide 84 text

class MyPluginFunctionalTest { @TempDir lateinit var projDir: File private lateinit var settingsFile: File private lateinit var buildFile: File @BeforeEach fun setup() { settingsFile = File(projDir, "settings.gradle.kts") buildFile = File(projDir, "build.gradle.kts") } } Testing Functional Tests with testKit

Slide 85

Slide 85 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {...} } Testing Functional Tests with testKit

Slide 86

Slide 86 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {...} } Testing Functional Tests with testKit

Slide 87

Slide 87 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {--.} @Test fun `when plugin's task is ran it produces the expected output`() { settingsFile.writeText( """ rootProject.name = "example" """.trimIndent() ) buildFile.writeText( """ plugins { java id("dev.iurysouza.myplugin") } myPluginConfig { shouldDoSomething.set(true) } """.trimIndent() ) -/ Run the plugin task val buildResult: BuildResult = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments("myPluginTask") .build() -/ Check if the output matches the expected result val expectedOutput = "didSomething" assertEquals(expectedOutput, buildResult.output) } } Testing Functional Tests with testKit

Slide 88

Slide 88 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {--.} @Test fun `when plugin's task is ran it produces the expected output`() { settingsFile.writeText( """ rootProject.name = "example" """.trimIndent() ) buildFile.writeText( """ plugins { java id("dev.iurysouza.myplugin") } myPluginConfig { shouldDoSomething.set(true) } """.trimIndent() ) -/ Run the plugin task val buildResult: BuildResult = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments("myPluginTask") .build() -/ Check if the output matches the expected result val expectedOutput = "didSomething" assertEquals(expectedOutput, buildResult.output) } } Testing Functional Tests with testKit

Slide 89

Slide 89 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {--.} @Test fun `when plugin's task is ran it produces the expected output`() { settingsFile.writeText( """ rootProject.name = "example" """.trimIndent() ) buildFile.writeText( """ plugins { java id("dev.iurysouza.myplugin") } myPluginConfig { shouldDoSomething.set(true) } """.trimIndent() ) -/ Run the plugin task val buildResult: BuildResult = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments("myPluginTask") .build() -/ Check if the output matches the expected result val expectedOutput = "Did something" assertEquals(expectedOutput, buildResult.output) } } Testing Functional Tests with testKit

Slide 90

Slide 90 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {--.} @Test fun `when plugin is ran it produces the expected output`() { settingsFile.writeText( """ rootProject.name = "example" """.trimIndent() ) buildFile.writeText( """ plugins { java id("dev.iurysouza.myplugin") } myPluginConfig { shouldDoSomething.set(true) } """.trimIndent() ) -/ Run the plugin task val buildResult: BuildResult = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments("myPluginTask") .build() -/ Check if the output matches the expected result val expectedOutput = "Did something" assertEquals(expectedOutput, buildResult.output) } } Testing Functional Tests with testKit

Slide 91

Slide 91 text

class MyPluginFunctionalTest { @BeforeEach fun setup() {--.} @Test fun `when plugin is ran it produces the expected output`() { settingsFile.writeText( """ rootProject.name = "example" """.trimIndent() ) buildFile.writeText( """ plugins { java id("dev.iurysouza.myplugin") } myPluginConfig { shouldDoSomething.set(true) } """.trimIndent() ) -/ Run the plugin task val buildResult: BuildResult = GradleRunner.create() .withProjectDir(testProjectDir) .withArguments("myPluginTask") .build() -/ Check if the output matches the expected result val expectedOutput = "Did Something" assertEquals(expectedOutput, buildResult.output) } } Testing Functional Tests with testKit

Slide 92

Slide 92 text

Testing When to use unit or functional tests?

Slide 93

Slide 93 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 94

Slide 94 text

Publishing How to share you plugin with the world

Slide 95

Slide 95 text

plugins { kotlin("jvm") `java-gradle-plugin` } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) testRuntimeOnly(libs.junit5Engine) testImplementation(libs.junit5Api) testImplementation(gradleTestKit()) } tasks.test { useJUnitPlatform() } Publishing Setup plugin-publish

Slide 96

Slide 96 text

plugins { kotlin("jvm") `java-gradle-plugin` id("com.gradle.plugin-publish") version "1.1.0" } dependencies { implementation(kotlin("stdlib")) implementation(gradleApi()) testRuntimeOnly(libs.junit5Engine) testImplementation(libs.junit5Api) testImplementation(gradleTestKit()) } tasks.test { useJUnitPlatform() } Publishing Setup plugin-publish

Slide 97

Slide 97 text

Publishing Setup plugin-publish $ ./gradlew :myplugin:tasks Plugin Portal tasks ------------------- publishPlugins - Publishes this plugin to the Gradle Plugin portal. Publishing tasks ---------------- publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.

Slide 98

Slide 98 text

Publishing Setup plugin-publish $ ./gradlew :myplugin:tasks Plugin Portal tasks ------------------- publishPlugins - Publishes this plugin to the Gradle Plugin portal. Publishing tasks ---------------- publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.

Slide 99

Slide 99 text

Publishing Setup plugin-publish $ ./gradlew :myplugin:tasks Plugin Portal tasks ------------------- publishPlugins - Publishes this plugin to the Gradle Plugin portal. Publishing tasks ---------------- publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.

Slide 100

Slide 100 text

Publishing Publishing locally $ ./gradlew :myplugin:publishToMavenLocal

Slide 101

Slide 101 text

Publishing Publishing locally $ cd ~/.m2/repository/dev/iurysouza/myplugin/0.0.1 -& ls -la .rw-r--r-- 261 myplugin-0.0.1-javadoc.jar .rw-r--r-- 4.9k myplugin-0.0.1-sources.jar .rw-r--r-- 28k myplugin-0.0.1.jar .rw-r--r-- 3.9k myplugin-0.0.1.module .rw-r--r-- 973 myplugin-0.0.1.pom

Slide 102

Slide 102 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 103

Slide 103 text

〉settings.gradle.kts pluginManagement { repositories { mavenCentral() } } Consuming How to add your plugin to a build

Slide 104

Slide 104 text

〉settings.gradle.kts pluginManagement { repositories { mavenCentral() } } Consuming Add the local gradle repository

Slide 105

Slide 105 text

〉settings.gradle.kts pluginManagement { repositories { mavenCentral() mavenLocal() } } Consuming Add the local gradle repository

Slide 106

Slide 106 text

〉sample 〉build.gradle.kts plugins { id("dev.iurysouza.myplugin") version ("0.0.1") } Consuming Finally, apply the plugin

Slide 107

Slide 107 text

〉sample 〉build.gradle.kts plugins { id("dev.iurysouza.myplugin") version ("0.0.1") } Finally, apply the plugin

Slide 108

Slide 108 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 109

Slide 109 text

$ ./gradlew > Configure project :sample MyPlugin was applied! Running Is this thing on?

Slide 110

Slide 110 text

$ ./gradlew > Configure project :sample MyPlugin was applied! Running Yes!

Slide 111

Slide 111 text

import org.gradle.api.Plugin import org.gradle.api.Project class MyPlugin : Plugin { override fun apply(project: Project) { println("MyPlugin was applied!") } } Running Remember this?

Slide 112

Slide 112 text

〉sample 〉build.gradle.kts plugins { id("dev.iurysouza.myplugin") version ("0.0.1") } myPluginConfig { shouldDoSomething.set(true) } Running Configuring the plugin

Slide 113

Slide 113 text

〉sample 〉build.gradle.kts plugins { id("dev.iurysouza.myplugin") version ("0.0.1") } myPluginConfig { shouldDoSomething.set(true) } Running Configuring the plugin

Slide 114

Slide 114 text

$ ./gradlew myPluginTask Did Something Running Is this thing on?

Slide 115

Slide 115 text

$ ./gradlew myPluginTask Did Something Running Is this thing on?

Slide 116

Slide 116 text

import org.gradle.api.DefaultTask import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction abstract class MyPluginTask : DefaultTask() { @get:Input abstract val shouldDoSomething: Property @TaskAction fun execute() { if (shouldDoSomething.get()) { println("Did something") } else { println("Did something else") } } } Running Remember this?

Slide 117

Slide 117 text

$ ./gradlew myPluginTask Did Something Running Is this thing on?

Slide 118

Slide 118 text

$ ./gradlew myPluginTask Did Something Running You may be thinking: "Is that it?"

Slide 119

Slide 119 text

$ ./gradlew myPluginTask Did Something Running Think of it as your starting point

Slide 120

Slide 120 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 121

Slide 121 text

〉Getting started Implementation Testing Publishing Consuming Running Setup

Slide 122

Slide 122 text

〉Getting started

Slide 123

Slide 123 text

〉Getting started

Slide 124

Slide 124 text

〉Getting started

Slide 125

Slide 125 text

〉Getting started The Gradle Plugin Puzzle

Slide 126

Slide 126 text

〉Getting started The Gradle Plugin Puzzle 🤨

Slide 127

Slide 127 text

Live Demo time!

Slide 128

Slide 128 text

Where to go from Here? - Rules for Gradle plugin authors - Defensive development Gradle plugin development for busy engineers - Module Graph plugin

Slide 129

Slide 129 text

Thanks! @iurysza iurysouza.dev