CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-nbdev

Create delightful software with Jupyter Notebooks

Pending
Overview
Eval results
Files

release-management.mddocs/

Release Management

Automated publishing to PyPI, GitHub releases, and changelog generation. nbdev provides comprehensive release management tools that handle version bumping, changelog generation, and publishing to multiple platforms.

Capabilities

Release Class

Main class for managing package releases across platforms.

class Release:
    """
    Release management for nbdev projects.
    
    Handles the complete release process including:
    - Version management
    - Changelog generation  
    - PyPI publishing
    - GitHub release creation
    - Documentation updates
    """
    
    def __init__(self, owner: str = None, repo: str = None, token: str = None):
        """
        Initialize release manager.
        
        Args:
            owner: GitHub repository owner
            repo: GitHub repository name  
            token: GitHub API token for releases
        """

Git Release Functions

Create git tags and releases.

def release_git(tag: str = None, msg: str = None):
    """
    Create git tag and release.
    
    Args:
        tag: Version tag (defaults to current version in settings)
        msg: Release message (defaults to changelog entry)
        
    Creates a git tag for the current version and pushes it to
    the remote repository for release tracking.
    """

GitHub Integration

Create GitHub releases with assets and release notes.

def release_gh(tag: str = None, notes: str = None, 
               draft: bool = False, prerelease: bool = False):
    """
    Create GitHub release.
    
    Args:
        tag: Release tag (defaults to current version)
        notes: Release notes (defaults to changelog)
        draft: Create as draft release
        prerelease: Mark as prerelease
        
    Creates a GitHub release with automatically generated
    release notes from changelog and project information.
    """

Changelog Management

Generate and manage project changelogs.

def changelog(tag: str = None, since_tag: str = None):
    """
    Generate changelog for release.
    
    Args:
        tag: Target release tag
        since_tag: Previous release tag to compare from
        
    Returns:
        Formatted changelog with commits, issues, and PRs
        since the last release.
    """

PyPI Integration

Get information about PyPI packages and releases.

def pypi_json(name: str):
    """
    Get PyPI package information.
    
    Args:
        name: Package name on PyPI
        
    Returns:
        JSON data about the package including versions,
        metadata, and download statistics.
    """

def latest_pypi(name: str):
    """
    Get latest PyPI version for a package.
    
    Args:
        name: Package name on PyPI
        
    Returns:
        Latest version string available on PyPI
    """

Release Workflow

Complete Release Process

from nbdev.release import Release, release_git, release_gh, changelog
from nbdev.config import get_config

def complete_release(version: str):
    """Complete release workflow."""
    
    config = get_config()
    
    # 1. Update version in project
    from nbdev.config import update_version
    update_version(version)
    
    # 2. Generate changelog
    notes = changelog(tag=version)
    print(f"Changelog:\n{notes}")
    
    # 3. Create git release
    release_git(tag=version, msg=f"Release {version}")
    
    # 4. Create GitHub release
    release_gh(tag=version, notes=notes)
    
    # 5. Publish to PyPI (manual step)
    print(f"Ready to publish {config.lib_name} {version} to PyPI")
    print("Run: python -m build && twine upload dist/*")

complete_release("1.2.0")

Version Management

from nbdev.config import update_version, get_config
from nbdev.release import latest_pypi

def check_version_status():
    """Check current version against PyPI."""
    
    config = get_config()
    current_version = config.version
    
    try:
        pypi_version = latest_pypi(config.lib_name)
        print(f"Current version: {current_version}")
        print(f"PyPI version: {pypi_version}")
        
        if current_version == pypi_version:
            print("⚠ Version matches PyPI - need to bump version")
        else:
            print("✓ Version is different from PyPI")
            
    except Exception as e:
        print(f"Could not check PyPI: {e}")

check_version_status()

GitHub Integration

Release Creation

from nbdev.release import Release, release_gh

# Create GitHub release with custom notes
release_notes = """
## New Features
- Added advanced export functionality
- Improved test performance

## Bug Fixes  
- Fixed merge conflict resolution
- Resolved documentation links

## Breaking Changes
- Updated API for configuration management
"""

release_gh(tag="2.0.0", notes=release_notes)

Draft Releases

from nbdev.release import release_gh

# Create draft release for review
release_gh(tag="2.0.0-beta", draft=True, prerelease=True)
# Review and publish manually on GitHub

