Rename integration for consistent branding: - User-facing name: "Spotify Voice Assistant" - Integration name: "Spotify Voice Assistant Search" - Domain: spotify_voice_assistant Changes: - Rename custom_components/spotify_search/ to spotify_voice_assistant/ - Update domain in manifest.json and __init__.py - Update all service references in examples - Update all documentation references
386 lines
11 KiB
Markdown
386 lines
11 KiB
Markdown
# Development Guide
|
|
|
|
## Development Setup
|
|
|
|
This repository is set up for active development while being used in a running Home Assistant instance.
|
|
|
|
### Recommended Setup: Docker Bind Mount
|
|
|
|
For Docker-based Home Assistant installations, use a bind mount to link this repository directly into your container. This is the cleanest approach for active development.
|
|
|
|
**Add this volume to your Docker run command or docker-compose.yml:**
|
|
|
|
```bash
|
|
# Docker run example
|
|
docker run ... \
|
|
-v /path/to/spotify-voice-assistant/custom_components/spotify_voice_assistant:/config/custom_components/spotify_voice_assistant:ro \
|
|
...
|
|
|
|
# docker-compose.yml example
|
|
services:
|
|
homeassistant:
|
|
volumes:
|
|
- /path/to/spotify-voice-assistant/custom_components/spotify_voice_assistant:/config/custom_components/spotify_voice_assistant:ro
|
|
```
|
|
|
|
**Benefits:**
|
|
- ✅ Edit files in your development repository
|
|
- ✅ Changes immediately reflected (after restart/reload)
|
|
- ✅ Develop, test, and commit from one location
|
|
- ✅ No file duplication or sync issues
|
|
- ✅ Read-only mount (`:ro`) protects your source files
|
|
|
|
**Note:** You'll need to recreate/restart your container after adding the bind mount.
|
|
|
|
### Alternative: Symlink Development (Non-Docker or Host Config)
|
|
|
|
If you have direct filesystem access to your Home Assistant config directory:
|
|
|
|
```bash
|
|
# Remove existing installation (if using HACS version)
|
|
rm -rf /path/to/homeassistant/config/custom_components/spotify_voice_assistant
|
|
|
|
# Create symlink to your development repo
|
|
ln -s /path/to/your/spotify-voice-assistant/custom_components/spotify_voice_assistant \
|
|
/path/to/homeassistant/config/custom_components/spotify_voice_assistant
|
|
```
|
|
|
|
**Important for Docker:** If using symlinks with Docker, ensure the symlink target path is accessible from inside the container (either mounted or within the config volume).
|
|
|
|
### When to Restart vs Reload
|
|
|
|
Understanding when you need to restart Home Assistant vs just reloading the integration:
|
|
|
|
**Full Restart Required:**
|
|
- Python code changes (`__init__.py`)
|
|
- Manifest changes (`manifest.json`)
|
|
- Adding/removing the integration
|
|
- First-time setup
|
|
|
|
**Reload Integration Only:**
|
|
- Service definition changes (`services.yaml`)
|
|
- Go to Developer Tools > YAML > Reload "Core Configuration"
|
|
|
|
**No Action Required:**
|
|
- Documentation changes (README.md, DEVELOPMENT.md)
|
|
- Git operations (commit, push, tag)
|
|
|
|
## Development Workflow
|
|
|
|
### 1. Make Changes
|
|
|
|
```bash
|
|
cd /path/to/your/spotify-voice-assistant
|
|
# Edit files in custom_components/spotify_voice_assistant/
|
|
```
|
|
|
|
### 2. Test Changes
|
|
|
|
```bash
|
|
# For Python code changes - full restart
|
|
docker restart homeassistant
|
|
|
|
# For YAML changes - reload only (faster)
|
|
# Use Developer Tools > YAML > Core Configuration
|
|
|
|
# Watch logs in real-time
|
|
docker logs -f homeassistant 2>&1 | grep spotify_voice_assistant
|
|
```
|
|
|
|
### 3. Commit Changes
|
|
|
|
```bash
|
|
git add .
|
|
git commit -m "Description of changes"
|
|
git push
|
|
```
|
|
|
|
### 4. Create Release (when ready)
|
|
|
|
- Update version in `manifest.json`
|
|
- Push changes
|
|
- Create new GitHub release (e.g., v1.1.0)
|
|
- HACS will auto-detect and notify users
|
|
|
|
## Switching Between Development and HACS
|
|
|
|
### Switch to HACS Version
|
|
|
|
When you want to use the stable HACS version instead of development:
|
|
|
|
**For bind mount setup:**
|
|
```bash
|
|
# Remove the bind mount from your Docker configuration
|
|
# Recreate the container without the bind mount
|
|
docker restart homeassistant
|
|
|
|
# Install via HACS
|
|
# HACS > Integrations > Spotify Voice Assistant > Install
|
|
# Restart Home Assistant
|
|
```
|
|
|
|
**For symlink setup:**
|
|
```bash
|
|
# Remove symlink
|
|
rm /path/to/homeassistant/config/custom_components/spotify_voice_assistant
|
|
|
|
# Install via HACS
|
|
# HACS > Integrations > Spotify Voice Assistant > Install
|
|
# Restart Home Assistant
|
|
```
|
|
|
|
### Switch Back to Development
|
|
|
|
**For bind mount setup:**
|
|
```bash
|
|
# Add the bind mount back to your Docker configuration
|
|
# Recreate/restart the container
|
|
docker restart homeassistant
|
|
```
|
|
|
|
**For symlink setup:**
|
|
```bash
|
|
# Remove HACS version
|
|
rm -rf /path/to/homeassistant/config/custom_components/spotify_voice_assistant
|
|
|
|
# Recreate symlink
|
|
ln -s /path/to/your/spotify-voice-assistant/custom_components/spotify_voice_assistant \
|
|
/path/to/homeassistant/config/custom_components/spotify_voice_assistant
|
|
|
|
# Restart Home Assistant
|
|
```
|
|
|
|
## Testing Checklist
|
|
|
|
Before each release:
|
|
|
|
- [ ] Test artist search with exact match (e.g., "Coldplay")
|
|
- [ ] Test artist search with first result fallback
|
|
- [ ] Test album search
|
|
- [ ] Test track search
|
|
- [ ] Test playlist search (user playlists and public)
|
|
- [ ] Test queue functionality (play vs queue modes)
|
|
- [ ] Test shuffle controls (on/off)
|
|
- [ ] Test via voice commands through Extended OpenAI Conversation
|
|
- [ ] Test via Developer Tools service call
|
|
- [ ] Test clear_cache service
|
|
- [ ] Check debug logs for errors
|
|
- [ ] Verify caching is working (check debug logs for "Using cached Spotify client")
|
|
- [ ] Verify version in manifest.json is updated
|
|
- [ ] Update README if features changed
|
|
|
|
## File Structure
|
|
|
|
```
|
|
spotify-voice-assistant/
|
|
├── custom_components/
|
|
│ └── spotify_voice_assistant/
|
|
│ ├── __init__.py # Main integration code
|
|
│ ├── manifest.json # Version and metadata
|
|
│ └── services.yaml # Service definitions
|
|
├── examples/ # User examples
|
|
├── README.md # Main documentation
|
|
├── LICENSE # MIT License
|
|
├── .gitignore # Git ignore patterns
|
|
├── DEVELOPMENT.md # This file
|
|
└── GITHUB-SETUP.md # GitHub setup instructions
|
|
```
|
|
|
|
## Debugging
|
|
|
|
### Enable Debug Logging
|
|
|
|
In Home Assistant `configuration.yaml`:
|
|
```yaml
|
|
logger:
|
|
default: info
|
|
logs:
|
|
custom_components.spotify_voice_assistant: debug
|
|
```
|
|
|
|
After adding debug logging, restart Home Assistant to apply.
|
|
|
|
### Common Debug Commands
|
|
|
|
```bash
|
|
# Watch integration logs in real-time (Docker example)
|
|
docker logs -f homeassistant 2>&1 | grep spotify_voice_assistant
|
|
|
|
# Check if integration loaded successfully
|
|
docker logs homeassistant 2>&1 | grep "Setting up spotify_voice_assistant"
|
|
|
|
# Verify bind mount or symlink
|
|
# For bind mount:
|
|
docker inspect homeassistant | grep spotify_voice_assistant
|
|
|
|
# For symlink:
|
|
ls -la /path/to/homeassistant/config/custom_components/spotify_voice_assistant
|
|
|
|
# Check manifest version
|
|
cat custom_components/spotify_voice_assistant/manifest.json | grep version
|
|
|
|
# Check Python syntax without running
|
|
python3 -m py_compile custom_components/spotify_voice_assistant/__init__.py
|
|
```
|
|
|
|
### Debug Logging Output
|
|
|
|
When working correctly, you should see:
|
|
```
|
|
INFO Setting up spotify_voice_assistant
|
|
INFO Setup of domain spotify_voice_assistant took 0.00 seconds
|
|
DEBUG Cache miss, performing Spotify entity lookup
|
|
DEBUG Found Spotify entity: media_player.spotify_xxx
|
|
DEBUG Spotify client type: SpotifyClient
|
|
INFO Cached Spotify client for entity: media_player.spotify_xxx
|
|
DEBUG Searching for artist: Coldplay
|
|
INFO Found Spotify artist: Coldplay (spotify:artist:4gzpq5DPGxSnKTe4SA8HAU) - exact match
|
|
```
|
|
|
|
Subsequent searches should show:
|
|
```
|
|
DEBUG Using cached Spotify client # <-- Caching is working!
|
|
```
|
|
|
|
### Test Service Call
|
|
|
|
Via Developer Tools > Services:
|
|
```yaml
|
|
service: spotify_voice_assistant.search
|
|
data:
|
|
query: "Coldplay"
|
|
type: "artist"
|
|
```
|
|
|
|
Expected response:
|
|
```json
|
|
{
|
|
"uri": "spotify:artist:4gzpq5DPGxSnKTe4SA8HAU",
|
|
"name": "Coldplay",
|
|
"type": "artist"
|
|
}
|
|
```
|
|
|
|
### Test Clear Cache Service
|
|
|
|
```yaml
|
|
service: spotify_voice_assistant.clear_cache
|
|
```
|
|
|
|
Expected response:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Cache cleared"
|
|
}
|
|
```
|
|
|
|
## Performance Notes
|
|
|
|
The v1.0.0 release includes client caching that provides 15-50x performance improvement:
|
|
|
|
- **Without cache:** ~150-500ms per search (full entity lookup)
|
|
- **With cache:** ~3-10ms per search (cached client reuse)
|
|
|
|
Cache automatically invalidates if the Spotify integration is reloaded or removed.
|
|
|
|
## Version Numbering
|
|
|
|
Follow semantic versioning:
|
|
- **v1.0.x** - Bug fixes only
|
|
- **v1.x.0** - New features (config options, additional search types, etc.)
|
|
- **v2.0.0** - Breaking changes (API changes, config changes, etc.)
|
|
|
|
## Release Process
|
|
|
|
When making improvements:
|
|
|
|
1. Make changes and test thoroughly with checklist above
|
|
2. Update version in `manifest.json`
|
|
3. Commit with descriptive message (no AI attribution)
|
|
4. Push to main branch
|
|
5. Create GitHub release with tag matching manifest version
|
|
6. HACS users will be notified automatically
|
|
|
|
**Example:**
|
|
```bash
|
|
# Update manifest.json version to 1.1.0
|
|
git add custom_components/spotify_voice_assistant/manifest.json
|
|
git commit -m "Add support for podcast search"
|
|
git push
|
|
|
|
# Create release on GitHub
|
|
gh release create v1.1.0 --title "v1.1.0 - Podcast Search Support" \
|
|
--notes "Added support for searching Spotify podcasts"
|
|
```
|
|
|
|
## Backup Strategy
|
|
|
|
Before making major changes, create a backup:
|
|
|
|
```bash
|
|
# Backup your development repository
|
|
tar -czf spotify-voice-assistant-backup-$(date +%Y%m%d).tar.gz \
|
|
custom_components/
|
|
|
|
# Optionally backup your HA configuration
|
|
cp /path/to/homeassistant/config/configuration.yaml \
|
|
configuration-backup-$(date +%Y%m%d).yaml
|
|
```
|
|
|
|
## Common Issues
|
|
|
|
### Integration Not Loading
|
|
|
|
**Symptom:** No "Setting up spotify_voice_assistant" in logs
|
|
|
|
**Check:**
|
|
1. Verify bind mount or symlink is correct
|
|
2. Check `configuration.yaml` has `spotify_voice_assistant:` entry
|
|
3. Ensure files are readable by HA container user
|
|
4. Look for Python syntax errors in logs
|
|
|
|
**Docker bind mount check:**
|
|
```bash
|
|
docker inspect homeassistant | grep -A2 spotify_voice_assistant
|
|
```
|
|
|
|
### Symlink Not Working in Docker
|
|
|
|
**Symptom:** Integration loads but shows errors about missing files
|
|
|
|
**Solution:** Symlinks must point to paths accessible from inside the container. Use bind mounts instead (see setup section above).
|
|
|
|
### Changes Not Reflecting
|
|
|
|
**Symptom:** Made changes but HA still runs old code
|
|
|
|
**Solution:**
|
|
1. Ensure you're editing the correct files (check bind mount/symlink target)
|
|
2. Restart HA after Python code changes
|
|
3. Check for cached `.pyc` files in `__pycache__/` and clear if needed
|
|
4. Verify bind mount is not read-only when testing (remove `:ro` temporarily)
|
|
|
|
## Code Quality
|
|
|
|
### Before Committing
|
|
|
|
```bash
|
|
# Check Python syntax
|
|
python3 -m py_compile custom_components/spotify_voice_assistant/__init__.py
|
|
|
|
# Check for common issues
|
|
grep -n "TODO\|FIXME\|XXX" custom_components/spotify_voice_assistant/*.py
|
|
|
|
# Ensure no debug print statements
|
|
grep -n "print(" custom_components/spotify_voice_assistant/*.py
|
|
```
|
|
|
|
### Code Standards
|
|
|
|
- Use lazy logging: `_LOGGER.debug("Text: %s", var)` not `_LOGGER.debug(f"Text: {var}")`
|
|
- Use defensive programming: check attributes with `hasattr()` before accessing
|
|
- Validate all user inputs
|
|
- Handle specific exceptions before generic ones
|
|
- Keep functions focused and under 50 lines when possible
|