Add Development
475
Development.md
Normal file
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
|
||||||
Reference in New Issue
Block a user