Automation and CI/CD

GitHub Actions Integration

# .github/workflows/release.yml
name: Release
on:
  push:
    tags: ['v*']
    
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.9'
      - name: Install nbdev
        run: pip install nbdev
      - name: Create GitHub Release
        run: python -c "from nbdev.release import release_gh; release_gh()"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Automated Version Bumping

from nbdev.release import latest_pypi, Release
from nbdev.config import update_version, get_config

def auto_version_bump(bump_type='patch'):
    """Automatically bump version."""
    
    config = get_config()
    current = config.version
    
    # Parse version (simple implementation)
    parts = current.split('.')
    major, minor, patch = map(int, parts)
    
    if bump_type == 'major':
        major += 1
        minor = patch = 0
    elif bump_type == 'minor':
        minor += 1  
        patch = 0
    else:  # patch
        patch += 1
    
    new_version = f"{major}.{minor}.{patch}"
    update_version(new_version)
    
    print(f"Version bumped: {current} → {new_version}")
    return new_version

# Bump patch version
new_ver = auto_version_bump('patch')

Configuration

Release management uses configuration from settings.ini:

# Release configuration
version = 1.0.0
author = Your Name
author_email = you@example.com
copyright = 2024 onwards, %(author)s
license = apache2
git_url = https://github.com/yourusername/yourproject

Constants and URLs

GH_HOST: str

GitHub API host URL for release operations.

CONDA_WARNING: str

Warning message about conda package publishing requirements.

Advanced Release Features

Multi-Platform Releases

from nbdev.release import Release, release_gh
from nbdev.config import get_config

def multi_platform_release():
    """Release to multiple platforms."""
    
    config = get_config()
    version = config.version
    
    # 1. GitHub release
    release_gh(tag=version)
    
    # 2. PyPI release (requires separate setup)
    print("Publishing to PyPI...")
    import subprocess
    subprocess.run(['python', '-m', 'build'])
    subprocess.run(['twine', 'upload', 'dist/*'])
    
    # 3. Conda release (if configured)
    print("Consider publishing to conda-forge")
    print(CONDA_WARNING)

multi_platform_release()

Release Validation

from nbdev.release import pypi_json, latest_pypi
from nbdev.test import nbdev_test
from nbdev.export import nb_export

def validate_release():
    """Validate project before release."""
    
    print("1. Running tests...")
    if not nbdev_test():
        return False, "Tests failed"
    
    print("2. Checking exports...")
    nb_export()
    
    print("3. Checking PyPI status...")
    config = get_config()
    try:
        current_pypi = latest_pypi(config.lib_name)
        if current_pypi == config.version:
            return False, "Version already exists on PyPI"
    except:
        pass  # Package might not exist yet
    
    return True, "Ready for release"

valid, message = validate_release()
print(f"Release validation: {message}")

Complete Release Example:

from nbdev.release import Release, release_git, release_gh, changelog
from nbdev.config import update_version, get_config
from nbdev.test import nbdev_test
from nbdev.export import nb_export

def full_release_workflow(new_version: str):
    """Complete release workflow with validation."""
    
    print(f"Starting release workflow for version {new_version}")
    
    # 1. Validate current state
    print("Validating project state...")
    if not nbdev_test():
        print("❌ Tests failed - aborting release")
        return False
    
    # 2. Update version
    print(f"Updating version to {new_version}")
    update_version(new_version)
    
    # 3. Export latest code
    print("Exporting notebooks...")
    nb_export()
    
    # 4. Generate changelog
    print("Generating changelog...")
    notes = changelog(tag=new_version)
    
    # 5. Create releases
    print("Creating git release...")
    release_git(tag=new_version, msg=f"Release {new_version}")
    
    print("Creating GitHub release...")
    release_gh(tag=new_version, notes=notes)
    
    print(f"✅ Release {new_version} completed successfully!")
    print("Don't forget to publish to PyPI with:")
    print("  python -m build && twine upload dist/*")
    
    return True

# Execute full release
full_release_workflow("1.3.0")

Install with Tessl CLI

npx tessl i tessl/pypi-nbdev

docs

cleaning.md

configuration.md

development-tools.md

documentation.md

export.md

git-integration.md

index.md

release-management.md

synchronization.md

testing.md

tile.json