Take control. write a plugin. part II

810 views

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
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
810
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
9
Comments
0
Likes
1
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
  • 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

    ×