Skip to content

Latest commit

 

History

History
122 lines (80 loc) · 3.84 KB

File metadata and controls

122 lines (80 loc) · 3.84 KB

Releasing

For maintainers. Releases are published by .github/workflows/release.yml, triggered by pushing a v* tag. That is the only path to PyPI; there is no separate local publishing route. You drive it from your machine with git and gh, as below.

The version lives in one place

src/eegprep/__init__.py:

__version__ = "0.3.0"

pyproject.toml declares dynamic = ["version"] and reads that attribute, so there is no version string to edit in pyproject.toml.

Release from your machine

1. Dry run first. This runs the whole pipeline except publishing, so you find problems before a tag exists:

gh workflow run release.yml --ref master -f dry_run=true
gh run watch "$(gh run list --workflow=release.yml --limit 1 --json databaseId --jq '.[0].databaseId')"

2. Bump the version in src/eegprep/__init__.py, then commit and land it on master:

git commit -am "release: 0.3.0"
git checkout master && git merge --no-ff develop && git push origin master

Tip

If master is strictly behind develop, git push origin develop:master fast-forwards it without checking out master. Useful when you have local changes — for example a modified src/eegprep/eeglab submodule — that would block the checkout.

3. Tag and push. Pushing the tag starts the release:

git tag -a v0.3.0 -m "Release version 0.3.0"
git push origin v0.3.0

4. Watch it. Nothing reaches PyPI unless every check passes:

gh run watch "$(gh run list --workflow=release.yml --limit 1 --json databaseId --jq '.[0].databaseId')" --exit-status

If it fails, inspect and fix:

gh run view --log-failed

5. Add a section to :ref:`changelog`.

What the workflow does

  1. verifyruff check, ruff format --check, ty check, and the full test suite with EEGPREP_SKIP_MATLAB=1.
  2. builduv build, then checks that the tag matches __version__, that the vendored EEGLAB checkout is absent from both artifacts, that packaged data (ICLabel weights, help resources) is present, that twine check --strict passes, and that the built wheel installs and imports.
  3. publish — uploads to PyPI using Trusted Publishing, so no API token is stored in the repository.
  4. github-release — creates the GitHub release with the artifacts attached.

Note

Trusted Publishing needs one-time setup on PyPI under Manage project → Publishing → Add a new publisher: owner sccn, repository eegprep, workflow release.yml, environment pypi.

If a tag was pushed at a bad commit

Fix the problem, then move the tag. This is safe only while the tag published nothing; once a version is on PyPI it can never be replaced.

git push origin :refs/tags/v0.3.0     # delete the remote tag
git tag -f v0.3.0 && git push origin v0.3.0

Docker image

CI does not build Docker images. After the tag is published, build and push the image, which also updates the pin in tools/hpc/main.pbs:

docker login
uv run python scripts/build_docker.py

Commit the updated pin. Use --no-push to build without publishing.

Warning

PyPI uploads are immutable. A version number can never be reused, even after the release is deleted. Always dry-run first.

Note

Build with uv build, never python -m build. The repository contains a build/ output directory that shadows the build package on sys.path, so python -m build fails with "'build' is a package and cannot be directly executed" no matter what is installed.