-
Notifications
You must be signed in to change notification settings - Fork 20
387 lines (338 loc) · 13.1 KB
/
ci.yaml
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
name: CI
on:
push:
branches:
- master
tags:
# Version tags.
#
# Tags matching this pattern will cause the "release" job below to run,
# so edit it carefully! It should not match arbitrary tags.
- "[0-9]+.[0-9]+.[0-9]+*"
pull_request:
workflow_dispatch:
# Routinely check that we continue to work in the face of external changes.
schedule:
# Every day at 17:42 UTC / 9:42 Seattle (winter) / 10:42 Seattle (summer)
- cron: "42 17 * * *"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: nextstrain/.github/actions/shellcheck@master
test-source:
name: test-source (python=${{ matrix.python }} os=${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
python:
- '3.6'
- '3.7'
- '3.8'
- '3.9'
- '3.10'
# Python 3.6 is not available on Ubuntu 22.04, which is what
# ubuntu-latest points to as of Q4 2022¹, so replace that job with 3.6
# on Ubuntu 20.04.
# -trs, 22 Nov 2022
#
# ¹ <https://github.blog/changelog/2022-11-09-github-actions-ubuntu-latest-workflows-will-use-ubuntu-22-04/>
#
# A bodged https://github.com/actions/python-version build of 3.7.17
# for macOS mistakenly doesn't include the bz2 module of the stdlib¹,
# which breaks us because some of our deps (fsspec, at the least)
# assume bz2 is available² (though that will be fixed in its next
# release³). Replace the 3.7 macOS job with a 3.7.16 job.
# -trs, 22 June 2023
#
# ¹ <https://github.com/actions/setup-python/issues/682>
# ² <https://github.com/nextstrain/cli/pull/289#issuecomment-1595417903>
# ³ <https://github.com/fsspec/filesystem_spec/pull/1295>
exclude:
- os: ubuntu-latest
python: '3.6'
- os: macos-latest
python: '3.7'
include:
- os: ubuntu-20.04
python: '3.6'
- os: macos-latest
python: '3.7.16'
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python }}
- name: Install Nextstrain CLI
run: python3 -m pip install --upgrade '.[dev]'
- run: ./devel/pytest -v
build-dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
with:
python-version: "3.10"
# Install up-to-date packaging toolchain.
- run: python3 -m pip install --upgrade pip setuptools wheel
- run: python3 -m pip install --upgrade build
# Update version to include local git rev if we're not building a release tag.
- if: github.ref_type != 'tag'
run: |
version="$(./devel/read-version)"
git_rev="$(git rev-parse --short @)"
./devel/update-version "${version%%+*}+git.${git_rev}"
# Build dists.
- run: python3 -m build
# Upload dists as workflow artifacts.
- uses: actions/upload-artifact@v3
with:
name: dist
path: dist/
build-standalone:
needs: build-dist
strategy:
fail-fast: false
matrix:
# Generally we want to build on the oldest supported OS to maximize the
# final binary's compatibility. See pyoxidizer's docs for more
# considerations affecting the choice of build machine OS¹ and future
# plans for robust, turnkey build environments².
#
# On Linux, we build inside a container to avoid portability issues, so
# the container's host OS version here doesn't have an impact (other
# than CI stability).
#
# ¹ https://pyoxidizer.readthedocs.io/en/stable/pyoxidizer_distributing_binary_portability.html
# ² https://pyoxidizer.readthedocs.io/en/stable/pyoxidizer_status.html#an-official-build-environment
#
# XXX TODO: GitHub doesn't yet host any runners on M1 (Apple Silicon,
# aarch64, arm64) hardware, and we don't have M1 hardware on which to
# self-host a runner. Amazon's mac2.metal EC2 instances are M1, but
# they cost a minimum of ~$15/day. It would be cheaper to buy an M1
# Mac Mini for ~$700 which would pay for itself in less than 2 months.
# -trs, 31 May 2022
include:
- os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
exe: nextstrain
- os: macos-11
target: x86_64-apple-darwin
exe: nextstrain
- os: windows-2019
target: x86_64-pc-windows-msvc
exe: nextstrain.exe
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
# Note that this Python version doesn't impact the actual build.
- uses: actions/setup-python@v3
with:
python-version: "3.10"
# Build the executable + necessary external files from the dists.
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: dist
path: dist/
- name: Set DIST, DIST_VERSION, and INSTALLATION_ARCHIVE_STEM
run: |
# shellcheck disable=SC2034
DISTS=(dist/nextstrain_cli-*-py3-none-any.whl)
DIST="${DISTS[0]}"
DIST_VERSION="$DIST"
DIST_VERSION="${DIST_VERSION#dist/nextstrain_cli-}"
DIST_VERSION="${DIST_VERSION%-py3-none-any.whl}"
INSTALLATION_ARCHIVE_STEM="nextstrain-cli-${DIST_VERSION}-standalone-${{ matrix.target }}"
for var in DIST DIST_VERSION INSTALLATION_ARCHIVE_STEM; do
echo "${var}=${!var}" | tee -a "$GITHUB_ENV"
done
- run: |
./devel/pyoxidizer build \
--release \
--target-triple ${{ matrix.target }} \
--var NEXTSTRAIN_CLI_DIST "$DIST"
# Analyze the executable for potential portability issues.
#
# This is for informational purposes only in build logs, so we don't care
# if it fails. Currently it only works on Linux, though it's supposed to
# eventually work on all platforms supported by pyoxidizer.
- if: runner.os == 'Linux'
run: ./devel/pyoxidizer analyze build/${{ matrix.target }}/release/installation/${{ matrix.exe }}
continue-on-error: true
# XXX TODO: Review and report on licensing of all the stuff built into
# the binary, as bundling things statically can trigger different license
# terms than "normal" installs (e.g. via pip). See also pyoxidizer's
# docs about this and the tooling it includes to support license review.¹
# -trs, 1 June 2022
#
# ¹ https://pyoxidizer.readthedocs.io/en/stable/pyoxidizer_packaging_licensing.html#licensing-considerations
# Create installation archive.
#
# Use tar on Unix to preserve file modes (e.g. the executable bit), thus
# avoiding having to restore them manually after archive extraction. Use
# zip on Windows because it's a native format which requires no extra
# tooling.
- if: runner.os != 'Windows'
run: tar czvpf "$INSTALLATION_ARCHIVE_STEM.tar.gz" -C build/${{ matrix.target }}/release/installation/ .
- if: runner.os == 'Windows'
run: Compress-Archive -DestinationPath "$Env:INSTALLATION_ARCHIVE_STEM.zip" -Path build/${{ matrix.target }}/release/installation/*
shell: pwsh
# Upload installation archive as a workflow artifact.
#
# At least one path needs to match, or this errors.
- uses: actions/upload-artifact@v3
with:
name: standalone-${{ matrix.target }}
path: |
${{ env.INSTALLATION_ARCHIVE_STEM }}.tar.gz
${{ env.INSTALLATION_ARCHIVE_STEM }}.zip
if-no-files-found: error
# Quick smoke test that the executable at least runs! Useful before
# launching the more extensive tests below.
- run: ./build/${{ matrix.target }}/release/installation/${{ matrix.exe }} --help
test-dist:
needs: build-dist
name: test-dist (python=${{ matrix.python }} os=${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
python:
- '3.6'
- '3.7'
- '3.8'
- '3.9'
# XXX TODO: Add 3.10 here once supported by Conda/Bioconda/Conda Forge.
runs-on: ${{ matrix.os }}
defaults:
run:
# Add -l for setup-integration-tests → setup-miniconda → automatic
# activation of "test" environment.
shell: bash -l -eo pipefail {0}
steps:
- uses: actions/checkout@v3
with:
path: src/
- uses: ./src/.github/actions/setup-integration-tests
with:
python-version: ${{ matrix.python }}
- uses: actions/download-artifact@v3
with:
name: dist
path: dist/
- name: Install Nextstrain CLI
run: python3 -m pip install --upgrade dist/nextstrain_cli-*-py3-none-any.whl
- uses: ./src/.github/actions/run-integration-tests
test-standalone:
needs: build-standalone
name: test-standalone (os=${{ matrix.os}}, target=${{ matrix.target }})
strategy:
fail-fast: false
matrix:
# Test on all the platforms available via GitHub Actions.
#
# Ideally we'd test on machines with ~fresh OS installs. The kitchen
# sink of development/build software pre-installed into GitHub Action's
# virtual-environments has a decent risk of making this CI blind to
# end-user runtime issues with our binaries (e.g. missing DLLs). Such
# fresh CI machines are not readily available, however, since
# pre-installation is convenient for builds.
#
# XXX TODO: macOS aarch64 (M1, Apple Silicon, arm64); see above.
include:
- { os: ubuntu-20.04, target: x86_64-unknown-linux-gnu }
- { os: ubuntu-22.04, target: x86_64-unknown-linux-gnu }
- { os: macos-11, target: x86_64-apple-darwin }
- { os: macos-12, target: x86_64-apple-darwin }
- { os: windows-2019, target: x86_64-pc-windows-msvc }
- { os: windows-2022, target: x86_64-pc-windows-msvc }
runs-on: ${{matrix.os}}
defaults:
run:
# Add -l for setup-integration-tests → setup-miniconda → automatic
# activation of "test" environment.
shell: bash -l -eo pipefail {0}
steps:
- uses: actions/checkout@v3
with:
path: src/
- uses: ./src/.github/actions/setup-integration-tests
with:
python-version: '3.9'
# Download and extract the installation archive.
- uses: actions/download-artifact@v3
with:
name: standalone-${{ matrix.target }}
- if: runner.os != 'Windows'
run: tar xzvpf nextstrain-cli-*-standalone-${{ matrix.target }}.tar.gz
- if: runner.os == 'Windows'
run: Expand-Archive -Path nextstrain-cli-*-standalone-${{ matrix.target }}.zip -DestinationPath .
shell: pwsh
- run: echo "$PWD" >> "$GITHUB_PATH"
- uses: ./src/.github/actions/run-integration-tests
doc:
uses: nextstrain/.github/.github/workflows/docs-ci.yaml@master
with:
docs-directory: doc/
pip-install-target: .[dev]
make-target: dirhtml
release:
# Restricted to version tags by the "on: push: tags: …" config at the top.
if: |2
github.event_name == 'push'
&& github.ref_type == 'tag'
needs:
- build-dist
- build-standalone
- test-source
- test-dist
- test-standalone
- lint
- doc
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# In actions/checkout@v3 above, annotated tags are intentionally
# **overwritten** and converted to a lightweight tag. Forcibly restore
# the annotated tag object from the remote so we can verify/use it later.
- run: git fetch --force origin tag "$GITHUB_REF_NAME"
- uses: actions/setup-python@v3
with:
python-version: "3.10"
- run: python3 -m pip install --upgrade twine
- uses: actions/download-artifact@v3
with:
name: dist
path: dist/
- uses: actions/download-artifact@v3
with:
name: standalone-x86_64-unknown-linux-gnu
- uses: actions/download-artifact@v3
with:
name: standalone-x86_64-apple-darwin
- uses: actions/download-artifact@v3
with:
name: standalone-x86_64-pc-windows-msvc
- run: twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
TWINE_REPOSITORY_URL: https://upload.pypi.org/legacy/
- run: ./devel/create-github-release "${{github.ref_name}}" dist/* nextstrain-cli-*-standalone-*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}