Thank you for your interest in contributing to WebStatusπ! This document provides guidelines for contributing to the project.
- Code of Conduct
- How Can I Contribute?
- Development Setup
- Running Tests
- Pull Request Process
- Code Style
This project follows a simple code of conduct:
- Be respectful and inclusive
- Focus on constructive feedback
- Help others learn and grow
- Keep discussions technical and on-topic
Before creating a bug report, please check existing issues to avoid duplicates.
When reporting a bug, include:
- Environment: Raspberry Pi model, OS version, Python version
- Steps to reproduce: Clear, numbered steps
- Expected behavior: What you expected to happen
- Actual behavior: What actually happened
- Logs/Output: Relevant console output or error messages
- Configuration: Your
config.yaml(redact sensitive URLs if needed)
Feature suggestions are welcome! Please:
- Check existing issues for similar suggestions
- Open a new issue with the
enhancementlabel - Describe the use case and why it would be useful
- Consider the hardware constraints (Pi 1B+ has limited resources)
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes following the code style
- Write/update tests as needed
- Ensure all tests pass
- Submit a pull request
- Python 3.11+ (required for modern language features)
- SQLite3 (usually pre-installed)
- Git
# 1. Fork and clone the repository
git clone https://github.com/<your-username>/webstatuspi.git
cd webstatuspi
# 2. Create a virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# 3. Install development dependencies
pip install -e .[dev]
# 4. Create your configuration file
cp config.example.yaml config.yaml
# Edit config.yaml with your test URLs
# 5. Run the application
python -m webstatuspiYou can develop and test without physical hardware using mocks:
# Run with hardware mocks enabled
MOCK_GPIO=true MOCK_DISPLAY=true python -m webstatuspiSee docs/testing/MOCKING.md for detailed mocking documentation.
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run specific test file
pytest tests/test_monitor.py
# Run with coverage report
pytest --cov=webstatuspi --cov-report=html
# Open coverage report (macOS)
open htmlcov/index.htmltests/test_config.py- Configuration loading and validationtests/test_database.py- Database operationstests/test_monitor.py- URL monitoring logictests/test_api.py- API endpoints
- Run linters: Ensure code passes ruff checks
ruff check . ruff format --check .
- Update tests: Add or modify tests for your changes
- Run tests: Ensure all tests pass (
pytest) - Update docs: If your change affects user-facing behavior, update relevant documentation
Tip: Install the pre-commit hook to run linters automatically before each commit:
pre-commit install
- One feature per PR: Keep PRs focused and reviewable
- Clear title: Use a descriptive title (e.g., "Add timeout configuration per URL")
- Description: Explain what changes you made and why
- Link issues: Reference related issues (e.g., "Fixes #123")
## Summary
Brief description of the changes.
## Changes
- Change 1
- Change 2
## Testing
How did you test these changes?
## Related Issues
Fixes #issue_number (if applicable)- A maintainer will review your PR
- Address any feedback or requested changes
- Once approved, a maintainer will merge your PR
This project follows specific coding conventions optimized for the Raspberry Pi 1B+ constraints.
For detailed code style guidelines, see AGENTS.md.
- Type hints: Required for all functions. Use Python 3.11+ syntax:
list[str]notList[str],X | NonenotOptional[X] - Functional approach: Prefer functions over classes for logic
- Naming:
snake_casefor functions/variables,PascalCasefor types - Imports: Standard library first, then third-party, then local (alphabetically sorted)
- Line length: Maximum 120 characters
- Dependencies: Minimal - avoid adding new dependencies without discussion
- Linting: Code must pass
ruff checkandruff format
from dataclasses import dataclass
@dataclass
class CheckResult:
"""Result of a URL health check."""
url: str
status_code: int | None
response_time_ms: int
is_success: bool
error_message: str | None = None
def check_url(url: str, timeout: int = 10) -> CheckResult:
"""Check if a URL is accessible and return the result."""
# Implementation...If you have questions about contributing, feel free to:
- Open an issue with the
questionlabel - Check the documentation
Thank you for contributing!