From b310bed082980c041910fc800c8105bbb46dcbf4 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Sun, 30 Jul 2023 12:30:17 +0200 Subject: [PATCH] CI/CD: Add Mellium-based integration test to Github workflow This adds a very basic Mellium-based test to the Github CI workflow. Mellium defines 'proper' integration tests, but its framework for IT is a bit different than what we're used to. Were we typically start a server, and tell a framework to start testing against it, the Mellium framework has hooks where it starts clean servers on demand. Our existing scripts do no facilitate that. To get a ball rolling, this commit introduces a Mellium 'test' that uses an examplebot that's included with Mellium, and make it connect against a running Openfire instance. --- .../continuous-integration-workflow.yml | 51 +++++- runMelliumIntegrationTests | 151 ++++++++++++++++++ 2 files changed, 200 insertions(+), 2 deletions(-) create mode 100755 runMelliumIntegrationTests diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 423ffa7b35..cba49ea314 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -50,6 +50,7 @@ jobs: path: | runIntegrationTests runAioxmppIntegrationTests + runMelliumIntegrationTests runConnectivityIntegrationTests test.gradle - name: Upload coverage report for 'xmppserver' module @@ -179,11 +180,57 @@ jobs: - name: Run smack tests run: ./runIntegrationTests -d -l -i 127.0.0.1 + mellium: + + name: Execute Mellium-based CI tests + runs-on: ubuntu-latest + needs: build + + steps: + - name: Set JAVA_HOME to use Java 11 + run: echo "JAVA_HOME=$(echo $JAVA_HOME_11_X64)" >> $GITHUB_ENV + - name: Download distribution artifact from build job. + uses: actions/download-artifact@v3 + with: + name: distribution-java11 + path: distribution/target/distribution-base + - name: Download test files from build job. + uses: actions/download-artifact@v3 + with: + name: test-files + - name: Fix file permissions + run: | + chmod +x distribution/target/distribution-base/bin/openfire.sh + chmod +x ./runMelliumIntegrationTests + + - name: Set up Go + uses: actions/setup-go@v4 + + - name: Run Mellium tests + env: + XMPP_ADDR: jane@example.org + XMPP_PASS: secret + run: ./runMelliumIntegrationTests -d -l -h example.org -i 127.0.0.1 + + - name: Expose test output + if: always() + uses: actions/upload-artifact@v3 + with: + name: mellium test output + path: mellium/output + + - name: Expose openfire output + if: always() + uses: actions/upload-artifact@v3 + with: + name: openfire logs + path: distribution/target/distribution-base/logs/* + publish-maven: name: Publish to Maven runs-on: ubuntu-latest - needs: [aioxmpp, connectivity, smack, check_branch] + needs: [aioxmpp, mellium, connectivity, smack, check_branch] if: ${{github.repository == 'igniterealtime/Openfire' && github.event_name == 'push' && needs.check_branch.outputs.is_publishable_branch == 'true'}} steps: @@ -212,7 +259,7 @@ jobs: # Based on https://github.com/GabLeRoux/github-actions-examples/blob/e0468ce2731b08bd8b1f7cd09d0b94c541310693/.github/workflows/secret_based_conditions.yml name: Check if Docker Hub secrets exist runs-on: ubuntu-latest - needs: [build, aioxmpp, connectivity, smack] + needs: [build, aioxmpp, mellium, connectivity, smack] outputs: is_DOCKERHUB_SECRET_set: ${{ steps.checksecret_job.outputs.is_DOCKERHUB_SECRET_set }} steps: diff --git a/runMelliumIntegrationTests b/runMelliumIntegrationTests new file mode 100755 index 0000000000..46b0cba38b --- /dev/null +++ b/runMelliumIntegrationTests @@ -0,0 +1,151 @@ +#!/usr/bin/env bash +set -euo pipefail + +DEBUG=false +LOCAL_RUN=false + +DOMAIN='example.org' +HOST='localhost' + +usage() +{ + echo "Usage: $0 [-d] [-l] [-i IPADDRESS] [-h HOST] [-s DOMAIN]" + echo " -d: Enable debug mode. Prints commands, and preserves temp directories if used (default: off)" + echo " -l: Launch a local Openfire. (default: off)" + echo " -i: Set a hosts file for the given IP and host (or for example.com if running locally). Reverted at exit." + echo " -h: The hostname for the Openfire under test (default: localhost)" + echo " -s: The XMPP domain name for the Openfire under test (default: example.org)" + exit 2 +} + +while getopts dlh:i:s: OPTION "$@"; do + case $OPTION in + d) + DEBUG=true + set -x + ;; + l) + LOCAL_RUN=true + ;; + h) + HOST="${OPTARG}" + ;; + i) + IPADDRESS="${OPTARG}" + ;; + s) + DOMAIN="${OPTARG}" + ;; + \? ) usage;; + : ) usage;; + * ) usage;; + esac +done + +if [[ $LOCAL_RUN == true ]] && [[ $DOMAIN != "example.org" ]]; then + echo "Domain is fixed if launching a local instance. If you have an already-running instance to test against, omit the -l flag (and provide -h 127.0.0.1 if necessary)." + exit 1 +fi + +function setBaseDirectory { + # Pretty fancy method to get reliable the absolute path of a shell + # script, *even if it is sourced*. Credits go to GreenFox on + # stackoverflow: http://stackoverflow.com/a/12197518/194894 + pushd . > /dev/null + SCRIPTDIR="${BASH_SOURCE[0]}"; + while [ -h "${SCRIPTDIR}" ]; do + cd "$(dirname "${SCRIPTDIR}")" + SCRIPTDIR="$(readlink "$(basename "${SCRIPTDIR}")")"; + done + cd "$(dirname "${SCRIPTDIR}")" > /dev/null + SCRIPTDIR="$(pwd)"; + popd > /dev/null + BASEDIR="${SCRIPTDIR}" + cd "${BASEDIR}" +} + +function createTempDirectory { + OFTEMPDIR=$(mktemp -d) +} + +function cleanup { + if [[ $DEBUG == false && -n "${OFTEMPDIR-}" ]]; then + echo "Removing temp directories" + rm -rf "${OFTEMPDIR}" + fi + if [[ $LOCAL_RUN == true ]]; then + echo "Stopping Openfire" + pkill -f openfire.lib #TODO: Can this be made more future-proof against changes in the start script? + fi +} + +function setUpMelliumEnvironment { + MELLIUMDIR="${BASEDIR}/mellium" + AIOXMPPCONFIG="${MELLIUMDIR}/openfire-config.ini" + if [ -d "${MELLIUMDIR}" ]; then + pushd "${MELLIUMDIR}" + git pull + else + git clone -b main https://github.com/mellium/xmpp "${MELLIUMDIR}" + pushd "${MELLIUMDIR}" + fi + popd +} + +function setHostsFile { + if [[ -n "${IPADDRESS-}" ]]; then + echo "Setting hosts file for local running. This may prompt for sudo." + sudo /bin/sh -c "echo \"$IPADDRESS $HOST\" >> /etc/hosts" + fi +} + +function launchOpenfire { + declare -r OPENFIRE_SHELL_SCRIPT="${BASEDIR}/distribution/target/distribution-base/bin/openfire.sh" + + if [[ ! -f "${OPENFIRE_SHELL_SCRIPT}" ]]; then + mvn verify -P ci + fi + + rm -f distribution/target/distribution-base/conf/openfire.xml + cp distribution/target/distribution-base/conf/openfire-demoboot.xml \ + distribution/target/distribution-base/conf/openfire.xml + + echo "Starting Openfire…" + "${OPENFIRE_SHELL_SCRIPT}" & + + # Wait 120 seconds for Openfire to open up the web interface and + # assume Openfire is fully operational once that happens (not sure if + # this assumption is correct). + echo "Waiting for Openfire…" + timeout 120 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 0.3; done' localhost 7070 +} + +function runTests { + echo "Starting Integration Tests (using Mellium)…" + pushd "${MELLIUMDIR}" + if [ -d output ]; then rm -Rf output; fi + mkdir output + + pushd "${MELLIUMDIR}/examples/echobot" + go build + ./echobot -vv 2>&1 | tee "${MELLIUMDIR}/output/mellium.test.output.txt" + if [ ${PIPESTATUS[0]} -ne 0 ]; then false; fi; + popd + + # Mellium's integration test require hooks that will launch new servers on demand. Not currently supported by this script. + # go build + # go test -v -tags "integration" -run Integration ./... 2>&1 | tee output/mellium.test.output.txt + # if [ ${PIPESTATUS[0]} -ne 0 ]; then false; fi; + popd +} + +setBaseDirectory +trap cleanup EXIT +setUpMelliumEnvironment +if [[ -n "${IPADDRESS-}" ]]; then + setHostsFile +fi +if [[ $LOCAL_RUN == true ]]; then + launchOpenfire +fi +runTests