Skip to content

Commit 8db73ef

Browse files
committed
update e2e to run for both spring-boot and also the docker workbench/server with tomcat
1 parent 6723e4e commit 8db73ef

4 files changed

Lines changed: 210 additions & 108 deletions

File tree

.github/workflows/pr-verify.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,17 @@ jobs:
142142

143143

144144
e2e:
145+
name: e2e (${{ matrix.runtime.label }})
145146
needs: formatting-and-quick-compile
146147
runs-on: ubuntu-latest
148+
strategy:
149+
fail-fast: false
150+
matrix:
151+
runtime:
152+
- label: Spring Boot
153+
argument: spring-boot
154+
- label: Docker Tomcat
155+
argument: docker-tomcat
147156
steps:
148157
- uses: actions/checkout@v4
149158
- name: Register JVM thread dump on cancel
@@ -160,9 +169,9 @@ jobs:
160169
uses: actions/setup-node@v3
161170
with:
162171
node-version: 18
163-
- name: Run end-to-end tests of RDF4J Server and Workbench
172+
- name: Run end-to-end tests of RDF4J Server and Workbench (${{ matrix.runtime.label }})
164173
working-directory: ./e2e
165-
run: exec ../scripts/ci/run-with-thread-dump.sh ./run.sh
174+
run: exec ../scripts/ci/run-with-thread-dump.sh ./run.sh ${{ matrix.runtime.argument }}
166175

167176
frontend-unit-tests:
168177
needs: formatting-and-quick-compile

e2e/README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# End-to-end tests
22

3-
This directory contains end-to-end tests for the project. The suite now boots the RDF4J Server and Workbench using a Spring Boot wrapper with an embedded Tomcat instance, so Docker is no longer required.
3+
This directory contains end-to-end tests for the project. The suite can run against either the Spring Boot wrapper with embedded Tomcat or the Docker image that deploys the regular WAR files to Tomcat.
44

55
The tests are written using Microsoft Playwright and interact with the server and workbench in a real browser.
66

@@ -11,7 +11,24 @@ Requirements:
1111
- maven
1212
- npm
1313
- npx
14+
- docker (for `docker-tomcat`)
1415

15-
The tests can be run using the `run.sh` script. The script builds the Spring Boot runner, launches it in the background, waits until the HTTP endpoints are reachable, and then executes the Playwright test suite.
16+
The tests can be run using the `run.sh` script. The script builds the selected runtime, waits until the HTTP endpoints are reachable, and then executes the Playwright test suite.
17+
18+
Run against the Spring Boot implementation:
19+
20+
```bash
21+
./run.sh spring-boot
22+
```
23+
24+
Run against the Docker/Tomcat image:
25+
26+
```bash
27+
./run.sh docker-tomcat
28+
```
29+
30+
The default runtime is `spring-boot`, so `./run.sh` keeps the original local behavior.
31+
32+
If Playwright browsers are already installed locally, set `E2E_SKIP_PLAYWRIGHT_INSTALL=true` to skip the browser installer.
1633

1734
To run the tests interactively use `npx playwright test --ui`

e2e/run.sh

Lines changed: 137 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,29 @@
1010
# SPDX-License-Identifier: BSD-3-Clause
1111
#
1212

13-
set -e
13+
set -euo pipefail
1414

15+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
16+
E2E_DIR="${ROOT_DIR}/e2e"
17+
DOCKER_DIR="${ROOT_DIR}/docker"
18+
SERVER_RUNTIME="${1:-${E2E_SERVER_RUNTIME:-spring-boot}}"
1519
SERVER_PID=""
20+
DOCKER_STARTED="false"
21+
SPRING_BOOT_DATA_DIR=""
1622

