Thank you for your interest in contributing to hier-config-cli! This document provides guidelines and instructions for contributing.
By participating in this project, you agree to maintain a respectful and inclusive environment for everyone.
If you find a bug, please open an issue on GitHub with:
- Clear title describing the issue
- Detailed description of the bug
- Steps to reproduce the issue
- Expected behavior vs actual behavior
- Environment details (OS, Python version, hier-config-cli version)
- Sample configs if applicable (sanitized)
Example:
## Bug Report
### Description
hier-config-cli fails when processing FortiOS configurations with certain syntax.
### Steps to Reproduce
1. Run: `hier-config-cli remediation --platform fortios --running-config running.conf --generated-config intended.conf`
2. Error occurs during parsing
### Expected Behavior
Should generate remediation configuration
### Actual Behavior
Raises parsing error: [error message]
### Environment
- OS: Ubuntu 22.04
- Python: 3.11.5
- hier-config-cli: 0.2.0
- hier-config: 3.4.0Feature requests are welcome! Please open an issue with:
- Clear use case explaining why the feature would be useful
- Detailed description of the proposed functionality
- Example usage showing how it would work
- Alternative solutions you've considered
- Fork the repository
- Create a feature branch from
main - Make your changes
- Add tests for new functionality
- Update documentation as needed
- Run all quality checks (tests, linting, type checking)
- Submit a pull request
- Python 3.10 or higher
- Poetry for dependency management
- Git
# Clone your fork
git clone https://github.com/YOUR_USERNAME/hier-config-cli.git
cd hier-config-cli
# Install dependencies
poetry install
# Activate virtual environment
poetry shell
# Verify installation
hier-config-cli version# Run all tests
pytest
# Run with coverage
pytest --cov=hier_config_cli --cov-report=html
# Run specific test file
pytest tests/test_cli.py
# Run with verbose output
pytest -v
# Run and watch for changes
pytest-watchBefore submitting a PR, ensure all quality checks pass:
# Format code with black
black src/ tests/
# Check linting with ruff
ruff check src/ tests/
# Fix auto-fixable issues
ruff check --fix src/ tests/
# Type check with mypy
mypy src/
# Run all checks at once
black src/ tests/ && ruff check src/ tests/ && mypy src/ && pytestWe recommend using pre-commit hooks:
# Install pre-commit
pip install pre-commit
# Install hooks
pre-commit install
# Run manually
pre-commit run --all-files.pre-commit-config.yaml:
repos:
- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
args: [--fix]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.13.0
hooks:
- id: mypy
additional_dependencies: [types-pyyaml]- Follow PEP 8 style guidelines
- Use Black for code formatting (line length: 100)
- Use type hints for all functions
- Write docstrings for all public functions/classes
from pathlib import Path
from typing import Optional
def process_config(
config_path: Path,
platform: str,
output_format: str = "text",
) -> str:
"""Process configuration file.
Args:
config_path: Path to configuration file
platform: Platform name
output_format: Output format (text, json, yaml)
Returns:
Processed configuration as string
Raises:
FileNotFoundError: If config file doesn't exist
ValueError: If platform is unknown
"""
# Implementation
passUse Google-style docstrings:
def example_function(param1: str, param2: int) -> bool:
"""Brief description of function.
Longer description if needed. Can span multiple
lines and paragraphs.
Args:
param1: Description of param1
param2: Description of param2
Returns:
Description of return value
Raises:
ValueError: When param2 is negative
TypeError: When param1 is not a string
Example:
>>> example_function("test", 42)
True
"""
passimport click
# Use click.ClickException for user-facing errors
try:
config = read_file(path)
except FileNotFoundError:
raise click.ClickException(
f"Configuration file not found: {path}"
) from None
# Chain exceptions for debugging
except Exception as e:
raise click.ClickException(
f"Error processing configuration: {e}"
) from eimport pytest
from pathlib import Path
from hier_config_cli import process_configs
def test_remediation_generation():
"""Test remediation configuration generation."""
# Arrange
platform = "ios"
running_config = "test_data/running.conf"
intended_config = "test_data/intended.conf"
# Act
result, platform_enum = process_configs(
platform,
running_config,
intended_config,
"remediation",
)
# Assert
assert result is not None
assert len(list(result.all_children())) > 0
def test_invalid_platform():
"""Test error handling for invalid platform."""
with pytest.raises(click.ClickException) as exc_info:
process_configs(
"invalid_platform",
"running.conf",
"intended.conf",
"remediation",
)
assert "Unknown platform" in str(exc_info.value)- Aim for >90% code coverage
- Test happy paths and error conditions
- Include edge cases
- Use fixtures for common test data
import pytest
from pathlib import Path
@pytest.fixture
def test_configs(tmp_path):
"""Create test configuration files."""
running = tmp_path / "running.conf"
running.write_text("hostname test-router\n")
intended = tmp_path / "intended.conf"
intended.write_text("hostname new-router\n")
return {
"running": str(running),
"intended": str(intended),
}
def test_with_fixture(test_configs):
"""Test using fixture."""
result = process_configs(
"ios",
test_configs["running"],
test_configs["intended"],
"remediation",
)
assert result is not None- Update docs in the
docs/directory - Use Markdown format
- Include code examples
- Add links to related pages
# Install mkdocs
pip install mkdocs mkdocs-material mkdocstrings[python]
# Serve locally
mkdocs serve
# Build static site
mkdocs build
# Open in browser
# Navigate to http://127.0.0.1:8000- Use clear, concise language
- Provide working examples
- Include expected output
- Add troubleshooting tips
- Link to related documentation
- All tests pass
- Code is formatted with Black
- No linting errors from Ruff
- Type checking passes with mypy
- Documentation is updated
- CHANGELOG.md is updated (if applicable)
- Commit messages are clear and descriptive
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
Describe the tests you ran and their results
## Checklist
- [ ] Tests pass locally
- [ ] Code follows style guidelines
- [ ] Documentation updated
- [ ] No new warnings- Maintainer reviews code
- Automated checks run (tests, linting, type checking)
- Feedback is provided if changes needed
- Once approved, PR is merged
(For maintainers)
- Update version in
pyproject.tomlandsrc/hier_config_cli/__main__.py - Update
CHANGELOG.md - Create a git tag:
git tag v0.x.x - Push tag:
git push origin v0.x.x - GitHub Actions will build and publish to PyPI
- GitHub Issues: Report bugs or request features
- GitHub Discussions: Ask questions
- Email: james.williams@packetgeek.net
Contributors will be recognized in:
- CHANGELOG.md
- GitHub contributors page
- Release notes
Thank you for contributing to hier-config-cli!