Skip to content

Commit faad204

Browse files
sawenzelclaude
andcommitted
Run the simulation tests against a CVMFS release
This adds a GitHub Actions job that runs test/run_tests.sh against a published O2PDPSuite release instead of building the software. - The job runs on a self-hosted runner labelled cvmfs and compiles nothing. - test/ci/resolve_tag.sh picks the newest daily-* release, or the one named by a "sim-tests-tag: <tag>" line in the pull request body, or the one given to a manual run. - test/tests/resolve_tag.sh checks that selection offline. - Logs are uploaded as an artifact and are readable without a CERN account. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 09a1faa commit faad204

3 files changed

Lines changed: 208 additions & 0 deletions

File tree

‎.github/workflows/sim-tests.yml‎

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
name: Simulation tests
3+
4+
'on':
5+
pull_request:
6+
paths:
7+
- 'DATA/**'
8+
- 'MC/**'
9+
- 'test/**'
10+
- 'RelVal/**'
11+
workflow_dispatch:
12+
inputs:
13+
tag:
14+
description: 'O2PDPSuite tag to test against (default: newest daily)'
15+
type: string
16+
required: false
17+
18+
permissions: {}
19+
20+
concurrency:
21+
group: sim-tests-${{ github.event.pull_request.number || github.ref }}
22+
cancel-in-progress: true
23+
24+
jobs:
25+
sim-tests:
26+
name: Simulation tests against CVMFS
27+
runs-on: [self-hosted, cvmfs]
28+
timeout-minutes: 180
29+
30+
steps:
31+
- name: Checkout code
32+
uses: actions/checkout@v4
33+
with:
34+
# The changed-file logic diffs against the PR base, so the full
35+
# history is needed, not a shallow clone.
36+
fetch-depth: 0
37+
38+
- name: Check the CVMFS environment
39+
run: |
40+
set -eu
41+
test -d /cvmfs/alice.cern.ch || {
42+
echo "::error title=CVMFS unavailable::/cvmfs/alice.cern.ch is not mounted on this runner"
43+
exit 1
44+
}
45+
test -x /cvmfs/alice.cern.ch/bin/alienv || {
46+
echo "::error title=CVMFS unavailable::/cvmfs/alice.cern.ch/bin/alienv is missing"
47+
exit 1
48+
}
49+
50+
- name: Skip when the pull request opted into the source build
51+
id: sentinel
52+
if: github.event_name == 'pull_request'
53+
env:
54+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
55+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
56+
run: |
57+
set -eu
58+
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -qx 'test/needs-o2-dev' ; then
59+
echo "::notice title=Skipped::this pull request touches test/needs-o2-dev, so it is tested by build/O2DPG/sim/o2dev against O2 dev instead"
60+
echo "skip=true" >> "$GITHUB_OUTPUT"
61+
else
62+
echo "skip=false" >> "$GITHUB_OUTPUT"
63+
fi
64+
65+
- name: Resolve the O2PDPSuite tag
66+
id: tag
67+
if: steps.sentinel.outputs.skip != 'true'
68+
env:
69+
REQUESTED_TAG: ${{ inputs.tag }}
70+
PR_BODY: ${{ github.event.pull_request.body }}
71+
run: |
72+
set -eu
73+
# shellcheck source=test/ci/resolve_tag.sh
74+
. test/ci/resolve_tag.sh
75+
moduledir=/cvmfs/alice.cern.ch/el9-x86_64/Modules/modulefiles/O2PDPSuite
76+
requested=$REQUESTED_TAG
77+
if [ -z "$requested" ]; then
78+
# A PR can pin the release with a line "sim-tests-tag: <tag>".
79+
requested=$(printf '%s\n' "$PR_BODY" |
80+
sed -n 's/^[[:space:]]*sim-tests-tag:[[:space:]]*//p' | head -n 1 |
81+
tr -d '[:space:]')
82+
fi
83+
tag=$(resolve_o2pdpsuite_tag "$moduledir" "$requested") || {
84+
echo "::error title=No usable O2PDPSuite release::see the message above"
85+
exit 1
86+
}
87+
echo "Testing against O2PDPSuite::$tag"
88+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
89+
90+
- name: Run the O2DPG tests
91+
if: steps.sentinel.outputs.skip != 'true'
92+
env:
93+
O2PDPSUITE_TAG: ${{ steps.tag.outputs.tag }}
94+
O2DPG_TEST_HASH_BASE: ${{ github.event.pull_request.base.sha }}
95+
O2DPG_TEST_HASH_HEAD: ${{ github.event.pull_request.head.sha }}
96+
JOBS: 8
97+
run: |
98+
set -eu
99+
/cvmfs/alice.cern.ch/bin/alienv setenv "O2PDPSuite/$O2PDPSUITE_TAG" -c \
100+
env O2DPG_ROOT="$PWD" O2DPG_MC_CONFIG_ROOT="$PWD" \
101+
O2DPG_TEST_REPO_DIR="$PWD" \
102+
O2DPG_TEST_HASH_BASE="$O2DPG_TEST_HASH_BASE" \
103+
O2DPG_TEST_HASH_HEAD="$O2DPG_TEST_HASH_HEAD" \
104+
JOBS="$JOBS" \
105+
bash test/run_tests.sh
106+
107+
- name: Upload logs
108+
if: always()
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: o2dpg-test-logs
112+
path: |
113+
o2dpg_tests/**/*.log
114+
o2dpg_tests/**/*serverlog*
115+
o2dpg_tests/**/*workerlog*
116+
o2dpg_tests/**/*mergerlog*
117+
if-no-files-found: ignore
118+
retention-days: 14

