-
Notifications
You must be signed in to change notification settings - Fork 0
256 lines (227 loc) · 8.33 KB
/
Copy pathci.yml
File metadata and controls
256 lines (227 loc) · 8.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
fortran-syntax:
name: Fortran syntax check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install gfortran
run: sudo apt-get update && sudo apt-get install -y gfortran
- name: Check base module files compile
run: |
PASS=0
FAIL=0
# Check critical base files that have been modernized
# Note: CONTRL.f90 excluded because it INCLUDEs variant headers
for f in src-converted/base/main.f90 \
src-converted/base/myopen.f90 \
src-converted/base/volkey.f90 \
src-converted/base/algevl.f90 \
src-converted/base/evldx.f90 \
src-converted/base/errgro.f90; do
if [ -f "$f" ]; then
if gfortran -c -fsyntax-only -ffree-form -fPIC "$f" 2>/dev/null; then
echo "[OK] $f"
PASS=$((PASS+1))
else
echo "[FAIL] $f"
FAIL=$((FAIL+1))
fi
fi
done
echo ""
echo "Results: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] || exit 1
build-ne-variant:
name: Build FVS-NE shared library
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install gfortran
run: sudo apt-get update && sudo apt-get install -y gfortran
- name: Build NE variant
run: |
bash deployment/scripts/build_fvs_libraries.sh \
src-converted lib ne
echo ""
echo "Build output:"
ls -lh lib/FVS*.so 2>/dev/null || echo "No .so files produced"
- name: Verify NE library symbols
run: |
SO=lib/FVSne.so
if [ ! -f "$SO" ]; then
echo "FAIL: FVSne.so not found"
exit 1
fi
SIZE=$(stat -c%s "$SO")
echo "FVSne.so size: $SIZE bytes"
if [ "$SIZE" -lt 1000000 ]; then
echo "FAIL: Library suspiciously small (<1MB)"
exit 1
fi
# Check API symbols that fvs2py and rFVS use to drive simulations
MISSING=0
for sym in fvssetcmdline_ fvssummary_ fvsdimsizes_ fvstreeattr_ volinit_; do
if nm "$SO" 2>/dev/null | grep -q " [Tt] ${sym}"; then
echo "[OK] $sym"
else
echo "[WARN] $sym not found"
MISSING=$((MISSING+1))
fi
done
# fvssetcmdline_ and fvssummary_ are essential API entry points
for sym in fvssetcmdline_ fvssummary_; do
nm "$SO" 2>/dev/null | grep -q " [Tt] ${sym}" || {
echo "FAIL: critical API symbol $sym missing"
exit 1
}
done
echo ""
TOTAL=$(nm "$SO" 2>/dev/null | grep -c " T ")
echo "Total exported text symbols: $TOTAL"
- name: Python ctypes load test
run: |
python3 << 'PYEOF'
import ctypes, ctypes.util, os, sys
so_path = os.path.abspath('lib/FVSne.so')
print(f'Loading {so_path} via ctypes...')
# FVS .so files have some unresolved internal symbols (e.g., debug_mod
# from NVEL) that are harmless at runtime but cause RTLD_NOW to fail
# on some Python/glibc combinations. Use RTLD_LAZY (0x1 on Linux).
RTLD_LAZY = 0x1
try:
lib = ctypes.CDLL(so_path, mode=RTLD_LAZY)
except OSError:
# Fallback: try default mode (works on some Python versions)
try:
lib = ctypes.CDLL(so_path)
except OSError as e:
print(f'FAIL: Could not load library: {e}')
sys.exit(1)
print(f' Loaded successfully: {lib._name}')
# Verify key API functions are callable
api_funcs = ['fvssetcmdline_', 'fvssummary_', 'fvsdimsizes_']
for fname in api_funcs:
try:
fn = getattr(lib, fname)
print(f' [OK] {fname} -> {fn}')
except AttributeError:
print(f' [WARN] {fname} not found')
# Verify fvssetcmdline_ is present (critical for any simulation)
try:
_ = lib.fvssetcmdline_
print()
print('PASS: FVSne.so loads and API entry points are accessible')
except AttributeError:
print('FAIL: fvssetcmdline_ missing from loaded library')
sys.exit(1)
PYEOF
build-executables:
name: Build FVS executables (NE, LS)
needs: build-ne-variant
runs-on: ubuntu-latest
# Exe builds may fail on CI due to gfortran version differences in
# F77->F90 conversion handling. This job is informational: the
# .so library build (above) is the gate that must pass.
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Install gfortran
run: sudo apt-get update && sudo apt-get install -y gfortran
- name: Build shared libraries (needed for fallback linking)
run: bash deployment/scripts/build_fvs_libraries.sh . lib ne ls
- name: Build executables (NE + LS)
run: |
echo "gfortran version: $(gfortran --version | head -1)"
ls -lh lib/FVS*.so 2>/dev/null || echo "No .so files yet"
echo ""
bash deployment/scripts/build_fvs_executables.sh . lib ne ls || true
echo ""
ls -lh lib/FVS* 2>/dev/null || echo "No executables found"
echo ""
for var in ne ls; do
EXE="lib/FVS${var}"
if [ -f "$EXE" ]; then
SIZE=$(stat -c%s "$EXE")
echo "FVS${var}: $SIZE bytes"
else
echo "FVS${var}: not built (gfortran version may differ from local)"
fi
done
- name: Smoke test (banner prints and exits)
run: |
export LD_LIBRARY_PATH="$(pwd)/lib:${LD_LIBRARY_PATH:-}"
for var in ne ls; do
EXE="./lib/FVS${var}"
if [ ! -f "$EXE" ]; then
echo "SKIP: FVS${var} not available"
continue
fi
OUTPUT=$(echo "" | timeout 10 "$EXE" 2>&1 || true)
echo "=== FVS${var} ==="
echo "$OUTPUT"
if echo "$OUTPUT" | grep -q "FVS VARIANT"; then
echo "PASS: FVS${var} banner detected"
else
echo "WARN: FVS${var} banner not found"
fi
done
nvel-audit:
name: NVEL coefficient audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Run NVEL upstream audit
run: |
python3 scripts/audit_nvel_upstream.py --verbose \
--allow-differ r8clist.inc
validate-calibration:
name: Validate calibrated configs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Validate calibrated config integrity
# Guardrail for issue #54: every calibrated config must carry a
# consistent calibration_multipliers block (five component arrays of
# length maxsp, availability-consistent, finite). Fails the build if a
# config silently drops a component it claims to calibrate.
run: python3 config/validate_calibrated.py
lint:
name: Lint scripts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Shellcheck deployment scripts
run: |
ERRORS=0
for f in deployment/scripts/*.sh; do
echo "Checking $f..."
shellcheck --severity=error "$f" || ERRORS=$((ERRORS+1))
done
# Report but don't fail on shellcheck warnings for now
echo "Scripts with errors: $ERRORS"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install ruff
run: pip install ruff
- name: Lint Python code
run: |
ruff check calibration/python/ deployment/fvs2py/ config/ \
--select=E,F,W --ignore=E501 || true