Publishing a Python library version (GitHub → Zenodo, PyPI, conda)#
Recipe with some steps that work for
kvalused by ØF. There are definitely many ways to do it, but this works for me on Ubuntu. Unlikely to work out of the box on any system..
Example: Publishing kval#
Example: publishing kval. Last updated for kval 0.5.0 (September 2026).
Before you start (one-time setup)#
Accounts with upload rights on PyPI and anaconda.org (the
npioceanchannel), plus API tokens configured locally.The GitHub repo is linked to Zenodo: Zenodo → Account → GitHub → repository switched on.
A separate conda environment for release tools, so they don’t clash with your working environment:
mamba create -n release -c conda-forge python=3.12 build "twine>=7" grayskull conda-build anaconda-client
(twine must be ≥ 7. Recent hatchling writes metadata version 2.5, which older twine rejects.)
1. Update version and release notes#
Version number in
pyproject.tomlandsrc/kval/__init__.py. They must match.Release notes in
README.mdand in Latest release indocs/source/other/about.md.Commit and push.
2. Build and test locally, before tagging#
The GitHub release triggers a permanent Zenodo DOI, so check that everything works first.
In your development environment (kval installed from the repo with pip install -e ".[dev]", which includes pytest):
pytest # full test suite
In the release environment:
rm -rf dist
python -m build # should create kval-X.Y.Z.tar.gz and .whl in dist/
3. GitHub release (→ Zenodo)#
On the repo page: Releases → Draft a new release.
Tag:
vX.Y.Z. Title:Version X.Y.Z. Paste the release notes into the text field.Publish it as a normal release, not as a draft.
Zenodo picks the release up automatically and issues a DOI. This usually takes a few minutes. Check its status under Zenodo → Account → GitHub → the repository.
If it stays at “Received” for hours, do not re-release. Re-releasing can create a duplicate DOI, which you can’t delete yourself. Wait, and if it is still stuck, contact Zenodo support.
The steps below don’t depend on Zenodo, so carry on.
DOI badge: use the concept DOI. It always points to the latest version, so the README badge never needs updating. For kval:
[](https://doi.org/10.5281/zenodo.10360162)
(To find a concept DOI, open any record on Zenodo and look under Versions for “Cite all versions?”)
4. Publish to PyPI#
twine upload dist/*
The new version should appear at https://pypi.org/project/kval/ within a minute.
5. Publish to anaconda.org#
Go to your conda recipes folder and generate the recipe:
grayskull pypi kval
This takes under a minute and writes kval/meta.yaml. Then check and edit meta.yaml:
Version: it should be the new one. PyPI can take a little while to propagate. If it’s the old version, wait and rerun.
Version caps survived: e.g.
ipykernel >=6.26.0,<7andmatplotlib-base >=3.10,<3.11. Grayskull renamesmatplotlibtomatplotlib-base, which is fine.ruamel: keep
ruamel.yaml >=.... Delete any other spelling that grayskull adds (ruamel_yaml,ruamel-yaml); those refer to a different or non-existent package.Add at the end:
channels: - npiocean - conda-forge
Build:
conda build . -c npiocean -c conda-forge
It takes 1–2 minutes. Warnings about numpy variants, “number of parsed outputs” and conda-verify can be ignored.
The build ends with an import test and
pip check. Both should pass.
Upload. The build prints the exact file path at the end, or you can get it with conda build . --output:
anaconda upload <path>/noarch/kval-X.Y.Z-py_0.conda
It should show up immediately at https://anaconda.org/npiocean/kval. Paste the README contents into the description there; it supports Markdown.
6. Test the conda install#
mamba env remove -n kval_test_env
mamba create -n kval_test_env python=3.12
mamba activate kval_test_env
mamba install -c npiocean -c conda-forge kval pytest
Run the test suite from the kval repo folder.
Open JupyterLab in this environment. Check that the notebook runs this environment’s Python, and that the interactive plots work when called several times:
import sys, ipykernel; print(sys.executable, ipykernel.__version__)
- conda-forge
Also, remove the line
ruamel-yaml >=0.18.15from meta.yaml if applicable.Correct line is
ruamel.yaml >=0.18.15(some issue in translation here - removing the line above fixes it).
Build the package from meta.yaml: ´conda build . -c npiocean -c conda-forge´
Some initial warnings (numpy, Jinja) don’t seem to matter - ignore them.
Should run (1-2 min) without any errors or major warnings
Now cd to
~/miniforge3/envs/oyv/conda-bld/noarchwhere I just built the .cond file.Upload to anaconda.org: anaconda upload NNN-py_0.conda
Should dimmediately be able to see it at https://anaconda.org/npiocean/kval
Good idea to replace the description there with the README.md contents. Supports markdown so just c/p.
Now test that things work:
mamba env remove -n kval_test_envmamba create -n kval_test_env python=3.12mamba activate kval_test_envmamba install -c npiocean -c conda-forge kvalmamba install pytestcdto the kval base directory and run the test suite (pytest)