Your SlideShare is downloading. ×
0
Jenkins User Conference   San Francisco, Sept 30 2012   #jenkinsconf       Take Control. Write a Plugin.       Part II    ...
About meDeveloper Advocate @JFrogJob definition:     Write code     Talk about itgithub.com/jbaruch@jbaruch
JFrog & JenkinsWith Jenkins from day 1Jenkins Artifactory PluginHosted JUC Israelrepo.jenkins-ci.orgJavaOne DEMOzone
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
First, let’s voteWho saw “Take Control. Write a Plugin” sessionon YouTube?Let me guess…              one or two hands…
“Hello, my name is Noam Tenne”PREVIOUSLY IN “TAKE CONTROL.WRITE A PLUGIN”…
Overview – Why pluginsWhat you can do with pluginsWhat you can’t do with pluginsPlugins statistics
What can I extend?UISCMBuild ProcessesSlave managementTooling... Many, many, moreYou can even create new extension points!
EnvironmentIDE  All majors have good support  We love IntelliJ IDEABuild tool  Can be Maven or Gradle
The “Motivation” PluginTarget: Rewarding failing builds with insultingmockeryGlobal configuration: Motivation phraseProjec...
Nowdays…BACK TO OUR AGENDA
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
Working with remote agentsJenkins has remote agents!
Working with remote agentsSend closures to remote agentshudson.remoting.Callable              Java Serialization
Closure    Poor guy’s Java closure    Usually anonymous inner class (not always)1   private static class GetSystemProperti...
Cast your bread on the waters1   this.systemProperties = channel.call(new GetSystemProperties());    Channel?
ChannelRepresents a communication channel to theremote peerObtain from:
Distribution Abstractions – FilePathWhere is the file?
Distribution Abstractions – FilePathhudson.FilePath  Much like java.util.FileConsider pushing logic to the file  Use FileP...
Distribution Abstractions – LauncherLaunch stuff remotely!
Distribution Abstractions – Launcherhudson.Launcher  Much like java.lang.ProcessBuilderPick your environment variables wis...
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
Working in multiple OSsWORA. You know. But./ vs .sh vs .batQuotes around commandsPermissions      (wait for it…)
Running script…Executing     file…             remotely…                 platform independent…
Can You Spot The Error?1 String workspaceDir = build.getWorkspace().getRemote();2 String scriptName = launcher.isUnix() ? ...
Going Remote with FileUse FilePath – it will take care of all the details!Execute FilePath.act(FileCallable)If you need th...
Permissions Dance 1   public boolean isDirectoryReadOnly(final FilePath filePath) throws IOException, 2           Interrup...
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
Creating UI using GroovyFirst, let’s look at the docs:
Creating UI using GroovyAnalogous to JellyCan use Jelly tags and libraries     Kohsuke:                   When            ...
Creating UI using GroovyAnalogous to JellyCan use Jelly tags and libraries     me:               When                 What...
Creating UI using Groovy    Jelly:1 <j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">2     <f:section title="Motivation P...
Creating UI using Groovy   Real code   Debuggable, etc.         (stay tuned…)1 f=namespace(lib/form)23 f.section(title:Mot...
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
Writing custom Jelly(?) tagsDocumentation:
Writing custom Jelly(?) tags
Writing custom Jelly Groovy tagsSimple as 1,2…     that’s it.
1. Implement 1 class MotivationTagLib extends 2         AbstractGroovyViewModule { 3     def tools = builder.namespace(hud...
2. Use! 1   import org._10ne.jenkins.MotivationTagLib 2 3   f = namespace(lib/form) 4   m = new MotivationTagLib(builder);...
AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting cust...
Maintaining backwards compatibilityBack to Motivation plugin…
Refactoring!Rename defaultMotivatingMessage             to         motivatingMessageWhat happens to existing configuration...
XStream Aliasing To The Rescue1   @Initializer(before = PLUGINS_STARTED)2   public static void addAliases() {3      Items....
Thank you!See you at our DEMOzone!
Thank You To Our Sponsors
Take control. write a plugin. part II
Upcoming SlideShare
Loading in...5
×

Take control. write a plugin. part II

705

Published on

In this session I will talk about advanced aspects of plugin development, such as working with remote agents, working in multiple operation systems, creating UI using Groovy, extending Jelly components, etc.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
705
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Let it runOverall structureGlobal.jellyConfig.jellyCode:Extends NotifierDatabound constructorPerform Descriptor:ExtensionSerializationXML
  • MD5 digest
  • Represents file path, but may be local or remoteisRemote()moveAllChilderenTo()Etc.Push – MD5
  • MD5 digest
  • Starts a process, but may be local or remoteCall to launch() returns builderjoin() on builder actually starts the processDon’t include machine specific ones, like PATH, TIMEZONE, etc.
  • Show defaultMotivating method refactoring
  • Transcript of "Take control. write a plugin. part II"

    1. 1. Jenkins User Conference San Francisco, Sept 30 2012 #jenkinsconf Take Control. Write a Plugin. Part II Baruch Sadogursky JFrog www.jfrog.com
    2. 2. About meDeveloper Advocate @JFrogJob definition: Write code Talk about itgithub.com/jbaruch@jbaruch
    3. 3. JFrog & JenkinsWith Jenkins from day 1Jenkins Artifactory PluginHosted JUC Israelrepo.jenkins-ci.orgJavaOne DEMOzone
    4. 4. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    5. 5. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    6. 6. First, let’s voteWho saw “Take Control. Write a Plugin” sessionon YouTube?Let me guess… one or two hands…
    7. 7. “Hello, my name is Noam Tenne”PREVIOUSLY IN “TAKE CONTROL.WRITE A PLUGIN”…
    8. 8. Overview – Why pluginsWhat you can do with pluginsWhat you can’t do with pluginsPlugins statistics
    9. 9. What can I extend?UISCMBuild ProcessesSlave managementTooling... Many, many, moreYou can even create new extension points!
    10. 10. EnvironmentIDE All majors have good support We love IntelliJ IDEABuild tool Can be Maven or Gradle
    11. 11. The “Motivation” PluginTarget: Rewarding failing builds with insultingmockeryGlobal configuration: Motivation phraseProject configuration: Is motivator enabledOutcome: Message appears in log after failure
    12. 12. Nowdays…BACK TO OUR AGENDA
    13. 13. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    14. 14. Working with remote agentsJenkins has remote agents!
    15. 15. Working with remote agentsSend closures to remote agentshudson.remoting.Callable Java Serialization
    16. 16. Closure Poor guy’s Java closure Usually anonymous inner class (not always)1 private static class GetSystemProperties implements Callable<Properties,RuntimeException> {2 public Properties call() {3 return System.getProperties();4 }5 private static final long serialVersionUID = 1L;6 }
    17. 17. Cast your bread on the waters1 this.systemProperties = channel.call(new GetSystemProperties()); Channel?
    18. 18. ChannelRepresents a communication channel to theremote peerObtain from:
    19. 19. Distribution Abstractions – FilePathWhere is the file?
    20. 20. Distribution Abstractions – FilePathhudson.FilePath Much like java.util.FileConsider pushing logic to the file Use FilePath.act(FileCallable)
    21. 21. Distribution Abstractions – LauncherLaunch stuff remotely!
    22. 22. Distribution Abstractions – Launcherhudson.Launcher Much like java.lang.ProcessBuilderPick your environment variables wisely!
    23. 23. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    24. 24. Working in multiple OSsWORA. You know. But./ vs .sh vs .batQuotes around commandsPermissions (wait for it…)
    25. 25. Running script…Executing file… remotely… platform independent…
    26. 26. Can You Spot The Error?1 String workspaceDir = build.getWorkspace().getRemote();2 String scriptName = launcher.isUnix() ? "proc.sh" : "proc.bat";3 Launcher.ProcStarter procStarter =launcher.launch().stdout(System.out);4 procStarter.cmds(new File(workspaceDir, scriptName)).join(); Executed locally!
    27. 27. Going Remote with FileUse FilePath – it will take care of all the details!Execute FilePath.act(FileCallable)If you need the File API, invoke() method has it, converted to remote file properly
    28. 28. Permissions Dance 1 public boolean isDirectoryReadOnly(final FilePath filePath) throws IOException, 2 InterruptedException { 3 return filePath.getChannel().call(new Callable<Boolean, IOException>() { 4 public Boolean call() throws IOException { 5 Path path = FileSystems.getDefault().getPath(filePath.getRemote()); 6 Set<String> systems = FileSystems.getDefault().supportedFileAttributeViews(); 7 if (systems.contains("dos")) { 8 DosFileAttributeView dosView = 9 Files.getFileAttributeView(path, DosFileAttributeView.class);10 DosFileAttributes dosAttributes = dosView.readAttributes();11 return dosAttributes.isReadOnly();12 }13 if (systems.contains("posix")) {14 PosixFileAttributeView posixView =15 Files.getFileAttributeView(path, PosixFileAttributeView.class);16 PosixFileAttributes posixAttributes = posixView.readAttributes();17 Set<PosixFilePermission> permissions = posixAttributes.permissions();18 return !permissions.contains(PosixFilePermission.OTHERS_WRITE)19 }20 throw new IOException("Unknown filesystem");21 }22 });23 }
    29. 29. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    30. 30. Creating UI using GroovyFirst, let’s look at the docs:
    31. 31. Creating UI using GroovyAnalogous to JellyCan use Jelly tags and libraries Kohsuke: When What Lots of program logic Groovy Lots of HTML layout markup Jelly
    32. 32. Creating UI using GroovyAnalogous to JellyCan use Jelly tags and libraries me: When What Always! Groovy
    33. 33. Creating UI using Groovy Jelly:1 <j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">2 <f:section title="Motivation Plugin">3 <f:entry title=" Motivating Message" field="motivatingMessage"4 description="The motivational message to display when a build fails">5 <f:textbox/>6 </f:entry>7 </f:section>8 </j:jelly> Groovy:1 f=namespace(lib/form)23 f.section(title:Motivation Plugin) {4 f.entry(title:Motivating Message, field:motivatingMessage,5 description:The motivational message to display when a build fails){6 f.textbox()7 }8 }
    34. 34. Creating UI using Groovy Real code Debuggable, etc. (stay tuned…)1 f=namespace(lib/form)23 f.section(title:Motivation Plugin) {4 f.entry(title:Motivating Message, field:motivatingMessage,5 description:The motivational message to display when a build fails){6 f.textbox()7 }8 }
    35. 35. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    36. 36. Writing custom Jelly(?) tagsDocumentation:
    37. 37. Writing custom Jelly(?) tags
    38. 38. Writing custom Jelly Groovy tagsSimple as 1,2… that’s it.
    39. 39. 1. Implement 1 class MotivationTagLib extends 2 AbstractGroovyViewModule { 3 def tools = builder.namespace(hudson/tools) 4 5 MotivationTagLib(JellyBuilder b) { 6 super(b) 7 } 8 9 def evilLaugh() {10 tools.label(mu-ha-ha!)11 }12 }
    40. 40. 2. Use! 1 import org._10ne.jenkins.MotivationTagLib 2 3 f = namespace(lib/form) 4 m = new MotivationTagLib(builder); 5 6 f.entry(title: ) { 7 m.evilLaugh() 8 f.checkbox(…)11 }
    41. 41. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    42. 42. Maintaining backwards compatibilityBack to Motivation plugin…
    43. 43. Refactoring!Rename defaultMotivatingMessage to motivatingMessageWhat happens to existing configuration onusers machines?
    44. 44. XStream Aliasing To The Rescue1 @Initializer(before = PLUGINS_STARTED)2 public static void addAliases() {3 Items.XSTREAM2.aliasField("defaultMotivatingMessage",4 DescriptorImpl.class, "motivatingMessage");5 } Register field (or class) alias In Initializer that runs before plugins started More complex cases might reqiure XStream converter
    45. 45. Thank you!See you at our DEMOzone!
    46. 46. Thank You To Our Sponsors
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×