diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3735e92..3d9483a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,17 @@ name: Build -on: [push, pull_request] +on: + # Trigger on push to develop or main branches + push: + branches: + - develop + - main + + # Trigger on pull request (any branch that creates a PR) + pull_request: + branches: + - develop + - main jobs: build: @@ -26,3 +37,14 @@ jobs: - name: Build run: mvn --batch-mode --update-snapshots install + + - name: Integration tests + run: mvn --batch-mode clean verify -pl it.tests -Pit + + # Save logs only if the job fails + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v3 + with: + name: failure-logs + path: it.tests/target/launchers/model/logs/* diff --git a/bundle/pom.xml b/bundle/pom.xml index d249c95..ae9ab31 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -31,7 +31,7 @@ diff --git a/it.tests/pom.xml b/it.tests/pom.xml new file mode 100644 index 0000000..405a245 --- /dev/null +++ b/it.tests/pom.xml @@ -0,0 +1,195 @@ + + + + 4.0.0 + + + be.orbinson.aem + aem-groovy-console + 19.0.9-SNAPSHOT + + + aem-groovy-console-it-tests + AEM Groovy Console - IT Tests + + + + + apache-snapshot + https://repository.apache.org/content/groups/snapshots + + + + + + + biz.aQute.bnd + bnd-maven-plugin + + + bnd-process + + bnd-process + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + + + + it + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + reserve-network-port + + reserve-network-port + + process-resources + + + http.port + + + + + + + org.apache.sling + slingfeature-maven-plugin + 1.8.4 + true + + + aggregate-features + + aggregate-features + + + + + + org.apache.sling + org.apache.sling.starter + oak_tar + slingosgifeature + 13-SNAPSHOT + + *.json + + + groovy.version + + + + + attach-features + + attach-features + + + + + org.apache.sling + feature-launcher-maven-plugin + 0.1.6 + + + + model + ${skipTests} + + ${project.groupId} + ${project.artifactId} + ${project.version} + slingosgifeature + + + + + ${http.port} + + + + + + + 180 + + + + + + + start + stop + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.3.1 + + + ${http.port} + ${project.build.directory}/../build.log + + + + + + integration-test + verify + + + + + + + + + + + + + org.junit.jupiter + junit-jupiter + 5.10.2 + test + + + org.awaitility + awaitility + 4.2.2 + test + + + org.apache.httpcomponents + httpclient + 4.5.14 + test + + + com.google.code.gson + gson + 2.11.0 + test + + + diff --git a/it.tests/src/main/features/groovy.json b/it.tests/src/main/features/groovy.json new file mode 100644 index 0000000..6ee2427 --- /dev/null +++ b/it.tests/src/main/features/groovy.json @@ -0,0 +1,8 @@ +{ + "bundles": [ + { + "id": "org.apache.groovy:groovy-dateutil:${groovy.version}", + "start-order": "20" + } + ] +} diff --git a/it.tests/src/main/features/groovyconsole-repoinit.txt b/it.tests/src/main/features/groovyconsole-repoinit.txt new file mode 100644 index 0000000..c9ad0a2 --- /dev/null +++ b/it.tests/src/main/features/groovyconsole-repoinit.txt @@ -0,0 +1,8 @@ +create path /conf/groovyconsole/replication(sling:Folder) +create path /var/groovyconsole/audit(sling:Folder) + +create service user aem-groovy-console-service with path system/aem-groovy-console +set ACL for aem-groovy-console-service + allow jcr:all on / + allow jcr:all on /var/groovyconsole/audit +end \ No newline at end of file diff --git a/it.tests/src/main/features/groovyconsole.json b/it.tests/src/main/features/groovyconsole.json new file mode 100644 index 0000000..5a9043b --- /dev/null +++ b/it.tests/src/main/features/groovyconsole.json @@ -0,0 +1,25 @@ + +{ + "bundles":[ + { + "id": "be.orbinson.aem:groovy-osgi:${project.version}", + "start-order": "19" + }, + { + "id":"be.orbinson.aem:aem-groovy-console-api:${project.version}", + "start-order":"20" + }, + { + "id":"be.orbinson.aem:aem-groovy-console-bundle:${project.version}", + "start-order":"20" + } + ], + "configurations": { + "org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~groovyconsole":{ + "user.mapping":[ + "aem-groovy-console-bundle=[aem-groovy-console-service]" + ] + } + }, + "repoinit:TEXT|true":"@file" +} \ No newline at end of file diff --git a/it.tests/src/test/java/be/orbinson/aem/groovy/console/it/GroovyConsoleServiceIT.java b/it.tests/src/test/java/be/orbinson/aem/groovy/console/it/GroovyConsoleServiceIT.java new file mode 100644 index 0000000..aca5d2e --- /dev/null +++ b/it.tests/src/test/java/be/orbinson/aem/groovy/console/it/GroovyConsoleServiceIT.java @@ -0,0 +1,92 @@ +package be.orbinson.aem.groovy.console.it; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import org.apache.commons.codec.binary.Base64; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.*; + +class GroovyConsoleServiceIT { + + private static final int SLING_PORT = Integer.getInteger("HTTP_PORT", 8080); + + @BeforeEach + void beforeEach() { + await().atMost(30, TimeUnit.SECONDS) // Set maximum wait time to 30 seconds + .pollInterval(5, TimeUnit.SECONDS) + .untilAsserted(() -> assertTrue(servicesAreAvailable())); + } + + @Test + void testScriptReturnsResult() throws Exception { + String script = "print 'test'"; + JsonObject response = executeScript(script); + System.out.println("Got response script at " + Instant.now()); + + assertNotNull(response, "Could not get response from API"); + assertEquals("test", response.get("output").getAsString()); + } + + private static boolean servicesAreAvailable() throws IOException { + System.out.println("Checking if services are available"); + try (CloseableHttpClient httpclient = HttpClients.createDefault()) { + HttpGet printHealth = new HttpGet("http://localhost:" + SLING_PORT + "/system/health.json?tags=systemalive,bundles"); + printHealth.addHeader("Authorization", "Basic " + Base64.encodeBase64String("admin:admin".getBytes(StandardCharsets.UTF_8))); + try (CloseableHttpResponse response = httpclient.execute(printHealth)) { + String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + JsonObject jsonResponse = JsonParser.parseString(body).getAsJsonObject(); + try { + boolean systemAlive = "OK".equals(jsonResponse.get("overallResult").getAsString()); + if (!systemAlive) { + System.out.println("Not alive yet:"); + System.out.println(body); + } + return systemAlive; + } catch (JsonSyntaxException e) { + return false; + } + } + } + } + + + private static JsonObject executeScript(String script) throws IOException { + try (CloseableHttpClient httpclient = HttpClients.createDefault()) { + HttpPost executeScript = new HttpPost("http://localhost:" + SLING_PORT + "/bin/groovyconsole/post"); + List basicNameValuePairs = new java.util.ArrayList<>(); + basicNameValuePairs.add(new BasicNameValuePair("script", script)); + executeScript.setEntity(new UrlEncodedFormEntity(basicNameValuePairs, StandardCharsets.UTF_8)); + executeScript.addHeader("Authorization", "Basic " + Base64.encodeBase64String("admin:admin".getBytes(StandardCharsets.UTF_8))); + + try (CloseableHttpResponse response = httpclient.execute(executeScript)) { + System.out.println(response.getStatusLine()); + + String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + try { + return JsonParser.parseString(body).getAsJsonObject(); + } catch (JsonSyntaxException e) { + System.out.println("Could not parse body from JSON: " + e.getMessage()); + return null; + } + } + } + } +} diff --git a/pom.xml b/pom.xml index 8667aff..099a43f 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ ui.apps.aem ui.config ui.content + it.tests https://github.com/orbinson/aem-groovy-console