forked from OpenMDAO/build_pyoptsparse
-
Notifications
You must be signed in to change notification settings - Fork 0
422 lines (362 loc) · 15.2 KB
/
test_workflow.yml
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
name: Tests
on:
# Trigger on push or pull request events for the master branch
push:
branches: [ master ]
pull_request:
branches: [ master ]
# Run the workflow Sundays at 0400 UTC
schedule:
- cron: '0 4 * * 0'
# Allow running the workflow manually from the Actions tab
workflow_dispatch:
inputs:
run_name:
description: 'Name of workflow run as it will appear under Actions tab (optional):'
type: string
required: false
default: ''
job_name:
description: 'Select a job from the matrix to run (default: all jobs)'
type: choice
options:
- ''
- 'Ubuntu Baseline'
- 'Ubuntu Baseline, no MPI'
- 'MacOS Baseline'
- 'Ubuntu Latest'
- 'Ubuntu Oldest'
- 'Ubuntu Baseline, no MPI, forced build'
- 'MacOS Baseline, no MPI, forced build'
- 'Ubuntu Latest, no MPI, forced build'
- 'MacOS Baseline on ARM'
required: false
default: ''
debug_enabled:
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
type: boolean
required: false
default: false
run-name: ${{ inputs.run_name }}
jobs:
tests:
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
# test baseline versions on Ubuntu
- NAME: Ubuntu Baseline
OS: ubuntu-latest
PY: '3.12'
NUMPY: '1.26'
SCIPY: '1.13'
MPICC: 4
PYOPTSPARSE: 'default'
# PAROPT: true
SNOPT: 7.7
# test baseline versions on Ubuntu without MPI
- NAME: Ubuntu Baseline, no MPI
OS: ubuntu-latest
PY: '3.12'
NUMPY: '1.26'
SCIPY: '1.13'
PYOPTSPARSE: 'default'
SNOPT: 7.7
# test baseline versions on MacOS
- NAME: MacOS Baseline
OS: macos-13
PY: '3.11'
NUMPY: '1.26'
SCIPY: '1.13'
MPICC: 4
PYOPTSPARSE: 'default'
# PAROPT: true
SNOPT: 7.7
# test latest versions
- NAME: Ubuntu Latest
OS: ubuntu-latest
PY: 3
NUMPY: 1
SCIPY: 1
MPICC: 4
PYOPTSPARSE: 'latest'
# PAROPT: true
SNOPT: 7.7
# test oldest supported versions
- NAME: Ubuntu Oldest
OS: ubuntu-latest
PY: 3.8
NUMPY: 1.22
SCIPY: 1.7
PYOPTSPARSE: 'v1.2'
NO_IPOPT: true
SNOPT: 7.2
# test baseline versions on Ubuntu without MPI with forced build
- NAME: Ubuntu Baseline, no MPI, forced build
OS: ubuntu-latest
PY: '3.12'
NUMPY: '1.26'
SCIPY: '1.13'
PYOPTSPARSE: 'default'
SNOPT: 7.7
FORCE_BUILD: true
# test baseline versions on MacOS without MPI with forced build
- NAME: MacOS Baseline, no MPI, forced build
OS: macos-13
PY: '3.11'
NUMPY: '1.26'
SCIPY: '1.13'
PYOPTSPARSE: 'default'
SNOPT: 7.7
FORCE_BUILD: true
XCODE: '14.2'
# test latest versions without MPI with forced build
- NAME: Ubuntu Latest, no MPI, forced build
OS: ubuntu-latest
PY: 3
NUMPY: 1
SCIPY: 1
PYOPTSPARSE: 'latest'
SNOPT: 7.7
FORCE_BUILD: true
# test baseline versions on MacOS latest (ARM64)
- NAME: MacOS Baseline on ARM
OS: macos-latest
PY: '3.12'
NUMPY: '1.26'
SCIPY: '1.13'
BREW: true
MPICC: 4
PYOPTSPARSE: 'default'
SNOPT: 7.7
runs-on: ${{ matrix.OS }}
name: ${{ matrix.NAME }}
defaults:
run:
shell: bash -l {0}
steps:
- name: Display run details
run: |
echo "============================================================="
echo "Run #${GITHUB_RUN_NUMBER}"
echo "Run ID: ${GITHUB_RUN_ID}"
echo "Testing: ${GITHUB_REPOSITORY}"
echo "Triggered by: ${GITHUB_EVENT_NAME}"
echo "Initiated by: ${GITHUB_ACTOR}"
echo "============================================================="
- name: Exit if this job was not selected
if: github.event_name == 'workflow_dispatch' && inputs.job_name != '' && inputs.job_name != matrix.NAME
uses: actions/github-script@v7
with:
script: core.setFailed('The ${{ matrix.NAME }} job was not included in the run, exiting...');
- name: Create SSH key
if: matrix.SNOPT
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
run: |
mkdir -p ~/.ssh/
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
sudo chmod 600 ~/.ssh/id_rsa
echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- name: Checkout code
uses: actions/checkout@v4
- name: Setup conda
uses: conda-incubator/setup-miniconda@v3
with:
miniconda-version: latest
python-version: ${{ matrix.PY }}
channels: conda-forge
channel-priority: true
- name: Install
run: |
conda install numpy=${{ matrix.NUMPY }} scipy=${{ matrix.SCIPY }} -q -y
if [[ "${{ matrix.BREW }}" ]]; then
brew install swig meson
if [[ "${{ matrix.OS }}" == "macos-latest" ]]; then
ln -s /opt/homebrew/bin/gfortran-13 /opt/homebrew/bin/gfortran
fi
else
conda install compilers cython swig -q -y
fi
if [[ "${{ matrix.XCODE }}" ]]; then
sudo xcode-select -s "/Applications/Xcode_${{ matrix.XCODE }}.app"
fi
echo "============================================================="
echo "Install build_pyoptsparse"
echo "============================================================="
python -m pip install .
- name: Install MPI
if: matrix.MPICC
run: |
echo "============================================================="
echo "Install MPI"
echo "============================================================="
if [[ "${{ matrix.BREW }}" ]]; then
brew install open-mpi mpi4py
else
conda install openmpi-mpicc=${{ matrix.MPICC }} mpi4py -q -y
fi
echo "OMPI_MCA_rmaps_base_oversubscribe=1" >> $GITHUB_ENV
- name: Display environment before
run: |
conda info
conda list
echo "============================================================="
echo "Check installed versions of Python, Numpy and Scipy"
echo "============================================================="
python -c "import sys; assert str(sys.version).startswith(str(${{ matrix.PY }})), \
f'Python version {sys.version} is not the requested version (${{ matrix.PY }})'"
python -c "import numpy; assert str(numpy.__version__).startswith(str(${{ matrix.NUMPY }})), \
f'Numpy version {numpy.__version__} is not the requested version (${{ matrix.NUMPY }})'"
python -c "import scipy; assert str(scipy.__version__).startswith(str(${{ matrix.SCIPY }})), \
f'Scipy version {scipy.__version__} is not the requested version (${{ matrix.SCIPY }})'"
- name: Build pyOptSparse
run: |
echo "============================================================="
echo "Build pyoptsparse"
echo "============================================================="
if [[ "${{ matrix.PYOPTSPARSE }}" == "default" ]]; then
BRANCH=""
elif [[ "${{ matrix.PYOPTSPARSE }}" == "latest" ]]; then
LATEST_URL=`curl -fsSLI -o /dev/null -w %{url_effective} https://github.com/mdolab/pyoptsparse/releases/latest`
LATEST_VER=`echo $LATEST_URL | awk '{split($0,a,"/tag/"); print a[2]}'`
BRANCH="-b $LATEST_VER"
else
BRANCH="-b ${{ matrix.PYOPTSPARSE }}"
fi
if [[ "${{ matrix.PAROPT }}" ]]; then
PAROPT="-a"
fi
if [[ "${{ matrix.SNOPT }}" == "7.7" && "${{ secrets.SNOPT_LOCATION_77 }}" ]]; then
echo " > Secure copying SNOPT 7.7 over SSH"
mkdir SNOPT
scp -qr ${{ secrets.SNOPT_LOCATION_77 }} SNOPT
SNOPT="-s SNOPT/src"
elif [[ "${{ matrix.SNOPT }}" == "7.2" && "${{ secrets.SNOPT_LOCATION_72 }}" ]]; then
echo " > Secure copying SNOPT 7.2 over SSH"
mkdir SNOPT
scp -qr ${{ secrets.SNOPT_LOCATION_72 }} SNOPT
SNOPT="-s SNOPT/source"
elif [[ "${{ matrix.SNOPT }}" ]]; then
echo "SNOPT version ${{ matrix.SNOPT }} was requested but source is not available"
fi
if [[ "${{ matrix.LINEAR_SOLVER }}" == "hsl" ]]; then
if "${{ secrets.HSL_LOCATION }}" ]]; then
scp -q ${{ secrets.HSL_LOCATION }} hsl.tar.gz
LINEAR_SOLVER="-l hsl -t hsl.tar.gz"
else
echo "---------------------------------------------------------------------------"
echo "HSL was requested but source is not available, using default linear solver."
echo "---------------------------------------------------------------------------"
fi
elif [[ "${{ matrix.LINEAR_SOLVER }}" == "pardiso" ]]; then
echo "-------------------------------------------------------------------------------"
echo "Pardiso requires Intel compilers, which are not installed. The build will fail."
echo "-------------------------------------------------------------------------------"
LINEAR_SOLVER="-l pardiso"
fi
if [[ "${{ matrix.NO_IPOPT }}" ]]; then
NO_IPOPT="--no-ipopt"
fi
if [[ "${{ matrix.FORCE_BUILD }}" ]]; then
FORCE_BUILD="--force-build"
fi
echo "build_pyoptsparse -v $BRANCH $FORCE_BUILD $PAROPT $SNOPT $NO_IPOPT $LINEAR_SOLVER"
build_pyoptsparse -v $BRANCH $FORCE_BUILD $PAROPT $SNOPT $NO_IPOPT $LINEAR_SOLVER -d
echo "BRANCH=${BRANCH}" >> $GITHUB_ENV
- name: Display build log
if: failure()
run: |
for f in $(find /tmp/ -name 'meson-log.txt'); do
echo "============================================================="
echo $f
echo "============================================================="
cat $f
done
if test -d /private/var/folders; then
for f in $(find /private/var/folders/ -name 'meson-log.txt'); do
echo "============================================================="
echo $f
echo "============================================================="
cat $f
done
for f in $(find /private/var/folders/ -name 'compile.log'); do
echo "============================================================="
echo $f
echo "============================================================="
cat $f
done
fi
# Enable tmate debugging of manually-triggered workflows if the input option was provided
#
# To access the terminal through the web-interface:
# 1. Click on the web-browser link printed out in this action from the github
# workflow terminal
# 2. Press cntrl + c in the new tab that opens up to reveal the terminal
# 3. To activate the conda environment run:
# $ source $CONDA/etc/profile.d/conda.sh
# $ conda activate test
- name: Setup tmate session
if: github.event_name == 'workflow_dispatch' && inputs.debug_enabled && inputs.job_name == matrix.NAME
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
- name: Setup tmate session after failure
if: github.event_name == 'workflow_dispatch' && inputs.debug_enabled && inputs.job_name == matrix.NAME && failure()
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
- name: Display environment after
run: |
conda info
conda list
echo "============================================================="
echo "Check installed versions of Python, Numpy and Scipy"
echo "============================================================="
python -c "import sys; assert str(sys.version).startswith(str(${{ matrix.PY }})), \
f'Python version {sys.version} is not the requested version (${{ matrix.PY }})'"
python -c "import numpy; assert str(numpy.__version__).startswith(str(${{ matrix.NUMPY }})), \
f'Numpy version {numpy.__version__} is not the requested version (${{ matrix.NUMPY }})'"
python -c "import scipy; assert str(scipy.__version__).startswith(str(${{ matrix.SCIPY }})), \
f'Scipy version {scipy.__version__} is not the requested version (${{ matrix.SCIPY }})'"
- name: Run tests
run: |
python -m pip install testflo parameterized six
echo "============================================================="
echo "Run tests from pyoptsparse repository"
echo "============================================================="
unset DYLD_LIBRARY_PATH
if [[ "$BRANCH" == "" ]]; then
BRANCH=`python -c "from build_pyoptsparse import build_info; print(build_info['pyoptsparse']['branch'])"`
BRANCH="-b $BRANCH"
fi
echo "git clone $BRANCH https://github.com/mdolab/pyoptsparse"
git clone $BRANCH https://github.com/mdolab/pyoptsparse
cd pyoptsparse/test*/
testflo --pre_announce --timeout=120 --show_skipped .
- name: Audit dependencies
id: audit
continue-on-error: true
run: |
python -m pip install pip-audit
echo "============================================================="
echo "Scan environment for packages with known vulnerabilities"
echo "============================================================="
python -m pip_audit
- name: Slack audit warnings
if: steps.audit.outcome == 'failure' && matrix.NAME != 'Ubuntu Oldest'
uses: act10ns/[email protected]
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
status: 'warning'
message: |
pip-audit detected vulnerabilities.
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
- name: Notify slack
uses: act10ns/[email protected]
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
status: ${{ job.status }}
if: failure()