3a5775f Feb 6, 2017
976 lines (723 sloc) 29.2 KB

Release Notes

Release 0.3.8 (NOT RELEASED YET)

API Changes

  • ?

Release 0.3.7

  • Changed Eclipse Formatting configuration.

Fixed Issue 186

  • Correctly escaping { and } for range syntax.

Fixed Issue 166

  • Added a supplemental package with classifier apachehttp which includes the packages org.apache.httpcomponents:httpclient and org.apache.httpcomponents:httpcore.

API Changes

  • Fixed Issue 215

    The JenkinsServer class will return JenkinsVersion instead of String if you call getJenkinsVersion().

public class JenkinsVersion ... {
    public boolean isGreaterThan(String version);
    public boolean isGreaterOrEqual(String version);
    public boolean isLessThan(String version);
    public boolean isLessOrEqual(String version);
    public boolean isEqualTo(String version);

The JenkinsVersion class can be used to compare different versions with each other.

JenkinsVersion jv = new JenkinsVersion("1.651.1");
  • Fixed issue 184

    Based on the differences between getting a TestReport for a MavenJob type and a freestyle job etc. you would have hit by getting 0 from getTotalCount() like in the following code snippet:

JobWithDetails job = js.getJob("non-maven-test");
Build lastCompletedBuild = job.getLastCompletedBuild();
TestReport testReport = lastCompletedBuild.getTestReport();

This is caused by the difference in the API of Jenkins which results in the following for a MavenJob type:

