diff --git a/.mvn/maven.config b/.mvn/maven.config index 2a0299c..ccd03b8 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1,2 +1,3 @@ -Pconsume-incrementals -Pmight-produce-incrementals +-Dchangelist.format=-%d.v%s diff --git a/Jenkinsfile b/Jenkinsfile index 18218b7..401533f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,4 +2,7 @@ See the documentation for more options: https://github.com/jenkins-infra/pipeline-library/ */ -buildPlugin(useContainerAgent: true) +buildPlugin(useContainerAgent: true,configurations: [ + [platform: 'linux', jdk: 11], + [platform: 'windows', jdk: 11], +]) diff --git a/pom.xml b/pom.xml index 8238616..66640da 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 4.24 + 4.80 io.jenkins.plugins @@ -12,15 +12,12 @@ ${revision}${changelist} hpi - 4.0.8 + 4.0.12 -SNAPSHOT jenkinsci/leapwork-plugin - -SNAPSHOT - 2.277.1 - 8 - jenkinsci/leapwork-plugin + 2.440.1 Leapwork https://github.com/${gitHubRepo} @@ -30,65 +27,22 @@ io.jenkins.tools.bom - bom-2.277.x - 923.v08bdc07cd40f + bom-2.440.x + 2815.vf5d6f093b_23e import pom - - io.jenkins.plugins - jakarta-activation-api - 2.0.0-2 - - - - org.jenkins-ci.plugins - structs - - - org.jenkins-ci.plugins.workflow - workflow-cps - test - - - org.jenkins-ci.plugins.workflow - workflow-job - test - - - org.jenkins-ci.plugins.workflow - workflow-basic-steps - test - com.ning async-http-client 1.9.40 - org.slf4j - slf4j-api - 1.7.32 - - - org.slf4j - slf4j-nop - 1.7.32 - test - - - com.google.code.gson - gson - 2.8.0 - - - - org.jenkins-ci.plugins - anything-goes-formatter - 1.0 + io.jenkins.plugins + gson-api jakarta.xml.bind @@ -101,18 +55,26 @@ 3.0.0 runtime - - com.google.code.findbugs - annotations - 3.0.1u2 + org.slf4j + slf4j-nop + 1.7.32 + test - - - org.jenkins-ci.plugins.workflow - workflow-durable-task-step - test + io.jenkins.plugins + jquery3-api + 3.7.1-2 + + + io.jenkins.plugins + commons-lang3-api + 3.13.0-62.v7d18e55f51e2 + + + io.jenkins.plugins + commons-text-api + 1.11.0-95.v22a_d30ee5d36 diff --git a/src/main/java/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder.java b/src/main/java/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder.java index e803d0e..f3acf29 100644 --- a/src/main/java/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder.java +++ b/src/main/java/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder.java @@ -44,6 +44,7 @@ public class LeapworkJenkinsBridgeBuilder extends Builder implements SimpleBuild private final String leapworkPort; private final Secret leapworkAccessKey; private String leapworkDelay; + private String leapworkTimeout; private String leapworkDoneStatusAs; private String leapworkReport; private final String leapworkSchIds; @@ -59,13 +60,14 @@ public class LeapworkJenkinsBridgeBuilder extends Builder implements SimpleBuild // "DataBoundConstructor" @DataBoundConstructor public LeapworkJenkinsBridgeBuilder(String leapworkHostname, String leapworkPort, String leapworkAccessKey, - String leapworkDelay, String leapworkDoneStatusAs, String leapworkReport, String leapworkSchNames, + String leapworkDelay, String leapworkTimeout, String leapworkDoneStatusAs, String leapworkReport, String leapworkSchNames, String leapworkSchIds, boolean leapworkWritePassedFlowKeyFrames, boolean leapworkEnableHttps) { this.leapworkHostname = leapworkHostname; this.leapworkPort = leapworkPort; this.leapworkAccessKey = Secret.fromString(leapworkAccessKey); this.leapworkDelay = leapworkDelay; + this.leapworkTimeout = leapworkTimeout; this.leapworkDoneStatusAs = leapworkDoneStatusAs; this.leapworkReport = leapworkReport; this.leapworkSchIds = leapworkSchIds; @@ -89,6 +91,11 @@ public void setLeapworkDelay(String leapworkDelay) { this.leapworkDelay = leapworkDelay; } + @DataBoundSetter + public void setLeapworkTimeout(String leapworkTimeout) { + this.leapworkTimeout = leapworkTimeout; + } + @DataBoundSetter public void setLeapworkWritePassedFlowKeyFrames(boolean leapworkWritePassedFlowKeyFrames) { this.leapworkWritePassedFlowKeyFrames = leapworkWritePassedFlowKeyFrames; @@ -120,6 +127,10 @@ public String getLeapworkDelay() { return leapworkDelay; } + public String getLeapworkTimeout() { + return leapworkTimeout; + } + public String getLeapworkSchNames() { return leapworkSchNames; } @@ -154,6 +165,8 @@ public void perform(final Run build, FilePath workspace, Launcher launcher EnvVars env = build.getEnvironment(listener); ArrayList invalidSchedules = new ArrayList<>(); + + int timeout = pluginHandler.getTimeout(leapworkTimeout, listener); String workspacePath = pluginHandler.getWorkSpaceSafe(workspace, env); this.leapworkReport = pluginHandler.getReportFileName(this.getLeapworkReport(), @@ -174,8 +187,8 @@ public void perform(final Run build, FilePath workspace, Launcher launcher .getScheduleVariablesRequestPart(getLeapworkScheduleVariables(), listener); AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder() - .setReadTimeout(TIMEOUT_IN_SECONDS * 1000) - .setRequestTimeout(TIMEOUT_IN_SECONDS * 1000) + .setReadTimeout(timeout * 1000) + .setRequestTimeout(timeout * 1000) .build(); try (AsyncHttpClient mainClient = new AsyncHttpClient(config)) { @@ -206,7 +219,7 @@ public void perform(final Run build, FilePath workspace, Launcher launcher if (runId != null) { resultsMap.put(runId, run); CollectScheduleRunResults(controllerApiHttpAddress, Secret.toString(leapworkAccessKey), runId, - schTitle, timeDelay, isDoneStatusAsSuccess, writePassedKeyframes, run, listener); + schTitle, timeDelay, timeout, isDoneStatusAsSuccess, writePassedKeyframes, run, listener); } else resultsMap.put(UUID.randomUUID(), run); @@ -288,12 +301,17 @@ public void perform(final Run build, FilePath workspace, Launcher launcher } private static void CollectScheduleRunResults(String controllerApiHttpAddress, String accessKey, UUID runId, - String scheduleName, int timeDelay, boolean isDoneStatusAsSuccess, boolean writePassedKeyframes, + String scheduleName, int timeDelay, int timeout, boolean isDoneStatusAsSuccess, boolean writePassedKeyframes, LeapworkRun resultRun, final TaskListener listener) throws AbortException, InterruptedException { List runItemsId = new ArrayList<>(); Object waiter = new Object(); + + AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder() + .setReadTimeout(timeout * 1000) + .setRequestTimeout(timeout * 1000) + .build(); // get statuses - try (AsyncHttpClient client = new AsyncHttpClient()) { + try (AsyncHttpClient client = new AsyncHttpClient(config)) { boolean isStillRunning = true; do { @@ -380,7 +398,7 @@ private static void CollectScheduleRunResults(String controllerApiHttpAddress, S String interruptedExceptionMessage = String.format(Messages.INTERRUPTED_EXCEPTION, e.getMessage()); listener.error(interruptedExceptionMessage); RunItem invalidItem = new RunItem("Aborted run", "Cancelled", 0, e.getMessage(), scheduleName); - pluginHandler.stopRun(controllerApiHttpAddress, runId, scheduleName, accessKey, listener); + pluginHandler.stopRun(controllerApiHttpAddress, runId, scheduleName, accessKey, timeout, listener); resultRun.incErrors(); resultRun.runItems.add(invalidItem); } finally { @@ -405,6 +423,7 @@ private void printPluginInputs(final TaskListener listener, String workspace) { listener.getLogger().println(String.format(Messages.INPUT_SCHEDULE_NAMES_VALUE, getLeapworkSchNames())); listener.getLogger().println(String.format(Messages.INPUT_SCHEDULE_IDS_VALUE, getLeapworkSchIds())); listener.getLogger().println(String.format(Messages.INPUT_DELAY_VALUE, getLeapworkDelay())); + listener.getLogger().println(String.format(Messages.INPUT_TIMEOUT_VALUE, getLeapworkTimeout())); listener.getLogger().println(String.format(Messages.INPUT_DONE_VALUE, getLeapworkDoneStatusAs())); listener.getLogger().println(String.format(Messages.INPUT_WRITE_PASSED, isLeapworkWritePassedFlowKeyFrames())); listener.getLogger().println(String.format(Messages.INPUT_VARIABLES, getLeapworkScheduleVariables())); @@ -435,6 +454,7 @@ public boolean isApplicable(Class aClass) { } public static final String DEFAULT_DELAY = "5"; + public static final String DEFAULT_TIMEOUT = "300"; public static final String DEFAULT_REPORT_NAME = "report.xml"; public static final boolean DEFAULT_WRITE_PASSED_FLOW_KEYFRAMES = false; public static final boolean DEFAULT_ENABLE_lEAPWORK_HTTPS = false; @@ -453,10 +473,28 @@ public FormValidation doCheckLeapworkDelay(@QueryParameter("leapworkDelay") Stri return FormValidation.ok(); } + public FormValidation doCheckLeapworkTimeout(@QueryParameter("leapworkTimeout") String timeout) { + int temp; + try { + temp = Integer.parseInt(timeout); + + if (temp < 1) { + return FormValidation.error("Entered number must be higher than 0"); + } + } catch (NumberFormatException ex) { + return FormValidation.error("Invalid number"); + } + return FormValidation.ok(); + } + public String getDefaultLeapworkDelay() { return DEFAULT_DELAY; } + public String getDefaultLeapworkTimeout() { + return DEFAULT_TIMEOUT; + } + public String getDefaultLeapworkReport() { return DEFAULT_REPORT_NAME; } diff --git a/src/main/java/com/Leapwork/Leapwork_plugin/Messages.java b/src/main/java/com/Leapwork/Leapwork_plugin/Messages.java index 0c2e16e..551f4d1 100644 --- a/src/main/java/com/Leapwork/Leapwork_plugin/Messages.java +++ b/src/main/java/com/Leapwork/Leapwork_plugin/Messages.java @@ -75,6 +75,7 @@ public class Messages { public static final String NO_DISK_SPACE = "No enough disk space to start schedule"; public static final String PORT_NUMBER_IS_INVALID = "Port number is invalid, setting to default %1$d"; public static final String TIME_DELAY_NUMBER_IS_INVALID = "Time delay number is invalid: %1$s, setting to default %2$s"; + public static final String TIMEOUT_NUMBER_IS_INVALID = "Timeout number is invalid: %1$s, setting to default %2$s"; public static final String FULL_REPORT_FILE_PATH = "Creating report file by path: %1$s"; public static final String SCHEDULE_DISABLED = "Schedule %1$s[%2$s] is disabled"; public static final String INVALID_SCHEDULE_VARIABLE = "Failed to parse variable: %1$s"; @@ -90,6 +91,7 @@ public class Messages { public static final String INPUT_SCHEDULE_NAMES_VALUE = "Schedule names: %1$s"; public static final String INPUT_SCHEDULE_IDS_VALUE = "Schedule ids: %1$s"; public static final String INPUT_DELAY_VALUE = "Delay between status checks: %1$s"; + public static final String INPUT_TIMEOUT_VALUE = "Leapwork API Request/Response Timeout: %1$s"; public static final String INPUT_DONE_VALUE = "Done Status As: %1$s"; public static final String INPUT_WRITE_PASSED = "Write keyframes of passed flows: %1$b"; public static final String INPUT_VARIABLES = "Passed schedule variables: %1$s"; diff --git a/src/main/java/com/Leapwork/Leapwork_plugin/PluginHandler.java b/src/main/java/com/Leapwork/Leapwork_plugin/PluginHandler.java index b46362c..95575f1 100644 --- a/src/main/java/com/Leapwork/Leapwork_plugin/PluginHandler.java +++ b/src/main/java/com/Leapwork/Leapwork_plugin/PluginHandler.java @@ -28,6 +28,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.ning.http.client.AsyncHttpClient; +import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -125,6 +126,23 @@ public int getTimeDelay(String rawTimeDelay, TaskListener listener) { } } + public int getTimeout(String rawTimeout, TaskListener listener) { + int defaultTimeout = 300; + try { + if (!rawTimeout.isEmpty() || !"".equals(rawTimeout)) + return Integer.parseInt(rawTimeout); + else { + listener.getLogger() + .println(String.format(Messages.TIMEOUT_NUMBER_IS_INVALID, rawTimeout, defaultTimeout)); + return defaultTimeout; + } + } catch (Exception e) { + listener.getLogger() + .println(String.format(Messages.TIMEOUT_NUMBER_IS_INVALID, rawTimeout, defaultTimeout)); + return defaultTimeout; + } + } + public boolean isDoneStatusAsSuccess(String doneStatusAs) { return doneStatusAs.contentEquals("Success"); } @@ -388,13 +406,19 @@ private static UUID OnScheduleRunConnectionFailure(Exception e, TaskListener lis } @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION") - public boolean stopRun(String controllerApiHttpAddress, UUID runId, String scheduleTitle, String accessKey, + public boolean stopRun(String controllerApiHttpAddress, UUID runId, String scheduleTitle, String accessKey, int timeout, final TaskListener listener) { boolean isSuccessfullyStopped = false; listener.error(String.format(Messages.STOPPING_RUN, scheduleTitle, runId)); String uri = String.format(Messages.STOP_RUN_URI, controllerApiHttpAddress, runId.toString()); - try (AsyncHttpClient client = new AsyncHttpClient()) { + + AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder() + .setReadTimeout(timeout * 1000) + .setRequestTimeout(timeout * 1000) + .build(); + + try (AsyncHttpClient client = new AsyncHttpClient(config)) { Response response = client.preparePut(uri).setBody("").setHeader("AccessKey", accessKey).execute().get(); client.close(); diff --git a/src/main/java/com/Leapwork/Leapwork_plugin/model/RunCollection.java b/src/main/java/com/Leapwork/Leapwork_plugin/model/RunCollection.java index 6d62907..0e025c7 100644 --- a/src/main/java/com/Leapwork/Leapwork_plugin/model/RunCollection.java +++ b/src/main/java/com/Leapwork/Leapwork_plugin/model/RunCollection.java @@ -11,8 +11,8 @@ @XmlRootElement(name = "testsuites") @XmlAccessorType(XmlAccessType.NONE) public final class RunCollection { - - public int totalTests = 0; + + private int totalTests = 0; private int passedTests = 0; diff --git a/src/main/resources/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder/config.jelly b/src/main/resources/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder/config.jelly index 7e22a4f..ebcaeaa 100644 --- a/src/main/resources/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder/config.jelly +++ b/src/main/resources/com/Leapwork/Leapwork_plugin/LeapworkJenkinsBridgeBuilder/config.jelly @@ -1,5 +1,6 @@ +