diff --git a/Jenkinsfile b/Jenkinsfile
index 71142c6..338fc9b 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -2,6 +2,6 @@
def configurations = [
[ platform: 'linux', jdk: '8' ],
- [ platform: 'linux', jdk: '11', jenkins: '2.332.2' ],
+ [ platform: 'linux', jdk: '11', jenkins: '2.361' ],
]
buildPlugin(configurations: configurations)
diff --git a/README.adoc b/README.adoc
index 97237ee..62ee832 100644
--- a/README.adoc
+++ b/README.adoc
@@ -45,7 +45,7 @@ horreumUpload (
----
-You can access the response status code and content within a groovy script:
+You can access the response within a groovy script:
[source,groovy]
----
@@ -60,17 +60,18 @@ def response = horreumUpload (
abortOnfailure: false,
quiet: false
)
-println("Status: "+response.status)
-println("Content: "+response.content)
+println("Response: "+response)
----
-== Building
+The created Run ID by Horreum is provided in the response.
-The plugin can be built and tested locally using a Maven HPI:
+== Building and Testing
+
+The plugin can be built and tested using Maven and JUnit:
[source, bash]
----
-mvn hpi:run
+mvn test
----
== Configure Global Settings
diff --git a/pom.xml b/pom.xml
index 8dc9ea6..c6fdb45 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@ THE SOFTWARE.
org.jenkins-ci.plugins
plugin
- 4.40
+ 4.52
io.jenkins.plugins
@@ -61,16 +61,27 @@ THE SOFTWARE.
HEAD
jenkinsci/horreum-plugin
- 2.332.3
+ 2.361
+ 3.37
1C
- 2.14.1
+ 2.17.2
1.25
1.17.6
5.9.1
- 0.7
+ 0.15.1
+ 25.0.2
+ 17
+ quay.io/keycloak/keycloak:${keycloak.version}
+ quay.io/hyperfoil/horreum:${horreum.version}
+ apache/activemq-artemis:2.32.0
+ postgres:16
+
+ jenkins-releases
+ https://repo.jenkins-ci.org/releases/
+
repo.jenkins-ci.org
https://repo.jenkins-ci.org/public/
@@ -96,6 +107,13 @@ THE SOFTWARE.
1
true
+
+ ${dev.images.keycloak}
+ ${dev.images.postgres}
+ ${dev.images.amqp}
+ ${dev.images.horreum}
+ quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-11
+
@@ -119,6 +137,9 @@ THE SOFTWARE.
org.jenkins-ci.tools
maven-hpi-plugin
true
+
+ true
+
org.codehaus.mojo
@@ -130,143 +151,54 @@ THE SOFTWARE.
-
-
-
- io.jenkins.tools.bom
- bom-2.332.x
- 1422.v0773c659e58f
- import
- pom
-
-
- io.netty
- netty-bom
- 4.1.77.Final
- pom
- import
-
-
- commons-io
- commons-io
- 2.11.0
-
-
- org.slf4j
- slf4j-api
- 1.7.36
-
-
- io.smallrye.config
- smallrye-config
- 2.10.0
-
-
- org.jboss.logging
- jboss-logging
-
-
-
-
- io.smallrye.common
- smallrye-common-annotation
- 1.11.0
-
-
- org.eclipse.microprofile.config
- microprofile-config-api
- 2.0.1
-
-
- org.eclipse.microprofile.context-propagation
- microprofile-context-propagation-api
- 1.3
-
-
- io.vertx
- vertx-core
- 4.2.7
-
-
- org.apache.commons
- commons-compress
- 1.22
-
-
- org.apache.httpcomponents
- httpclient
- 4.5.13
-
-
- org.apache.httpcomponents
- httpasyncclient
- 4.1.5
-
-
- org.apache.httpcomponents
- httpcore
- 4.4.15
-
-
- org.apache.httpcomponents
- httpcore-nio
- 4.4.15
-
-
- org.jboss.logging
- jboss-logging
- 3.4.3.Final
-
-
- org.apache.logging.log4j
- log4j-api
- 2.17.1
-
-
-
-
io.hyperfoil.tools
horreum-client
${horreum.version}
-
-
- org.slf4j
- slf4j-api
-
-
- org.jboss.logging
- jboss-logging
-
-
- com.fasterxml.jackson.core
- jackson-core
-
com.fasterxml.jackson.core
jackson-databind
-
- io.smallrye.config
- smallrye-config
-
-
- io.smallrye.common
- smallrye-common-annotation
-
org.eclipse.microprofile.config
microprofile-config-api
- org.eclipse.microprofile.context-propagation
- microprofile-context-propagation-api
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+
+ org.apache.maven.wagon
+ wagon-http-shared
+ 3.5.3
+
+
+
+ org.jenkins-ci.plugins
+ credentials
+ 1087.1089.v2f1b_9a_b_040e4
+
+
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-step-api
+ 639.v6eca_cd8c04a_a_
+
+
+
+ org.keycloak
+ keycloak-core
+ ${keycloak.version}
+
- io.vertx
- vertx-core
+ com.fasterxml.jackson.core
+ jackson-databind
@@ -278,103 +210,112 @@ THE SOFTWARE.
- com.fasterxml.jackson.core
- jackson-annotations
- ${jackson.version}
+ org.apache.commons
+ commons-compress
+ 1.26.0
- com.fasterxml.jackson.core
- jackson-databind
- ${jackson.version}
+ org.kohsuke.stapler
+ stapler
+ 1711.1713.vc400cfb_5597a_
- com.github.fge
- jackson-coreutils
- 1.8
+ javax.annotation
+ javax.annotation-api
+ 1.3.2
- org.apache.commons
- commons-compress
+ org.jenkins-ci.main
+ jenkins-core
+ ${jenkins.version}
- org.jenkins-ci.plugins
- credentials
+ org.jenkins-ci.plugins.workflow
+ workflow-job
+ 1239.v71b_b_a_124a_725
+
org.jenkins-ci.plugins
- plain-credentials
+ credentials
+ 1087.1089.v2f1b_9a_b_040e4
+
org.jenkins-ci.plugins.workflow
workflow-step-api
- true
+ 639.v6eca_cd8c04a_a_
-
- io.hyperfoil.tools
- horreum-integration
- ${horreum.version}
- test
+ javax.ws.rs
+ javax.ws.rs-api
+ 2.1.1
+
+
+
+ commons-io
+ commons-io
+ 2.15.1
+
io.hyperfoil.tools
- horreum-integration
+ horreum-api
${horreum.version}
- test-jar
- test
- org.jenkins-ci.plugins.workflow
- workflow-step-api
- tests
+ io.hyperfoil.tools
+ horreum-infra-common
+ ${horreum.version}
test
- org.jenkins-ci.plugins.workflow
- workflow-basic-steps
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.jupiter.version}
+ test
- org.jenkins-ci.plugins.workflow
- workflow-cps
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
test
org.jenkins-ci.plugins.workflow
- workflow-durable-task-step
+ workflow-basic-steps
+ 994.vd57e3ca_46d24
+ test
org.jenkins-ci.plugins.workflow
- workflow-job
+ workflow-cps
+ 3536.vb_8a_6628079d5
test
- org.jboss.logging
- jboss-logging
-
-
-
- org.junit.jupiter
- junit-jupiter-engine
- ${junit.jupiter.version}
+ org.postgresql
+ postgresql
+ 42.5.4
test
- org.testcontainers
- testcontainers
- ${testcontainers.version}
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ 2.19.0
test
@@ -390,5 +331,10 @@ THE SOFTWARE.
Radim Vansa
rvansa@redhat.com
+
+ jwhiting
+ Jeremy Whiting
+ jwhiting@redhat.com
+
diff --git a/src/main/java/jenkins/plugins/horreum/BaseExecutionContext.java b/src/main/java/jenkins/plugins/horreum/BaseExecutionContext.java
index 956dc42..495ee39 100644
--- a/src/main/java/jenkins/plugins/horreum/BaseExecutionContext.java
+++ b/src/main/java/jenkins/plugins/horreum/BaseExecutionContext.java
@@ -47,11 +47,9 @@ public BaseExecutionContext(String url, String credentials, PrintStream logger)
this.remoteLogger = new RemoteOutputStream(new CloseProofOutputStream(logger));
this.localLogger = logger;
- //Retrieve Credentials
- //TODO:: pass in DomainRequirement
List credentialsList = CredentialsProvider.lookupCredentials(
- StandardCredentials.class, // (1)
- Jenkins.get(), // (1)
+ StandardCredentials.class,
+ Jenkins.get(),
ACL.SYSTEM,
Collections.emptyList()
) ;
@@ -143,9 +141,6 @@ private static ByteArrayOutputStream toByteArrayOutputStream(InputStream stream)
protected HorreumClient createClient() {
HorreumClient.Builder clientBuilder = new HorreumClient.Builder()
.horreumUrl(url)
- .keycloakUrl(keycloak.getBaseUrl())
- .keycloakRealm(keycloak.getRealm())
- .clientId(keycloak.getClientId())
.horreumUser(usernameCredentials.getUsername())
.horreumPassword(usernameCredentials.getPassword().getPlainText());
return clientBuilder.build();
diff --git a/src/main/java/jenkins/plugins/horreum/auth/KeycloakAuthentication.java b/src/main/java/jenkins/plugins/horreum/auth/KeycloakAuthentication.java
index d3f5897..fc20f92 100644
--- a/src/main/java/jenkins/plugins/horreum/auth/KeycloakAuthentication.java
+++ b/src/main/java/jenkins/plugins/horreum/auth/KeycloakAuthentication.java
@@ -1,18 +1,10 @@
package jenkins.plugins.horreum.auth;
import java.io.Serializable;
-import java.util.List;
-
-import com.cloudbees.plugins.credentials.CredentialsMatchers;
-import com.cloudbees.plugins.credentials.CredentialsProvider;
-import com.cloudbees.plugins.credentials.common.StandardCredentials;
-import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
-import hudson.security.ACL;
-import jenkins.model.Jenkins;
public class KeycloakAuthentication extends AbstractDescribableImpl implements Serializable {
diff --git a/src/main/java/jenkins/plugins/horreum/upload/HorreumUploadExecutionContext.java b/src/main/java/jenkins/plugins/horreum/upload/HorreumUploadExecutionContext.java
index 302c11a..510d388 100644
--- a/src/main/java/jenkins/plugins/horreum/upload/HorreumUploadExecutionContext.java
+++ b/src/main/java/jenkins/plugins/horreum/upload/HorreumUploadExecutionContext.java
@@ -13,7 +13,6 @@
import java.util.function.Supplier;
import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -25,7 +24,8 @@
import hudson.model.Run;
import hudson.model.TaskListener;
import io.hyperfoil.tools.HorreumClient;
-import io.hyperfoil.tools.horreum.entity.json.Access;
+import io.hyperfoil.tools.horreum.api.data.Access;
+import jakarta.ws.rs.core.Response;
import jenkins.model.Jenkins;
import jenkins.plugins.horreum.BaseExecutionContext;
import jenkins.plugins.horreum.HorreumGlobalConfig;
diff --git a/src/test/java/jenkins/plugins/horreum/HorreumExpectStepTest.java b/src/test/java/jenkins/plugins/horreum/HorreumExpectStepTest.java
index a9c59fa..68de42f 100644
--- a/src/test/java/jenkins/plugins/horreum/HorreumExpectStepTest.java
+++ b/src/test/java/jenkins/plugins/horreum/HorreumExpectStepTest.java
@@ -1,41 +1,42 @@
package jenkins.plugins.horreum;
-import static io.hyperfoil.tools.HorreumTestClientExtension.dummyTest;
-import static io.hyperfoil.tools.HorreumTestClientExtension.horreumClient;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static jenkins.plugins.horreum.junit.HorreumTestExtension.*;
+import static jenkins.plugins.horreum.junit.HorreumTestClientExtension.getHorreumClient;
import java.util.List;
import java.util.stream.Collectors;
+import io.hyperfoil.tools.horreum.api.alerting.RunExpectation;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.jupiter.api.Test;
-
-import io.hyperfoil.tools.horreum.entity.alerting.RunExpectation;
+import org.junit.jupiter.api.TestInfo;
public class HorreumExpectStepTest extends HorreumPluginTestBase {
@Test
- public void testExpect() throws Exception {
+ public void testExpect(TestInfo info) throws Exception {
WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "Horreum-Expect-Pipeline");
+ io.hyperfoil.tools.horreum.api.data.Test dummyTest = createTest(info.getTestClass() + "-expect-step", "dev-team");
proj.setDefinition(new CpsFlowDefinition(
- "node {\n" +
- "horreumExpect(\n" +
- "credentials: '" + HorreumPluginTestBase.HORREUM_UPLOAD_CREDENTIALS + "',\n" +
- "test: '" + dummyTest.name + "',\n" +
- "timeout: 60,\n" +
- "expectedBy: 'Jenkins CI',\n" +
- "backlink: \"${env.BUILD_URL}\",\n" +
- ")\n" +
- "}\n",
- true));
+ "node {\n" +
+ "horreumExpect(\n" +
+ "credentials: '" + HORREUM_UPLOAD_CREDENTIALS + "',\n" +
+ "test: '" + dummyTest.name + "',\n" +
+ "timeout: 60,\n" +
+ "expectedBy: 'Jenkins CI',\n" +
+ "backlink: \"${env.BUILD_URL}\",\n" +
+ ")\n" +
+ "}\n",
+ true));
WorkflowRun run = proj.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(run);
- List expectations = horreumClient.alertingService.expectations();
+ List expectations = getHorreumClient().alertingService.expectations();
expectations = expectations.stream().filter(e -> e.testId == dummyTest.id).collect(Collectors.toList());
assertEquals(1, expectations.size());
RunExpectation runExpectation = expectations.get(0);
diff --git a/src/test/java/jenkins/plugins/horreum/HorreumExpectTest.java b/src/test/java/jenkins/plugins/horreum/HorreumExpectTest.java
index e571e1b..8c9d51a 100644
--- a/src/test/java/jenkins/plugins/horreum/HorreumExpectTest.java
+++ b/src/test/java/jenkins/plugins/horreum/HorreumExpectTest.java
@@ -1,36 +1,38 @@
package jenkins.plugins.horreum;
-import static io.hyperfoil.tools.HorreumTestClientExtension.dummyTest;
-import static io.hyperfoil.tools.HorreumTestClientExtension.horreumClient;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static jenkins.plugins.horreum.junit.HorreumTestExtension.*;
+import static jenkins.plugins.horreum.junit.HorreumTestClientExtension.getHorreumClient;
import java.util.List;
import java.util.stream.Collectors;
+import io.hyperfoil.tools.horreum.api.alerting.RunExpectation;
import org.junit.jupiter.api.Test;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
-import io.hyperfoil.tools.horreum.entity.alerting.RunExpectation;
import jenkins.plugins.horreum.expect.HorreumExpect;
+import org.junit.jupiter.api.TestInfo;
public class HorreumExpectTest extends HorreumPluginTestBase {
@Test
- public void testExpectRun() throws Exception {
+ public void testExpectRun(TestInfo info) throws Exception {
+ io.hyperfoil.tools.horreum.api.data.Test dummyTest = createTest(info.getTestClass() + "-expect", "dev-team");
HorreumExpect horreumExpect = new HorreumExpect(
- HORREUM_UPLOAD_CREDENTIALS, dummyTest.name, 60, "Jenkins CI", "$BUILD_URL"
+ HORREUM_UPLOAD_CREDENTIALS, dummyTest.name, 60L, "Jenkins CI", "$BUILD_URL"
);
// Run build
- FreeStyleProject project = this.j.createFreeStyleProject("Horreum-Expect-Freestyle");
+ FreeStyleProject project = j.createFreeStyleProject("Horreum-Expect-Freestyle");
project.getBuildersList().add(horreumExpect);
FreeStyleBuild build = project.scheduleBuild2(0).get();
// Check expectations
j.assertBuildStatusSuccess(build);
- List expectations = horreumClient.alertingService.expectations();
+ List expectations = getHorreumClient().alertingService.expectations();
expectations = expectations.stream().filter(e -> e.testId == dummyTest.id).collect(Collectors.toList());
assertEquals(1, expectations.size());
RunExpectation runExpectation = expectations.get(0);
diff --git a/src/test/java/jenkins/plugins/horreum/HorreumPluginTestBase.java b/src/test/java/jenkins/plugins/horreum/HorreumPluginTestBase.java
index 85c17cb..7b0de00 100644
--- a/src/test/java/jenkins/plugins/horreum/HorreumPluginTestBase.java
+++ b/src/test/java/jenkins/plugins/horreum/HorreumPluginTestBase.java
@@ -1,52 +1,25 @@
package jenkins.plugins.horreum;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.jupiter.api.BeforeEach;
+import io.hyperfoil.tools.horreum.api.data.Test;
+import jenkins.plugins.horreum.junit.HorreumTestClientExtension;
+import jenkins.plugins.horreum.junit.HorreumTestExtension;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-import com.cloudbees.plugins.credentials.Credentials;
-import com.cloudbees.plugins.credentials.CredentialsScope;
-import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
-import com.cloudbees.plugins.credentials.domains.Domain;
-import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
-import io.hyperfoil.tools.HorreumTestClientExtension;
-import io.hyperfoil.tools.HorreumTestExtension;
+import static jenkins.plugins.horreum.junit.HorreumTestClientExtension.getHorreumClient;
@ExtendWith(HorreumTestClientExtension.class)
public class HorreumPluginTestBase {
- public static final String HORREUM_UPLOAD_CREDENTIALS = "horreum-creds";
- @RegisterExtension
- public JenkinsExtension j = new JenkinsExtension();
- private Map> credentials;
-
- void registerBasicCredential(String id, String username, String password) {
- credentials.get(Domain.global()).add(
- new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL,
- id, "", username, password));
- SystemCredentialsProvider.getInstance().setDomainCredentialsMap(credentials);
+ Test createTest(String name, String owner) {
+ Test test = new Test();
+ test.name = name;
+ test.owner = owner;
+ return getHorreumClient().testService.add(test);
}
- @BeforeEach
- public void init() {
- credentials = new HashMap<>();
- credentials.put(Domain.global(), new ArrayList());
- this.registerBasicCredential(HORREUM_UPLOAD_CREDENTIALS, "user", "secret");
-
- HorreumGlobalConfig globalConfig = HorreumGlobalConfig.get();
- if (globalConfig != null) {
- globalConfig.setKeycloakRealm("horreum");
- globalConfig.setClientId("horreum-ui");
- globalConfig.setKeycloakBaseUrl(HorreumTestExtension.HORREUM_KEYCLOAK_BASE_URL);
- globalConfig.setBaseUrl(HorreumTestExtension.HORREUM_BASE_URL);
- } else {
- System.out.println("Can not find Horreum Global Config");
- }
+ @BeforeAll
+ public static void before() throws Exception {
+ HorreumTestExtension.beforeAll();
}
}
diff --git a/src/test/java/jenkins/plugins/horreum/HorreumUploadStepTest.java b/src/test/java/jenkins/plugins/horreum/HorreumUploadStepTest.java
index 277f294..cf4d4b9 100644
--- a/src/test/java/jenkins/plugins/horreum/HorreumUploadStepTest.java
+++ b/src/test/java/jenkins/plugins/horreum/HorreumUploadStepTest.java
@@ -1,84 +1,88 @@
package jenkins.plugins.horreum;
-import static io.hyperfoil.tools.HorreumTestClientExtension.dummyTest;
-import static io.hyperfoil.tools.HorreumTestClientExtension.horreumClient;
+import static jenkins.plugins.horreum.junit.HorreumTestExtension.*;
import static org.junit.jupiter.api.Assertions.*;
+import static jenkins.plugins.horreum.junit.HorreumTestClientExtension.getHorreumClient;
import java.net.URL;
-import java.util.Map;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import hudson.FilePath;
+import io.hyperfoil.tools.horreum.api.services.RunService;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.jupiter.api.Test;
-
-import io.hyperfoil.tools.horreum.api.RunService;
+import org.junit.jupiter.api.TestInfo;
public class HorreumUploadStepTest extends HorreumPluginTestBase {
@Test
public void testUpload() throws Exception {
URL jsonResource = Thread.currentThread().getContextClassLoader().getResource("data/config-quickstart.jvm.json");
- WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "Horreum-Upload-Pipeline");
+ WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "Horreum-Upload-Pipeline-testUpload");
+ io.hyperfoil.tools.horreum.api.data.Test dummyTest = createTest("upload-single", "dev-team");
proj.setDefinition(new CpsFlowDefinition(
- "node {\n" +
- "def id = horreumUpload(\n" +
- "credentials: '" + HorreumPluginTestBase.HORREUM_UPLOAD_CREDENTIALS + "',\n" +
- "test: '" + dummyTest.name + "',\n" +
- "owner: '" + dummyTest.owner + "',\n" +
- "access: 'PUBLIC',\n" +
- "start: '$.build-timestamp',\n" +
- "stop: '$.build-timestamp',\n" +
- "jsonFile: '" + jsonResource.getPath() + "',\n" +
- "addBuildInfo: true\n" +
- ")\n" +
- "println(id)\n" +
- "}\n",
- true));
+ "node {\n" +
+ "def id = horreumUpload(\n" +
+ "credentials: '" + HORREUM_UPLOAD_CREDENTIALS + "',\n" +
+ "test: '" + dummyTest.name + "',\n" +
+ "owner: '" + dummyTest.owner + "',\n" +
+ "access: 'PUBLIC',\n" +
+ "start: '$.build-timestamp',\n" +
+ "stop: '$.build-timestamp',\n" +
+ "jsonFile: '" + jsonResource.getPath() + "',\n" +
+ "addBuildInfo: true\n" +
+ ")\n" +
+ "println(id)\n" +
+ "}\n",
+ true));
WorkflowRun run = proj.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(run);
- RunService.RunsSummary summary = horreumClient.runService.listTestRuns(dummyTest.id, false, null, null, "", null);
+ RunService.RunsSummary summary = getHorreumClient().runService.listTestRuns(dummyTest.id, false, null, null, "", null);
assertEquals(1, summary.total);
assertEquals(1, summary.runs.size());
}
@Test
- public void testUploadMultiple() throws Exception {
+ public void testUploadMultiple(TestInfo info) throws Exception {
URL jsonResource1 = Thread.currentThread().getContextClassLoader().getResource("data/config-quickstart.jvm.json");
URL jsonResource2 = Thread.currentThread().getContextClassLoader().getResource("data/another-file.json");
- WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "Horreum-Upload-Pipeline");
+ assertNotNull(j);
+ assertNotNull(j.jenkins);
+ WorkflowJob proj = j.jenkins.createProject(WorkflowJob.class, "Horreum-Upload-Pipeline-testUploadMultiple");
FilePath folder = j.jenkins.getWorkspaceFor(proj).child("run");
folder.child("config-quickstart.jvm.json").copyFrom(jsonResource1);
folder.child("another-file.json").copyFrom(jsonResource2);
+ io.hyperfoil.tools.horreum.api.data.Test dummyTest = createTest(info.getTestClass() + "-upload-multiple", "dev-team");
proj.setDefinition(new CpsFlowDefinition(
- "node {\n" +
- "def id = horreumUpload(\n" +
- "credentials: '" + HorreumPluginTestBase.HORREUM_UPLOAD_CREDENTIALS + "',\n" +
- "test: '" + dummyTest.name + "',\n" +
- "owner: '" + dummyTest.owner + "',\n" +
- "access: 'PUBLIC',\n" +
- "start: '1970-01-01T00:00:00.00Z',\n" +
- "stop: '1970-01-01T00:00:01.00Z',\n" +
- "files: '**/*.json',\n"+
- "addBuildInfo: true\n" +
- ")\n" +
- "println(id)\n" +
- "}\n",
- true));
+ "node {\n" +
+ "def id = horreumUpload(\n" +
+ "credentials: '" + HORREUM_UPLOAD_CREDENTIALS + "',\n" +
+ "test: '" + dummyTest.name + "',\n" +
+ "owner: '" + dummyTest.owner + "',\n" +
+ "access: 'PUBLIC',\n" +
+ "start: '1970-01-01T00:00:00.00Z',\n" +
+ "stop: '1970-01-01T00:00:01.00Z',\n" +
+ "files: '**/*.json',\n"+
+ "addBuildInfo: true\n" +
+ ")\n" +
+ "println(id)\n" +
+ "}\n",
+ true));
WorkflowRun run = proj.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(run);
- RunService.RunsSummary summary = horreumClient.runService.listTestRuns(dummyTest.id, false, null, null, "", null);
+ RunService.RunsSummary summary = getHorreumClient().runService.listTestRuns(dummyTest.id, false, null, null, "", null);
assertEquals(1, summary.total);
assertEquals(1, summary.runs.size());
- Object runObject = horreumClient.runService.getRun(summary.runs.get(0).id,summary.runs.get(0).token);
+ RunService.RunExtended runObject = getHorreumClient().runService.getRun(summary.runs.get(0).id,summary.runs.get(0).token);
assertNotNull(runObject);
- assertTrue(runObject instanceof Map,"run should return a map");
- Object data = ((Map)runObject).get("data");
+ assertInstanceOf(RunService.RunExtended.class, runObject,"run should return a RunService.RunExtended");
+ Object data = runObject.data;
assertNotNull(data);
- assertTrue(data instanceof Map,"data should be a map");
- assertEquals(2,((Map, ?>) data).size(),"data should have an entry for each file");
+ assertInstanceOf(ObjectNode.class, data,"data should be a ObjectNode");
+ assertEquals(2,((ObjectNode) data).size(),"data should have an entry for each file");
}
}
diff --git a/src/test/java/jenkins/plugins/horreum/HorreumUploadTest.java b/src/test/java/jenkins/plugins/horreum/HorreumUploadTest.java
index d8669b3..4973f1c 100644
--- a/src/test/java/jenkins/plugins/horreum/HorreumUploadTest.java
+++ b/src/test/java/jenkins/plugins/horreum/HorreumUploadTest.java
@@ -1,7 +1,7 @@
package jenkins.plugins.horreum;
-import static io.hyperfoil.tools.HorreumTestClientExtension.dummyTest;
-import static io.hyperfoil.tools.HorreumTestClientExtension.horreumClient;
+import static jenkins.plugins.horreum.junit.HorreumTestExtension.*;
+import static jenkins.plugins.horreum.junit.HorreumTestClientExtension.getHorreumClient;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -10,89 +10,94 @@
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Arrays;
+import java.util.Objects;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
import org.jvnet.hudson.test.CreateFileBuilder;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.tasks.Builder;
-import io.hyperfoil.tools.horreum.api.RunService;
-import io.hyperfoil.tools.horreum.entity.json.Access;
-import io.hyperfoil.tools.horreum.entity.json.Schema;
+import io.hyperfoil.tools.horreum.api.services.RunService;
+import io.hyperfoil.tools.horreum.api.data.Access;
+import io.hyperfoil.tools.horreum.api.data.Schema;
import jenkins.plugins.horreum.upload.HorreumUpload;
public class HorreumUploadTest extends HorreumPluginTestBase {
@Test
- public void testUpload() throws Exception {
+ public void testUpload(TestInfo info) throws Exception {
URL jsonResource = Thread.currentThread().getContextClassLoader().getResource("data/config-quickstart.jvm.json");
+ io.hyperfoil.tools.horreum.api.data.Test dummyTest = createTest(info.getTestClass() + "-upload-single", "dev-team");
// Prepare HttpRequest#
HorreumUpload horreumUpload = new HorreumUpload(
- HORREUM_UPLOAD_CREDENTIALS,
- dummyTest.name,
- dummyTest.owner,
- "PUBLIC",
- "$.build-timestamp",
- "$.build-timestamp",
- "",
- jsonResource.getPath(),
- null,
- true
+ HORREUM_UPLOAD_CREDENTIALS,
+ dummyTest.name,
+ dummyTest.owner,
+ "PUBLIC",
+ "$.build-timestamp",
+ "$.build-timestamp",
+ "",
+ jsonResource.getPath(),
+ null,
+ true
);
- runInFreeStyleProject("Horreum-Upload-Freestyle", horreumUpload);
+ runInFreeStyleProject("Horreum-Upload-Freestyle", dummyTest, horreumUpload);
}
@Test
- public void testUploadMultiple() throws Exception {
+ public void testUploadMultiple(TestInfo info) throws Exception {
String json1 = readFile("data/config-quickstart.jvm.json");
String json2 = readFile("data/another-file.json");
+ io.hyperfoil.tools.horreum.api.data.Test dummyTest = createTest(info.getTestClass() + "-upload-multiple", "dev-team");
- addSchema("Some schema", "urn:some-schema");
- addSchema("Foobar", "urn:foobar");
+ addSchema("Some schema", "urn:some-schema", dummyTest);
+ addSchema("Foobar", "urn:foobar", dummyTest);
// Prepare HttpRequest#
HorreumUpload horreumUpload = new HorreumUpload(
- HORREUM_UPLOAD_CREDENTIALS,
- dummyTest.name,
- dummyTest.owner,
- "PUBLIC",
- "2022-12-07T01:23:45Z", // cannot use JSONPath with multiple files...
- "2022-12-07T01:23:45Z",
- "urn:some-schema",
- null,
- "**/*.json",
- true
+ HORREUM_UPLOAD_CREDENTIALS,
+ dummyTest.name,
+ dummyTest.owner,
+ "PUBLIC",
+ "2022-12-07T01:23:45Z", // cannot use JSONPath with multiple files...
+ "2022-12-07T01:23:45Z",
+ "urn:some-schema",
+ null,
+ "**/*.json",
+ true
);
- RunService.RunSummary summary = runInFreeStyleProject("Horreum-Upload-Multiple",
- new CreateFileBuilder("file1.json", json1),
- new CreateFileBuilder("file2.json", json2),
- horreumUpload);
+ RunService.RunSummary summary = runInFreeStyleProject("Horreum-Upload-Multiple", dummyTest,
+ new CreateFileBuilder("file1.json", json1),
+ new CreateFileBuilder("file2.json", json2),
+ horreumUpload);
assertEquals(2, summary.schemas.size());
}
- private void addSchema(String name, String uri) {
+
+ private void addSchema(String name, String uri, io.hyperfoil.tools.horreum.api.data.Test dummyTest) {
Schema schema = new Schema();
schema.name = name;
schema.uri = uri;
schema.owner = dummyTest.owner;
schema.access = Access.PUBLIC;
- horreumClient.schemaService.add(schema);
+ getHorreumClient().schemaService.add(schema);
}
private String readFile(String filename) throws IOException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(cl.getResourceAsStream(filename)))) {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(cl.getResourceAsStream(filename))))) {
return reader.lines().collect(Collectors.joining("\n"));
}
}
- private RunService.RunSummary runInFreeStyleProject(String name, Builder... builders) throws Exception {
+ private RunService.RunSummary runInFreeStyleProject(String name, io.hyperfoil.tools.horreum.api.data.Test dummyTest, Builder... builders) throws Exception {
// Run build
- FreeStyleProject project = this.j.createFreeStyleProject(name);
+ FreeStyleProject project = j.createFreeStyleProject(name);
assertTrue(builders.length > 0);
assertTrue(Arrays.stream(builders).anyMatch(b -> b instanceof HorreumUpload));
project.getBuildersList().addAll(Arrays.asList(builders));
@@ -101,7 +106,7 @@ private RunService.RunSummary runInFreeStyleProject(String name, Builder... buil
// Check expectations
j.assertBuildStatusSuccess(build);
- RunService.RunsSummary summary = horreumClient.runService.listTestRuns(dummyTest.id, false, null, null, "", null);
+ RunService.RunsSummary summary = getHorreumClient().runService.listTestRuns(dummyTest.id, false, null, null, "", null);
assertEquals(1, summary.total);
assertEquals(1, summary.runs.size());
return summary.runs.get(0);
diff --git a/src/test/java/jenkins/plugins/horreum/JenkinsExtension.java b/src/test/java/jenkins/plugins/horreum/JenkinsExtension.java
index c0a3c79..9fc3a14 100644
--- a/src/test/java/jenkins/plugins/horreum/JenkinsExtension.java
+++ b/src/test/java/jenkins/plugins/horreum/JenkinsExtension.java
@@ -9,6 +9,7 @@
// Copied from https://issues.jenkins.io/browse/JENKINS-48466
public class JenkinsExtension extends org.jvnet.hudson.test.JenkinsRule implements BeforeEachCallback, AfterEachCallback {
+
@Override
public void beforeEach(ExtensionContext context) throws Exception {
this.testDescription = Description.createTestDescription(
diff --git a/src/test/java/jenkins/plugins/horreum/it/JenkinsResources.java b/src/test/java/jenkins/plugins/horreum/it/JenkinsResources.java
new file mode 100644
index 0000000..e44c3be
--- /dev/null
+++ b/src/test/java/jenkins/plugins/horreum/it/JenkinsResources.java
@@ -0,0 +1,49 @@
+package jenkins.plugins.horreum.it;
+
+import io.hyperfoil.tools.horreum.infra.common.HorreumResources;
+import io.hyperfoil.tools.horreum.infra.common.resources.ArtemisMQResource;
+import io.hyperfoil.tools.horreum.infra.common.resources.HorreumResource;
+import org.testcontainers.containers.Network;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class JenkinsResources extends HorreumResources {
+ public static ArtemisMQResource amqpResource = new ArtemisMQResource();
+ public static HorreumResource horreumResource = new HorreumResource();
+
+ public static Map startAMQPContainer(Map initArgs) {
+ Map envVariables = new HashMap<>(initArgs);
+ Optional optionalNetwork= Optional.of(HorreumResources.getNetwork());
+
+ amqpResource.init(envVariables);
+ envVariables.putAll(amqpResource.start(optionalNetwork));
+ return envVariables;
+ }
+
+
+ public static Map startHorreumContainer(Map initArgs) {
+ Map envVariables = new HashMap<>(initArgs);
+ Optional optionalNetwork= Optional.of(HorreumResources.getNetwork());
+ horreumResource.init(envVariables);
+ envVariables.putAll(horreumResource.start(optionalNetwork));
+ return envVariables;
+ }
+
+ public static void stopContainers() {
+ stopAMQPContainer();
+ stopHorreumContainer();
+ }
+
+ public static void stopAMQPContainer() {
+ if (amqpResource != null) {
+ amqpResource.stop();
+ }
+ }
+ public static void stopHorreumContainer() {
+ if (horreumResource != null) {
+ horreumResource.stop();
+ }
+ }
+}
diff --git a/src/test/java/jenkins/plugins/horreum/junit/HorreumTestClientExtension.java b/src/test/java/jenkins/plugins/horreum/junit/HorreumTestClientExtension.java
new file mode 100644
index 0000000..f9f9a6d
--- /dev/null
+++ b/src/test/java/jenkins/plugins/horreum/junit/HorreumTestClientExtension.java
@@ -0,0 +1,33 @@
+package jenkins.plugins.horreum.junit;
+
+import io.hyperfoil.tools.HorreumClient;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+public class HorreumTestClientExtension extends HorreumTestExtension implements BeforeAllCallback {
+ private static HorreumClient horreumClient;
+
+ public static void instantiateClient() {
+ if (horreumClient == null) {
+ String horreumUrl = "http://".concat(horreumHost).concat(":").concat(horreumPort).concat("/");
+ horreumClient = new HorreumClient.Builder()
+ .horreumUrl(horreumUrl)
+ .horreumUser("horreum.bootstrap")
+ .horreumPassword("secret")
+ .build();
+ Assertions.assertNotNull(horreumClient);
+ }
+ }
+
+ public static HorreumClient getHorreumClient() {
+ if (horreumClient == null) {
+ instantiateClient();
+ }
+ return horreumClient;
+ }
+
+ @Override
+ public void beforeAll(ExtensionContext extensionContext) {
+ }
+}
diff --git a/src/test/java/jenkins/plugins/horreum/junit/HorreumTestExtension.java b/src/test/java/jenkins/plugins/horreum/junit/HorreumTestExtension.java
new file mode 100644
index 0000000..b571bfd
--- /dev/null
+++ b/src/test/java/jenkins/plugins/horreum/junit/HorreumTestExtension.java
@@ -0,0 +1,138 @@
+package jenkins.plugins.horreum.junit;
+
+import com.cloudbees.plugins.credentials.Credentials;
+import com.cloudbees.plugins.credentials.CredentialsScope;
+import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
+import com.cloudbees.plugins.credentials.domains.Domain;
+import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
+import io.hyperfoil.tools.horreum.api.services.ConfigService;
+import io.hyperfoil.tools.horreum.infra.common.SelfSignedCert;
+import jenkins.plugins.horreum.HorreumGlobalConfig;
+import jenkins.plugins.horreum.JenkinsExtension;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.extension.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static io.hyperfoil.tools.horreum.infra.common.Const.*;
+import static io.hyperfoil.tools.horreum.infra.common.HorreumResources.startContainers;
+import static java.lang.System.getProperty;
+import static jenkins.plugins.horreum.it.JenkinsResources.*;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class HorreumTestExtension {
+
+ private static final Logger log = Logger.getLogger(HorreumTestExtension.class);
+ private static boolean started = false;
+ public static String horreumHost;
+ public static String horreumPort = "8080";
+ private static final Map> credentials = new HashMap<>();
+ public static final String HORREUM_UPLOAD_CREDENTIALS = "horreum-creds";
+ public static final String DEFAULT_BOOTSTRAP_USERNAME = "horreum.bootstrap";
+ public static final String DEFAULT_BOOTSTRAP_PASSWORD = "secret";
+
+ @RegisterExtension
+ public static JenkinsExtension j = new JenkinsExtension();
+
+ public static void beforeAll() throws Exception {
+ synchronized (HorreumTestExtension.class) {
+ if (!started) {
+ log.info("Starting Jenkins IT resources");
+
+ try {
+ String keycloakImage = getProperty(HORREUM_DEV_KEYCLOAK_IMAGE);
+ String postgresImage = getProperty(HORREUM_DEV_POSTGRES_IMAGE);
+ String amqpImage = getProperty(HORREUM_DEV_AMQP_IMAGE);
+ String horreumImage = getProperty(HORREUM_DEV_HORREUM_HORREUM_IMAGE);
+
+ if ( keycloakImage == null || postgresImage == null || amqpImage == null || horreumImage == null){
+ throw new RuntimeException("Test container images are not defined as system properties");
+ }
+
+ SelfSignedCert postgresSelfSignedCert = new SelfSignedCert("RSA", "SHA256withRSA", "localhost", 123);
+ Map containerArgs = new HashMap<>();
+ containerArgs.putAll(
+ Map.ofEntries(
+ Map.entry(HORREUM_DEV_KEYCLOAK_ENABLED, "true"),
+ Map.entry(HORREUM_DEV_KEYCLOAK_IMAGE, keycloakImage),
+ Map.entry(HORREUM_DEV_KEYCLOAK_NETWORK_ALIAS, DEFAULT_KEYCLOAK_NETWORK_ALIAS),
+ Map.entry(HORREUM_DEV_POSTGRES_ENABLED, "true"),
+ Map.entry(HORREUM_DEV_POSTGRES_IMAGE, postgresImage),
+ Map.entry(HORREUM_DEV_POSTGRES_NETWORK_ALIAS, DEFAULT_POSTGRES_NETWORK_ALIAS),
+ Map.entry(HORREUM_DEV_POSTGRES_SSL_CERTIFICATE, postgresSelfSignedCert.getCertString()),
+ Map.entry(HORREUM_DEV_POSTGRES_SSL_CERTIFICATE_KEY, postgresSelfSignedCert.getKeyString()),
+ Map.entry(HORREUM_DEV_KEYCLOAK_DB_USERNAME, DEFAULT_KC_DB_USERNAME),
+ Map.entry(HORREUM_DEV_KEYCLOAK_DB_PASSWORD, DEFAULT_KC_DB_PASSWORD),
+ Map.entry(HORREUM_DEV_KEYCLOAK_ADMIN_USERNAME, DEFAULT_KC_ADMIN_USERNAME),
+ Map.entry(HORREUM_DEV_KEYCLOAK_ADMIN_PASSWORD, DEFAULT_KC_ADMIN_PASSWORD),
+ Map.entry(HORREUM_DEV_HORREUM_HORREUM_IMAGE, horreumImage),
+ Map.entry("horreum.roles.provider", "database"),
+ Map.entry("quarkus.keycloak.admin-client.client-id", "horreum-client"),
+ Map.entry("quarkus.keycloak.admin-client.realm", "horreum"),
+ Map.entry("quarkus.keycloak.admin-client.client-secret", "secret"),
+ Map.entry("quarkus.keycloak.admin-client.grant-type", "client_credentials"),
+ Map.entry("keycloak.use.https", "false"),
+ Map.entry("keycloak.service.client", "horreum-client"),
+ Map.entry("keycloak.realm", "horreum"),
+ Map.entry("keycloak.token.admin-roles", "admin,manager,tester,viewer,uploader"),
+ Map.entry(HORREUM_DEV_AMQP_ENABLED, "true"),
+ Map.entry(HORREUM_DEV_AMQP_IMAGE, amqpImage),
+ Map.entry(HORREUM_DEV_AMQP_NETWORK_ALIAS, DEFAULT_AMQP_NETWORK_ALIAS),
+ Map.entry("amqp-username", DEFAULT_AMQP_USERNAME),
+ Map.entry("amqp-password", DEFAULT_AMQP_PASSWORD),
+ Map.entry("inContainer", "true"),
+ Map.entry("quarkus.http.host", DEFAULT_HORREUM_NETWORK_ALIAS),
+ Map.entry("quarkus.http.port", "8080"),
+ Map.entry("quarkus.profile", "dev"),
+ Map.entry(HORREUM_DEV_HORREUM_NETWORK_ALIAS, DEFAULT_HORREUM_NETWORK_ALIAS)
+ ));
+ containerArgs.putAll(startContainers(containerArgs));
+ containerArgs.putAll(startAMQPContainer(containerArgs));
+ containerArgs.putAll(startHorreumContainer(containerArgs));
+ try {
+ j.before();
+ started = true;
+ } catch (Throwable e){
+ log.fatal("Could not start Jenkins service", e);
+ throw new Exception(e);
+ }
+ horreumHost = "localhost";
+ horreumPort = containerArgs.get("horreum.container.port");
+ } catch (Exception e){
+ log.fatal("Could not start services", e);
+ throw new RuntimeException("Could not start Jenkins/Horreum services", e);
+ }
+ try {
+ HorreumGlobalConfig globalConfig = HorreumGlobalConfig.get();
+ if (globalConfig != null) {
+ globalConfig.setKeycloakRealm("horreum");
+ globalConfig.setClientId("horreum-ui");
+ globalConfig.setKeycloakBaseUrl(ConfigService.KEYCLOAK_BOOTSTRAP_URL);
+ String baseUrl = String.format("http://%s:%s", horreumHost, horreumPort);
+ globalConfig.setBaseUrl(baseUrl);
+ } else {
+ System.out.println("Can not find Horreum Global Config");
+ }
+ credentials.put(Domain.global(), new ArrayList());
+ registerBasicCredential(HORREUM_UPLOAD_CREDENTIALS, DEFAULT_BOOTSTRAP_USERNAME, DEFAULT_BOOTSTRAP_PASSWORD);
+ } catch (Throwable throwable) {
+ log.fatal("Could not configure basic credentials re-configure Keycloak", throwable);
+ throw new RuntimeException(throwable);
+ }
+
+ }
+ }
+ }
+
+ static void registerBasicCredential(String id, String username, String password) {
+ credentials.get(Domain.global()).add(
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL,
+ id, "", username, password));
+ SystemCredentialsProvider scp = SystemCredentialsProvider.getInstance();
+ assertNotNull(scp);
+ scp.setDomainCredentialsMap(credentials);
+ }
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
new file mode 100644
index 0000000..41c39c0
--- /dev/null
+++ b/src/test/resources/application.properties
@@ -0,0 +1,3 @@
+horreum.username=horreum.bootstrap
+horreum.password=secret
+quarkus.datasource.password=secret
diff --git a/src/test/resources/env.properties b/src/test/resources/env.properties
new file mode 100644
index 0000000..e69de29
diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml
new file mode 100644
index 0000000..e69de29