Add Development

2025-11-06 16:46:06 +00:00
parent 9b821d3fed
commit 8a5765d83f

475
Development.md Normal file

@@ -0,0 +1,475 @@
# Development
### Development Environment Setup
#### Prerequisites
- **Python**: 3.9, 3.10, or 3.11
- **Git**: For version control
- **Docker**: (Optional) For containerized testing
- **IDE**: VS Code, PyCharm, or similar with Python support
#### Initial Setup
1. **Clone the repository:**
```bash
git clone https://git.serendipity.systems/k.eaven/pterodactyl-discord-bot.git
cd pterodactyl-discord-bot
```
2. **Create virtual environment:**
```bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
3. **Install dependencies:**
```bash
# Production dependencies
pip install -r requirements.txt
# Development and testing dependencies
pip install -r requirements-test.txt
```
4. **Set up pre-commit hooks (optional but recommended):**
```bash
pip install pre-commit
pre-commit install
```
5. **Create development configuration:**
```bash
cp config.ini.example config.ini
# Edit config.ini with your development credentials
```
### Project Structure
```
pterodactyl-discord-bot/
├── .gitea/
│ └── workflows/
│ ├── test.yml # Test-only CI workflow
│ ├── ci-cd.yml # Complete CI/CD pipeline
│ └── docker-build.yml # Docker build workflow
├── embed/
│ └── embed_locations.json # Persistent embed tracking
├── logs/
│ └── pterodisbot.log # Application logs
├── tests/
│ └── test_pterodisbot.py # Test suite
├── pterodisbot.py # Main bot application
├── server_metrics_graphs.py # Metrics and graphing module
├── generate_config.py # Config generator from env vars
├── requirements.txt # Production dependencies
├── requirements-test.txt # Testing dependencies
├── pytest.ini # Pytest configuration
├── Makefile # Development shortcuts
├── run_tests.sh # Test runner script
├── Dockerfile # Container definition
├── docker-compose.yml # Docker Compose configuration
├── config.ini.example # Example configuration
├── README.md # Application Features Documentation
└── LICENSE # GPL-3.0 License
```
### Development Workflow
#### 1. Feature Development
```bash
# Create feature branch
git checkout -b feature/your-feature-name
# Make changes and test frequently
python pterodisbot.py # Manual testing
make test # Automated testing
# Check code quality
make lint
make format
# Commit changes
git add .
git commit -m "feat: add your feature description"
# Push and create PR
git push origin feature/your-feature-name
```
#### 2. Bug Fixes
```bash
# Create bugfix branch
git checkout -b fix/bug-description
# Write test that reproduces bug
# (in test_pterodisbot.py)
# Verify test fails
pytest test_pterodisbot.py::TestClass::test_new_bug -v
# Fix the bug
# (in pterodisbot.py or server_metrics_graphs.py)
# Verify test passes
pytest test_pterodisbot.py::TestClass::test_new_bug -v
# Run full test suite
make test
# Commit both test and fix
git add .
git commit -m "fix: resolve bug description"
```
#### 3. Testing Changes
```bash
# Run all tests
make test
# Run specific test class
pytest test_pterodisbot.py::TestConfigValidation -v
# Run with coverage
make test-coverage
# Quick test (no coverage)
make test-quick
# Watch mode (requires pytest-watch)
make watch
```
### Testing Infrastructure
#### Test Suite Organization
```python
# test_pterodisbot.py structure
├── Fixtures (reusable test setup)
│ ├── mock_config
│ ├── mock_pterodactyl_api
│ ├── sample_server_data
│ ├── sample_resources_data
│ └── mock_discord_interaction
├── TestConfigValidation
│ ├── test_valid_config
│ ├── test_missing_sections
│ ├── test_invalid_api_keys
│ └── test_invalid_urls
├── TestPterodactylAPI
│ ├── test_initialization
│ ├── test_request_success
│ ├── test_request_error
│ ├── test_get_servers
│ ├── test_get_server_resources
│ └── test_send_power_action
├── TestServerMetricsGraphs
│ ├── test_add_data_point
│ ├── test_data_rotation
│ ├── test_cpu_scale_calculation
│ ├── test_generate_graphs
│ └── test_get_data_summary
├── TestServerMetricsManager
│ ├── test_server_creation
│ ├── test_cleanup_old_servers
│ └── test_get_summary
├── TestServerStatusView
│ ├── test_authorization
│ └── test_button_interactions
├── TestPterodactylBot
│ ├── test_embed_tracking
│ ├── test_load_save_locations
│ └── test_state_management
└── TestIntegration
├── test_complete_workflow
└── test_metrics_collection
```
#### Running Tests Locally
```bash
# Using Makefile (recommended)
make test # Full test suite with coverage
make test-quick # Fast run without coverage
make test-unit # Only unit tests
make test-integration # Only integration tests
make ci # Simulate full CI pipeline
# Using shell script
./run_tests.sh # Interactive full test run
./run_tests.sh --quick # Skip linting and security
./run_tests.sh --coverage-only # Just coverage report
# Direct pytest
pytest test_pterodisbot.py -v
pytest test_pterodisbot.py::TestClass::test_method -v
pytest -m "not slow" -v # Skip slow tests
pytest --lf # Run last failed tests only
```
#### Coverage Goals
- **Minimum**: 70% overall coverage
- **Target**: 85% overall coverage
- **Critical Modules**: 90%+ coverage
- Configuration validation
- Pterodactyl API client
- Metrics tracking system
#### Viewing Coverage Reports
```bash
# Generate HTML report
make test-coverage
# Open in browser
python -m http.server --directory htmlcov 8000
# Navigate to http://localhost:8000
# Terminal report
pytest --cov=pterodisbot --cov-report=term-missing
```
### Code Quality Standards
#### Linting and Formatting
```bash
# Check all quality standards
make lint
# Auto-format code
make format
# Individual tools
flake8 pterodisbot.py --max-line-length=120
pylint pterodisbot.py --max-line-length=120
black --check --line-length=120 pterodisbot.py
isort --check-only --profile black pterodisbot.py
```
#### Style Guidelines
**PEP 8 Compliance:**
- Maximum line length: 120 characters
- 4 spaces for indentation
- Snake_case for functions and variables
- PascalCase for classes
- UPPER_CASE for constants
**Type Hints:**
```python
def function_name(param1: str, param2: int) -> Optional[dict]:
"""Function docstring."""
return result
```
**Docstrings:**
```python
def complex_function(arg1: str, arg2: int) -> dict:
"""
Brief description of function purpose.
Detailed explanation of what the function does,
including any important behavior or side effects.
Args:
arg1: Description of first argument
arg2: Description of second argument
Returns:
Description of return value
Raises:
ValueError: When invalid input is provided
APIError: When API request fails
"""
pass
```
**Comments:**
- Use comments to explain **why**, not **what**
- Complex algorithms should have explanatory comments
- TODO comments should include ticket references
### Security Best Practices
#### Running Security Scans
```bash
# All security checks
make security
# Individual tools
bandit -r . -ll # Code security
safety check # Dependency vulnerabilities
pip-audit # Package auditing
```
#### Security Checklist
- [ ] No hardcoded credentials in code
- [ ] API keys stored in config.ini (gitignored)
- [ ] All user input validated
- [ ] SQL injection prevention (N/A - no database)
- [ ] Rate limiting on API calls
- [ ] Error messages don't leak sensitive info
- [ ] Logs don't contain API keys or tokens
### Debugging Tips
#### Logging Levels
```python
# Add debug logging
logger.debug(f"Processing server {server_id}")
# Log important state changes
logger.info(f"Server {name} changed state to {new_state}")
# Log warnings
logger.warning(f"API rate limit approaching")
# Log errors with context
logger.error(f"Failed to update embed: {str(e)}")
```
#### Common Debugging Commands
```bash
# View logs in real-time
tail -f logs/pterodisbot.log
# Search logs for errors
grep ERROR logs/pterodisbot.log
# Run bot with verbose logging
PYTHONUNBUFFERED=1 python pterodisbot.py
# Debug specific test
pytest test_pterodisbot.py::test_name --pdb # Drop into debugger on failure
pytest test_pterodisbot.py -vv --showlocals # Show local variables
```
#### VS Code Launch Configuration
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Bot",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/pterodisbot.py",
"console": "integratedTerminal",
"env": {
"PYTHONUNBUFFERED": "1"
}
},
{
"name": "Python: Current Test",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"${file}",
"-v"
],
"console": "integratedTerminal"
}
]
}
```
### CI/CD Integration
#### Automated Workflows
The project uses Gitea Actions for continuous integration and deployment:
**1. Test Workflow** (`.gitea/workflows/test.yml`)
- Triggers: Push to any branch, PRs to main
- Matrix testing: Python 3.9, 3.10, 3.11
- Steps: Lint → Test → Security Scan → Coverage Report
**2. CI/CD Workflow** (`.gitea/workflows/ci-cd.yml`)
- Triggers: Push to main/experimental/dev, version tags, manual dispatch
- Steps: Test → Build Docker → Push Registry → Report
- Features: Multi-arch builds, automatic versioning
#### Local CI Simulation
```bash
# Run full CI pipeline locally
make ci
# This executes:
# 1. Clean previous artifacts
# 2. Install dependencies
# 3. Run all tests with coverage
# 4. Run linting checks
# 5. Run security scans
# 6. Generate reports
```
#### Branch Protection Rules
Recommended settings for `main` branch:
- ✅ Require status checks to pass
- ✅ Unit Tests (Python 3.11)
- ✅ Code Quality
- ✅ Security Scan
- ✅ Require branches to be up to date
- ✅ Require pull request reviews (1+ approvals)
- ✅ Dismiss stale reviews on new commits
### Performance Testing
```bash
# Profile the application
python -m cProfile -o profile.stats pterodisbot.py
# Analyze profile
python -m pstats profile.stats
> sort cumtime
> stats 20
# Memory profiling
pip install memory_profiler
python -m memory_profiler pterodisbot.py
```
### Documentation
#### Generating API Documentation
```bash
# Install documentation tools
pip install pdoc3
# Generate HTML documentation
pdoc --html --output-dir docs pterodisbot.py server_metrics_graphs.py
# View documentation
python -m http.server --directory docs 8080
```
#### Updating Documentation
When adding new features:
1. Update inline code comments
2. Update function/class docstrings
3. Update README.md if user-facing
5. Add architecture diagrams if complex