Jenkins API - trigger jobs programmatically

There are several ways to trigger a Jenkins build. You can trigger a build manually or through Jenkins schedule.

There is also the Jenkins API that allows us to trigger a Jenkins job through http calls, if the job requires passing parameters we can do that as well.

Jenkins API Interface

This is an example of the API inetrface that we will use to make calls to the Jenkins API.

Having this interface also allows us to document the API interface and it’s readable and easy to undersatnd.

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

public interface Jenkins {
  @POST
  @Path("/view/<path to your job>/buildWithParameters")
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  Response buildMyJob(@HeaderParam("Jenkins-Crumb") String crumb, @FormParam("environment") String selectedEnvironment);
 
  @GET
  @Path("/view/<path to your job>/lastBuild/api/json")
  JobStatusResponse myJobStatus();
 
  @GET
  @Path("/crumbIssuer/api/json")
  CrumbResponse getCrumbs();
}

Authentication

This is how we add Basic Authorization header to every request


import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.core.MultivaluedMap;
import java.util.Base64;

public class Authenticator implements ClientRequestFilter {

    private final String user;
    private final String password;

    public Authenticator(String user, String password) {
        this.user = user;
        this.password = password;
    }

    @Override
    public void filter(ClientRequestContext requestContext) {
        MultivaluedMap<String, Object> headers = requestContext.getHeaders();
        final String basicAuthentication = getBasicAuthentication();
        headers.add("Authorization", basicAuthentication);

    }

    private String getBasicAuthentication() {

        String token = user + ":" + password;
        return "Basic " + Base64.getEncoder().encodeToString(token.getBytes());
    }
}
 

Jenkins API Client


httpClient = new ResteasyClientBuilder().disableTrustManager().build()
				.register(new Authenticator(userName, password));
Jenkins jenkins = new ResteasyClientBuilder().disableTrustManager().build()
				.register(new Authenticator(userName, password));
				.target(jenkinsUrl)
				.proxy(Jenkins.class);

Before calling any Jenkins endpoint we have to make the getCrumbs call.

This how we can trigger our Jenkins job programmatically

CrumbResponse crumbResponse = jenkins.getCrumbs();
jenkins.buildMyJob(crumbResponse.getCrumb(), "QA");

Also we can check the status of the job

JobStatusResponse statusRespose = jenkins.myJobStatus();

If we need to wait for the build completion

private static void waitForBuildCompletionWithTimeOut() throws InterruptedException {
    int timeSpent = 0;
    boolean building = true;
    JobStatusResponse statusResponse = null;
    while (building == true && timeSpent < JENKINS_JOB_COMPLETION_TIMEOUT_SEC) {
        System.out.println("Waiting for 10 seconds");
        Thread.sleep(10000);
        timeSpent = timeSpent + 10;
        statusResponse = jenkins.myJobStatus();
        System.out.println("The job status: " + (statusResponse.isBuilding() ? "Building" : statusResponse.getResult()));
        building = statusResponse.isBuilding();
    }
    if (timeSpent >= JENKINS_JOB_COMPLETION_TIMEOUT_SEC) {
        fail("=== Jenkins Job Completion Time Out - " + JENKINS_JOB_COMPLETION_TIMEOUT_SEC + "secs ===");
    }
    if (!"SUCCESS".equals(statusResponse.getResult())) {
        fail("The Job Build failed with result code: " + statusResponse.getResult());
    }
}

You may also find these posts interesting: