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