  "_class" : "hudson.maven.reporters.SurefireAggregatedReport",
  "failCount" : 0,
  "skipCount" : 0,
  "totalCount" : 489,
  "urlName" : "testReport",
  "childReports" : [
      "child" : {
        "_class" : "hudson.maven.MavenBuild",
        "number" : 2,
        "url" : "http://localhost:27100/buildserver/job/maven-test/com.soebes.subversion.sapm$sapm/2/"
      "result" : {
        "_class" : "hudson.tasks.junit.TestResult",
        "testActions" : [

        "duration" : 0.009,
        "empty" : false,
        "failCount" : 0,
        "passCount" : 489,
        "skipCount" : 0,
        "suites" : [
            "cases" : [

But for a non Maven job like freestyle job you will get the following:

  "_class" : "hudson.tasks.junit.TestResult",
  "testActions" : [

  "duration" : 0.01,
  "empty" : false,
  "failCount" : 0,
  "passCount" : 489,
  "skipCount" : 0,
  "suites" : [
      "cases" : [
          "testActions" : [

          "age" : 0,
          "className" : "com.soebes.subversion.sapm.AccessRuleGroupTest",
          "duration" : 0.003,

This is exactly the cause for this result.

The API has been enhanced to get the correct result. This can be achieved by calling the following in cases where you have a non Maven job type.

TestResult testResult = lastCompletedBuild.getTestResult();

This means you need to take care yourself if you are getting the test results from Maven job type or non Maven job. (Future releases of the lib hopefully handle that in a more convenient way).

  • Fixed issue 209

    Consider Returning null from the "getTestReport()" of class for builds that Never run.

    The type BUILD_HAS_NEVER_RUN has been enhanced to return TestReport.NO_TEST_REPORT if you call getTestReport() and return BuildWithDetails.BUILD_HAS_NEVER_RUN if you call details() on the type.

    Furthermore JobWithDetails class has been enhanced with the following methods:

public class JobWithDetails ... {
    public boolean hasFirstBuildRun();
    public boolean hasLastBuildRun();
    public boolean hasLastCompletedBuildRun();
    public boolean hasLastFailedBuildRun();
    public boolean hasLastStableBuildRun();
    public boolean hasLastSuccessfulBuildRun();
    public boolean hasLastUnstableBuildRun();
    public boolean hasLastUnsuccessfulBuildRun();

to make checking more convenient. The following code snippet shows how you need to go before this change:

JobWithDetails job = server.getJob(jobName);
if (Build.BUILD_HAS_NEVER_RUN.equals(job.getLastBuild()) {
} else {
  // Now we can get the TestReport

This can now be simplified to the following:

JobWithDetails job = server.getJob(jobName);
if (job.hasLastBuildRun()) {
  // Now we can get the TestReport
} else {
public class JobWithDetails .. {
    public void updateDescription(String description);
    public void updateDescription(String description, boolean crumbFlag);
    public void clearDescription();
    public void clearDescription(boolean crumbFlag);
  • Fixed issue 188

    Added methods to update the description and the display name of a build.

public class BuildWithDetails .. {
    public void updateDisplayNameAndDescription(String displayName, String description, boolean crumbFlag);
    public void updateDisplayNameAndDescription(String displayName, String description);
    public void updateDisplayName(String displayName, boolean crumbFlag);
    public void updateDisplayName(String displayName);
    public void updateDescription(String description, boolean crumbFlag);
    public void updateDescription(String description);
public class JenkinsServer {
    public String runScript(String script,boolean crumb);
  • Fixed issue 197 Provide method for waiting until job has finished.

    Added a helper class to support this.

public class JenkinsTriggerHelper {
    public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName);
    public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, boolean crumbFlag);
    public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, Map<String, String> params);
    public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, Map<String, String> params,boolean crumbFlag);
  • Fixed Issue 104 all build* methods now return consistently QueueReference to make it possible to query for a queued build and if a build from the queue has been cancelled or to see if a build is running.
 public class Job extends BaseModel {
   public QueueReference build();
   public QueueReference build(boolean crumbFlag);
   public QueueReference build(Map<String, String> params);
   public QueueReference build(Map<String, String> params, boolean crumbFlag);
public class JenkinsServer {
  String getJobXml(FolderJob folder, String jobName);
  void updateJob(FolderJob folder, String jobName, String jobXml, boolean crumbFlag);
public class QueueItem extends BaseModel {

  List<QueueItemActions> getActions();

and the new QueueItemActions will offer access to the actions.

public class JenkinsServer {
  deleteJob(FolderJob folder, String jobName, boolean crumbFlag);
public class JenkinsServer {
  void createView(String viewName, String viewXml);
  void createView(String viewName, String viewXml, Boolean crumbFlag);
  void createView(FolderJob folder, String viewName, String viewXml);
  void createView(FolderJob folder, String viewName, String viewXml, Boolean crumbFlag);
  void updateView(String viewName, String viewXml);
  void updateView(String viewName, String viewXml, boolean crumbFlag);
  • Fixed Issue 38787

    Returning null instead of IOException if view is not found in JenkinsServer.getView

  • Fixed Issue 201

    MavenJobsWithDetails is now in line with JobWithDetails and returns MavenBuild.BUILD_HAS_NEVER_RUN in cases where the run has not taken place yet.

public class MavenJobWithDetails { 
   public MavenBuild getLastBuild();
   public MavenBuild getLastCompletedBuild();
   public MavenBuild getLastFailedBuild();
   public MavenBuild getLastStableBuild();
   public MavenBuild getLastSuccessfulBuild();
   public MavenBuild getLastUnstableBuild();
   public MavenBuild getLastUnsuccessfulBuild();

The getBuilds() method will return an empty list instead of NULL in cases no builds exists.

Fixed grammar and changed Build.BUILD_HAS_NEVER_RAN into Build.BUILD_HAS_NEVER_RUN

public class MavenJobWithDetails { 
   public MavenBuild getFirstBuild();
  • Fixed Issue 198

    Enhanced the QueueItem to add information about the task (QueueTask).

public class QueueItem {
    public QueueTask getTask();
  • Fixed Issue 200

    Added two methods to get all builds and a range of builds so we are more in line wiht JobWithDetails.

public class MavenJobWithDetails { 
    public List<MavenBuild> getAllBuilds();
    public List<MavenBuild> getAllBuilds(Range range);

Release 0.3.6

General Changes

Fixed #182 remove duplicated code

Upgraded Maven Plugins

  • maven-release-plugin to 2.5.3
  • maven-site-plugin to 3.5.1
  • maven-shade-plugin to 2.4.3
  • maven-jar-plugin to 3.0.2
  • maven-source-plugin 3.0.1
  • maven-surefire/failsafe-plugin to 2.19.1
  • maven-resources-plugin to 3.0.1
  • Add missing maven-javadoc-plugin 2.10.4

Upgraded Maven Plugins JENKINS-35108

  • maven-clean-plugin to 3.0.0
  • maven-resources-plugin to 3.0.0
  • maven-jar-plugin to 3.0.0

Fixed issue 176 HttpResponseException: Not Found (createJob) Based on the wrong usage of the sub methods using crumbFlag=true instead of crumbFlag=false.

Fixed issue 162

JenkinsJob.details() produced NPE which has been got via view.getJob().

Fixed issue 172

The implementation BuildWithDetails.getCauses() could cause an NPE which now has been imroved to prevent it. Thanks for hint which brought me to reconsider the implementation.

Serveral issues fixed related to using logging framework issue-161, issue-113 and JENKINS-35002

Added slf4j-api as foundation for logging. Using log4j2-slf4j-impl in jenkins-client-it-docker for logging. As a user you can now decide which logging framework you would like to use.

Changed the structure and integrated Docker IT

API Changes

The attributes of the following classes have been made private. They are only accessible via getters/setters.

MavenArtifact, ComputerWithDetails, Executable, FolderJob, JobWithDetails, MavenJobWithDetails, MavenModule, MavenModuleRecord, PluginManager

Fixed issue 179

The getTestReport has been moved up from MavenBuild into Build class. This makes the TestReport accessible from any kind of build and not only from a Maven build.

Fixed issue 174

jenkins.getComputerSet().getComputer() produced an error. Changed getComputer() into getComputers() cause it returns a list an not only a single computer. Based on the above problem the Executor needed to be changed to represent the correct data which is being returned.

public class ComputerSet {
   public List<ComputerWithDetails> getComputers();
public class Executor {
  public Job getCurrentExecutable();
  public Job getCurrentWorkUnit();

Fixed issue 169 Add crumbFlag to renameJob

Added supplemental renameJob method which supports crumbFlag. Furthermore added renameJob which supports folder with and without crumbFlag. So we now have the following methods to rename jobs:

public class JenkinsServer {
  public void renameJob(String oldJobName, String newJobName) throws IOException;
  public void renameJob(String oldJobName, String newJobName, Boolean crumbFlag) throws IOException;
  public void renameJob(FolderJob folder, String oldJobName, String newJobName) throws IOException;
  public void renameJob(FolderJob folder, String oldJobName, String newJobName, Boolean crumbFlag) throws IOException;

Fixed issue 168 deletejobs in folder

Added new method to delete a job within a folder.

public class JenkinsServer {
 public void deleteJob(FolderJob folder, String jobName) throws IOException;

Changing getLocalContext(), setLocalContext()

The protected method getLocalContext() now returns HttpContext instead of BasicHttpContext. So the API has changed from the following:

public class JenkinsServer {
  protected BasicHttpContext getLocalContext();
  protected void setLocalContext(BasicHttpContext localContext); 

into this:

public class JenkinsServer {
  protected HttpContext getLocalContext();
  protected void setLocalContext(HttpContext localContext); 

Apart from that the visibility of the class PreemptiveAuth has been changed from package private to public.

Get Jenkins Version from http header

public class JenkinsServer {
  public String getVersion();

Added description for Job

public class JobWithDetails {
  public String getDescription();

Release 0.3.5

API Changes

Fixed issue 159

The following methods have been changed to return Collections.emtpyList() if no builds exists or have ran before.

getAllBuilds(Range range);

Fixed NPE

The JobWithDetails class contains several methods which could have returned null. This has been changed to return non null values.

     public List<Job> getDownstreamProjects();
     public List<Job> getUpstreamProjects();

They will return Collections.emptyList().

The following methods will return Build.BUILD_HAS_NEVER_RAN in cases where no build has executed for the appropriate methods instead of the previous null value.

    public Build getFirstBuild();
    public Build getLastBuild();
    public Build getLastCompletedBuild();
    public Build getLastFailedBuild();
    public Build getLastStableBuild();
    public Build getLastSuccessfulBuild();
    public Build getLastUnstableBuild();
    public Build getLastUnsuccessfulBuild();

Added getAllBuilds(), getAllBuilds(Range range)

The JobWithDetails has been enhanced with two methods to get all builds which exists or a range can be used to select.

Note: There seemed to be no option to extract simply the number of existing builds of a particular job via the REST API.

public class JobWithDetails {
    public List<Build> getAllBuilds() throws IOException;
    public List<Build> getAllBuilds(Range range) throws IOException;

Added renameJob(..)

public class JenkinsServer {
  renameJob(String jobName, String newJobName) throws IOException;

Release 0.3.4

API Changes

Added toggleOffline Node Added toggleOffline to ComputerWithDetails class.

public class ComputerWithDetails {
  public void toggleOffline(boolean crumbFlag) throws IOException;
  public void toggleOffline() throws IOException;
PluginManager getPluginManager() throws IOException;

Added method to get Plugin.

public class PluginManager extends BaseModel {
    public List<Plugin> getPlugins()

Plugin class contains methods to get informations about the plugins plus a PluginDependency class.

Added getFileFromWorkspace() to Job Added method getFileFromWorkspace() to Job class to get a file from workspace in Jenkins.

String getFileFromWorkspace(String fileName)

Make jobNames case sensitive.

TestCase class enhanced Now the TestCase contains the information about the errorDetails and the errorStackTrace of a failed test case.

String getErrorDetails();
String getErrorStackTrace()

Added disableJob, enabledJob The following methods have been added to support enabling and disabling jobs.

void disableJob(String jobName);
void disableJob(String jobName, boolean crumbFlag);
void enableJob(String jobName);
void enableJob(String jobName, boolean crumbFlag);

Fixed #128 Added OfflineCause as a real object in ComputerWithDetails Added OfflineCause class which can now being used as a return type for the attribute offlineCause instead of Object in ComputerWithDetails.

public class ComputerWithDetails {
  Object offlineCause;

into the following which also influenced the appropriate return types of the getters:


public class ComputerWithDetails {
    OfflineCause offlineCause;

    public OfflineCause getOfflineCause() throws IOException;


Fixed #135 Created documentation area Started a documentation area under src/site/ for either Markdown or asciidoctor.

Fixed #130 org.jvnet.hudson:xstream I needed to remove the toString method from View class which uses the XStream classes which does not make sense from my point of view.

Fixed #144 Problems with spaces in paths and job names

Fixed #133 How do we find out which system the built was build on?

Now BuildWithDetails API has been enhanced with the following method get the information on which node this build has ran.

String getBuiltOn();

Fixed #146 duration / estimatedDuration are long

The API in BuildWithDetailshas been changed to represent the change in datatype.

int getDuration();
int getEstimatedDuration();


long getDuration();
long getEstimatedDuration();

Release 0.3.3

Fixed #111 A missing dependency to jaxen caused problems The problem was that the dependency has missed from the compile scope which caused problems for users to use. The dependency was there via transitive dependency of a test scoped artifact.

Do not propagate IOException when GET for /CrumbIssuer fails

API Changes

Added Cloudbees Folder support The following methods have been added to support FolderJob type.

void createFolder(String jobName, Boolean crumbFlag);
Optional<FolderJob> getFolderJob(Job job);
Map<String, Job> getJobs(FolderJob folder);
Map<String, Job> getJobs(FolderJob folder, String view);
Map<String, View> getViews(FolderJob folder);
View getView(FolderJob folder, String name);
JobWithDetails getJob(FolderJob folder, String jobName);
MavenJobWithDetails getMavenJob(FolderJob folder, String jobName);
void createJob(FolderJob folder, String jobName, String jobXml);
void createJob(FolderJob folder, String jobName, String jobXml, Boolean crumbFlag);

Release 0.3.2

API Changes:

JobWithDetails has been enhanced with information about the first build.

Build getFirstBuild()

The JenkinsServer API has been enhanced to get information about the Queue

QueueItem getQueueItem(QueueReference ref) throws IOException 
Build getBuild(QueueItem q)  throws IOException 

The JenkinsHttpClient API has been changed from the following:

JenkinsHttpClient(URI uri, DefaultHttpClient defaultHttpClient);


JenkinsHttpClient(URI uri, CloseableHttpClient client);

Furthermore the JenkinsHttpClient API has been enhanced with the following method which allows to create an unauthenticated Jenkins HTTP client.

JenkinsHttpClient(URI uri, HttpClientBuilder builder);

The Build class Stop method needed to be changed internally based on an inconsistencies in Jenkins versions. (This might be change in future). There are versions 1.565 which supports the stop method as a post call, version 1.609.1 support it as a get call and 1.609.2 as a post call.

The Job class has been enhanced to trigger parameterized builds.

QueueReference build(Map<String, String> params, boolean crumbFlag) throws IOException;

Release 0.3.1

API Changes:

Until to Release 0.3.0 the getLoadStatistics() method returned a simple Map which needed to be changed to represent the information which is returned.

So the old one looked like this:

Map getLoadStatistics();

The new one looks like this:

LoadStatistics getLoadStatistics() throws IOException

You can see how it works by using the

The API for getExecutors() has been changed from a simple Map into something more meaningful.

The old one looked like this:

List<Map> getExecutors(); 

where as the new API looks like this:

List<Executor> getExecutors();

This will result in a list of Executor which contain supplemental informations about the appropriate executor.


Issue #53

This release contains new functionality like support to get the list of existing views. This can be accomplished by using the following:

Map<String, View> views = jenkins.getViews();

Issue #67

The change for getExecutors() which is documented in API changes.

Issue #82

The information about the ChangeSet and the culprit has been improved.

JenkinsServer jenkins = new JenkinsServer(new URI("http://localhost:8080/jenkins"), "admin", "password");
MavenJobWithDetails mavenJob = js.getMavenJob("javaee");
BuildWithDetails details = mavenJob.getLastSuccessfulBuild().details();

So now you can extract the causes which is related to the trigger which triggered the build.

List<BuildCause> causes = details.getCauses();

With the help of getChangeSet() you can extract the changeset information of your build:

BuildChangeSet changeSet = details.getChangeSet();

By using the changeSet.getKind() you would expect to get the kind of version control which has been used. If you use Git or Subversion this is true but unfortunately it is not true for all version control systems (for example TFS).

The information about files which have been changed an other information can be extracted by using the following:

List<BuildChangeSetItem> items = changeSet.getItems();

If you like to get a better overview check the example file in the project.

Issue #89

Extract TestReport from Jenkins

JenkinsServer js = new JenkinsServer(URI.create("http://jenkins-server/"));
MavenJobWithDetails mavenJob = js.getMavenJob("MavenJob");
BuildWithDetails details = mavenJob.getLastSuccessfulBuild().details();
TestReport testReport = mavenJob.getLastSuccessfulBuild().getTestReport(); 

You can extract the information about the tests which have run which contains information about the number of tests, failed tests and skipped tests etc. For a more detailed example take a look into the project.