Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Gradle Plugin Goodness
@BRWNGRLDEV
@BRWNGRLDEV
apply plugin: 'checkstyle'

apply plugin: 'findbugs'

apply plugin: 'pmd'



task checkstyle(type: Checkstyle) {

descripti...
apply plugin: 'checkstyle'

apply plugin: 'findbugs'

apply plugin: 'pmd'



task checkstyle(type: Checkstyle) {

descripti...
OVERVIEW
▸Plugin Skeleton
▸Dependencies
▸Plugin.groovy
▸CustomTask.groovy
▸Publishing
@BRWNGRLDEV
PLUGIN SKELETON
@BRWNGRLDEV
PLUGIN SKELETON
@BRWNGRLDEV
PLUGIN SKELETON
@BRWNGRLDEV
PLUGIN SKELETON
How Gradle finds the Plugin Implementation
@BRWNGRLDEV
PLUGIN SKELETON
implementation-class=info.adavis.qualitychecks.QualityChecksPlugin
@BRWNGRLDEV
DEPENDENCIES
@BRWNGRLDEV
DEPENDENCIES
apply plugin: ‘groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
@BRWNGRLDEV
DEPENDENCIES
dependencies {
…
testCompile 'junit:junit:4.12'

testCompile ('org.spockframework:spock-core:1.0-groovy-2.4')...
THE CODE
@BRWNGRLDEV
BUT FIRST…
@BRWNGRLDEV
GRADLE BUILD
@BRWNGRLDEV
PROJECT
TASK TASK TASK
BUILD
GRADLE BUILD
@BRWNGRLDEV
PROJECT
TASK TASK TASK
BUILD
PROJECT
TASK TASK TASK
PLUGIN.GROOVY
class CustomPlugin implements Plugin<Project> {
}
@BRWNGRLDEV
PLUGIN.GROOVY
class CustomPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
}
}
@BRWNGRLDEV
QUALITYCHECKSPLUGIN.GROOVY
@BRWNGRLDEV
APPLY METHOD
@BRWNGRLDEV
void apply(Project project) {

this.project = project



}
APPLY METHOD
@BRWNGRLDEV
void apply(Project project) {

this.project = project



project.extensions.create('qualityChecks...
APPLY METHOD
@BRWNGRLDEV
void apply(Project project) {

this.project = project



project.extensions.create('qualityChecks...
PROJECT EXTENSION
@BRWNGRLDEV
class QualityChecksExtension {



String pmdConfigFile = 'quality-checks/pmd-ruleset.xml'



...
PROJECT EXTENSION
@BRWNGRLDEV
class QualityChecksExtension {



String pmdConfigFile = 'quality-checks/pmd-ruleset.xml'



...
PROJECT EXTENSION
Back in the application’s build.gradle file…
@BRWNGRLDEV
qualityChecks {

pmdConfigFile = ‘checks/pmd.xml’...
PROJECT EXTENSION
Back in the application’s build.gradle file…
@BRWNGRLDEV
qualityChecks {

pmdConfigFile = ‘checks/pmd.xml’...
TASKS
@BRWNGRLDEV
CREATING TASKS
Give it a name and a type
@BRWNGRLDEV
CREATING TASKS
@BRWNGRLDEV
▸Build on existing task
▸Extend the DefaultTask
BUILD ON EXISTING TASK
@BRWNGRLDEV
BUILD ON EXISTING
@BRWNGRLDEV
EXTEND DEFAULT TASK
@BRWNGRLDEV
CUSTOMTASK.GROOVY
class CustomTask extends DefaultTask {
CustomTask() {
group: ‘verification’
}
}
@BRWNGRLDEV
CUSTOMTASK.GROOVY
class CustomTask extends DefaultTask {
CustomTask() {
group: ‘verification’
}
}
@BRWNGRLDEV
CUSTOMTASK.GROOVY
CustomTask() {
group: ‘verification’
onlyIf {
// skip under certain conditions
}
}
@BRWNGRLDEV
CUSTOMTASK.GROOVY
@TaskAction
def defaultAction() {
description: ‘What my task does’
}
@BRWNGRLDEV
CUSTOMTASK.GROOVY
@BRWNGRLDEV
@TaskAction
def defaultAction() {
description: ‘What my task does’
<do your cool stuff here>...
GRADLE TASK DOCUMENTATION
@BRWNGRLDEV
SO FAR…
▸Plugin Skeleton
▸Dependencies
▸Plugin.groovy
▸CustomTask.groovy
@BRWNGRLDEV
PUBLISHING
@BRWNGRLDEV
PUBLISHING
@BRWNGRLDEV
PUBLISHING
buildscript {
…
dependencies {
classpath "com.gradle.publish:plugin-publish-plugin:0.9.4"
}
}
apply plugin: 'co...
PUBLISHING
version = "0.1.3"
group = "info.adavis"
@BRWNGRLDEV
PUBLISHING
pluginBundle {
website = 'https://github.com/adavis/quality-checks'
vcsUrl = 'https://github.com/adavis/quality...
PUBLISHING
pluginBundle {
…
plugins {
qualityChecksPlugin {
id = 'info.adavis.qualitychecks'
displayName = 'Quality Checks...
@BRWNGRLDEV
@BRWNGRLDEV
WE’RE DONE…
WRONG!
@BRWNGRLDEV
WE’RE DONE…
TESTS
@BRWNGRLDEV
TESTING - WITH JUNIT
@Before

void setUp() {

projectDir = temporaryFolder.root

projectDir.mkdirs()





}
@BRWNGRLDEV
TESTING - WITH JUNIT
@Before

void setUp() {

projectDir = temporaryFolder.root

projectDir.mkdirs()



project = ProjectB...
TESTING - WITH JUNIT
@Test
void shouldBeAbleToCreateTask() {
assertTrue(task instanceof WriteConfigFileTask)
}
@BRWNGRLDEV
TESTING - WITH JUNIT
@Test
void pluginShouldBeApplied() {
project.apply(plugin: QualityChecksPlugin)
assertNotNull(project...
SPOCK
@BRWNGRLDEV
TESTING - WITH SPOCK
def createCheckstyleTask() {

given: "we have a project"

def project = ProjectBuilder.builder().buil...
TESTING - WITH SPOCK
def createCheckstyleTask() {



and: "we apply the extension"

project.extensions.create('qualityChec...
TESTING - WITH SPOCK
def createCheckstyleTask() {



when: "we create a checkstyle task"

def checkstyleTask = project.tas...
TESTING - WITH SPOCK
def createCheckstyleTask() {



then: "it should not replace our previous file"

checkstyleTask.configF...
TESTING - WITH SPOCK
@BRWNGRLDEV
TESTING - REPORT
@BRWNGRLDEV
TESTING - SPOCK-REPORT
dependencies {
…
testCompile( 'com.athaydes:spock-reports:1.2.12' ) {

transitive = false
}
}
@BRWN...
TESTING - SPOCK-REPORT
@BRWNGRLDEV
@BRWNGRLDEV
BONUS: README
@BRWNGRLDEV
BONUS: README
@BRWNGRLDEV
BONUS: README
@BRWNGRLDEV
SUMMARY
▸Helps avoid copy/paste horror
▸Simple project structure
▸Extending DefaultTask
▸Testing techniques
▸Easy to publi...
THANKS!
@brwngrldev
+AnnyceDavis
www.adavis.info
@BRWNGRLDEV
Prochain SlideShare
Chargement dans…5
×

Creating Gradle Plugins - GR8Conf US

325 vues

Publié le

If you find yourself copying and pasting code from your build.gradle file every time you start a new project, then it's time you learn about Gradle Plugins. Come and learn what it takes to create a custom Gradle plugin for use in your Android/Java applications.

We're going to go over the following:

• Plugin Structure
• Key Components
• Testing
• Publishing

Walk away feeling empowered to create your own awesome plugins!

Publié dans : Logiciels
  • Soyez le premier à commenter

Creating Gradle Plugins - GR8Conf US

  1. 1. Gradle Plugin Goodness
  2. 2. @BRWNGRLDEV
  3. 3. @BRWNGRLDEV
  4. 4. apply plugin: 'checkstyle'
 apply plugin: 'findbugs'
 apply plugin: 'pmd'
 
 task checkstyle(type: Checkstyle) {
 description 'Checks if the code is somewhat acceptable'
 group 'verification'
 
 configFile file('./qa-check/checkstyle.xml')
 source 'src'
 include '**/*.java'
 exclude '**/gen/**'
 
 classpath = files()
 ignoreFailures = false
 }
 
 task findbugs(type: FindBugs) {

  5. 5. apply plugin: 'checkstyle'
 apply plugin: 'findbugs'
 apply plugin: 'pmd'
 
 task checkstyle(type: Checkstyle) {
 description 'Checks if the code is somewhat acceptable'
 group 'verification'
 
 configFile file('./qa-check/checkstyle.xml')
 source 'src'
 include '**/*.java'
 exclude '**/gen/**'
 
 classpath = files()
 ignoreFailures = false
 }
 
 task findbugs(type: FindBugs) {
 description 'Run findbugs'
 group 'verification'
 
 classes = files("$project.buildDir/intermediates/classes")
 source 'src'
 classpath = files()
 
 effort 'max'
 excludeFilter file('./qa-check/findbugs-exclude.xml')
 
 reports {
 xml.enabled = true
 html.enabled = false
 }
 
 ignoreFailures = true
 }
 
 task pmd(type: Pmd) {
 description 'Run PMD'
 group 'verification'
 
 ruleSetFiles = files("./qa-check/pmd-ruleset.xml")
 ruleSets = []
 
 source 'src'
 include '**/*.java'
 exclude '**/gen/**'
 
 reports {
 xml.enabled = false
 html.enabled = true
 }
 
 ignoreFailures = true
 } apply plugin: 'info.adavis.qualitychecks'
  6. 6. OVERVIEW ▸Plugin Skeleton ▸Dependencies ▸Plugin.groovy ▸CustomTask.groovy ▸Publishing @BRWNGRLDEV
  7. 7. PLUGIN SKELETON @BRWNGRLDEV
  8. 8. PLUGIN SKELETON @BRWNGRLDEV
  9. 9. PLUGIN SKELETON @BRWNGRLDEV
  10. 10. PLUGIN SKELETON How Gradle finds the Plugin Implementation @BRWNGRLDEV
  11. 11. PLUGIN SKELETON implementation-class=info.adavis.qualitychecks.QualityChecksPlugin @BRWNGRLDEV
  12. 12. DEPENDENCIES @BRWNGRLDEV
  13. 13. DEPENDENCIES apply plugin: ‘groovy' dependencies { compile gradleApi() compile localGroovy() } @BRWNGRLDEV
  14. 14. DEPENDENCIES dependencies { … testCompile 'junit:junit:4.12'
 testCompile ('org.spockframework:spock-core:1.0-groovy-2.4') {
 exclude module: 'groovy-all'
 } } @BRWNGRLDEV
  15. 15. THE CODE @BRWNGRLDEV
  16. 16. BUT FIRST… @BRWNGRLDEV
  17. 17. GRADLE BUILD @BRWNGRLDEV PROJECT TASK TASK TASK BUILD
  18. 18. GRADLE BUILD @BRWNGRLDEV PROJECT TASK TASK TASK BUILD PROJECT TASK TASK TASK
  19. 19. PLUGIN.GROOVY class CustomPlugin implements Plugin<Project> { } @BRWNGRLDEV
  20. 20. PLUGIN.GROOVY class CustomPlugin implements Plugin<Project> { @Override void apply(Project project) { } } @BRWNGRLDEV
  21. 21. QUALITYCHECKSPLUGIN.GROOVY @BRWNGRLDEV
  22. 22. APPLY METHOD @BRWNGRLDEV void apply(Project project) {
 this.project = project
 
 }
  23. 23. APPLY METHOD @BRWNGRLDEV void apply(Project project) {
 this.project = project
 
 project.extensions.create('qualityChecks', QualityChecksExtension)
 
 }
  24. 24. APPLY METHOD @BRWNGRLDEV void apply(Project project) {
 this.project = project
 
 project.extensions.create('qualityChecks', QualityChecksExtension)
 
 createConfigFilesIfNeeded()
 createConfigFileTasks()
 createQualityChecksTasks()
 }
  25. 25. PROJECT EXTENSION @BRWNGRLDEV class QualityChecksExtension {
 
 String pmdConfigFile = 'quality-checks/pmd-ruleset.xml'
 
 String checkstyleConfigFile = 'quality-checks/checkstyle.xml'
 
 String findBugsExclusionFile = 'quality-checks/findbugs-exclude.xml'
 
 }
  26. 26. PROJECT EXTENSION @BRWNGRLDEV class QualityChecksExtension {
 
 String pmdConfigFile = 'quality-checks/pmd-ruleset.xml'
 
 String checkstyleConfigFile = 'quality-checks/checkstyle.xml'
 
 String findBugsExclusionFile = 'quality-checks/findbugs-exclude.xml'
 
 }
  27. 27. PROJECT EXTENSION Back in the application’s build.gradle file… @BRWNGRLDEV qualityChecks {
 pmdConfigFile = ‘checks/pmd.xml’ checkstyleConfigFile = ‘checks/checkstyle.xml’
 }
  28. 28. PROJECT EXTENSION Back in the application’s build.gradle file… @BRWNGRLDEV qualityChecks {
 pmdConfigFile = ‘checks/pmd.xml’ checkstyleConfigFile = ‘checks/checkstyle.xml’
 }
  29. 29. TASKS @BRWNGRLDEV
  30. 30. CREATING TASKS Give it a name and a type @BRWNGRLDEV
  31. 31. CREATING TASKS @BRWNGRLDEV ▸Build on existing task ▸Extend the DefaultTask
  32. 32. BUILD ON EXISTING TASK @BRWNGRLDEV
  33. 33. BUILD ON EXISTING @BRWNGRLDEV
  34. 34. EXTEND DEFAULT TASK @BRWNGRLDEV
  35. 35. CUSTOMTASK.GROOVY class CustomTask extends DefaultTask { CustomTask() { group: ‘verification’ } } @BRWNGRLDEV
  36. 36. CUSTOMTASK.GROOVY class CustomTask extends DefaultTask { CustomTask() { group: ‘verification’ } } @BRWNGRLDEV
  37. 37. CUSTOMTASK.GROOVY CustomTask() { group: ‘verification’ onlyIf { // skip under certain conditions } } @BRWNGRLDEV
  38. 38. CUSTOMTASK.GROOVY @TaskAction def defaultAction() { description: ‘What my task does’ } @BRWNGRLDEV
  39. 39. CUSTOMTASK.GROOVY @BRWNGRLDEV @TaskAction def defaultAction() { description: ‘What my task does’ <do your cool stuff here> }
  40. 40. GRADLE TASK DOCUMENTATION @BRWNGRLDEV
  41. 41. SO FAR… ▸Plugin Skeleton ▸Dependencies ▸Plugin.groovy ▸CustomTask.groovy @BRWNGRLDEV
  42. 42. PUBLISHING @BRWNGRLDEV
  43. 43. PUBLISHING @BRWNGRLDEV
  44. 44. PUBLISHING buildscript { … dependencies { classpath "com.gradle.publish:plugin-publish-plugin:0.9.4" } } apply plugin: 'com.gradle.plugin-publish' @BRWNGRLDEV
  45. 45. PUBLISHING version = "0.1.3" group = "info.adavis" @BRWNGRLDEV
  46. 46. PUBLISHING pluginBundle { website = 'https://github.com/adavis/quality-checks' vcsUrl = 'https://github.com/adavis/quality-checks.git' description = 'Gradle Plugin for…’ tags = ['Checkstyle', 'FindBugs', 'PMD'] } @BRWNGRLDEV
  47. 47. PUBLISHING pluginBundle { … plugins { qualityChecksPlugin { id = 'info.adavis.qualitychecks' displayName = 'Quality Checks Plugin' } } @BRWNGRLDEV
  48. 48. @BRWNGRLDEV
  49. 49. @BRWNGRLDEV
  50. 50. WE’RE DONE… WRONG! @BRWNGRLDEV
  51. 51. WE’RE DONE… TESTS @BRWNGRLDEV
  52. 52. TESTING - WITH JUNIT @Before
 void setUp() {
 projectDir = temporaryFolder.root
 projectDir.mkdirs()
 
 
 } @BRWNGRLDEV
  53. 53. TESTING - WITH JUNIT @Before
 void setUp() {
 projectDir = temporaryFolder.root
 projectDir.mkdirs()
 
 project = ProjectBuilder.builder().withProjectDir(projectDir).build()
 task = project.tasks.create('writeConfigFile', WriteConfigFileTask)
 } @BRWNGRLDEV
  54. 54. TESTING - WITH JUNIT @Test void shouldBeAbleToCreateTask() { assertTrue(task instanceof WriteConfigFileTask) } @BRWNGRLDEV
  55. 55. TESTING - WITH JUNIT @Test void pluginShouldBeApplied() { project.apply(plugin: QualityChecksPlugin) assertNotNull(project.tasks.findByName(‘mytask’)) } @BRWNGRLDEV
  56. 56. SPOCK @BRWNGRLDEV
  57. 57. TESTING - WITH SPOCK def createCheckstyleTask() {
 given: "we have a project"
 def project = ProjectBuilder.builder().build() 
 }
  58. 58. TESTING - WITH SPOCK def createCheckstyleTask() {
 
 and: "we apply the extension"
 project.extensions.create('qualityChecks', QualityChecksExtension)
 
 and: "we supply an existing checkstyle config file"
 project.qualityChecks.checkstyleConfigFile = File.createTempFile('temp', '.xml').path
 }
  59. 59. TESTING - WITH SPOCK def createCheckstyleTask() {
 
 when: "we create a checkstyle task"
 def checkstyleTask = project.tasks.create('checkstyle', CheckstyleTask)
 
 
 }
  60. 60. TESTING - WITH SPOCK def createCheckstyleTask() {
 
 then: "it should not replace our previous file"
 checkstyleTask.configFile.name.startsWith('temp')
 }
  61. 61. TESTING - WITH SPOCK @BRWNGRLDEV
  62. 62. TESTING - REPORT @BRWNGRLDEV
  63. 63. TESTING - SPOCK-REPORT dependencies { … testCompile( 'com.athaydes:spock-reports:1.2.12' ) {
 transitive = false } } @BRWNGRLDEV
  64. 64. TESTING - SPOCK-REPORT @BRWNGRLDEV
  65. 65. @BRWNGRLDEV
  66. 66. BONUS: README @BRWNGRLDEV
  67. 67. BONUS: README @BRWNGRLDEV
  68. 68. BONUS: README @BRWNGRLDEV
  69. 69. SUMMARY ▸Helps avoid copy/paste horror ▸Simple project structure ▸Extending DefaultTask ▸Testing techniques ▸Easy to publish @BRWNGRLDEV
  70. 70. THANKS! @brwngrldev +AnnyceDavis www.adavis.info @BRWNGRLDEV

×