Skip to content

Latest commit

 

History

History
247 lines (174 loc) · 9.7 KB

File metadata and controls

247 lines (174 loc) · 9.7 KB

Nextstrain CLI Development

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

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

Running with local changes

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.)

External resources

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.

Releasing

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.

Recovering from release CI failures

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.

Updating the Bioconda recipe

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

Tests are run with pytest. To run everything, use:

./devel/pytest

This includes Cram and the type annotation and static analysis checks described below.

Cram

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.

Type annotations and static analysis

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!

Documentation

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.