CI #1578
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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@v4 | |
- 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.8' | |
- '3.9' | |
- '3.10' | |
- '3.11' | |
- '3.12' | |
runs-on: ${{ matrix.os }} | |
defaults: | |
run: | |
shell: bash | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v5 | |
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@v4 | |
- uses: actions/setup-python@v5 | |
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@v4 | |
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 | |
include: | |
- os: ubuntu-22.04 | |
target: x86_64-unknown-linux-gnu | |
exe: nextstrain | |
- os: macos-13 | |
target: x86_64-apple-darwin | |
exe: nextstrain | |
- os: macos-14 | |
target: aarch64-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@v5 | |
with: | |
python-version: "3.10" | |
# Build the executable + necessary external files from the dists. | |
- uses: actions/checkout@v4 | |
- uses: actions/download-artifact@v4 | |
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@v4 | |
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 | |
write-install-commands: | |
needs: build-standalone | |
runs-on: ubuntu-latest | |
steps: | |
- name: Write installation commands to job summary | |
run: | | |
cat >"$GITHUB_STEP_SUMMARY" <<'~~' | |
Build complete. Commands to install locally: | |
Linux: | |
```bash | |
curl -fsSL --proto '=https' https://nextstrain.org/cli/installer/linux | bash -s ci-build/${{ github.run_id }} | |
``` | |
macOS: | |
```bash | |
curl -fsSL --proto '=https' https://nextstrain.org/cli/installer/mac | bash -s ci-build/${{ github.run_id }} | |
``` | |
Windows: | |
```powershell | |
Invoke-Expression "& { $(Invoke-RestMethod https://nextstrain.org/cli/installer/windows) } ci-build/${{ github.run_id }}" | |
``` | |
~~ | |
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.8' | |
- '3.9' | |
- '3.10' | |
# XXX TODO: Add 3.11 here once supported by bioconda: https://github.com/nextstrain/augur/issues/1334 | |
# XXX TODO: Add 3.12 here once supported by bioconda: https://github.com/nextstrain/augur/issues/1334 | |
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@v4 | |
with: | |
path: src/ | |
- uses: ./src/.github/actions/setup-integration-tests | |
with: | |
python-version: ${{ matrix.python }} | |
- uses: actions/download-artifact@v4 | |
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. | |
include: | |
- { os: ubuntu-20.04, target: x86_64-unknown-linux-gnu } | |
- { os: ubuntu-22.04, target: x86_64-unknown-linux-gnu } | |
- { os: ubuntu-24.04, target: x86_64-unknown-linux-gnu } | |
- { os: macos-13, target: x86_64-apple-darwin } | |
- { os: macos-14, target: x86_64-apple-darwin } | |
- { os: macos-15, target: x86_64-apple-darwin } | |
- { os: macos-14, target: aarch64-apple-darwin } | |
- { os: macos-15, target: aarch64-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@v4 | |
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@v4 | |
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@v4 | |
# In actions/checkout@v4 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@v5 | |
with: | |
python-version: "3.10" | |
- run: python3 -m pip install --upgrade twine | |
- uses: actions/download-artifact@v4 | |
with: | |
name: dist | |
path: dist/ | |
- uses: actions/download-artifact@v4 | |
with: | |
name: standalone-x86_64-unknown-linux-gnu | |
- uses: actions/download-artifact@v4 | |
with: | |
name: standalone-x86_64-apple-darwin | |
- uses: actions/download-artifact@v4 | |
with: | |
name: standalone-aarch64-apple-darwin | |
- uses: actions/download-artifact@v4 | |
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 }} |