diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 3dfe659f..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Build releases and (on tags) publish to PyPI -name: Release - -# always build releases (to make sure wheel-building works) -# but only publish to PyPI on tags -on: - push: - pull_request: - -jobs: - build-release: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.8 - - - name: install build package - run: | - pip install --upgrade pip - pip install build - pip freeze - - - name: build release - run: | - python -m build --sdist --wheel . - ls -l dist - - - name: publish to pypi - uses: pypa/gh-action-pypi-publish@v1.4.1 - if: startsWith(github.ref, 'refs/tags/') - with: - user: __token__ - password: ${{ secrets.pypi_password }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..a3a7848d --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,54 @@ +# This is a GitHub workflow defining a set of jobs with a set of steps. +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions +# +name: Release + +# Always tests wheel building, but only publish to PyPI on pushed tags. +on: + pull_request: + paths-ignore: + - "docs/**" + - ".github/workflows/*.yaml" + - "!.github/workflows/release.yaml" + push: + paths-ignore: + - "docs/**" + - ".github/workflows/*.yaml" + - "!.github/workflows/release.yaml" + branches-ignore: + - "dependabot/**" + - "pre-commit-ci-update-config" + tags: ["**"] + workflow_dispatch: + +jobs: + build-release: + runs-on: ubuntu-22.04 + permissions: + # id-token=write is required for pypa/gh-action-pypi-publish, and the PyPI + # project needs to be configured to trust this workflow. + # + # ref: https://github.com/jupyterhub/team-compass/issues/648 + # + id-token: write + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: install build package + run: | + pip install --upgrade pip + pip install build + pip freeze + + - name: build release + run: | + python -m build --sdist --wheel . + ls -l dist + + - name: publish to pypi + uses: pypa/gh-action-pypi-publish@release/v1 + if: startsWith(github.ref, 'refs/tags/') diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 00000000..76e38152 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,117 @@ +# This is a GitHub workflow defining a set of jobs with a set of steps. +# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions +# +name: Tests + +on: + pull_request: + paths-ignore: + - "docs/**" + - "**.md" + - ".github/workflows/*.yaml" + - "!.github/workflows/test.yaml" + push: + paths-ignore: + - "docs/**" + - "**.md" + - ".github/workflows/*.yaml" + - "!.github/workflows/test.yaml" + branches-ignore: + - "dependabot/**" + - "pre-commit-ci-update-config" + tags: ["**"] + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-22.04 + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + include: + - python-version: "3.7" + pip-install-spec: "jupyterhub==1.0.0 sqlalchemy==1.*" + - python-version: "3.8" + pip-install-spec: "jupyterhub==2.* sqlalchemy==1.*" + - python-version: "3.9" + pip-install-spec: "jupyterhub==3.*" + - python-version: "3.11" + pip-install-spec: "jupyterhub==4.*" + - python-version: "3.11" + pip-install-spec: "jupyterhub==4.*" + test-variation: internal-ssl + - python-version: "3.11" + pip-install-spec: "jupyterhub==4.*" + test-variation: podman + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - uses: actions/setup-node@v3 + with: + node-version: "18" + + - name: setup docker swarm + run: docker swarm init + + - name: Install Python dependencies + run: | + pip install ${{ matrix.pip-install-spec }} + pip install -e "." -r dev-requirements.txt + + - name: List Python dependencies + run: | + pip freeze + + - name: Install Node dependencies + run: | + npm install -g configurable-http-proxy + + - name: Run tests + if: matrix.test-variation == '' + run: | + pytest tests --cov=dockerspawner + + - name: Run examples/internal-ssl tests + if: matrix.test-variation == 'internal-ssl' + # FIXME: --cov=dockerspawner is omitted as the tested code lives inside + # the built dockerspawner image, so --cov=dockerspawner + # referencing the local source code doesn't get us test coverage. + # + run: | + pytest examples/internal-ssl --capture=no + + - name: Prepare for user-mode podman tests + if: matrix.test-variation == 'podman' + # Podman's system service is started as a user managed process + # (user-mode / rootless), and the docker-api provided by podman is used + # by setting DOCKER_HOST to the podman provided docker-api. + # + # ref: https://docs.podman.io/en/latest/markdown/podman-system-service.1.html + # ref: https://docker-py.readthedocs.io/en/stable/client.html#envvar-DOCKER_HOST + # + run: | + # Default is unix://$XDG_RUNTIME_DIR/podman/podman.sock but XDG_RUNTIME_DIR may not be set + export DOCKER_HOST=unix://$HOME/podman.sock + + podman system service --time=0 $DOCKER_HOST & + + for n in $(seq 1 10); do + if ! docker version &>/dev/null; then + echo "podman system service - starting..." + sleep 1 + else + echo "podman system service - started!" + echo "" + break + fi + done + + pytest tests/test_dockerspawner.py --cov=dockerspawner + + # GitHub action reference: https://github.com/codecov/codecov-action + - uses: codecov/codecov-action@v3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 29994b25..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,117 +0,0 @@ -# This is a GitHub workflow defining a set of jobs with a set of steps. -# ref: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions -# -name: Tests - -on: - pull_request: - push: - workflow_dispatch: - -jobs: - # Run tests - test: - runs-on: ubuntu-20.04 - timeout-minutes: 10 - - strategy: - fail-fast: false - matrix: - include: - - python: 3.8 - test: internal-ssl - - python: 3.7 - jupyterhub: 1.5 - - python: 3.8 - jupyterhub: 2.0 - - python: 3.9 - jupyterhub: 2.2 - - python: "3.10" - jupyterhub: "2.1" - test: podman - - python: 3.9 - jupyterhub: 3.1.1 - - python: 3.11 - jupyterhub: 3.1.1 - - steps: - - uses: actions/checkout@v2 - - - name: setup docker swarm - run: docker swarm init - - - name: Install Python ${{ matrix.python }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python }} - - # preserve pip cache to speed up installation - - name: Cache pip - uses: actions/cache@v2 - with: - path: ~/.cache/pip - # Look to see if there is a cache hit for the corresponding requirements file - key: ${{ runner.os }}-pip-${{ hashFiles('*requirements.txt') }} - - - name: Install Python dependencies - run: | - pip install --upgrade pip - pip install --upgrade --pre -r dev-requirements.txt - if [[ ! -z "${{ matrix.jupyterhub }}" ]]; then - pip install jupyterhub==${{ matrix.jupyterhub }}.* - fi - pip install -e . - - pip freeze - - - name: Install Node - uses: actions/setup-node@v1 - with: - node-version: "14" - - - name: Install Node dependencies - run: | - npm install -g configurable-http-proxy - - - name: Pull images - if: matrix.test != 'podman' - run: | - for v in 1.0 1.1 1.2 1.3; do - docker pull jupyterhub/singleuser:$v - # preserve the layers with a different tag - docker tag jupyterhub/singleuser:$v jupyterhub/singleuser:${v}-cache - # untag so that pull actions are still required - docker rmi jupyterhub/singleuser:$v - done - - - name: Run tests - if: matrix.test != 'internal-ssl' && matrix.test != 'podman' - run: | - py.test --cov dockerspawner tests -v - - - name: Run internal-ssl tests - if: matrix.test == 'internal-ssl' - run: | - cd examples/internal-ssl - pytest -vsx - - - name: Run user-mode podman tests - if: matrix.test == 'podman' - run: | - sudo systemctl stop docker - # Default is unix://$XDG_RUNTIME_DIR/podman/podman.sock but XDG_RUNTIME_DIR may not be set - export DOCKER_HOST=unix://$HOME/podman.sock - podman system service --time=0 $DOCKER_HOST & - for n in $(seq 1 10); do - if ! docker version; then - sleep 2 - else - break - fi - done - docker ps - py.test --cov dockerspawner tests/test_dockerspawner.py -v - - - name: Submit codecov report - run: | - codecov diff --git a/dev-requirements.txt b/dev-requirements.txt index 079eb6ca..337b1d3d 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,7 +1,5 @@ -codecov netifaces notebook<7 -pyflakes pytest>=3.6 pytest-asyncio pytest-cov diff --git a/pyproject.toml b/pyproject.toml index 54de4d17..53ebc757 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,6 @@ profile = "black" [tool.black] skip-string-normalization = true target_version = [ - "py36", "py37", "py38", "py39", @@ -27,7 +26,15 @@ target_version = [ # ref: https://docs.pytest.org/en/stable/ # [tool.pytest.ini_options] -addopts = "--verbose --color=yes --durations=10" +addopts = "--verbose --color=yes --durations=10 --maxfail=2" asyncio_mode = "auto" -# Ignore thousands of tests in dependencies installed in a virtual environment -norecursedirs = "lib lib64" +testpaths = ["tests"] +# These markers are registered to avoid warnings triggered by importing from +# jupyterhub.tests.test_api. +markers = [ + "role", + "user", + "slow", + "group", + "services", +]