This document provides step-by-step instructions for releasing a new version of hedtools to PyPI.
Platform support: This guide includes commands for both Windows (PowerShell) and Linux/macOS (Bash).
Before starting the release process, ensure you have:
- Write access to the hed-python repository (maintainer/collaborator)
- PyPI account with maintainer access to the
hedtoolspackage - Git configured with your credentials
- Python 3.10+ installed
- Virtual environment activated (if using one)
- Your fork of hed-python set up as
originremote - hed-standard/hed-python set up as
upstreamremote - All intended changes merged to the
mainbranch of upstream
Git remote setup:
If you haven't set up your remotes, run:
# Check your current remotes
git remote -v
# If needed, add upstream (assuming origin is your fork)
git remote add upstream https://github.com/hed-standard/hed-python.gitYour setup should look like:
origin→ your fork (e.g.,yourusername/hed-python)upstream→hed-standard/hed-python
Windows (PowerShell):
# Check git status
git status
# If there are uncommitted changes, commit or stash them
git add .
git commit -m "Pre-release cleanup"Linux/macOS (Bash):
# Check git status
git status
# If there are uncommitted changes, commit or stash them
git add .
git commit -m "Pre-release cleanup"Add a new entry at the top of CHANGELOG.md with:
- Release version number (e.g., "Release 0.9.1")
- Release date
- Bullet points describing:
- New features
- Enhancements
- Bug fixes
- Documentation improvements
- Breaking changes (if any)
Recommend asking coPilot to produce a draft change log reflecting changes between the last release and the current commit on the main branch.
Example:
Release 0.9.1 October 13, 2025
- Applied Black code formatter to entire codebase for consistent code style
- Added Black to development dependencies and CI workflow
- Enhanced CONTRIBUTING.md with code formatting guidelines
- Updated README.md with Black usage instructionsBefore releasing, ensure all code quality checks pass:
All platforms:
# Run code formatter check
ruff format --check .
# Run linter
ruff check hed/ tests/
# Run spell checker
typos
# Run all tests
python -m unittest discover tests -v
# Run spec tests
python -m unittest discover spec_tests -vFix any issues before proceeding.
All Platforms:
git add CHANGELOG.md
git commit -m "Update CHANGELOG for version 0.9.1"Push your changes to your fork and create a pull request to upstream:
All Platforms:
# Push to your fork (origin)
git push origin your-feature-branch
# OR if you're working directly on main in your fork:
git push origin mainCreate pull request:
- Go to your fork on GitHub:
https://github.com/yourusername/hed-python - Click "Contribute" → "Open pull request"
- Target:
hed-standard/hed-python(base:main) - Source: Your fork and branch
- Title: "Update CHANGELOG for version 0.9.1" (or similar)
- Create and merge the pull request
Important: Ensure the CHANGELOG updates are merged into the upstream main branch (hed-standard/hed-python) before proceeding.
The project uses setuptools-scm for version management, which automatically derives the version from git tags. We'll create the release tag and release directly on GitHub.
Go to: https://github.com/hed-standard/hed-python/releases/new
Fill in the release form:
-
Choose a tag: Type a new tag:
0.9.0- Target: main branch
- Use semantic versioning: MAJOR.MINOR.PATCH
- Do NOT use a prefix (e.g., use
0.9.0, notv0.9.0)
-
Release title:
Release 0.9.0 -
Description: Paste the detailed changelog information generated by Copilot
Example description:
## What's New in 0.9.0
### Features
- Added comprehensive logging infrastructure with configurable log levels and file output
- Enhanced validate_bids script with improved error reporting and filtering capabilities
- Added error code counting and filtering by count/file in ErrorHandler
### Documentation
- Added comprehensive CONTRIBUTING.md with development guidelines
- Significantly enhanced README.md with better documentation structure
- Improved user guide documentation
### Bug Fixes
- Fixed Windows path handling in tests
- Fixed typos and improved code documentation
### Full Changelog
See [CHANGELOG.md](https://github.com/hed-standard/hed-python/blob/main/CHANGELOG.md)-
Set as latest release: Check this box
-
Click Publish release
Verify the release on GitHub:
- Release appears at https://github.com/hed-standard/hed-python/releases
- Tag
0.9.0was created - Release notes display correctly
- Target is set to main branch
Zenodo automatically creates a DOI and archives the release when a GitHub release is published. This happens through the GitHub-Zenodo integration.
Wait a few minutes after creating the GitHub release for Zenodo to process it.
- Go to: https://zenodo.org/records/8056010 (or the latest Zenodo record for hed-python)
- Verify that a new version appears for your release
- Check that the DOI is generated
- Confirm the metadata is correct (title, authors, description)
Note: If the Zenodo release doesn't appear after 10-15 minutes, check the GitHub-Zenodo integration settings or contact a repository maintainer.
Now that the release is created on GitHub and verified on Zenodo, pull the tag to your local repository.
All Platforms:
# Switch to main branch
git checkout main
# Pull the latest changes from upstream (hed-standard/hed-python)
git pull upstream main
# Fetch all tags from upstream
git fetch upstream --tags
# Verify the tag exists locally
git tag -l 0.9.0
# Optional: Update your fork's main branch
git push origin mainAll Platforms:
# Check that the version is correctly detected
python -c "import hed; print(hed.__version__)"Expected output: 0.9.0
If you see something like 0+untagged.xxx.gxxxxxxx, ensure:
- You're on the main branch
- The tag was properly fetched:
git fetch --tags - The tag exists:
git tag -l
Windows (PowerShell):
# Remove old build artifacts
Remove-Item -Recurse -Force dist, build, *.egg-info -ErrorAction SilentlyContinueLinux/macOS (Bash):
# Remove old build artifacts
rm -rf dist build *.egg-infoAll Platforms:
python -m pip install --upgrade build twineAll Platforms:
# Build both wheel and source distributions
python -m buildThis creates:
dist/hedtools-0.9.0-py3-none-any.whl(wheel distribution)dist/hedtools-0.9.0.tar.gz(source distribution)
Windows (PowerShell):
# List contents of the wheel
python -m zipfile -l dist/hedtools-0.9.0-py3-none-any.whl
# Check the source distribution (requires tar in PATH)
tar -tzf dist/hedtools-0.9.0.tar.gzLinux/macOS (Bash):
# List contents of the wheel
unzip -l dist/hedtools-0.9.0-py3-none-any.whl
# Check the source distribution
tar -tzf dist/hedtools-0.9.0.tar.gzWindows (PowerShell):
# Create a fresh virtual environment for testing
python -m venv test_env
.\test_env\Scripts\Activate.ps1Linux/macOS (Bash):
# Create a fresh virtual environment for testing
python -m venv test_env
source test_env/bin/activateAll Platforms:
# Install the built wheel
pip install dist/hedtools-0.9.0-py3-none-any.whlWindows (PowerShell):
# Navigate back to the repository
cd h:\Repos\hed-python
# Run the test suite
python -m unittest discover tests -vLinux/macOS (Bash):
# Navigate back to the repository
cd ~/path/to/hed-python
# Run the test suite
python -m unittest discover tests -vAll Platforms:
# Check version
python -c "import hed; print(hed.__version__)"
# Test a basic import
python -c "from hed import load_schema_version; schema = load_schema_version('8.3.0'); print('Success!')"Windows (PowerShell):
deactivate
Remove-Item -Recurse -Force test_envLinux/macOS (Bash):
deactivate
rm -rf test_envAll Platforms:
# Validate the distribution packages
python -m twine check dist/*Expected output: Checking dist/hedtools-0.9.0.tar.gz: PASSED (and same for .whl)
All Platforms:
# Upload to TestPyPI first
python -m twine upload --repository testpypi dist/*You'll be prompted for your TestPyPI credentials.
Test installation from TestPyPI:
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ hedtools==0.9.0All Platforms:
# Upload to the real PyPI
python -m twine upload dist/*You'll be prompted for your PyPI credentials (or use an API token).
Alternative with API Token:
Windows (PowerShell):
# Set your PyPI API token as an environment variable
$env:TWINE_USERNAME = "__token__"
$env:TWINE_PASSWORD = "pypi-your-api-token-here"
# Upload
python -m twine upload dist/*Linux/macOS (Bash):
# Set your PyPI API token as an environment variable
export TWINE_USERNAME="__token__"
export TWINE_PASSWORD="pypi-your-api-token-here"
# Upload
python -m twine upload dist/*Visit https://pypi.org/project/hedtools/ and verify:
- Version 0.9.0 is listed
- README renders correctly
- All metadata is correct
- Download links work
You may want to attach the distribution files to the GitHub release for convenience.
Go to: https://github.com/hed-standard/hed-python/releases/tag/0.9.0
- Click Edit release
- Drag and drop or upload:
dist/hedtools-0.9.0-py3-none-any.whldist/hedtools-0.9.0.tar.gz
- Click Update release
In a fresh environment:
All Platforms:
pip install --upgrade hedtools
python -c "import hed; print(hed.__version__)"Expected output: 0.9.0
Check that documentation sites are updated (may take some time):
Consider announcing the release:
- GitHub Discussions
- HED mailing list
- Community forums
- Social media (if applicable)
Problem: python -c "import hed; print(hed.__version__)" shows wrong version
Solution:
# Fetch all tags from upstream (not from your fork)
git fetch upstream --tags
# Verify tag exists
git tag -l
# Check setuptools-scm can find the version
python -m setuptools_scmProblem: Missing dependencies during build
Solution:
# Ensure build tools are installed
pip install --upgrade pip setuptools wheel build
# Try building again
python -m buildProblem: Invalid credentials or API token
Solution:
- Create a new API token at https://pypi.org/manage/account/token/
- Scope it to the
hedtoolsproject only - Use
__token__as username and the token as password
Problem: You need to delete and recreate a tag
Solution:
Note: Tags are created on upstream (hed-standard/hed-python) via GitHub releases. If you need to delete a tag:
# Delete local tag
git tag -d 0.9.0To delete from upstream (requires maintainer access):
- Go to https://github.com/hed-standard/hed-python/releases
- Delete the release associated with the tag
- Delete the tag: Settings → (or use GitHub API/CLI)
OR use git (if you have push access to upstream):
# Delete remote tag from upstream (CAUTION: only if not yet released!)
git push upstream :refs/tags/0.9.0WARNING: Only delete remote tags if the release hasn't been published to PyPI yet!
HED-Python follows Semantic Versioning:
- MAJOR version (X.0.0): Incompatible API changes
- MINOR version (0.X.0): New features, backward-compatible
- PATCH version (0.0.X): Bug fixes, backward-compatible
- MAJOR: Breaking changes, API redesign, major architectural changes
- MINOR: New features, new functions/classes, enhancements (this release: 0.9.0)
- PATCH: Bug fixes, documentation fixes, small improvements (0.9.1)
New workflow summary:
- Update CHANGELOG and push to your fork (origin)
- Create PR to upstream and merge to hed-standard/hed-python main
- Create release tag and release on upstream GitHub (hed-standard/hed-python)
- Verify Zenodo release (automatic, linked to GitHub)
- Pull tag from upstream to local repository
- Build distributions and upload to PyPI
Important:
origin= your forkupstream= hed-standard/hed-python
Windows (PowerShell):
# Step 1: Update and push CHANGELOG to your fork
git status # Check working tree
git add CHANGELOG.md # Stage changelog
git commit -m "Update CHANGELOG for v0.9.0" # Commit
git push origin your-branch # Push to your fork
# Step 2: Create PR on GitHub (via web interface)
# - Go to your fork on GitHub
# - Create PR to hed-standard/hed-python main
# - Merge the PR
# Step 3: Create release on upstream GitHub (via web interface)
# - Go to https://github.com/hed-standard/hed-python/releases/new
# - Create tag 0.9.0 targeting main
# - Add release notes (paste Copilot-generated changelog)
# - Publish release
# Step 4: Verify Zenodo release (via web interface)
# - Wait a few minutes for Zenodo to process the GitHub release
# - Go to https://zenodo.org/records/17866854
# - Verify new version appears with DOI
# Step 5: Pull tag from upstream to local
git checkout main # Switch to main
git pull upstream main # Pull from upstream
git fetch upstream --tags # Fetch tags from upstream
python -c "import hed; print(hed.__version__)" # Verify version
# Step 6: Build and upload to PyPI
Remove-Item -Recurse -Force dist, build, *.egg-info -ErrorAction SilentlyContinue
python -m build # Build
python -m twine check dist/* # Verify
python -m twine upload dist/* # Upload to PyPILinux/macOS (Bash):
# Step 1: Update and push CHANGELOG to your fork
git status # Check working tree
git add CHANGELOG.md # Stage changelog
git commit -m "Update CHANGELOG for 0.9.0" # Commit
git push origin your-branch # Push to your fork
# Step 2: Create PR on GitHub (via web interface)
# - Go to your fork on GitHub
# - Create PR to hed-standard/hed-python main
# - Merge the PR
# Step 3: Create release on upstream GitHub (via web interface)
# - Go to https://github.com/hed-standard/hed-python/releases/new
# - Create tag 0.9.0 targeting main
# - Add release notes (paste Copilot-generated changelog)
# - Publish release
# Step 4: Verify Zenodo release (via web interface)
# - Wait a few minutes for Zenodo to process the GitHub release
# - Go to https://zenodo.org/records/17866854
# - Verify new version appears with DOI
# Step 5: Pull tag from upstream to local
git checkout main # Switch to main
git pull upstream main # Pull from upstream
git fetch upstream --tags # Fetch tags from upstream
python -c "import hed; print(hed.__version__)" # Verify version
# Step 6: Build and upload to PyPI
rm -rf dist build *.egg-info # Clean old builds
python -m build # Build
python -m twine check dist/* # Verify
python -m twine upload dist/* # UploadFor questions about the release process:
- Maintainer: Kay Robbins (Kay.Robbins@utsa.edu)
- Repository: https://github.com/hed-standard/hed-python
- Issues: https://github.com/hed-standard/hed-python/issues