Writing your Third Plugin

Senior Software Engineer at Netflix
Oct. 5, 2012
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
Writing your Third Plugin
1 of 63

More Related Content

What's hot

Cucumber Ru09 WebCucumber Ru09 Web
Cucumber Ru09 WebJoseph Wilk
MojoliciousMojolicious
MojoliciousMarcus Ramberg
Outside-in Development with Cucumber and RspecOutside-in Development with Cucumber and Rspec
Outside-in Development with Cucumber and RspecJoseph Wilk
SproutCore is Awesome - HTML5 Summer DevFestSproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFesttomdale
Djangocon 2014 angular + djangoDjangocon 2014 angular + django
Djangocon 2014 angular + djangoNina Zakharenko
greach 2014 marco vermeulen bdd using cucumber jvm and groovygreach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovyJessie Evangelista

Viewers also liked

Building an Eclipse plugin to recommend changes to developersBuilding an Eclipse plugin to recommend changes to developers
Building an Eclipse plugin to recommend changes to developerskim.mens
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14The Open-source Eclipse Plugin for Force.com Development, Summer ‘14
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14Salesforce Developers
A Simple Plugin Architecture for WicketA Simple Plugin Architecture for Wicket
A Simple Plugin Architecture for Wicketnielsvk
Building GPE: What We LearnedBuilding GPE: What We Learned
Building GPE: What We Learnedrajeevdayal
Plugin jQuery, Design PatternsPlugin jQuery, Design Patterns
Plugin jQuery, Design PatternsRobert Casanova
Eclipse Overview Eclipse Overview
Eclipse Overview Lars Vogel

Similar to Writing your Third Plugin

Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBob Paulin
Java 6 [Mustang] - Features and Enchantments Java 6 [Mustang] - Features and Enchantments
Java 6 [Mustang] - Features and Enchantments Pavel Kaminsky
Play frameworkPlay framework
Play frameworkAndrew Skiba
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
Spring boot introductionSpring boot introduction
Spring boot introductionRasheed Waraich
Jenkins and GroovyJenkins and Groovy
Jenkins and GroovyKiyotaka Oku

Recently uploaded

EuroBSDCon 2023 - (auto)Installing BSD Systems - Cases using pfSense, TrueNAS...EuroBSDCon 2023 - (auto)Installing BSD Systems - Cases using pfSense, TrueNAS...
EuroBSDCon 2023 - (auto)Installing BSD Systems - Cases using pfSense, TrueNAS...Vinícius Zavam
Chandrayaan 3.pptxChandrayaan 3.pptx
Chandrayaan 3.pptxPrasunJha12
GDSC Cloud Lead Presentation.pptxGDSC Cloud Lead Presentation.pptx
GDSC Cloud Lead Presentation.pptxAbhinavNautiyal8
"The Intersection of architecture and implementation", Mark Richards"The Intersection of architecture and implementation", Mark Richards
"The Intersection of architecture and implementation", Mark RichardsFwdays
How is AI changing journalism? Strategic considerations for publishers and ne...How is AI changing journalism? Strategic considerations for publishers and ne...
How is AI changing journalism? Strategic considerations for publishers and ne...Damian Radcliffe
Product Listing Presentation-Maidy Veloso.pptxProduct Listing Presentation-Maidy Veloso.pptx
Product Listing Presentation-Maidy Veloso.pptxMaidyVeloso

Writing your Third Plugin