‎test/ci/resolve_tag.sh‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
# Pick the O2PDPSuite release to test against. Kept free of CVMFS paths and of
4+
# CI variables so it can be exercised offline.
5+
6+
resolve_o2pdpsuite_tag()
7+
{
8+
local moduledir=${1:-}
9+
local requested=${2:-}
10+
11+
if [[ ! -d "${moduledir}" ]] ; then
12+
echo "resolve_o2pdpsuite_tag: no such directory: ${moduledir}" >&2
13+
return 1
14+
fi
15+
16+
if [[ -n "${requested}" ]] ; then
17+
if [[ ! -e "${moduledir}/${requested}" ]] ; then
18+
echo "resolve_o2pdpsuite_tag: requested tag not available: ${requested}" >&2
19+
return 1
20+
fi
21+
echo "${requested}"
22+
return 0
23+
fi
24+
25+
local newest
26+
newest=$(find "${moduledir}" -maxdepth 1 -name 'daily-*' -printf '%f\n' 2>/dev/null |
27+
sort -V | tail -n 1)
28+
if [[ -z "${newest}" ]] ; then
29+
echo "resolve_o2pdpsuite_tag: no daily-* tag in ${moduledir}" >&2
30+
return 1
31+
fi
32+
echo "${newest}"
33+
}

‎test/tests/resolve_tag.sh‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
# Offline harness for resolve_o2pdpsuite_tag: builds a fake modulefile
3+
# directory so the function can be checked without CVMFS.
4+
5+
set -u
6+
HERE=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
7+
# shellcheck source=../ci/resolve_tag.sh
8+
source "${HERE}/../ci/resolve_tag.sh"
9+
FAILURES=0
10+
11+
check()
12+
{
13+
local label=$1 expected=$2 actual=$3
14+
if [[ "${expected}" == "${actual}" ]] ; then
15+
echo "ok - ${label}"
16+
else
17+
echo "FAIL - ${label}: expected '${expected}', got '${actual}'"
18+
FAILURES=$((FAILURES + 1))
19+
fi
20+
}
21+
22+
TMP=$(mktemp -d)
23+
D="${TMP}/O2PDPSuite"
24+
mkdir -p "${D}"
25+
# Deliberately out of lexical-creation order, and with non-daily neighbours.
26+
touch "${D}/daily-20260919-0000-1" \
27+
"${D}/daily-20260921-0000-1" \
28+
"${D}/daily-20260920-0000-1" \
29+
"${D}/async-2024-pp-apass1-1" \
30+
"${D}/slc9-nightly-20260921-1"
31+
32+
out=$(resolve_o2pdpsuite_tag "${D}") ; rc=$?
33+
check "newest daily is chosen" "daily-20260921-0000-1" "${out}"
34+
check "success exit code" 0 "${rc}"
35+
36+
out=$(resolve_o2pdpsuite_tag "${D}" "daily-20260919-0000-1") ; rc=$?
37+
check "requested tag honoured" "daily-20260919-0000-1" "${out}"
38+
check "requested tag exit code" 0 "${rc}"
39+
40+
out=$(resolve_o2pdpsuite_tag "${D}" "daily-20991231-0000-1" 2>/dev/null) ; rc=$?
41+
check "absent requested tag fails" 1 "${rc}"
42+
check "absent requested tag prints nothing on stdout" "" "${out}"
43+
44+
out=$(resolve_o2pdpsuite_tag "${TMP}/does-not-exist" 2>/dev/null) ; rc=$?
45+
check "missing directory fails" 1 "${rc}"
46+
47+
mkdir -p "${TMP}/empty"
48+
out=$(resolve_o2pdpsuite_tag "${TMP}/empty" 2>/dev/null) ; rc=$?
49+
check "directory with no dailies fails" 1 "${rc}"
50+
51+
echo
52+
if [[ "${FAILURES}" == "0" ]] ; then
53+
echo "All resolve_tag tests passed"
54+
else
55+
echo "${FAILURES} test(s) failed"
56+
fi
57+
exit $(( FAILURES > 0 ? 1 : 0 ))

0 commit comments

Comments
 (0)