Skip to content

Commit c1c5245

Browse files
committed
Fixed #197
o Provided methods for waiting until a job has finished. Added JenkinsTriggerHelper class which contains such methods.
1 parent a7d0d4f commit c1c5245

File tree

5 files changed

+222
-5
lines changed

5 files changed

+222
-5
lines changed

ReleaseNotes.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414

1515
### API Changes
1616

17+
* [Fixed issue 197][issue-197] Provide method for waiting until job has finished.
18+
19+
Added a helper class to support this.
20+
21+
```java
22+
public class JenkinsTriggerHelper {
23+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName);
24+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, Map<String, String> params);
25+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, Map<String, String> params,boolean crumbFlag);
26+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, boolean crumbFlag);
27+
}
28+
```
29+
1730
* [Fixed Issue 104][issue-104] all build* methods now return consistently `QueueReference`
1831
to make it possible to query for a queued build and if a build from the queue has
1932
been cancelled or to see if a build is running.
@@ -727,6 +740,7 @@ TestReport testReport = mavenJob.getLastSuccessfulBuild().getTestReport();
727740
[issue-179]: https://github.com/jenkinsci/java-client-api/issues/179
728741
[issue-182]: https://github.com/jenkinsci/java-client-api/issues/182
729742
[issue-186]: https://github.com/jenkinsci/java-client-api/issues/186
743+
[issue-197]: https://github.com/jenkinsci/java-client-api/issues/197
730744
[issue-198]: https://github.com/jenkinsci/java-client-api/issues/198
731745
[issue-200]: https://github.com/jenkinsci/java-client-api/issues/200
732746
[issue-201]: https://github.com/jenkinsci/java-client-api/issues/201
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package com.offbytwo.jenkins;
2+
3+
import java.io.IOException;
4+
import java.util.Map;
5+
6+
import com.offbytwo.jenkins.model.Build;
7+
import com.offbytwo.jenkins.model.BuildResult;
8+
import com.offbytwo.jenkins.model.BuildWithDetails;
9+
import com.offbytwo.jenkins.model.JobWithDetails;
10+
import com.offbytwo.jenkins.model.QueueItem;
11+
import com.offbytwo.jenkins.model.QueueReference;
12+
13+
/**
14+
* collection of convenient methods which use methods from {@link JenkinsServer}
15+
* etc.
16+
*
17+
* @author Karl Heinz Marbaise
18+
*
19+
*/
20+
public class JenkinsTriggerHelper {
21+
22+
private JenkinsServer server;
23+
24+
public JenkinsTriggerHelper(JenkinsServer server) {
25+
this.server = server;
26+
}
27+
28+
/**
29+
* This method will trigger a build of the given job and will wait until the
30+
* builds is ended or if the build has been cancelled.
31+
*
32+
* @param jobName
33+
* The name of the job which should be triggered.
34+
* @return In case of an cancelled job you will get
35+
* {@link BuildWithDetails#getResult()}
36+
* {@link BuildResult#CANCELLED}. So you have to check first if the
37+
* build result is {@code CANCELLED}.
38+
* @throws IOException
39+
* in case of errors.
40+
* @throws InterruptedException
41+
* In case of interrupts.
42+
*/
43+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName) throws IOException, InterruptedException {
44+
return triggerJobAndWaitUntilFinished(jobName, false);
45+
}
46+
47+
/**
48+
* This method will trigger a build of the given job and will wait until the
49+
* builds is ended or if the build has been cancelled.
50+
*
51+
* @param jobName
52+
* The name of the job which should be triggered.
53+
* @param params
54+
* the job parameters
55+
* @return In case of an cancelled job you will get
56+
* {@link BuildWithDetails#getResult()}
57+
* {@link BuildResult#CANCELLED}. So you have to check first if the
58+
* build result is {@code CANCELLED}.
59+
* @throws IOException
60+
* in case of errors.
61+
* @throws InterruptedException
62+
* In case of interrupts.
63+
*/
64+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, Map<String, String> params)
65+
throws IOException, InterruptedException {
66+
return triggerJobAndWaitUntilFinished(jobName, params, false);
67+
}
68+
69+
/**
70+
* This method will trigger a build of the given job and will wait until the
71+
* builds is ended or if the build has been cancelled.
72+
*
73+
* @param jobName
74+
* The name of the job which should be triggered.
75+
* @param params
76+
* the job parameters
77+
* @param crumbFlag
78+
* set to <code>true</code> or <code>false</code>.
79+
* @return In case of an cancelled job you will get
80+
* {@link BuildWithDetails#getResult()}
81+
* {@link BuildResult#CANCELLED}. So you have to check first if the
82+
* build result is {@code CANCELLED}.
83+
* @throws IOException
84+
* in case of errors.
85+
* @throws InterruptedException
86+
* In case of interrupts.
87+
*/
88+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, Map<String, String> params,
89+
boolean crumbFlag) throws IOException, InterruptedException {
90+
JobWithDetails job = this.server.getJob(jobName);
91+
QueueReference queueRef = job.build(params, crumbFlag);
92+
93+
return triggerJobAndWaitUntilFinished(jobName, queueRef);
94+
}
95+
96+
/**
97+
* This method will trigger a build of the given job and will wait until the
98+
* builds is ended or if the build has been cancelled.
99+
*
100+
* @param jobName
101+
* The name of the job which should be triggered.
102+
* @param crumbFlag
103+
* set to <code>true</code> or <code>false</code>.
104+
* @return In case of an cancelled job you will get
105+
* {@link BuildWithDetails#getResult()}
106+
* {@link BuildResult#CANCELLED}. So you have to check first if the
107+
* build result is {@code CANCELLED}.
108+
* @throws IOException
109+
* in case of errors.
110+
* @throws InterruptedException
111+
* In case of interrupts.
112+
*/
113+
public BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, boolean crumbFlag)
114+
throws IOException, InterruptedException {
115+
JobWithDetails job = this.server.getJob(jobName);
116+
QueueReference queueRef = job.build(crumbFlag);
117+
118+
return triggerJobAndWaitUntilFinished(jobName, queueRef);
119+
}
120+
121+
/**
122+
* @param jobName
123+
* The name of the job.
124+
* @param queueRef
125+
* {@link QueueReference}
126+
* @return In case of an cancelled job you will get
127+
* {@link BuildWithDetails#getResult()}
128+
* {@link BuildResult#CANCELLED}. So you have to check first if the
129+
* build result is {@code CANCELLED}.
130+
* @throws IOException
131+
* in case of errors.
132+
* @throws InterruptedException
133+
* In case of interrupts.
134+
*/
135+
private BuildWithDetails triggerJobAndWaitUntilFinished(String jobName, QueueReference queueRef)
136+
throws IOException, InterruptedException {
137+
JobWithDetails job;
138+
job = this.server.getJob(jobName);
139+
QueueItem queueItem = this.server.getQueueItem(queueRef);
140+
while (!queueItem.isCancelled() && job.isInQueue()) {
141+
// TODO: May be we should make this configurable?
142+
Thread.sleep(200);
143+
job = this.server.getJob(jobName);
144+
queueItem = this.server.getQueueItem(queueRef);
145+
}
146+
147+
if (queueItem.isCancelled()) {
148+
// TODO: Check if this is ok?
149+
// We will get the details of the last build. NOT of the cancelled
150+
// build, cause there is no information about that available cause
151+
// it does not exist.
152+
BuildWithDetails result = new BuildWithDetails(job.getLastBuild().details());
153+
// TODO: Should we add more information here?
154+
result.setResult(BuildResult.CANCELLED);
155+
return result;
156+
}
157+
158+
job = this.server.getJob(jobName);
159+
Build lastBuild = job.getLastBuild();
160+
161+
boolean isBuilding = lastBuild.details().isBuilding();
162+
while (isBuilding) {
163+
// TODO: May be we should make this configurable?
164+
Thread.sleep(200);
165+
isBuilding = lastBuild.details().isBuilding();
166+
}
167+
168+
return lastBuild.details();
169+
}
170+
}

