Development of nextstrain-cli happens at https://github.com/nextstrain/cli.
We currently target compatibility with Python 3.8 and higher.
Versions for this project follow the Semantic Versioning rules.
Setup an isolated development environment in .venv/ with:
./devel/setup-venv
Activate the venv to run any of the commands below:
source .venv/bin/activate
(Or alternatively, run the commands below via ./devel/venv-run ….)
Now test that you can run:
nextstrain --help
The development environment includes our dev tools (described below):
pytest # runs doctests as well as cram, pyright, and flake8
cram tests/*.cram
pyright
flake8
make -C doc livehtml
The project is installed into editable mode when using the venv setup above, so any changes you make during development will be used automatically.
If you need to run with local changes in setups without editable mode, you can
run ./bin/nextstrain to test your local changes without installing them.
(Note that ./bin/nextstrain is not the script that gets installed by pip as
nextstrain; that script is generated by the entry_points configuration in
setup.py.)
Environment variables can be used to change the location or identity of external resources/services used by some Nextstrain CLI commands. This is helpful when performing manual integration testing against development or testing resources.
When running the nextstrain.org server locally, you can make the
nextstrain remote family of commands talk to it instead of the real
nextstrain.org by setting NEXTSTRAIN_DOT_ORG, e.g.:
NEXTSTRAIN_DOT_ORG=http://localhost:5000 \
nextstrain remote ls nextstrain.org/groups/test
If you need authenticated access and the local server is using the AWS Cognito
resources from our "testing" configuration, you can configure nextstrain
with the same, e.g.:
export NEXTSTRAIN_DOT_ORG=http://localhost:5000
nextstrain login
nextstrain whoami
nextstrain remote ls groups/test-private
Most of the times the above is not necessary, however, as you can specify the local remote explicitly instead of pretending it's nextstrain.org, e.g.:
nextstrain remote ls http://localhost:5000/groups/test
nextstrain login http://localhost:5000
nextstrain whoami http://localhost:5000
nextstrain remote ls http://localhost:5000/groups/test-private
Setting NEXTSTRAIN_DOT_ORG is mostly useful when testing the default-remote
code paths themselves.
New releases are made frequently and tagged in git using a signed tag.
There is a ./devel/release script which will prepare a new release from your
local repository. Run this script using the isolated development environment.
It ends with instructions for you on how to push the release commit/tag.
When a release tag is pushed, the CI workflow builds source distributions and built distributions (wheels), tests them, and if tests pass, uploads them to the nextstrain-cli project on PyPi.
The GitHub repository is configured with rulesets restricting tag management such that only maintainers have bypass permission to create tags and only admins have bypass permission to delete and update tags.
When CI for a release fails due to transient errors (like DNS or other network issues), it can be recovered by retrying the GitHub Action workflow run.
However, when CI for a release fails due to non-transient errors that require a
code change, the recovery method is to cut a new release. If only non-packaged
changes were made (e.g. fixes to the CI process itself but not in
nextstrain), then bump the version to a post-release version (e.g.
X.Y.Z.postN). Otherwise, use an appropriate semantic version bump. Update
the changelog to note the unreleased version as such and that the new version
contains all the changes from the unreleased version. You can compare to
previous unreleased versions for wording.
Two examples of recovering from a failed release:
-
The release of 7.3.0 failed due to issues with CI. CI was fixed and 7.3.0.post1 was released.
-
The release of 6.0.1 failed and required changes to packaged code. 6.0.2 was released with the fix.
Typically the autobump PR created by BiocondaBot when it notices the PyPI release will be sufficient. Look it over and comment:
@BiocondaBot please add label
to get it reviewed and merged.
However, if there are changes to the minimum Python version or dependency list in setup.py, then
create a PR in bioconda-recipes translating the changes in setup.py to
Conda package match specifications.
Follow instructions at nextstrain/bioconda-recipes/README.md.
You'll need to ask that the autobump PR is closed in favor of your own PR.
Tests are run with pytest. To run everything, use:
./devel/pytest
This includes Cram and the type annotation and static analysis checks described below.
Tests for the command-line interface use Cram and
are written in tests/*.cram files. You can run individual test files, e.g.:
$ cram -v tests/version.cram
tests/version.cram: passed
# Ran 1 tests, 0 skipped, 0 failed.
Cram tests should always start by sourcing tests/env so that they run
identically regardless of if they're run directly with cram or via
./devel/pytest.
Our goal is to gradually add type annotations to our code so that we can catch errors earlier and be explicit about the interfaces expected and provided. Annotation pairs well with the functional approach taken by the package.
During development you can run static type checks using pyright:
$ npx pyright
...
Found 40 source files
0 errors, 0 warnings, 0 infos
Completed in 2sec
There are also many editor integrations for Pyright.
The typing_extensions module should be used for features not yet available
in the the standard typings module of supported Python versions.
We also use Flake8 for some static analysis checks focusing on runtime safety and correctness. You can run them like this:
$ flake8
# No output is good!
A Sphinx project for Nextstrain CLI's documentation, primarily reference and
explanatory material, lives in the doc/
directory. Pages are written in reStructuredText (rST), though some older
pages originally written in Markdown haven't been converted yet.
To locally build the HTML version of the documentation (i.e. what's served at https://docs.nextstrain.org/projects/cli/), run:
$ make -C doc livehtml
This will start a server on http://localhost:8000 which you can browse. Changes to source documentation files will be reflected automatically.
The rST source documentation files for the individual nextstrain commands are
generated from the Python source files and checked into version control.
Changes should be kept in sync by regenerating with:
$ ./devel/generate-command-doc
This will emit the file paths it updates, if any. The
devel/generate-command-doc program also has --diff and --check modes
which may be helpful during development; see --help for details.
The project changelog, CHANGES.md, is included with [MyST-Parser][] Markdown
extensions in the documentation as the generated file doc/changes.md. Keep
it in sync by regenerating with:
$ ./devel/generate-changes-doc
This behaves similarly to devel/generate-command-doc.
You may sync all generated doc with:
$ ./devel/generate-doc
This also happens automatically as part of the documentation build process to ensure the built docs always reflect the current source. Tests run in CI ensure the generated files are current and don't vary based on ambient environmental factors.