17-
cleanup() {
23+
stop_spring_boot() {
1824
if [ -z "${SERVER_PID:-}" ]; then
1925
return
2026
fi
2127

22-
# If the process is already gone, nothing to do
2328
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
2429
return
2530
fi
2631

27-
echo "Sending SIGINT to server-boot module (pid=$SERVER_PID)"
32+
echo "Sending SIGINT to server-boot module (pid=${SERVER_PID})"
2833
kill -s INT "$SERVER_PID" 2>/dev/null || true
2934

30-
# Wait for graceful shutdown after SIGINT
31-
for i in 1 2 3 4 5 6 7 8 9 10; do
35+
for _ in 1 2 3 4 5 6 7 8 9 10; do
3236
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
3337
echo "server-boot module stopped gracefully after SIGINT"
3438
wait "$SERVER_PID" 2>/dev/null || true
@@ -38,12 +42,10 @@ cleanup() {
3842
sleep 0.5
3943
done
4044

41-
# Still alive: send a more aggressive TERM
42-
echo "Sending SIGTERM to server-boot module (pid=$SERVER_PID)"
45+
echo "Sending SIGTERM to server-boot module (pid=${SERVER_PID})"
4346
kill "$SERVER_PID" 2>/dev/null || true
4447

45-
# Wait for graceful shutdown after SIGTERM
46-
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
48+
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
4749
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
4850
echo "server-boot module stopped after SIGTERM"
4951
wait "$SERVER_PID" 2>/dev/null || true
@@ -52,47 +54,145 @@ cleanup() {
5254
sleep 0.5
5355
done
5456

55-
# Still alive after: kill definitively
56-
echo "Sending SIGKILL to server-boot module (pid=$SERVER_PID)"
57+
echo "Sending SIGKILL to server-boot module (pid=${SERVER_PID})"
5758
kill -9 "$SERVER_PID" 2>/dev/null || true
5859
wait "$SERVER_PID" 2>/dev/null || true
5960
}
6061

61-
trap cleanup EXIT
62+
stop_docker_tomcat() {
63+
if [ "${DOCKER_STARTED}" != "true" ]; then
64+
return
65+
fi
66+
67+
echo "Stopping Docker/Tomcat RDF4J stack"
68+
(cd "$DOCKER_DIR" && APP_SERVER=tomcat docker compose down -v) || true
69+
}
70+
71+
cleanup() {
72+
local status="${1:-$?}"
73+
trap - EXIT INT TERM
74+
stop_spring_boot
75+
stop_docker_tomcat
76+
exit "$status"
77+
}
78+
79+
usage() {
80+
echo "Usage: $0 [spring-boot|docker-tomcat]" >&2
81+
}
82+
83+
install_e2e_dependencies() {
84+
cd "$E2E_DIR"
85+
86+
if [ ! -d "node_modules" ]; then
87+
echo "Installing E2E npm dependencies"
88+
npm ci
89+
fi
90+
91+
if [ "${E2E_SKIP_PLAYWRIGHT_INSTALL:-false}" = "true" ]; then
92+
echo "Skipping Playwright browser install"
93+
else
94+
echo "Installing Playwright browsers"
95+
npx playwright install --with-deps
96+
fi
97+
}
6298

63-
npm install
99+
wait_for_url() {
100+
local label="$1"
101+
local url="$2"
64102

65-
cd ..
103+
printf 'Waiting for %s at %s' "$label" "$url"
104+
for _ in $(seq 1 90); do
105+
if curl --fail --location --silent --output /dev/null "$url"; then
106+
echo ""
107+
echo "${label} is ready"
108+
return
109+
fi
110+
ensure_runtime_running
111+
printf '.'
112+
sleep 1
113+
done
66114

67-
mvn -q install -Pquick
115+
echo ""
116+
echo "Timed out waiting for ${label} at ${url}" >&2
117+
return 1
118+
}
68119

69-
mvn -pl tools/server-boot spring-boot:run &
70-
SERVER_PID=$!
71-
# server-boot module will be stopped automatically on script exit (see cleanup trap above).
120+
ensure_runtime_running() {
121+
if [ -n "${SERVER_PID:-}" ] && ! kill -0 "$SERVER_PID" 2>/dev/null; then
122+
echo ""
123+
echo "server-boot module exited before RDF4J became ready" >&2
124+
wait "$SERVER_PID" 2>/dev/null || true
125+
SERVER_PID=""
126+
return 1
127+
fi
72128

73-
cd e2e
129+
if [ "${DOCKER_STARTED}" = "true" ]; then
130+
local container_id
131+
container_id="$(cd "$DOCKER_DIR" && APP_SERVER=tomcat docker compose ps -q rdf4j 2>/dev/null || true)"
132+
if [ -n "$container_id" ] && [ "$(docker inspect -f '{{.State.Running}}' "$container_id" 2>/dev/null || echo false)" != "true" ]; then
133+
echo ""
134+
echo "Docker/Tomcat container exited before RDF4J became ready" >&2
135+
(cd "$DOCKER_DIR" && APP_SERVER=tomcat docker compose logs --tail=200 rdf4j) || true
136+
return 1
137+
fi
138+
fi
139+
}
74140

75-
sleep 10
141+
wait_for_rdf4j() {
142+
wait_for_url "RDF4J Server" "http://localhost:8080/rdf4j-server/"
143+
wait_for_url "RDF4J Workbench" "http://localhost:8080/rdf4j-workbench/"
144+
}
76145

77-
if [ ! -d 'node_modules' ]; then
78-
echo "npm ci"
79-
npm ci
80-
fi
146+
start_spring_boot() {
147+
echo "Building RDF4J for Spring Boot E2E"
148+
(cd "$ROOT_DIR" && mvn install -Pquick)
81149

82-
npx playwright install --with-deps # install browsers
83-
npx playwright test
150+
SPRING_BOOT_DATA_DIR="${E2E_DATA_DIR:-$(mktemp -d "${TMPDIR:-/tmp}/rdf4j-e2e.XXXXXX")}"
151+
echo "Using RDF4J app data directory ${SPRING_BOOT_DATA_DIR}"
84152

85-
status_npx=$?
153+
echo "Starting RDF4J Server and Workbench with Spring Boot"
154+
(
155+
cd "$ROOT_DIR"
156+
mvn -pl tools/server-boot spring-boot:run \
157+
-Dspring-boot.run.jvmArguments="-Dorg.eclipse.rdf4j.appdata.basedir=${SPRING_BOOT_DATA_DIR}"
158+
) &
159+
SERVER_PID=$!
160+
}
86161

87-
cd ..
162+
start_docker_tomcat() {
163+
echo "Building Docker/Tomcat RDF4J image"
164+
(cd "$DOCKER_DIR" && APP_SERVER=tomcat ./build.sh)
88165

89-
# test for error code
90-
if [ $status_npx -ne 0 ]; then
91-
echo "Error in E2E test"
92-
exit $status_npx
93-
fi
166+
echo "Starting Docker/Tomcat RDF4J container"
167+
(cd "$DOCKER_DIR" && APP_SERVER=tomcat docker compose up --force-recreate -d)
168+
DOCKER_STARTED="true"
169+
}
94170

95-
echo "E2E test OK"
171+
run_playwright() {
172+
cd "$E2E_DIR"
173+
npx playwright test
174+
}
96175

97-
# don't redo the whole build process just for making another docker image
98-
export SKIP_BUILD="skip"
176+
trap 'cleanup $?' EXIT
177+
trap 'cleanup 130' INT
178+
trap 'cleanup 143' TERM
179+
180+
case "$SERVER_RUNTIME" in
181+
spring-boot)
182+
install_e2e_dependencies
183+
start_spring_boot
184+
;;
185+
docker | docker-tomcat | tomcat)
186+
install_e2e_dependencies
187+
start_docker_tomcat
188+
;;
189+
*)
190+
usage
191+
exit 2
192+
;;
193+
esac
194+
195+
wait_for_rdf4j
196+
run_playwright
197+
198+
echo "E2E test OK (${SERVER_RUNTIME})"

0 commit comments

Comments
 (0)