diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index febc41fb..00000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,20 +0,0 @@ -[bumpversion] -current_version = 4.3.1.dev -parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\.(?P[a-z0-9]+))? -tag_name = {new_version} -allow_dirty = True -commit = True -tag = False -serialize = - {major}.{minor}.{patch}.{release} - {major}.{minor}.{patch} - -[bumpversion:file:kubespawner/__init__.py] - -[bumpversion:file:setup.py] - -[bumpversion:part:release] -optional_value = stable -values = - dev - stable diff --git a/.flake8 b/.flake8 index 7b64faeb..05de5fa5 100644 --- a/.flake8 +++ b/.flake8 @@ -9,4 +9,5 @@ builtins = c, get_config exclude = .cache, .github, - docs + docs, + __init__.py diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 3d2c840a..127a694c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,31 +1,19 @@ # Configuration on how ReadTheDocs (RTD) builds our documentation # ref: https://readthedocs.org/projects/jupyterhub-kubespawner/ # ref: https://docs.readthedocs.io/en/stable/config-file/v2.html - -# Required (RTD configuration version) +# version: 2 -build: - os: ubuntu-20.04 - tools: - python: "3.8" - sphinx: configuration: docs/source/conf.py -# Optionally build docs in additional formats such as PDF and ePub -formats: [] +build: + os: ubuntu-22.04 + tools: + python: "3.10" -# Optionally set requirements required to build your docs python: install: - # WARNING: This requirements file will be installed without the pip - # --upgrade flag in an existing environment. This means that if a - # package is specified without a lower boundary, we may end up - # accepting the existing version. - # - # ref: https://github.com/readthedocs/readthedocs.org/blob/0e3df509e7810e46603be47d268273c596e68455/readthedocs/doc_builder/python_environments.py#L335-L344 - # - requirements: docs/requirements.txt # NOTE: We also install the kubespawner package itself, because we use # the autodoc_traits sphinx extension to generate documentation via diff --git a/RELEASE.md b/RELEASE.md index 75e39ee3..28c6a214 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,64 +1,50 @@ -# How to make a release +\*\*# How to make a release -`jupyterhub-kubespawner` is a package [available on -PyPI](https://pypi.org/project/jupyterhub-kubespawner/). These are instructions -on how to make a release on PyPI. +`jupyterhub-kubespawner` is a package available on [PyPI][] and [conda-forge][]. +These are instructions on how to make a release. -For you to follow along according to these instructions, you need: +## Pre-requisites -- To have push rights to the [kubespawner GitHub - repository](https://github.com/jupyterhub/kubespawner). +- Push rights to [github.com/jupyterhub/kubespawner][] +- Push rights to [conda-forge/jupyterhub-kubespawner-feedstock][] ## Steps to make a release -1. Update [CHANGELOG.md](CHANGELOG.md). Doing this can be made easier with the - help of the - [choldgraf/github-activity](https://github.com/choldgraf/github-activity) - utility to list merged PRs and generate a list of contributors. +1. Create a PR updating `docs/source/changelog.md` with [github-activity][] and + continue only when its merged. - ```bash - github-activity jupyterhub/kubespawner --output tmp-changelog-prep.md - ``` - -1. Once the changelog is up to date, checkout main and make sure it is up to date and clean. +1. Checkout main and make sure it is up to date. - ```bash - ORIGIN=${ORIGIN:-origin} # set to the canonical remote, e.g. 'upstream' if 'origin' is not the official repo + ```shell git checkout main - git fetch $ORIGIN main - git reset --hard $ORIGIN/main - # WARNING! This next command deletes any untracked files in the repo - git clean -xfd + git fetch origin main + git reset --hard origin/main ``` -1. Update version and tag, and return to a dev version, with `bump2version`. +1. Update the version, make commits, and push a git tag with `tbump`. - ```bash - VERSION=... # e.g. 1.2.3 - bump2version --tag --new-version $VERSION - - bump2version --no-tag patch + ```shell + pip install tbump + tbump --dry-run ${VERSION} - # verify tags, commits, and version tagged - git log + # run + tbump ${VERSION} ``` -1. Push your two commits to main along with the annotated tags referencing - commits on main. A GitHub workflow will trigger on the pushed git tag and - publish to PyPI. + Following this, the [CI system][] will build and publish a release. - ```bash - # pushing the commits standalone allows you to - # ensure you don't end up only pushing the tag - # because the commit were rejected but the tag - # wasn't - git push $ORIGIN main +1. Reset the version back to dev, e.g. `2.0.1.dev0` after releasing `2.0.0`. - # if you could push the commits without issues - # go ahead and push the tag also - git push --follow-tags $ORIGIN main + ```shell + tbump --no-tag ${NEXT_VERSION}.dev0 ``` -1. Verify that [the GitHub - workflow](https://github.com/jupyterhub/kubespawner/actions?query=workflow%3APublish) - triggers and succeeds and that that PyPI received a [new - release](https://pypi.org/project/jupyterhub-kubespawner/). +1. Following the release to PyPI, an automated PR should arrive to + [conda-forge/jupyterhub-kubespawner-feedstock][] with instructions. + +[github-activity]: https://github.com/executablebooks/github-activity +[github.com/jupyterhub/kubespawner]: https://github.com/jupyterhub/kubespawner +[pypi]: https://pypi.org/project/jupyterhub-kubespawner/ +[conda-forge]: https://anaconda.org/conda-forge/jupyterhub-kubespawner +[conda-forge/jupyterhub-kubespawner-feedstock]: https://github.com/conda-forge/jupyterhub-kubespawner-feedstock +[ci system]: https://github.com/jupyterhub/kubespawner/actions/workflows/publish.yaml diff --git a/kubespawner/__init__.py b/kubespawner/__init__.py index 13c59e65..ec65df34 100644 --- a/kubespawner/__init__.py +++ b/kubespawner/__init__.py @@ -10,7 +10,5 @@ # We export KubeSpawner specifically here. This simplifies import for users. # Users can simply import kubespawner.KubeSpawner in their applications # instead of the more verbose import kubespawner.spawner.KubeSpawner. +from ._version import __version__ from .spawner import KubeSpawner - -__version__ = '4.3.1.dev' -__all__ = ["KubeSpawner"] diff --git a/kubespawner/_version.py b/kubespawner/_version.py new file mode 100644 index 00000000..e3166eff --- /dev/null +++ b/kubespawner/_version.py @@ -0,0 +1,4 @@ +# __version__ should be updated using tbump, based on configuration in +# pyproject.toml, according to instructions in RELEASE.md. +# +__version__ = "4.3.1.dev0" diff --git a/pyproject.toml b/pyproject.toml index 87b5475d..62f2c28e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,56 @@ +# build-system +# - ref: https://peps.python.org/pep-0517/ +# +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + + +# project +# - ref 1: https://peps.python.org/pep-0621/ +# - ref 2: https://hatch.pypa.io/latest/config/metadata/#project-metadata +# +[project] +name = "jupyterhub-kubespawner" +description = "JupyterHub Spawner for Kubernetes" +readme = "README.md" +requires-python = ">=3.7" +license = {file = "LICENSE"} +keywords = ["jupyterhub", "spawner"] +authors = [ + {name = "Jupyter Contributors", email = "jupyter@googlegroups.com"}, +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3", +] +dependencies = [ + # NOTE: If lower bounds are updated, also update our test for the lower + # bounds in .github/workflows/test.yaml. + "escapism", + "jinja2", + "jupyterhub>=1.3.0", + "kubernetes_asyncio>=19.15.1", + "python-slugify", + "pyYAML", + "urllib3", +] +dynamic = ["version"] + +[project.optional-dependencies] +test = [ + "kubernetes>=11", + "pytest>=5.4", + "pytest-cov", + "pytest-asyncio>=0.17", +] + +[project.urls] +Documentation = "https://jupyterhub-kubespawner.readthedocs.io" +Source = "https://github.com/jupyterhub/kubespawner" +Issues = "https://github.com/jupyterhub/kubespawner/issues" + + # black is used for autoformatting Python code # # ref: https://black.readthedocs.io/en/stable/ @@ -15,6 +68,12 @@ target_version = [ ] +# hatch ref: https://hatch.pypa.io/latest/ +# +[tool.hatch.version] +path = "kubespawner/_version.py" + + # isort is used for autoformatting Python code # # ref: https://pycqa.github.io/isort/ @@ -32,3 +91,32 @@ addopts = "--verbose --color=yes --durations=10" asyncio_mode = "auto" # Ignore thousands of tests in dependencies installed in a virtual environment norecursedirs = "lib lib64" + + +# tbump is used to simplify and standardize the release process when updating +# the version, making a git commit and tag, and pushing changes. +# +# ref: https://github.com/your-tools/tbump#readme +# +[tool.tbump] +github_url = "https://github.com/jupyterhub/kubespawner" + +[tool.tbump.version] +current = "4.3.1.dev0" +regex = ''' + (?P\d+) + \. + (?P\d+) + \. + (?P\d+) + (?P
((a|b|rc)\d+)|)
+    \.?
+    (?P(?<=\.)dev\d*|)
+'''
+
+[tool.tbump.git]
+message_template = "Bump to {new_version}"
+tag_template = "{new_version}"
+
+[[tool.tbump.file]]
+src = "kubespawner/_version.py"
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 1f91af4a..00000000
--- a/setup.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import sys
-
-from setuptools import find_packages, setup
-
-v = sys.version_info
-if v[:2] < (3, 7):
-    error = "ERROR: kubespawner requires Python version 3.7 or above."
-    print(error, file=sys.stderr)
-    sys.exit(1)
-
-setup(
-    name='jupyterhub-kubespawner',
-    version='4.3.1.dev',
-    # NOTE: If lower bounds are updated, also update our test for the lower
-    #       bounds in .github/workflows/test.yaml.
-    install_requires=[
-        'escapism',
-        'python-slugify',
-        'jupyterhub>=1.3.0',
-        'jinja2',
-        'kubernetes_asyncio>=19.15.1',
-        'urllib3',
-        'pyYAML',
-    ],
-    python_requires='>=3.7',
-    extras_require={
-        'test': [
-            'bump2version',
-            'kubernetes>=11',
-            'pytest>=5.4',
-            'pytest-cov',
-            'pytest-asyncio>=0.17',
-        ]
-    },
-    description='JupyterHub Spawner for Kubernetes',
-    url='http://github.com/jupyterhub/kubespawner',
-    author='Jupyter Contributors',
-    author_email='jupyter@googlegroups.com',
-    long_description=open("README.md").read(),
-    long_description_content_type="text/markdown",
-    license='BSD',
-    packages=find_packages(),
-    project_urls={
-        'Documentation': 'https://jupyterhub-kubespawner.readthedocs.io',
-        'Source': 'https://github.com/jupyterhub/kubespawner',
-        'Tracker': 'https://github.com/jupyterhub/kubespawner/issues',
-    },
-)