Contributing to bunenv¶
Thank you for considering contributing to bunenv! This guide will help you get started.
Ways to Contribute¶
You don’t need to be a coding expert to contribute:
Documentation¶
Fix typos or unclear explanations
Add examples for common use cases
Improve error messages
Translate documentation
Bug Reports¶
Report issues you encounter
Provide reproduction steps
Test and verify fixes
Feature Requests¶
Suggest new features
Describe your use case
Discuss implementation approaches
Code Contributions¶
Fix bugs
Implement new features
Improve performance
Add tests
Development Setup¶
Prerequisites¶
You’ll need:
Python 3.10+ (bunenv’s minimum version)
Git for version control
uv (recommended) or pip for package management
Make (optional) for convenience commands
Clone the Repository¶
# Fork on GitHub first, then:
git clone https://github.com/YOUR-USERNAME/bunenv.git
cd bunenv
Install in Development Mode¶
Using uv (Recommended)¶
# Sync all dependencies including dev tools
uv sync
# Install bunenv in editable mode
uv pip install -e .
# Verify it works
uv run bunenv --version
Using pip¶
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# Verify it works
bunenv --version
Project Structure¶
Understanding the Layout¶
bunenv/
├── src/bunenv/
│ ├── __init__.py # Main module (all code here!)
│ └── py.typed # PEP 561 type marker
├── tests/ # Test suite
│ ├── test_*.py # Unit tests
│ └── conftest.py # Pytest configuration
├── docs/ # Documentation
│ ├── source/ # Sphinx source files
│ └── Makefile # Build documentation
├── .github/
│ └── workflows/ # CI/CD pipelines
├── pyproject.toml # Project metadata
├── README.md # GitHub README
└── LICENSE # BSD-3-Clause license
Key Design Principles¶
Single-file module: All code in
src/bunenv/__init__.pyZero dependencies: Pure Python stdlib only
nodeenv compatibility: Maintain similar architecture
Cross-platform: Support macOS, Linux, Windows
Minimal changes: Keep close to nodeenv’s proven design
Making Changes¶
Create a Feature Branch¶
# Create branch from main
git checkout main
git pull origin main
git checkout -b feature/your-feature-name
Development Workflow¶
# Make changes to src/bunenv/__init__.py
# Test locally
uv run bunenv /tmp/test-env --bun=latest
source /tmp/test-env/bin/activate
bun --version
deactivate_bun
# Run linters
uv run ruff check src/
uv run ruff format src/
# Run tests
uv run pytest
# Check coverage
uv run pytest --cov=src/bunenv --cov-report=html
Code Style Guidelines¶
We use Ruff for linting and formatting.
Python Style¶
# Good: Clear, documented, follows nodeenv patterns
def get_bun_versions() -> list[str]:
"""Return all available Bun versions.
Fetches version list from GitHub Releases API.
Returns:
List of version strings (e.g., ['1.3.3', '1.3.2', ...])
"""
return [dct["version"] for dct in _get_versions_json()]
# Bad: Unclear, undocumented
def get_vers():
return [d["v"] for d in get_json()]
Key Conventions¶
Naming:
# Functions: snake_case
def download_bun_bin(url: str) -> None: ...
# Constants: UPPER_SNAKE_CASE
ACTIVATE_SH: str = """..."""
# Variables: snake_case
bun_version: str = "1.3.3"
Type Hints (preferred but not required):
# Modern union syntax (Python 3.10+)
def get_env_dir(args: argparse.Namespace) -> str | None: ...
# Not: Optional[str], Union[str, None]
Line Length: 120 characters
Docstrings: Google style (like nodeenv)
def example_function(param1: str, param2: int = 42) -> dict:
"""Short one-line summary.
Longer description explaining what this does,
why it exists, and any important caveats.
Args:
param1: Description of parameter
param2: Description with default
Returns:
Description of return value
Raises:
ValueError: When this happens
"""
Running Quality Checks¶
Before Committing¶
# Run all quality checks
uv run ruff check src/
uv run ruff format src/
# Run tests
uv run pytest
# Check coverage (aim for >95%)
uv run pytest --cov=src/bunenv --cov-report=term-missing
Fix Lint Errors¶
# Auto-fix what's possible
uv run ruff check --fix src/
# Format code
uv run ruff format src/
# Check again
uv run ruff check src/
Writing Tests¶
Test Organization¶
Tests live in tests/ and follow this structure:
tests/
├── conftest.py # Fixtures
├── test_version_parsing.py # Version utilities
├── test_url_construction.py # URL building
├── test_environment.py # Environment creation
└── test_cli.py # Command-line interface
Writing a Test¶
# tests/test_example.py
import pytest
from bunenv import parse_version, get_bun_bin_url
def test_parse_version_basic():
"""Test basic version parsing"""
assert parse_version("1.3.3") == (1, 3, 3)
assert parse_version("v1.3.3") == (1, 3, 3)
assert parse_version("bun-v1.3.3") == (1, 3, 3)
def test_parse_version_invalid():
"""Test invalid version handling"""
assert parse_version("invalid") == ()
@pytest.mark.parametrize("version,expected", [
("1.3.3", (1, 3, 3)),
("2.0.0", (2, 0, 0)),
("invalid", ()),
])
def test_parse_version_parametrized(version, expected):
"""Test multiple cases"""
assert parse_version(version) == expected
Running Tests¶
# All tests
uv run pytest
# Specific test file
uv run pytest tests/test_version_parsing.py
# Specific test
uv run pytest tests/test_version_parsing.py::test_parse_version_basic
# With coverage
uv run pytest --cov=src/bunenv
# Verbose output
uv run pytest -v
# Stop on first failure
uv run pytest -x
Test Fixtures¶
Use fixtures for common setup:
# conftest.py
import pytest
import tempfile
from pathlib import Path
@pytest.fixture
def temp_env_dir():
"""Provide temporary directory for test environments"""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
# test_example.py
def test_create_environment(temp_env_dir):
"""Test environment creation"""
from bunenv import create_environment
import argparse
args = argparse.Namespace(
bun="1.3.3",
variant="",
python_virtualenv=False,
# ... other required args
)
create_environment(str(temp_env_dir), args)
assert (temp_env_dir / "bin" / "bun").exists()
Documentation Changes¶
Building Documentation Locally¶
# Install docs dependencies
uv sync --group docs
# Build HTML docs
cd docs
uv run make html
# View in browser
open build/html/index.html # macOS
xdg-open build/html/index.html # Linux
start build/html/index.html # Windows
Documentation Style¶
Follow these guidelines:
Headers:
Main Title
==========
Section
-------
Subsection
~~~~~~~~~~
Sub-subsection
^^^^^^^^^^^^^^
Code Blocks:
.. code-block:: bash
# Comment explaining what this does
bunenv .venv --bun=1.3.3
.. code-block:: python
# Python example
import bunenv
bunenv.main()
Admonitions:
.. note::
Helpful information
.. warning::
Something to watch out for
.. tip::
Pro tip for efficiency
.. important::
Critical information
.. danger::
Serious warning
Cross-References:
See :doc:`workflows` for examples.
Refer to :func:`bunenv.get_bun_versions`.
Check :ref:`installation-guide`.
Submitting Changes¶
Commit Messages¶
Follow Conventional Commits:
# Format: <type>: <description>
feat: add support for Bun variant selection
fix: correct architecture detection on ARM Macs
docs: improve quickstart tutorial
test: add tests for URL construction
refactor: simplify version parsing logic
build: update dependencies
ci: add Windows to test matrix
Types:
feat: New featurefix: Bug fixdocs: Documentation onlytest: Test changesrefactor: Code refactoringbuild: Build system changesci: CI/CD changesbump: Version bumps
Examples:
# Good
git commit -m "feat: add --clean-src option to save disk space"
git commit -m "fix: resolve musl detection on Alpine Linux"
git commit -m "docs: add troubleshooting section for rate limits"
# Bad
git commit -m "fixed stuff"
git commit -m "WIP"
git commit -m "asdf"
Push and Create Pull Request¶
# Push your branch
git push origin feature/your-feature-name
# Create PR on GitHub
# Or use GitHub CLI:
gh pr create --title "Add feature X" --body "Description of changes"
Pull Request Guidelines¶
Your PR should:
✓ Have a clear title: Describe what it does
✓ Include description: Explain why the change is needed
✓ Reference issues: Use “Fixes #123” or “Closes #456”
✓ Pass all checks: CI must be green
✓ Include tests: For new features or bug fixes
✓ Update docs: If behavior changes
PR Template:
## Description
Brief description of what this PR does.
## Motivation
Why is this change needed? What problem does it solve?
## Changes
- Added X
- Modified Y
- Fixed Z
## Testing
How did you test this?
- [ ] Local testing
- [ ] Added unit tests
- [ ] Tested on macOS/Linux/Windows
## Checklist
- [ ] Code follows style guidelines
- [ ] Tests pass locally
- [ ] Documentation updated
- [ ] Commit messages follow convention
## Related Issues
Fixes #123
Review Process¶
What to Expect¶
Automated checks run: Linting, tests, builds
Maintainer review: Usually within a few days
Feedback and iteration: Address review comments
Approval and merge: Once everything looks good
Responding to Review¶
# Make requested changes
# Edit files...
# Commit changes
git add .
git commit -m "Address review feedback"
# Push to update PR
git push origin feature/your-feature-name
Common Review Feedback¶
“Add tests for this code”
“Update docstring to explain X”
“Extract this into a separate function”
“Follow naming convention (snake_case)”
“Add type hints”
Don’t take it personally - reviews help improve code quality!
Release Process¶
(For Maintainers)
Version Bumping¶
# Update version in src/bunenv/__init__.py
bunenv_version: str = "0.2.0"
# Update pyproject.toml
version = "0.2.0"
# Commit
git commit -am "bump: version 0.2.0"
# Tag
git tag -a v0.2.0 -m "Release v0.2.0"
# Push
git push origin main --tags
Creating Release¶
# Create GitHub release (triggers publish workflow)
gh release create v0.2.0 \
--title "bunenv v0.2.0" \
--notes "$(git log --oneline v0.1.0..HEAD)"
This automatically:
Builds package with uv
Publishes to PyPI via trusted publishing
Updates documentation
Trusted Publishing¶
bunenv uses PyPI’s trusted publishing:
No manual token needed
GitHub Actions OIDC authentication
Configured in PyPI project settings
Getting Help¶
Questions About Contributing?¶
GitHub Discussions: https://github.com/JacobCoffee/bunenv/discussions
Open an Issue: Tag with “question”
Check nodeenv: bunenv follows nodeenv patterns
Stuck on Something?¶
Don’t hesitate to ask! Open a draft PR with:
## Work in Progress
I'm working on X but need help with Y.
Current status:
- [x] Did this
- [ ] Stuck on this
Questions:
- How should I approach Z?
Contributor Recognition¶
All contributors are recognized in:
GitHub contributors page
Release notes
Documentation credits
Your contributions, big or small, are valued!
Code of Conduct¶
Be Respectful¶
Use welcoming and inclusive language
Be respectful of differing viewpoints
Accept constructive criticism gracefully
Focus on what’s best for the community
Not Acceptable¶
Harassment or discriminatory language
Trolling or insulting comments
Personal or political attacks
Publishing others’ private information
Enforcement¶
Violations can be reported to the project maintainers.
Advanced Topics¶
Working with nodeenv Codebase¶
Since bunenv is adapted from nodeenv:
# Clone nodeenv for reference
git clone https://github.com/ekalinin/nodeenv.git ../nodeenv
# Compare implementations
diff -u ../nodeenv/nodeenv.py src/bunenv/__init__.py
When adapting nodeenv code:
Credit original author in commits
Maintain similar structure
Adapt for Bun-specific needs (GitHub API, etc.)
Document differences
Testing Across Platforms¶
GitHub Actions tests on:
Ubuntu (Linux glibc)
macOS (Intel and ARM)
Windows
For local cross-platform testing:
# Docker for Linux variants
docker run -it --rm -v $(pwd):/bunenv python:3.11-alpine
cd /bunenv && pip install -e . && bunenv /tmp/test --bun=latest
# Test musl variant
docker run -it --rm -v $(pwd):/bunenv python:3.11-alpine
Performance Profiling¶
If working on performance:
# Profile environment creation
python -m cProfile -o profile.stats -m bunenv /tmp/test --bun=1.3.3
# Analyze
python -c "import pstats; p = pstats.Stats('profile.stats'); p.sort_stats('cumulative'); p.print_stats(20)"
Next Steps¶
Ready to contribute?
Fork the repository
Set up development environment
Find an issue to work on (look for “good first issue” label)
Create a branch and start coding
Submit a pull request
Thank you for contributing to bunenv!