Skip to content

Commit d16c320

Browse files
committed
feat(.github/workflows/container_integration_test.yml): add container integration tests
1 parent c206ebf commit d16c320

1 file changed

Lines changed: 332 additions & 0 deletions

File tree

Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
name: Container Integration Tests Workflow
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
force_run:
7+
description: 'Force run even if ENABLE_DOCKER_TESTS is false'
8+
required: false
9+
type: boolean
10+
default: false
11+
push:
12+
branches:
13+
- develop
14+
paths-ignore:
15+
- "doc/**"
16+
- "**/*.md"
17+
- "**/*.txt"
18+
- ".github/ISSUE_TEMPLATE/**"
19+
- ".github/*.md"
20+
pull_request:
21+
branches:
22+
- develop
23+
paths-ignore:
24+
- "doc/**"
25+
- "**/*.md"
26+
- "**/*.txt"
27+
- ".github/ISSUE_TEMPLATE/**"
28+
- ".github/*.md"
29+
30+
concurrency:
31+
group: "container-integration-tests-group"
32+
cancel-in-progress: true
33+
34+
jobs:
35+
main-integration-tests-workflow:
36+
runs-on: ubuntu-latest
37+
timeout-minutes: 120
38+
39+
defaults:
40+
run:
41+
shell: bash
42+
43+
permissions:
44+
checks: write
45+
pull-requests: write
46+
47+
steps:
48+
49+
# ---------------------------
50+
# CHECKOUT
51+
# ---------------------------
52+
- name: Checkout repository
53+
uses: actions/checkout@v6
54+
55+
# ---------------------------
56+
# VERIFY DOCKER
57+
# ---------------------------
58+
- name: Verify Docker
59+
run: |
60+
set -euo pipefail
61+
docker version
62+
63+
# ---------------------------
64+
# SETUP JAVA + MAVEN
65+
# ---------------------------
66+
- name: Setup Java
67+
uses: actions/setup-java@v5
68+
with:
69+
distribution: "temurin"
70+
java-version: "21"
71+
cache: "maven"
72+
73+
- name: Verify Maven
74+
run: |
75+
set -euo pipefail
76+
mvn -version
77+
78+
# ---------------------------
79+
# CLEAN PREVIOUS VOLUMES
80+
# ---------------------------
81+
- name: Clean docker-dev-volumes
82+
run: |
83+
set -euo pipefail
84+
rm -rf docker-dev-volumes || true
85+
86+
# ---------------------------
87+
# BUILD IMAGES (Dataverse-native)
88+
# ---------------------------
89+
- name: Build Dataverse containers via Maven
90+
run: |
91+
set -euo pipefail
92+
# Force unit tests to run, generate coverage, and ignore failures so the build continues
93+
mvn clean package -Pct -P all-unit-tests \
94+
-DskipUnitTests=false \
95+
-Djacoco.skip=false \
96+
-Dmaven.test.failure.ignore=true
97+
98+
# ---------------------------
99+
# START CONTAINERS (BACKGROUND)
100+
# ---------------------------
101+
- name: Start Dataverse stack
102+
run: |
103+
set -euo pipefail
104+
mvn -Pct docker:start \
105+
-Ddataverse.cors.origin=* \
106+
-Ddataverse.cors.methods=GET,POST,PUT,DELETE,OPTIONS \
107+
-Ddataverse.cors.headers.allow=range,content-type,x-dataverse-key,accept \
108+
-Ddataverse.cors.headers.expose=content-encoding,content-range,accept-ranges \
109+
-Ddataverse.feature.index-harvested-metadata-source=true \
110+
-Ddataverse.oai.server.maxidentifiers=2 \
111+
-Ddataverse.oai.server.maxrecords=2 \
112+
113+
# ---------------------------
114+
# WAIT FOR API READINESS
115+
# ---------------------------
116+
- name: Wait for Dataverse API readiness
117+
run: |
118+
set -euo pipefail
119+
URL="http://localhost:8080/api/info/version"
120+
MAX_ATTEMPTS=10
121+
SLEEP_TIME=15
122+
echo "Waiting for Dataverse readiness..."
123+
for attempt in $(seq 1 $MAX_ATTEMPTS); do
124+
echo "Attempt $attempt..."
125+
RESPONSE=$(curl -s --max-time 15 "$URL" || true)
126+
STATUS=$(echo "$RESPONSE" | jq -r '.status' 2>/dev/null || echo "NOT_READY")
127+
if [ "$STATUS" = "OK" ]; then
128+
echo "Dataverse endpoint is READY."
129+
echo "Dataverse waiting for full readiness. Waiting 30 more seconds."
130+
sleep 30
131+
echo "Response: $RESPONSE"
132+
exit 0
133+
fi
134+
echo "Not ready. Sleeping ${SLEEP_TIME}s..."
135+
sleep $SLEEP_TIME
136+
if [ $SLEEP_TIME -lt 60 ]; then
137+
SLEEP_TIME=$((SLEEP_TIME * 2))
138+
if [ $SLEEP_TIME -gt 60 ]; then
139+
SLEEP_TIME=60
140+
fi
141+
fi
142+
done
143+
echo "Dataverse failed to become ready."
144+
docker ps
145+
CONTAINERS="$(docker ps -aq)"
146+
if [ -n "$CONTAINERS" ]; then
147+
for cid in $CONTAINERS; do
148+
echo "===== Logs for container $cid ====="
149+
docker logs "$cid" || true
150+
done
151+
else
152+
echo "No running containers to show logs for."
153+
fi
154+
exit 1
155+
156+
# ---------------------------
157+
# MAP LOCALSTACK TO LOCALHOST
158+
# ---------------------------
159+
- name: Map localstack to localhost for Maven tests
160+
run: echo "127.0.0.1 localstack" | sudo tee -a /etc/hosts
161+
162+
# ---------------------------
163+
# CONFIGURE DATAVERSE FOR TESTS
164+
# ---------------------------
165+
- name: Configure Dataverse API Settings
166+
run: |
167+
set -euo pipefail
168+
169+
echo "Setting API Database Settings via internal container curl..."
170+
171+
# We define the settings in an array
172+
declare -A settings=(
173+
[":BuiltinUsersKey"]="burrito"
174+
[":ProvCollectionEnabled"]="true"
175+
[":AllowApiTokenLookupViaApi"]="true"
176+
[":AllowSignUp"]="true"
177+
)
178+
# We run curl INSIDE the container so the source IP is 127.0.0.1
179+
for key in "${!settings[@]}"; do
180+
echo "Setting $key..."
181+
docker exec dev_dataverse curl -s -X PUT -d "${settings[$key]}" "http://localhost:8080/api/admin/settings/$key"
182+
echo ""
183+
done
184+
185+
# ---------------------------
186+
# PRE-TEST INJECTIONS (FROM YOUR ALTERNATE WORKFLOWS)
187+
# ---------------------------
188+
- name: Put SUSHI config file in place
189+
run: |
190+
set -euo pipefail
191+
# Fixes MakeDataCountApiIT
192+
docker exec dev_dataverse sh -c 'curl https://raw.githubusercontent.com/IQSS/dataverse/develop/src/test/java/edu/harvard/iq/dataverse/makedatacount/sushi_sample_logs.json > /tmp/sushi_sample_logs.json && head /tmp/sushi_sample_logs.json'
193+
194+
# ---------------------------
195+
# RUN MAVEN TESTS
196+
# ---------------------------
197+
- name: Run Maven Integration Tests
198+
env:
199+
DVAPIKEY: "burrito"
200+
DV_APIKEY: "burrito"
201+
DV_API_KEY: "burrito"
202+
run: |
203+
set -euo pipefail
204+
TEST_SUITE=$(cat tests/integration-tests.txt)
205+
206+
echo "Running suite: $TEST_SUITE"
207+
208+
# -Dmaven.test.failure.ignore=true forces the JVM to shut down cleanly
209+
# and write the jacoco.exec file, even when tests fail.
210+
mvn test \
211+
-Dtest="$TEST_SUITE" \
212+
-Dmaven.test.failure.ignore=true \
213+
-Ddataverse.test.baseurl=http://localhost:8080 \
214+
-DcompilerArgument=-Xlint:unchecked
215+
216+
# ---------------------------
217+
# GENERATE REPORTS & DEPOSIT TO COVERALLS
218+
# ---------------------------
219+
- name: Deposit to Coveralls
220+
if: always()
221+
env:
222+
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
223+
continue-on-error: true
224+
run: |
225+
set -euo pipefail
226+
227+
# The pom.xml automatically merged the files and put them here:
228+
mvn coveralls:report \
229+
-P all-unit-tests \
230+
-DrepoToken=$COVERALLS_REPO_TOKEN \
231+
-DjacocoReports=target/site/jacoco-merged-test-coverage-report/jacoco.xml
232+
233+
# ---------------------------
234+
# UPLOAD SUREFIRE/FAILSAFE REPORTS
235+
# ---------------------------
236+
- name: Upload Test Failure Reports
237+
if: always()
238+
uses: actions/upload-artifact@v4
239+
with:
240+
name: maven-test-reports
241+
path: |
242+
target/surefire-reports/
243+
target/failsafe-reports/
244+
target/site/jacoco/
245+
retention-days: 14
246+
247+
# ---------------------------
248+
# 2. PUBLISH TEST DASHBOARD IN GITHUB PR (Optional but highly recommended)
249+
# ---------------------------
250+
- name: Publish Test Results Dashboard
251+
uses: EnricoMi/publish-unit-test-result-action@v2
252+
if: always()
253+
with:
254+
files: |
255+
target/failsafe-reports/TEST-*.xml
256+
target/surefire-reports/TEST-*.xml
257+
258+
# ---------------------------
259+
# FAIL WORKFLOW IF TESTS FAILED
260+
# ---------------------------
261+
- name: Check for Test Failures
262+
if: always()
263+
run: |
264+
echo "Checking Surefire/Failsafe reports for failures..."
265+
if grep -q "<failure" target/surefire-reports/*.xml target/failsafe-reports/*.xml 2>/dev/null; then
266+
echo "Tests failed! Failing the workflow."
267+
exit 1
268+
fi
269+
echo "All tests passed."
270+
271+
# ---------------------------
272+
# COLLECT DOCKER LOGS (ALWAYS, WITH MAPPING)
273+
# ---------------------------
274+
- name: Collect Docker logs (mapped)
275+
if: always()
276+
run: |
277+
mkdir -p docker-logs
278+
echo "Gathering container metadata..."
279+
docker ps -a --format '{{.Names}}|{{.Image}}|{{.Status}}' > docker-logs/container-summary.txt
280+
while IFS='|' read -r name image status; do
281+
# Create a readable label
282+
label="$name"
283+
case "$name" in
284+
*dataverse*)
285+
label="dataverse-app"
286+
;;
287+
*postgres*)
288+
label="postgres-db"
289+
;;
290+
*solr*)
291+
label="solr-index"
292+
;;
293+
*localstack*)
294+
label="localstack-s3"
295+
;;
296+
esac
297+
echo "Collecting logs for $name ($label)"
298+
{
299+
echo "===== CONTAINER: $name ====="
300+
echo "Label: $label"
301+
echo "Image: $image"
302+
echo "Status: $status"
303+
echo ""
304+
echo "===== LOGS ====="
305+
docker logs --timestamps "$name" 2>&1 || true
306+
} > "docker-logs/${label}__${name}.log"
307+
done < docker-logs/container-summary.txt
308+
309+
# ---------------------------
310+
# UPLOAD DOCKER LOGS (ALWAYS)
311+
# ---------------------------
312+
- name: Upload Docker logs
313+
if: always()
314+
uses: actions/upload-artifact@v4
315+
with:
316+
name: docker-logs
317+
path: docker-logs/
318+
retention-days: 7
319+
320+
# ---------------------------
321+
# SHUTDOWN STACK
322+
# ---------------------------
323+
- name: Stop Dataverse stack
324+
if: always()
325+
run: |
326+
set -euo pipefail
327+
mvn -Pct docker:stop || true
328+
329+
- name: Final Docker cleanup
330+
if: always()
331+
run: |
332+
docker system prune -af || true

0 commit comments

Comments
 (0)