jenkins-client/src/main/java/com/offbytwo/jenkins/model/Build.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@
1313
public class Build extends BaseModel {
1414

1515
/**
16-
* This will be returned by the API in cases where no build has ever
17-
* been executed like {@link JobWithDetails#getLastBuild()} etc.
16+
* This will be returned by the API in cases where no build has ever been
17+
* executed like {@link JobWithDetails#getLastBuild()} etc.
1818
*/
19-
public static final Build BUILD_HAS_NEVER_RUN = new Build (-1, -1, "UNKNOWN");
19+
public static final Build BUILD_HAS_NEVER_RUN = new Build(-1, -1, "UNKNOWN");
20+
/**
21+
* This will be returned by the API in cases where a build has been
22+
* cancelled.
23+
*/
24+
public static final Build BUILD_HAS_BEEN_CANCELLED = new Build(-1, -1, "CANCELLED");
2025

2126
private int number;
2227
private int queueId;
@@ -28,7 +33,7 @@ private Build(int number, int queueId, String url) {
2833
this.queueId = queueId;
2934
this.url = url;
3035
}
31-
36+
3237
public Build() {
3338
}
3439

jenkins-client/src/main/java/com/offbytwo/jenkins/model/BuildResult.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@
77
package com.offbytwo.jenkins.model;
88

99
public enum BuildResult {
10-
FAILURE, UNSTABLE, REBUILDING, BUILDING, ABORTED, SUCCESS, UNKNOWN, NOT_BUILT
10+
FAILURE, UNSTABLE, REBUILDING, BUILDING, ABORTED, SUCCESS, UNKNOWN, NOT_BUILT,
11+
/**
12+
* This will be the result of a job in cases where it has been
13+
* cancelled during the time in the queue.
14+
*/
15+
CANCELLED
1116
}

jenkins-client/src/main/java/com/offbytwo/jenkins/model/BuildWithDetails.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,25 @@ public class BuildWithDetails extends Build {
4040
private String builtOn;
4141
private List<BuildChangeSetAuthor> culprits;
4242

43+
public BuildWithDetails(BuildWithDetails details) {
44+
this.actions = details.actions;
45+
this.description = details.description;
46+
this.building = details.building;
47+
this.duration = details.duration;
48+
this.estimatedDuration = details.estimatedDuration;
49+
this.fullDisplayName = details.fullDisplayName;
50+
this.id = details.id;
51+
this.timestamp = details.timestamp;
52+
this.result = details.result;
53+
this.artifacts = details.artifacts;
54+
this.consoleOutputHtml = details.consoleOutputHtml;
55+
this.consoleOutputText = details.consoleOutputText;
56+
this.changeSet = details.changeSet;
57+
this.builtOn = details.builtOn;
58+
this.culprits = details.culprits;
59+
this.setClient(details.getClient());
60+
}
61+
4362
public List<Artifact> getArtifacts() {
4463
return artifacts;
4564
}
@@ -200,6 +219,10 @@ public void setCulprits(List<BuildChangeSetAuthor> culprits) {
200219
this.culprits = culprits;
201220
}
202221

222+
public void setResult(BuildResult result) {
223+
this.result = result;
224+
}
225+
203226
public InputStream downloadArtifact(Artifact a) throws IOException, URISyntaxException {
204227
// We can't just put the artifact's relative path at the end of the url
205228
// string, as there could be characters that need to be escaped.

0 commit comments

Comments
 (0)