failedTests,
+ final AbstractBuild build,
+ final BuildListener listener) {
PrintStream logger = listener.getLogger();
String url = this.serverAddress + "rest/api/2/issue/";
+ DefaultHttpClient httpClient = getDefaultHttpClient();
+
for (CaseResult result : failedTests) {
if ((result.getAge() == 1) || (this.createAllFlag)) {
-// if (result.getAge() > 0) {
debugLog(listener,
- String.format("Creating issue in project %s at URL %s%n",
- this.projectKey, url)
- );
+ String.format("Creating issue in project %s at URL %s%n",
+ this.projectKey, url)
+ );
try {
- DefaultHttpClient httpClient = new DefaultHttpClient();
- Credentials creds = new UsernamePasswordCredentials(this.username, this.password);
- ((AbstractHttpClient) httpClient).getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpPost postRequest = new HttpPost(url);
- String summary = "Test " + result.getName() + " failed";
+ String summary = issueSummary(result.getName());
+
String description = "Test class: " + result.getClassName() + "\n\n" +
- "Jenkins job: " + build.getAbsoluteUrl() + "\n\n" +
- "{noformat}\n" + result.getErrorDetails() + "\n{noformat}\n\n" +
- "{noformat}\n" + result.getErrorStackTrace().replace(this.workspace.toString(), "") + "\n{noformat}\n\n";
+ "Jenkins job: " + build.getUrl() + "\n\n" +
+ "{noformat}\n" + result.getErrorDetails() + "\n{noformat}\n\n" +
+ "{noformat}\n" + result.getErrorStackTrace().replace(this.workspace.getRemote(), "") + "\n{noformat}\n\n";
JsonObjectBuilder issuetype = Json.createObjectBuilder().add("name", "Bug");
JsonObjectBuilder project = Json.createObjectBuilder().add("key", this.projectKey);
JsonObjectBuilder fields = Json.createObjectBuilder().add("project", project)
- .add("summary", summary)
- .add("description", description)
- .add("issuetype", issuetype);
+ .add("summary", summary)
+ .add("description", description)
+ .add("issuetype", issuetype);
JsonObjectBuilder payload = Json.createObjectBuilder().add("fields", fields);
StringWriter stWriter = new StringWriter();
JsonWriter jsonWriter = Json.createWriter(stWriter);
jsonWriter.writeObject(payload.build());
jsonWriter.close();
String jsonPayLoad = stWriter.toString();
-// logger.printf("%s JSON payload: %n", pVerbose, jsonPayLoad);
+
logger.printf("%s Reporting issue.%n", pInfo);
StringEntity params = new StringEntity(jsonPayLoad);
params.setContentType("application/json");
postRequest.setEntity(params);
- try {
- postRequest.addHeader(new BasicScheme().authenticate(new UsernamePasswordCredentials(this.username, this.password), postRequest));
- } catch (AuthenticationException a) {
- a.printStackTrace();
- }
+
+
+ postRequest.addHeader(getAuthenticationHeader(postRequest));
HttpResponse response = httpClient.execute(postRequest);
- debugLog(listener,
- String.format("statusLine: %s%n",
- response.getStatusLine())
- );
- debugLog(listener,
- String.format("statusCode: %d%n",
- response.getStatusLine().getStatusCode())
- );
- if (response.getStatusLine().getStatusCode() != JIRA_SUCCESS_CODE) {
- throw new RuntimeException(this.prefixError + " Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
- }
+ validateHttpResponse(response, listener, JIRA_SUCCESS_CODE_CREATED);
- httpClient.getConnectionManager().shutdown();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
+ } catch (AuthenticationException e) {
+ e.printStackTrace();
+ } finally {
+ httpClient.getConnectionManager().shutdown();
}
+
} else {
logger.printf("%s This issue is old; not reporting.%n", pInfo);
}
@@ -240,28 +324,128 @@ public boolean isApplicable(final Class extends AbstractProject> jobType) {
public String getDisplayName() {
return "Jira Test Result Reporter";
}
-
+
public FormValidation doCheckProjectKey(@QueryParameter String value) {
- if (value.isEmpty()) {
- return FormValidation.error("You must provide a project key.");
- } else {
- return FormValidation.ok();
- }
+ if (value.isEmpty()) {
+ return FormValidation.error("You must provide a project key.");
+ } else {
+ return FormValidation.ok();
+ }
}
public FormValidation doCheckServerAddress(@QueryParameter String value) {
- if (value.isEmpty()) {
- return FormValidation.error("You must provide an URL.");
- }
-
- try {
- new URL(value);
- } catch (final MalformedURLException e) {
- return FormValidation.error("This is not a valid URL.");
- }
-
- return FormValidation.ok();
+ if (value.isEmpty()) {
+ return FormValidation.error("You must provide an URL.");
+ }
+
+ try {
+ new URL(value);
+ } catch (final MalformedURLException e) {
+ return FormValidation.error("This is not a valid URL.");
+ }
+
+ return FormValidation.ok();
+ }
+ }
+
+
+ private DefaultHttpClient getDefaultHttpClient() {
+ DefaultHttpClient httpClient = new DefaultHttpClient();
+ Credentials creds = new UsernamePasswordCredentials(this.username, this.password);
+ (httpClient).getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
+ return httpClient;
+ }
+
+ private String getSummaryFromIssue(JsonObject issue) {
+ return issue.getJsonObject("fields").getString("summary");
+ }
+
+ private String issueSummary(String methodName) {
+ return MessageFormat.format("Test {0} failed", methodName);
+ }
+
+ private String getTransitionPayload(String issueID, AbstractBuild build, final BuildListener listener) {
+ //"transitions": { "id": "5" }
+ if (jiraResolveTransitionId == null) {
+ String transitionUrl = MessageFormat.format("{0}rest/api/2/issue/{1}/transitions?expand=transitions.fields",
+ serverAddress,
+ issueID);
+
+ DefaultHttpClient httpClient = getDefaultHttpClient();
+ try {
+
+ HttpGet httpGet = new HttpGet(transitionUrl);
+ httpGet.addHeader(getAuthenticationHeader(httpGet));
+ HttpResponse response = httpClient.execute(httpGet);
+
+ JsonReader jsonReader = Json.createReader(response.getEntity().getContent());
+ JsonObject jsonObject = jsonReader.readObject();
+ jsonReader.close();
+
+ JsonArray jsonArray = jsonObject.getJsonArray("transitions");
+ for (int i = 0; i < jsonArray.size(); i++) {
+ JsonObject transitionEntity = jsonArray.getJsonObject(i);
+ if (jiraUpdateStatus.equals(transitionEntity.getString("name"))) {
+ jiraResolveTransitionId = transitionEntity.getString("id");
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (AuthenticationException e) {
+ e.printStackTrace();
+ } finally {
+ httpClient.getConnectionManager().shutdown();
+ }
+
+ if (jiraResolveTransitionId == null) {
+ debugLog(listener, MessageFormat.format("Couldn't get the id for jira status -'{0}'", jiraUpdateStatus));
+ }
}
+
+ String comment = MessageFormat.format("Test case fixed in build# {0}.", build.getNumber());
+
+ JsonObjectBuilder payload = Json.createObjectBuilder()
+ .add("transition", Json.createObjectBuilder().add("id", jiraResolveTransitionId))
+ .add("update", Json.createObjectBuilder().
+ add("comment", Json.createArrayBuilder().
+ add(Json.createObjectBuilder().
+ add("add", Json.createObjectBuilder().add("body", comment)))));
+
+ StringWriter stWriter = new StringWriter();
+ JsonWriter jsonWriter = Json.createWriter(stWriter);
+ jsonWriter.writeObject(payload.build());
+ jsonWriter.close();
+ return stWriter.toString();
}
+
+ private void validateHttpResponse(HttpResponse response, BuildListener listener, int HTTP_CODE) {
+ debugLog(listener,
+ String.format("statusLine: %s%n",
+ response.getStatusLine())
+ );
+ debugLog(listener,
+ String.format("statusCode: %d%n",
+ response.getStatusLine().getStatusCode())
+ );
+ if (response.getStatusLine().getStatusCode() != HTTP_CODE) {
+ throw new RuntimeException(this.prefixError + " Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
+ }
+ }
+
+ private org.apache.http.Header getAuthenticationHeader(HttpRequest httpRequest) throws AuthenticationException {
+ return new BasicScheme().authenticate(
+ new UsernamePasswordCredentials(this.username, this.password),
+ httpRequest,
+ new BasicHttpContext());
+ }
+
+ void debugLog(final BuildListener listener, final String message) {
+ if (!this.debugFlag) {
+ return;
+ }
+ PrintStream logger = listener.getLogger();
+ logger.printf("%s %s%n", pDebug, message);
+ }
+
}
diff --git a/src/main/resources/JiraTestResultReporter/JiraReporter/config.jelly b/src/main/resources/JiraTestResultReporter/JiraReporter/config.jelly
index 9646f9a..91f5b40 100644
--- a/src/main/resources/JiraTestResultReporter/JiraReporter/config.jelly
+++ b/src/main/resources/JiraTestResultReporter/JiraReporter/config.jelly
@@ -20,4 +20,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/JiraTestResultReporter/JiraReporter/help-checkAllSuccessful.html b/src/main/resources/JiraTestResultReporter/JiraReporter/help-checkAllSuccessful.html
new file mode 100644
index 0000000..86dcca7
--- /dev/null
+++ b/src/main/resources/JiraTestResultReporter/JiraReporter/help-checkAllSuccessful.html
@@ -0,0 +1,5 @@
+
+ Check this option to check the status of all successful tests in the build. If the flag is off, the plugin will
+ analyse only the new successful tests and try to resolve in JIRA. This ommits some redundant checkes and makes
+ the execution a little faster.
+
diff --git a/src/main/resources/JiraTestResultReporter/JiraReporter/help-resolveIssueFlag.html b/src/main/resources/JiraTestResultReporter/JiraReporter/help-resolveIssueFlag.html
new file mode 100644
index 0000000..db8ebb9
--- /dev/null
+++ b/src/main/resources/JiraTestResultReporter/JiraReporter/help-resolveIssueFlag.html
@@ -0,0 +1,8 @@
+
+ Check this option to auto resolve the issue for recent successful tests.
+ This requires the
Junit Publish plugin
+ version 1.11 or higher.
+ There is compatibility of Junit report publisher with jenkins version lower than 1.587, reported
+ here
+ Please update your jenkins to 1.587 or higher to use this option
+
diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly
index f420311..d5563f2 100644
--- a/src/main/resources/index.jelly
+++ b/src/main/resources/index.jelly
@@ -2,5 +2,5 @@
This view is used to render the installed plugins page.
-->
-This plugin creates issues in Jira for failed unit tests.
+This plugin creates issues in Jira for failed unit tests. It also resolves the issue once its fixed.