Contributing Guide¶
Thank you for considering contributing to easy_sm! This guide will help you get started.
Development Setup¶
1. Fork and Clone¶
Fork the repository on GitHub, then clone your fork:
2. Install in Development Mode¶
Install easy_sm with all dependencies:
This allows code changes without reinstalling.
3. Install Development Dependencies¶
Install testing and quality tools:
This installs:
- pytest: Test framework
- mypy: Type checker
- ruff: Linter and formatter
- requests: HTTP library for tests
- statsmodels, joblib, pandas: Sample app dependencies
4. Verify Installation¶
# Run CLI
easy_sm --help
# Run tests
pytest
# Type checking
mypy easy_sm/
# Linting
ruff check easy_sm/
Development Workflow¶
1. Create a Branch¶
Create a feature branch for your changes:
Branch naming conventions:
feature/description- New featuresfix/description- Bug fixesdocs/description- Documentation changesrefactor/description- Code refactoringtest/description- Test improvements
2. Make Changes¶
Edit code following the Code Style Guide:
- Use type hints
- Follow naming conventions
- Add docstrings
- Write tests
3. Run Tests¶
Test your changes:
# Run all tests
pytest
# Run specific test file
pytest tests/test_my_feature.py
# Run with coverage
pytest --cov=easy_sm
4. Check Code Quality¶
5. Commit Changes¶
Write clear commit messages:
Commit message format:
feat:New featuresfix:Bug fixesdocs:Documentation changestest:Test improvementsrefactor:Code refactoringchore:Maintenance tasks
6. Push to Your Fork¶
7. Create Pull Request¶
- Go to your fork on GitHub
- Click "New Pull Request"
- Select
mainas the base branch - Describe your changes clearly
- Link any related issues
Adding New Commands¶
1. Create Command File¶
Create a new file in easy_sm/commands/:
2. Define Command¶
Follow existing patterns:
# easy_sm/commands/my_command.py
from typing import Annotated, Optional
import typer
from easy_sm.commands import helpers
from easy_sm.commands.helpers import get_app_name, load_config
@app.command()
def my_command(
app_name: Annotated[Optional[str], typer.Option("--app-name", "-a", help="App name")] = None,
param: Annotated[str, typer.Option("--param", "-p", help="Parameter description")],
) -> None:
"""
Description of what this command does.
This is a longer description that appears in help text.
"""
# Auto-detect app name
app_name = get_app_name(app_name)
# Load configuration
config = load_config(app_name)
# Command logic
result = do_something(config, param)
# Output result (pipe-friendly)
print(result)
3. Register Command¶
Add to easy_sm/__main__.py:
# Import command
from easy_sm.commands.my_command import my_command
# Register with app
app.command()(my_command)
4. Write Tests¶
Create test file:
# tests/test_my_command.py
import mock
import pytest
from easy_sm.commands.my_command import my_command
def test_my_command_basic():
"""Test basic functionality."""
# Arrange
app_name = "test-app"
param = "value"
# Act
result = my_command(app_name, param)
# Assert
assert result.success
@mock.patch('subprocess.run')
def test_my_command_with_subprocess(mock_run):
"""Test command that calls subprocess."""
# Setup mock
mock_run.return_value = mock.Mock(returncode=0)
# Test
result = my_command(...)
# Verify
mock_run.assert_called_once()
5. Add Documentation¶
Create command documentation in docs/commands/my-command.md:
# my-command
Description of the command.
## Synopsis
\`\`\`bash
easy_sm my-command [OPTIONS]
\`\`\`
## Options
| Option | Description |
|--------|-------------|
| `-a, --app-name` | App name |
| `-p, --param` | Parameter |
## Examples
\`\`\`bash
easy_sm my-command -p value
\`\`\`
Update docs/commands/index.md to include your command.
Testing Guidelines¶
Write Tests for All New Code¶
Every new feature should have tests:
def test_new_feature():
"""Test new feature works correctly."""
result = new_feature()
assert result.is_valid()
def test_new_feature_error_handling():
"""Test new feature handles errors."""
with pytest.raises(ValueError):
new_feature(invalid_input)
Mock External Dependencies¶
Don't make real AWS or Docker calls:
@mock.patch('boto3.client')
def test_with_aws(mock_boto):
"""Test function using AWS."""
mock_client = mock.Mock()
mock_boto.return_value = mock_client
# Test your function
result = my_aws_function()
# Verify AWS call
mock_client.some_method.assert_called_once()
Test Both Success and Failure¶
def test_success_case():
"""Test successful execution."""
assert my_function(valid_input).success
def test_failure_case():
"""Test error handling."""
with pytest.raises(ValueError):
my_function(invalid_input)
Documentation¶
Update Documentation¶
If your change affects user-facing behavior:
- Update relevant documentation in
docs/ - Update
README.mdif needed - Add examples showing new functionality
Docstrings¶
Add docstrings to all public functions:
def my_function(param: str) -> bool:
"""
Brief description of what function does.
Longer description with more details about behavior,
edge cases, and usage examples.
Args:
param: Description of parameter
Returns:
Description of return value
Raises:
ValueError: When input is invalid
"""
# Implementation
Code Review Process¶
What to Expect¶
- Automated Checks: CI/CD runs tests, linting, type checking
- Maintainer Review: A maintainer reviews your code
- Feedback: You may be asked to make changes
- Approval: Once approved, your PR will be merged
Review Criteria¶
- Tests: All tests pass, new code has tests
- Quality: Code follows style guide, passes linting
- Documentation: Changes are documented
- Functionality: Code works as intended
- Design: Fits with overall architecture
Best Practices¶
Keep PRs Focused¶
- One feature or fix per PR
- Small, reviewable changes
- Clear description of changes
Write Good Commit Messages¶
# Good
git commit -m "feat: add support for spot training instances"
git commit -m "fix: handle missing config file gracefully"
git commit -m "docs: update AWS setup guide with IAM details"
# Avoid
git commit -m "updates"
git commit -m "fix bug"
git commit -m "wip"
Follow Existing Patterns¶
- Look at existing commands for examples
- Use the same error handling patterns
- Follow the same testing style
Ask Questions¶
If you're unsure about anything:
- Open an issue to discuss your idea
- Ask in the pull request comments
- Reference related issues or PRs
Building and Testing Locally¶
Build Package¶
Install Locally¶
Run CLI¶
Run Full Test Suite¶
# All tests with coverage
pytest --cov=easy_sm
# Specific test file
pytest tests/test_build_command.py
# Type checking
mypy easy_sm/
# Linting
ruff check easy_sm/
Release Process¶
(For maintainers)
1. Update Version¶
Edit setup.py:
2. Update Changelog¶
Document changes in CHANGELOG.md.
3. Create Tag¶
4. Build and Publish¶
Getting Help¶
- Issues: github.com/prteek/easy_sm/issues
- Discussions: GitHub Discussions
- Email: prteek@icloud.com
Code of Conduct¶
- Be respectful and constructive
- Welcome newcomers
- Focus on what's best for the project
- Show empathy towards others
License¶
By contributing, you agree that your contributions will be licensed under the MIT License.
See Also¶
- Architecture - System design
- Code Style - Coding conventions
- Testing Guide - Testing practices