Your SlideShare is downloading. ×
Take control. write a plugin. part II
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Take control. write a plugin. part II

649
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 …

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
649
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
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

    • 1. Jenkins User Conference San Francisco, Sept 30 2012 #jenkinsconf Take Control. Write a Plugin. Part II Baruch Sadogursky JFrog www.jfrog.com
    • 2. About meDeveloper Advocate @JFrogJob definition: Write code Talk about itgithub.com/jbaruch@jbaruch
    • 3. JFrog & JenkinsWith Jenkins from day 1Jenkins Artifactory PluginHosted JUC Israelrepo.jenkins-ci.orgJavaOne DEMOzone
    • 4. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 5. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 6. First, let’s voteWho saw “Take Control. Write a Plugin” sessionon YouTube?Let me guess… one or two hands…
    • 7. “Hello, my name is Noam Tenne”PREVIOUSLY IN “TAKE CONTROL.WRITE A PLUGIN”…
    • 8. Overview – Why pluginsWhat you can do with pluginsWhat you can’t do with pluginsPlugins statistics
    • 9. What can I extend?UISCMBuild ProcessesSlave managementTooling... Many, many, moreYou can even create new extension points!
    • 10. EnvironmentIDE All majors have good support We love IntelliJ IDEABuild tool Can be Maven or Gradle
    • 11. The “Motivation” PluginTarget: Rewarding failing builds with insultingmockeryGlobal configuration: Motivation phraseProject configuration: Is motivator enabledOutcome: Message appears in log after failure
    • 12. Nowdays…BACK TO OUR AGENDA
    • 13. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 14. Working with remote agentsJenkins has remote agents!
    • 15. Working with remote agentsSend closures to remote agentshudson.remoting.Callable Java Serialization
    • 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. Cast your bread on the waters1 this.systemProperties = channel.call(new GetSystemProperties()); Channel?
    • 18. ChannelRepresents a communication channel to theremote peerObtain from:
    • 19. Distribution Abstractions – FilePathWhere is the file?
    • 20. Distribution Abstractions – FilePathhudson.FilePath Much like java.util.FileConsider pushing logic to the file Use FilePath.act(FileCallable)
    • 21. Distribution Abstractions – LauncherLaunch stuff remotely!
    • 22. Distribution Abstractions – Launcherhudson.Launcher Much like java.lang.ProcessBuilderPick your environment variables wisely!
    • 23. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 24. Working in multiple OSsWORA. You know. But./ vs .sh vs .batQuotes around commandsPermissions (wait for it…)
    • 25. Running script…Executing file… remotely… platform independent…
    • 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. 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. 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. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 30. Creating UI using GroovyFirst, let’s look at the docs:
    • 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. Creating UI using GroovyAnalogous to JellyCan use Jelly tags and libraries me: When What Always! Groovy
    • 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. 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. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 36. Writing custom Jelly(?) tagsDocumentation:
    • 37. Writing custom Jelly(?) tags
    • 38. Writing custom Jelly Groovy tagsSimple as 1,2… that’s it.
    • 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. 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. AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
    • 42. Maintaining backwards compatibilityBack to Motivation plugin…
    • 43. Refactoring!Rename defaultMotivatingMessage to motivatingMessageWhat happens to existing configuration onusers machines?
    • 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. Thank you!See you at our DEMOzone!
    • 46. Thank You To Our Sponsors