Editor's Notes

  1. Why are you here?\n\nEither you’ve written a plugin and had no idea what you’re doing. Or.... Or.... you’ve never written a plugin.\n\nI’m here to simplify things, make things clear which weren’t once before. I’m also trying to capture my experiences as a newbie, before I’m not one anymore.\n\nI know I’m going to have people come up to me afterwards to tell me how easy things are. Well, you all wouldn't be here if you thought the same thing. Maybe we can mob them afterwards.\n\nI’ll be making a lot of references to websites and plugins. There’s no need to write them all down in your notepad or go clickety-clack on your keyboard, I’ll put the slides up later, with nice hyperlinks. Follow @quidryan to see where post them.\n\nNo easy answer here. I don't have sage advice, I have war wounds.\n
  2. http://www.squidoo.com/zombies-hq\nhttp://www.evike.com/product_info.php?products_id=27951\n\nI believe what Jenkins has accomplished is nothing short of amazing. One particular miracle they’ve pulled off is being backwards compatible for so many versions. This has the side effect of certain core objects showing their age. Which means as you traverse the documentation, you will have to waste precious cycles of your brain. Don’t let Jenkins eat your brains.\n\nI should add that during the presentation, I might make disparaging remarks concerning the documentation. I fully understand that as an open source project the onus is on us to be fixing it as we see it. But I didn’t realize my qualms until I worked through this presentation. It just proves that we have selective memories, while working my plugns I just pushed through until it worked and forgot all the bad parts.\n
  3. http://www.squidoo.com/zombies-hq\nhttp://www.evike.com/product_info.php?products_id=27951\n\nI believe what Jenkins has accomplished is nothing short of amazing. One particular miracle they’ve pulled off is being backwards compatible for so many versions. This has the side effect of certain core objects showing their age. Which means as you traverse the documentation, you will have to waste precious cycles of your brain. Don’t let Jenkins eat your brains.\n\nI should add that during the presentation, I might make disparaging remarks concerning the documentation. I fully understand that as an open source project the onus is on us to be fixing it as we see it. But I didn’t realize my qualms until I worked through this presentation. It just proves that we have selective memories, while working my plugns I just pushed through until it worked and forgot all the bad parts.\n
  4. http://www.squidoo.com/zombies-hq\nhttp://www.evike.com/product_info.php?products_id=27951\n\nI believe what Jenkins has accomplished is nothing short of amazing. One particular miracle they’ve pulled off is being backwards compatible for so many versions. This has the side effect of certain core objects showing their age. Which means as you traverse the documentation, you will have to waste precious cycles of your brain. Don’t let Jenkins eat your brains.\n\nI should add that during the presentation, I might make disparaging remarks concerning the documentation. I fully understand that as an open source project the onus is on us to be fixing it as we see it. But I didn’t realize my qualms until I worked through this presentation. It just proves that we have selective memories, while working my plugns I just pushed through until it worked and forgot all the bad parts.\n
  5. Then one day you get one little use case you think needs some tweaking, so you decide it time to write a plugin. Right? You’ve heard how Jenkins is made up from Plugins, and there’s a friendly community behind them.\n\nSure, we all think if we write a Jenkins plugins we'll get famous. They’ll put out the red carpet at Devoxx, you get interviewed on the The Ship Show Podcast, the Java Posse will give you a mention.\n
  6. Wrong!\n\nIn your head is one or two lines which truly represent when you want to accomplish. But you’ll realize that writing a plugin is work. There’s boilerplate code you have to write. You have to maintain it.\n\n
  7. One direction to go into is one of these three.\n\n
  8. Available at the system level or in a job. Use system groovy when possible. It can go back and clean up jobs, enforce plugins. It has the advantage of being easy to code. Can be scheduled at regular intervals, when put into a Job. Plugins typically have to be enabled on a Job, which is hard when you have hundreds of jobs.\n\nExample: Disable failing jobs - People are going to be move on a project, or forget job. it’s not worth tracking them down. So after a period of time, we just disable the jobs. “If a builds get disabled in the Jenkins and no one notices, did really happen?” We also limit the number of builds to 20, unless they really want more\n
  9. I’ll show code examples, I don’t think it’s the best use of time to review them line by line.\n\nIn this sample, I’m going to each Job, aka Project, and looking at the log from the last build. \n
  10. Displays groovy objects, useful for exploration of Jenkins data model.\n
  11. Badges - addInfoBadge, addWarningBadge, addErrorBadge\nSummary - createSummary\nStatus - buildUnstable, buildFailure, buildSuccess\nAccess to Jenkins instance, Build and Listener\nSearching - logContains, contains to search file, getMatch, getLogMatcher\n\nCan’t be shared though. Needs scriptler integration.\n
  12. Examples looks for Sun priprietary APIs.\n
  13. You’ll have a hard time telling me this isn’t from a plugin.\n
  14. \n
  15. Allows programmatic approach to creating jobs\nCan come from source control. Can be accompanied with a job.\nWhich also gives you a lot of power to share common functionality.\nScales real nicely to build a few similar projects, instead of being tempted to parameterize them\n\n
  16. Sample loops through all the branches, creating a job for each one.\n
  17. OK, Fine, you want to write a plugin\n\nYou start with https://wiki.jenkins-ci.org/display/JENKINS/Plugin+tutorial but you’ll find nothing for how to code for it. It’ll talk just about setting up your environment\nIt’ll forward you to Stephen Connolly's 7 part tutorial, while thorough, it is bogged down maven mentuia and 5 years old\nMaybe you look at the hello-world plugin. But you still don’t know what is boilerplate and what should be changed.\nExisting tutorials show how to create a simple plugin. I’m taking a orthogonal approach today.\n\n
  18. There’s a lot of independent projects being used here, e.g. Java, Stapler, Jelly, HTML\n\nThe most important thing for me to build a mental model.\n\nAlong the lines of learning Hibernate and not learning how Sessions work. You’ll be left dazed and confused.\n\nIn our field, you need to ask questions, but sometimes you’re so far removed from the problem, that you don’t even know what questions to ask.\nThe rest of the talk is about diving a little deeper into each of these technologies so that you know what do look into when you come across them. \n\nThere’s a few way to slice and dice the models.\n\n
  19. Let’s start with what you know. Well, you don’t know that you know it.\n\nMaking a Describable allows you to define help files, form validation check methods, and so on correctly. \n\n https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitSCM.java\n
  20. \n
  21. Think of them attached as your implementations of your plugin. We’ll come back to how it’s viewed later, but here are some examples.\n\nCan always look it up:\n DescriptorImpl descriptor = Jenkins.getInstance().getDescriptorByType(DescriptorImpl.class);\nDescriptors are funny. Descriptor.load() in constructor, you’re responsibility to save(). \nnewInstance used to constantly create per-Project instances. Interestingly this calls stapler to do DataBoundConstructor for you, which is why you can ignore it, until you can’t.\nNothing stopping you from having multiple Descriptors in your plugin, where each \nBest done with a @Extension static class, will get created by Jenkins\nData can live on descriptor, because that’s global \nForced to use configure to get values, everyone should read:\n https://wiki.jenkins-ci.org/display/JENKINS/Structured+Form+Submission\n Most basic level: useFrench = json.getBoolean("useFrench");\n More complex: req.bindJSONToList(AnsiColorMap.class, req.getSubmittedForm().get("colorMap")\n Then always call save()\n\n
  22. Extension points provides answers to the question, “are there any implementations for this interface?” It then requires a consumer to call Jenkins.getInstance().getExtensionList(Class<T>);\n
  23. Up to consumer how it’ll collect the extension points. Each one has it’s own rules for how it’ll be used.\nStick with basics:\n BuildWrapper\n preCheckout\n setup, after checkout\n BuildStep\n Publisher\n“The save operation happens without any notice, and the restore operation happens without calling the constructor, just like Java serialization.” \n
  24. http://zombieapocalypseacademy.org/zombie-wallpapers/\n\nFirst, let’s talk about what is a HPI\nIt’ll build to real binaries, one jar and one hpi.\nJust unzip look around\nMETA-INF/MANIFEST.MF - Manifest, tells you about version numbers\nWEB-INF/classes - .class files and jelly files\nWEB-INF/classes/META-INF - Output from annotation scanning\nWEB-INF/lib just has the jars\nBinary. Wrapped with all dependencies, relying on Classloaders to isolate, like OSGI\n\n\nMANIFEST.MF\nManifest-Version: 1.0\nv: 1.0-beta\nUrl: https://wiki.jenkins-ci.org/display/JENKINS/Job+DSL+Plugin\nGroup-Id: org.jenkinsci.plugins\nJenkins-Version: 1.456\nPlugin-Version: 1.0-beta\nLong-Name: Job DSL\nShort-Name: job-dsl\n
  25. It’s an HPI. Really, it has no other meaning, there is no Plugin class that gets implemented.\n\n
  26. \n
  27. \n
  28. It is not a modern web framework. It is what it is.\nMost commonly needed to map HTML forms and bind the request to objects.\nRequired for Descriptor.configure.\nBest possible source is Structured Form Submission (https://wiki.jenkins-ci.org/display/JENKINS/Structured+Form+Submission) and http://stapler.kohsuke.org/\nThe lesson is to use good consistent names and everything will be easy.\n\n
  29. Let’s start talking about how they’re loaded, I’m going to skim over UI pieces\n\n* Startup - Loads HPI, Finds Extensions, Instantiates Descriptions\n* Global Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/global.jelly”\nsave calls configure(StaplerRequest req, JSONObject json)\n* Job Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/config.jelly”\n(Loading values via XSTREAM, then applying via Jelly)\n
  30. Let’s start talking about how they’re loaded, I’m going to skim over UI pieces\n\n* Startup - Loads HPI, Finds Extensions, Instantiates Descriptions\n* Global Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/global.jelly”\nsave calls configure(StaplerRequest req, JSONObject json)\n* Job Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/config.jelly”\n(Loading values via XSTREAM, then applying via Jelly)\n
  31. Let’s start talking about how they’re loaded, I’m going to skim over UI pieces\n\n* Startup - Loads HPI, Finds Extensions, Instantiates Descriptions\n* Global Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/global.jelly”\nsave calls configure(StaplerRequest req, JSONObject json)\n* Job Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/config.jelly”\n(Loading values via XSTREAM, then applying via Jelly)\n
  32. Let’s start talking about how they’re loaded, I’m going to skim over UI pieces\n\n* Startup - Loads HPI, Finds Extensions, Instantiates Descriptions\n* Global Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/global.jelly”\nsave calls configure(StaplerRequest req, JSONObject json)\n* Job Config\nLoads “src/main/resources/${plugin-package}/${plugin-class-name}/config.jelly”\n(Loading values via XSTREAM, then applying via Jelly)\n
  33. I don’t think it’s relevant, but it creates URL for your classes, which have backend values for ajax calls and pages for your plugins.\ndoCheckFoo - Validation\ndoFillFooItems - Auto-populate field, used by jclouds plugin to fill in hardware types\ndoAutocompleteFoo - Contributes to auto complete values\n\n
  34. From hudson.scm.SubversionSCM\n\nCame from this:\n<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">\n <f:section title="${%Subversion}">\n <f:entry title="${%Subversion Workspace Version}" help="/descriptor/hudson.scm.SubversionSCM/help/workspaceFormat">\n <select name="svn.workspaceFormat">\n <f:option value="8" selected="${descriptor.workspaceFormat==8}" >1.4</f:option>\n <f:option value="9" selected="${descriptor.workspaceFormat==9}" >1.5</f:option>\n <f:option value="10" selected="${descriptor.workspaceFormat==10}">1.6 (svn:externals to file)</f:option>\n </select>\n </f:entry>\n <f:entry title="${%Exclusion revprop name}" help="/descriptor/hudson.scm.SubversionSCM/help/excludedRevprop">\n <f:textbox name="svn.global_excluded_revprop" value="${descriptor.globalExcludedRevprop}"/>\n </f:entry>\n <f:optionalBlock\n name="svn.validateRemoteUpToVar"\n checked="${descriptor.validateRemoteUpToVar}"\n title="${%Validate repository URLs up to the first variable name}"\n help="/descriptor/hudson.scm.SubversionSCM/help/validateRemoteUpToVar"/>\n <f:optionalBlock\n name="svn.storeAuthToDisk"\n checked="${descriptor.storeAuthToDisk}"\n title="${%Update default Subversion credentials cache after successful authentication}"/>\n </f:section>\n</j:jelly>\n
  35. \n
  36. \nCan write in Groovy, which is a facade over jelly. But it's even worse documented\nui-samples plugin is the best reference for groovy examples. Though I was tripped up by s:sample notation.\nStapler identifies appropriate file to render\nTags are run. Everything is executed on the server. Though some will output HTML that could come with javascript to run.\nPage renders\nCallbacks to fillFooItems, prototype.js behind the scenes.\n\n
  37. \nCan write in Groovy, which is a facade over jelly. But it's even worse documented\nui-samples plugin is the best reference for groovy examples. Though I was tripped up by s:sample notation.\nStapler identifies appropriate file to render\nTags are run. Everything is executed on the server. Though some will output HTML that could come with javascript to run.\nPage renders\nCallbacks to fillFooItems, prototype.js behind the scenes.\n\n
  38. \n/jenkins/tree/master/core/src/main/resources/lib/[hudson,layout,form]\njelly:core\nwhile, choose/when/otherwise, \nPointless: core:scope, core:thread, core:parse, core:mute\n/lib/hudson\n/lib/form\nSection, almost necessary div identifying your plugin verses others\n<f:section title="Environment Selector Set-up">\nEntry\nDoes magic with doCheck, and binding help-*.html foo, auto population, \nExcept for boolean/checkboxes\n<f:entry title="${%Environment}">\nTextbox\nShouldn’t need name and value, if wrapped in entry\n<f:textbox name="env.envName" value="${env.envName}"/>\nRuby doesn’t have it much better:\nhttps://github.com/rtyler/vagrant-plugin/blob/master/views/vagrant/sudo_builder/config.erb\n\n
  39. Simplified because anything Describable can have a view\n
  40. \nDocumentation is typically poor, so just install them. It's so crazy easy to run Jenkins locally.\nThere will be no end to people telling you to look at existing plugins.\nWork with modern plugins, with @Extensions, like\n Associated File Plugin - For Gradle Example\n https://github.com/jenkinsci/hello-world-plugin\n https://wiki.jenkins-ci.org/display/JENKINS/TEPCO+Plugin For Widget, Recurring work\n Don’t use static analysis plugins and Job Property Plugin\n\n
  41. Number of installations per plugin follows a steep hockey curve. If you ignore the core, all plugins have a real limited install base. There is a daunting number of plugins out there. It’s hard to know what is new/old/modern.\n
  42. This graph represents just the middle. The bar isn’t that high though. SBT is a major build tool, and it’s at 310. Then again, there’s a emma plugin which mis-spells column and a plugin that just shows Bruce Scheneier is here. But at the same time there’s plugins which serve a small community, that doesn’t make it old or worthless.\n
  43. http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html\n\nSpeaking of Jenkins the class, this is a place to start exploring. Starts with ItemGroup, containing a specific type of Item. "Full Name" is the join of '/'.\nKeep in mind that properties of Item as you work with objects, because it won’t be obvious. E.g. ItemListener for things like onLoad()\nSpecial type of item: TopLevelItem\n\n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. Pretty much any meta-data added to an object\nThe only real way to contribute actions to a Project is getProjectActions()\nI tried to save post-build data directly onto an project action, but it kept getting creamed. Best solution was to do with most other plugins do, which is store action on the build, then at the project level aggregate them.\n\n\n\n
  53. You can no longer assume files are local. Welcome to the world of distributed computing.\nJenkins will let you fake a synchronous call, via FileCallable. Let’s you ship code to slave to run.\n“On a slave, usually only a part of the Jenkins object graph is available. This means that, for instance, Hudson.getInstance() can return null. To work around this, grab all the information you need on the master side, assign them to final variables, then access them from the closure so that only those bits get sent to the slave.”\nYou get one from something like boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener)\n\n
  54. \n
  55. There's a long history of tight maven integration. Maven is not as bad as long as you have someone else writing the plugins, luckily that’s already done for Jenkins. Gradle is new enough that could cause confusion for new developers, especially without a Java background.\nThe only reason I used it was that I had Hans Dockter and Andrew Bayer around.\nI ran into issues around requiring maven plugin support, testCompile needing exclusions.\n\n
  56. I’d like to thank our sponsors. Having a conference like this is really important to the community.\n
  57. \n