From 1a352ddf559f62d40b6fbb34608fffd493db0ade Mon Sep 17 00:00:00 2001 From: Harsha Narayana Date: Wed, 7 Apr 2021 02:02:01 +0530 Subject: [PATCH] GIT-2023: Enable GitHub Actions support (#2050) * GIT-2023: Enable GitHub Actions support * GIT-2023: fix tox runtime trigger * GIT-2023: add top level action name * GIT-2023: rename tox step name * GIT-2023: rename build task names * GIT-2023: remove macos and windows + nightly versions * GIT-2023: add macos and windows back to os matrix * GIT-2023: expermiental flag to conditionally skip failure * GIT-2023: enable using custom actions * GIT-2023: fix matrix config rendering type * GIT-2023: fix naming issue with os label * GIT-2023: enable type-checking env for tox * GIT-2023: enable pypy3.7 support * GIT-2023: enable pypy experimental flag * GIT-2023: add pypy tox env config * add max timeout of 5 min for pypy tests * GIT-2023: add timeout for each actions * GIT-2023: fix codeQL workflow actions * GIT-2023: limit test matrix to ubuntu and support on demand * GIT-2023: enable docker image publish on release * GIT-2023: fix on-demand pypy action * GIT-2023: enable pypi publish workflow * GIT-2023: enable verbose logs for py3.9 * GIT-2023: reduce py3.9 verbosity * GIT-2023: enable docs linter * GIT-2023: extend test matrix to include macos + windows * GIT-2023: move windows based workflow to standalone task * GIT-2023: fix windows test matrix * GIT-2023: mark py39-no-ext as flaky test * GIT-2023: mark flaky test * GIT-2023: make timeout internal to steps for ease of management * GIT-2023: rename image publish step name * GIT-2023: mark keep alive client timeout for linux only * GIT-2023: enable retries on test failure Co-authored-by: Adam Hopkins --- .github/workflows/codeql-analysis.yml | 37 ++------------------- .github/workflows/on-demand.yml | 39 ++++++++++++++++++++++ .github/workflows/pr-bandit.yml | 32 ++++++++++++++++++ .github/workflows/pr-docs.yml | 29 ++++++++++++++++ .github/workflows/pr-linter.yml | 30 +++++++++++++++++ .github/workflows/pr-python-pypy.yml | 37 +++++++++++++++++++++ .github/workflows/pr-python37.yml | 34 +++++++++++++++++++ .github/workflows/pr-python38.yml | 34 +++++++++++++++++++ .github/workflows/pr-python39.yml | 36 ++++++++++++++++++++ .github/workflows/pr-type-check.yml | 32 ++++++++++++++++++ .github/workflows/pr-windows.yml | 33 ++++++++++++++++++ .github/workflows/publish-images.yml | 48 +++++++++++++++++++++++++++ .github/workflows/publish-package.yml | 28 ++++++++++++++++ docker/Dockerfile | 29 +++------------- docker/Dockerfile-base | 9 +++++ docker/bin/entrypoint.sh | 11 ------ docker/bin/install_python.sh | 17 ---------- hack/Dockerfile | 6 ++++ tests/test_keep_alive_timeout.py | 5 ++- tests/test_unix_socket.py | 5 +++ tox.ini | 2 +- 21 files changed, 444 insertions(+), 89 deletions(-) create mode 100644 .github/workflows/on-demand.yml create mode 100644 .github/workflows/pr-bandit.yml create mode 100644 .github/workflows/pr-docs.yml create mode 100644 .github/workflows/pr-linter.yml create mode 100644 .github/workflows/pr-python-pypy.yml create mode 100644 .github/workflows/pr-python37.yml create mode 100644 .github/workflows/pr-python38.yml create mode 100644 .github/workflows/pr-python39.yml create mode 100644 .github/workflows/pr-type-check.yml create mode 100644 .github/workflows/pr-windows.yml create mode 100644 .github/workflows/publish-images.yml create mode 100644 .github/workflows/publish-package.yml create mode 100644 docker/Dockerfile-base delete mode 100755 docker/bin/entrypoint.sh delete mode 100755 docker/bin/install_python.sh create mode 100644 hack/Dockerfile diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 391aad58..18415b68 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,22 +1,10 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# name: "CodeQL" on: push: - branches: [ master ] + branches: [ main ] pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] + branches: [ main ] schedule: - cron: '25 16 * * 0' @@ -29,39 +17,18 @@ jobs: fail-fast: false matrix: language: [ 'python' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - name: Checkout repository uses: actions/checkout@v2 - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/on-demand.yml b/.github/workflows/on-demand.yml new file mode 100644 index 00000000..1aa721f3 --- /dev/null +++ b/.github/workflows/on-demand.yml @@ -0,0 +1,39 @@ +name: On Demand Task +on: + workflow_dispatch: + inputs: + python-version: + description: 'Version of Python to use for running Test' + required: false + default: "3.8" + tox-env: + description: 'Test Environment to Run' + required: true + default: '' + os: + description: 'Operating System to Run Test on' + required: false + default: ubuntu-latest +jobs: + onDemand: + name: tox-${{ matrix.config.tox-env }}-on-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["${{ github.event.inputs.os}}"] + config: + - { tox-env: "${{ github.event.inputs.tox-env }}", py-version: "${{ github.event.inputs.python-version }}"} + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Run tests + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.py-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" + experimental-ignore-error: "yes" diff --git a/.github/workflows/pr-bandit.yml b/.github/workflows/pr-bandit.yml new file mode 100644 index 00000000..6ba4c0d5 --- /dev/null +++ b/.github/workflows/pr-bandit.yml @@ -0,0 +1,32 @@ +name: Security Analysis +on: + pull_request: + branches: + - main + +jobs: + bandit: + name: type-check-${{ matrix.config.python-version }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + config: + - { python-version: 3.7, tox-env: security} + - { python-version: 3.8, tox-env: security} + - { python-version: 3.9, tox-env: security} + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Linter Checks + id: linter-check + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" diff --git a/.github/workflows/pr-docs.yml b/.github/workflows/pr-docs.yml new file mode 100644 index 00000000..1a6871c2 --- /dev/null +++ b/.github/workflows/pr-docs.yml @@ -0,0 +1,29 @@ +name: Document Linter +on: + pull_request: + branches: + - main + +jobs: + docsLinter: + name: Lint Documentation + runs-on: ubuntu-latest + strategy: + matrix: + config: + - {python-version: "3.8", tox-env: "docs"} + fail-fast: false + + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Run Document Linter + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" diff --git a/.github/workflows/pr-linter.yml b/.github/workflows/pr-linter.yml new file mode 100644 index 00000000..6165a988 --- /dev/null +++ b/.github/workflows/pr-linter.yml @@ -0,0 +1,30 @@ +name: Linter Checks +on: + pull_request: + branches: + - main + +jobs: + linter: + name: lint + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + config: + - { python-version: 3.8, tox-env: lint} + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Linter Checks + id: linter-check + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" diff --git a/.github/workflows/pr-python-pypy.yml b/.github/workflows/pr-python-pypy.yml new file mode 100644 index 00000000..6f683c57 --- /dev/null +++ b/.github/workflows/pr-python-pypy.yml @@ -0,0 +1,37 @@ +name: Python PyPy Tests +on: + workflow_dispatch: + inputs: + tox-env: + description: 'Tox Env to run on the PyPy Infra' + required: false + default: 'pypy37' + pypy-version: + description: 'Version of PyPy to use' + required: false + default: 'pypy-3.7' +jobs: + testPyPy: + name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + config: + - { python-version: "${{ github.event.inputs.pypy-version }}", tox-env: "${{ github.event.inputs.tox-env }}" } + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Unit Tests + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" + experimental-ignore-error: "true" + command-timeout: '600000' diff --git a/.github/workflows/pr-python37.yml b/.github/workflows/pr-python37.yml new file mode 100644 index 00000000..c1a53112 --- /dev/null +++ b/.github/workflows/pr-python37.yml @@ -0,0 +1,34 @@ +name: Python 3.7 Tests +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + testPy37: + name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + config: + - { python-version: 3.7, tox-env: py37 } + - { python-version: 3.7, tox-env: py37-no-ext } + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Unit Tests + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" + test-failure-retry: "3" diff --git a/.github/workflows/pr-python38.yml b/.github/workflows/pr-python38.yml new file mode 100644 index 00000000..88745bee --- /dev/null +++ b/.github/workflows/pr-python38.yml @@ -0,0 +1,34 @@ +name: Python 3.8 Tests +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + testPy38: + name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + config: + - { python-version: 3.8, tox-env: py38} + - { python-version: 3.8, tox-env: py38-no-ext} + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Unit Tests + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" + test-failure-retry: "3" \ No newline at end of file diff --git a/.github/workflows/pr-python39.yml b/.github/workflows/pr-python39.yml new file mode 100644 index 00000000..6f96a827 --- /dev/null +++ b/.github/workflows/pr-python39.yml @@ -0,0 +1,36 @@ +name: Python 3.9 Tests +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + testPy39: + name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + config: + - { python-version: 3.9, tox-env: py39, ignore-error-flake: "false", command-timeout: '0'} + - { python-version: 3.9, tox-env: py39-no-ext, ignore-error-flake: "true", command-timeout: '600000'} + steps: + - name: Checkout the Repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Unit Tests + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }},-vv=''" + experimental-ignore-error: "${{ matrix.config.ignore-error-flake }}" + command-timeout: "${{ matrix.config.command-timeout }}" + test-failure-retry: "3" diff --git a/.github/workflows/pr-type-check.yml b/.github/workflows/pr-type-check.yml new file mode 100644 index 00000000..c5d12a74 --- /dev/null +++ b/.github/workflows/pr-type-check.yml @@ -0,0 +1,32 @@ +name: Typing Checks +on: + pull_request: + branches: + - main + +jobs: + typeChecking: + name: type-check-${{ matrix.config.python-version }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + config: + - { python-version: 3.7, tox-env: type-checking} + - { python-version: 3.8, tox-env: type-checking} + - { python-version: 3.9, tox-env: type-checking} + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + id: checkout-branch + + - name: Run Linter Checks + id: linter-check + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" diff --git a/.github/workflows/pr-windows.yml b/.github/workflows/pr-windows.yml new file mode 100644 index 00000000..d2875766 --- /dev/null +++ b/.github/workflows/pr-windows.yml @@ -0,0 +1,33 @@ +name: Run Unit Tests on Windows +on: + pull_request: + branches: + - main + +jobs: + testsOnWindows: + name: ut-${{ matrix.config.tox-env }} + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + config: + - { python-version: 3.7, tox-env: py37-no-ext } + - { python-version: 3.8, tox-env: py38-no-ext } + - { python-version: 3.9, tox-env: py39-no-ext } + - { python-version: pypy-3.7, tox-env: pypy37-no-ext } + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Run Unit Tests + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.config.python-version }} + test-infra-tool: tox + test-infra-version: latest + action: tests + test-additional-args: "-e=${{ matrix.config.tox-env }}" + experimental-ignore-error: "true" + command-timeout: '600000' diff --git a/.github/workflows/publish-images.yml b/.github/workflows/publish-images.yml new file mode 100644 index 00000000..8c78f96c --- /dev/null +++ b/.github/workflows/publish-images.yml @@ -0,0 +1,48 @@ +name: Publish Docker Images +on: + workflow_run: + workflows: + - 'Publish Artifacts' + types: + - completed + +jobs: + publishDockerImages: + name: Docker Image Build [${{ matrix.python-version }}] + runs-on: ubuntu-latest + + strategy: + fail-fast: true + matrix: + python-version: ["3.7", "3.8", "3.9"] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Build Latest Base images for ${{ matrix.python-version }} + uses: harshanarayana/custom-actions@main + with: + docker-image-base-name: sanicframework/sanic-build + ignore-python-setup: 'true' + dockerfile-base-dir: './docker' + action: 'image-publish' + docker-image-tag: "${{ matrix.python-version }}" + docker-file-suffix: "base" + docker-build-args: "PYTHON_VERSION=${{ matrix.python-version }}" + registry-auth-user: ${{ secrets.DOCKER_ACCESS_USER }} + registry-auth-password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + push-images: 'true' + + - name: Publish Sanic Docker Image for ${{ matrix.python-version }} + uses: harshanarayana/custom-actions@main + with: + docker-image-base-name: sanicframework/sanic + ignore-python-setup: 'true' + dockerfile-base-dir: './docker' + action: 'image-publish' + docker-build-args: "BASE_IMAGE_TAG=${{ matrix.python-version }}" + docker-image-prefix: "${{ matrix.python-version }}" + registry-auth-user: ${{ secrets.DOCKER_ACCESS_USER }} + registry-auth-password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + push-images: 'true' diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml new file mode 100644 index 00000000..cbfbd3d8 --- /dev/null +++ b/.github/workflows/publish-package.yml @@ -0,0 +1,28 @@ +name: Publish Artifacts +on: + push: + tags: + - 'v*.*.*' +jobs: + publishPythonPackage: + name: Publishing Sanic Release Artifacts + runs-on: ubuntu-latest + + strategy: + fail-fast: true + matrix: + python-version: ["3.8"] + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Publish Python Package + uses: harshanarayana/custom-actions@main + with: + python-version: ${{ matrix.python-version }} + package-infra-name: 'twine' + pypi-user: __token__ + pypi-access-token: ${{ secrets.PYPI_ACCESS_TOKEN }} + action: 'package-publish' + pypi-verify-metadata: 'true' diff --git a/docker/Dockerfile b/docker/Dockerfile index dc7832ff..245f9d91 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,28 +1,9 @@ -FROM alpine:3.7 +ARG BASE_IMAGE_TAG -RUN apk add --no-cache --update \ - curl \ - bash \ - build-base \ - ca-certificates \ - git \ - bzip2-dev \ - linux-headers \ - ncurses-dev \ - openssl \ - openssl-dev \ - readline-dev \ - sqlite-dev +FROM sanicframework/sanic-build:${BASE_IMAGE_TAG} +RUN apk update RUN update-ca-certificates -RUN rm -rf /var/cache/apk/* -ENV PYENV_ROOT="/root/.pyenv" -ENV PATH="$PYENV_ROOT/bin:$PATH" - -ADD . /app -WORKDIR /app - -RUN /app/docker/bin/install_python.sh 3.5.4 3.6.4 - -ENTRYPOINT ["./docker/bin/entrypoint.sh"] +RUN pip install sanic +RUN apk del build-base diff --git a/docker/Dockerfile-base b/docker/Dockerfile-base new file mode 100644 index 00000000..85a8c5fd --- /dev/null +++ b/docker/Dockerfile-base @@ -0,0 +1,9 @@ +ARG PYTHON_VERSION + +FROM python:${PYTHON_VERSION}-alpine +RUN apk update +RUN apk add --no-cache --update build-base \ + ca-certificates \ + openssl +RUN update-ca-certificates +RUN rm -rf /var/cache/apk/* diff --git a/docker/bin/entrypoint.sh b/docker/bin/entrypoint.sh deleted file mode 100755 index 762d2155..00000000 --- a/docker/bin/entrypoint.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -e - -eval "$(pyenv init -)" -eval "$(pyenv virtualenv-init -)" -source /root/.pyenv/completions/pyenv.bash - -pip install tox - -exec $@ - diff --git a/docker/bin/install_python.sh b/docker/bin/install_python.sh deleted file mode 100755 index e7c4aa1f..00000000 --- a/docker/bin/install_python.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -set -e - -export CFLAGS='-O2' -export EXTRA_CFLAGS="-DTHREAD_STACK_SIZE=0x100000" - -curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash -eval "$(pyenv init -)" - -for ver in $@ -do - pyenv install $ver -done - -pyenv global $@ -pip install --upgrade pip -pyenv rehash diff --git a/hack/Dockerfile b/hack/Dockerfile new file mode 100644 index 00000000..6908fc1c --- /dev/null +++ b/hack/Dockerfile @@ -0,0 +1,6 @@ +FROM catthehacker/ubuntu:act-latest +SHELL [ "/bin/bash", "-c" ] +ENTRYPOINT [] +RUN apt-get update +RUN apt-get install gcc -y +RUN apt-get install -y --no-install-recommends g++ diff --git a/tests/test_keep_alive_timeout.py b/tests/test_keep_alive_timeout.py index 0eaf2aed..6f88abd2 100644 --- a/tests/test_keep_alive_timeout.py +++ b/tests/test_keep_alive_timeout.py @@ -6,6 +6,7 @@ from os import environ import httpcore import httpx +import platform import pytest from sanic_testing.testing import HOST, SanicTestClient @@ -241,7 +242,9 @@ def test_keep_alive_timeout_reuse(): @pytest.mark.skipif( - bool(environ.get("SANIC_NO_UVLOOP")) or OS_IS_WINDOWS, + bool(environ.get("SANIC_NO_UVLOOP")) + or OS_IS_WINDOWS + or platform.system() != "Linux", reason="Not testable with current client", ) def test_keep_alive_client_timeout(): diff --git a/tests/test_unix_socket.py b/tests/test_unix_socket.py index c592dcde..90b1885f 100644 --- a/tests/test_unix_socket.py +++ b/tests/test_unix_socket.py @@ -1,6 +1,7 @@ import asyncio import logging import os +import platform import subprocess import sys @@ -175,6 +176,10 @@ def test_unix_connection_multiple_workers(): app_multi.run(host="myhost.invalid", unix=SOCKPATH, workers=2) +@pytest.mark.xfail( + condition=platform.system() != "Linux", + reason="Flaky Test on Non Linux Infra", +) async def test_zero_downtime(): """Graceful server termination and socket replacement on restarts""" from signal import SIGINT diff --git a/tox.ini b/tox.ini index 4837bbc1..825c742b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py37, py38, py39, pyNightly, {py37,py38,py39,pyNightly}-no-ext, lint, check, security, docs +envlist = py37, py38, py39, pyNightly, pypy37, {py37,py38,py39,pyNightly,pypy37}-no-ext, lint, check, security, docs, type-checking [testenv] usedevelop = True