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

Take control. write a plugin. part II

on

  • 814 views

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.

Statistics

Views

Total Views
814
Views on SlideShare
803
Embed Views
11

Actions

Likes
0
Downloads
7
Comments
0

1 Embed 11

http://lanyrd.com 11

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 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 Take control. write a plugin. part II Presentation Transcript

  • Jenkins User Conference San Francisco, Sept 30 2012 #jenkinsconf Take Control. Write a Plugin. Part II Baruch Sadogursky JFrog www.jfrog.com
  • 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 custom Jelly(?) tagsMaintaining backwards compatibility
  • AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
  • 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 phraseProject configuration: Is motivator enabledOutcome: Message appears in log after failure
  • Nowdays…BACK TO OUR AGENDA
  • AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
  • 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 GetSystemProperties implements Callable<Properties,RuntimeException> {2 public Properties call() {3 return System.getProperties();4 }5 private static final long serialVersionUID = 1L;6 }
  • 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 FilePath.act(FileCallable)
  • Distribution Abstractions – LauncherLaunch stuff remotely!
  • Distribution Abstractions – Launcherhudson.Launcher Much like java.lang.ProcessBuilderPick your environment variables wisely!
  • AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
  • 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() ? "proc.sh" : "proc.bat";3 Launcher.ProcStarter procStarter =launcher.launch().stdout(System.out);4 procStarter.cmds(new File(workspaceDir, scriptName)).join(); Executed locally!
  • 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
  • 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 }
  • AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
  • Creating UI using GroovyFirst, let’s look at the docs:
  • 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
  • Creating UI using GroovyAnalogous to JellyCan use Jelly tags and libraries me: When What Always! Groovy
  • 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 }
  • 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 }
  • AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
  • 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(hudson/tools) 4 5 MotivationTagLib(JellyBuilder b) { 6 super(b) 7 } 8 9 def evilLaugh() {10 tools.label(mu-ha-ha!)11 }12 }
  • 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 }
  • AgendaVote and guessingWorking with remote agentsWorking in multiple operation systemsCreating UI using GroovyWriting custom Jelly(?) tagsMaintaining backwards compatibility
  • Maintaining backwards compatibilityBack to Motivation plugin…
  • Refactoring!Rename defaultMotivatingMessage to motivatingMessageWhat happens to existing configuration onusers machines?
  • 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
  • Thank you!See you at our DEMOzone!
  • Thank You To Our Sponsors