Skip to content

Commit

Permalink
Merge pull request #18 from launchableinc/overreporting-fix
Browse files Browse the repository at this point in the history
Overreporting fix
  • Loading branch information
Konboi authored Jan 7, 2025
2 parents 4b51655 + f50d9cf commit 83166e4
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 65 deletions.
36 changes: 0 additions & 36 deletions src/main/java/io/jenkins/plugins/launchable/GraphListenerImpl.java

This file was deleted.

61 changes: 32 additions & 29 deletions src/main/java/io/jenkins/plugins/launchable/Ingester.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hudson.tasks.junit.TestResult;
import hudson.util.Secret;
import jenkins.model.GlobalConfiguration;
import jenkins.util.Timer;
import net.sf.json.JSONObject;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
Expand All @@ -17,6 +18,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.util.logging.Level.*;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;
import static org.apache.http.entity.ContentType.APPLICATION_OCTET_STREAM;

Expand Down Expand Up @@ -47,44 +49,45 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti
* @param properties Additional contextual data to submit along with the test results.
*/
/*package*/ void slurp(File dir, PropsBuilder<?> properties) throws IOException {
try {
File report = new File(dir, "junitResult.xml");
if (!report.exists()) return; // be defensive just in case
File report = new File(dir, "junitResult.xml");
if (!report.exists()) return; // be defensive just in case

if (apiKey==null) return; // not yet configured
Timer.get().execute(() -> {// don't slow down people's builds and risk getting kicked out
try {
if (apiKey==null) return; // not yet configured
OrganizationWorkspace orgWs = OrganizationWorkspace.fromApiKey(apiKey.getPlainText());

OrganizationWorkspace orgWs = OrganizationWorkspace.fromApiKey(apiKey.getPlainText());
// attempted to use JDK HttpRequest, but gave up due to the lack of multipart support
// TODO: how do I obtain a properly configured HttpClient for the proxy setting in Jenkins?
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
String endpoint = System.getProperty("INSIGHT_UPLOAD_URL") ;

// attempted to use JDK HttpRequest, but gave up due to the lack of multipart support
// TODO: how do I obtain a properly configured HttpClient for the proxy setting in Jenkins?
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
String endpoint = System.getProperty("INSIGHT_UPLOAD_URL") ;

if (endpoint==null) {
endpoint = DEFAULT_UPLOAD_URL;
}
HttpPost hc = new HttpPost(String.format("%s/intake/organizations/%s/workspaces/%s/events/jenkins", endpoint, orgWs.getOrganization(), orgWs.getWorkspace()));
if (endpoint==null) {
endpoint = DEFAULT_UPLOAD_URL;
}
HttpPost hc = new HttpPost(String.format("%s/intake/organizations/%s/workspaces/%s/events/jenkins", endpoint, orgWs.getOrganization(), orgWs.getWorkspace()));

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("metadata", properties.build().toString(), APPLICATION_JSON);
builder.addPart("file", new GzipFileMimePart(report, APPLICATION_OCTET_STREAM, "junitResult.xml.gz"));
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("metadata", properties.build().toString(), APPLICATION_JSON);
builder.addPart("file", new GzipFileMimePart(report, APPLICATION_OCTET_STREAM, "junitResult.xml.gz"));

hc.setEntity(builder.build());
hc.addHeader("Authorization", "Bearer " + apiKey.getPlainText());
hc.setEntity(builder.build());
hc.addHeader("Authorization", "Bearer " + apiKey.getPlainText());

try (CloseableHttpResponse response = httpClient.execute(hc)) {
if (response.getStatusLine().getStatusCode() >= 300) {
// treat redirect as an error, for the time being. we submit a big payload, so we don't want
// to be forced to repeat the payload after we send the whole thing once.
LOGGER.log(Level.WARNING, "Failed to submit test results: {0}", response.getStatusLine());
try (CloseableHttpResponse response = httpClient.execute(hc)) {
if (response.getStatusLine().getStatusCode() >= 300) {
// treat redirect as an error, for the time being. we submit a big payload, so we don't want
// to be forced to repeat the payload after we send the whole thing once.
LOGGER.log(WARNING, "Failed to submit test results: {0}", response.getStatusLine());
}
}
}
} catch (Exception e) {
// don't let our bug get in the way of orderly execution of jobs, as that'd be the fasest way to
// get kicked out of installations.
LOGGER.log(WARNING, "Failed to submit test results", e);
}
} catch (Exception e) {
// don't let our bug get in the way of orderly execution of jobs, as that'd be the fasest way to
// get kicked out of installations.
LOGGER.log(Level.WARNING, "Failed to submit test results", e);
}
});
}

private static final Logger LOGGER = Logger.getLogger(Ingester.class.getName());
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/io/jenkins/plugins/launchable/RunListenerImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.jenkins.plugins.launchable;

import hudson.Extension;
import hudson.model.listeners.RunListener;
import org.jenkinsci.plugins.workflow.flow.GraphListener;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;

import javax.inject.Inject;
import java.util.logging.Logger;

import static java.util.logging.Level.*;

/**
* Records test results reported into {@link WorkflowRun}.
*
* <p>
* Our earlier attempt to implement {@link GraphListener} backfired, as when 'junitReport' step was called
* multiple times, we end up reporting all test results accumulated up to that point, resulting in duplicate
* data reporting.
*
* <p>
* This approach defers the data ingestion all the way down to the end of a workflow run.
*/
@Extension
public class RunListenerImpl extends RunListener<WorkflowRun> {
@Inject
Ingester ingester;

@Override
public void onFinalized(WorkflowRun run) {
try {
ingester.slurp(run.getRootDir(), new PropsBuilder<>(run));
} catch (Exception e) {
// Priority #1: Do no harm to people's build
LOGGER.log(WARNING, "Failed to send JUnit result to Launchable", e);
}
}

private static final Logger LOGGER = Logger.getLogger("io.jenkins.plugins.launchable.RunListenerImpl");
}

0 comments on commit 83166e4

Please sign in to comment.