--- name: local-frappe description: Local Frappe development environment for testing APIs before production deployment. Use when developing or testing Python/API changes locally. allowed-tools: Bash, Read, Grep, Edit, Write user-invocable: true --- # /local-frappe - Local Frappe Development ## CRITICAL: TEST LOCALLY FIRST - NO EXCEPTIONS **NEVER deploy Frappe/Python changes directly to production.** | Action | Time | When to Use | |--------|------|-------------| | Local test | **Seconds** | ALWAYS - every code change | | Production deploy | 15-20 min | ONLY after local testing passes | **The 15-20 minute production build/deploy cycle is UNACCEPTABLE for iterative development.** ## What This Command Does Sets up and manages a local Frappe development environment for testing BEI custom APIs before deploying to production. **MANDATORY:** Always test changes locally BEFORE pushing to production. The local environment matches production (Frappe v15, ERPNext v15, HRMS v15). ## Quick Start ```bash cd docker-dev dev.bat start # Windows (first run takes 10-15 minutes) ./dev.sh start # Linux/Mac ``` ## Access | URL | Purpose | |-----|---------| | http://localhost:8000 | Frappe web UI | | http://localhost:8000/api/method/frappe.ping | API test endpoint | | http://localhost:8000/api/method/hrms.api.hello.hello | BEI test API | | localhost:3307 | MariaDB (user: root, pass: admin) | **Login:** Administrator / admin ## Development Workflow ### Standard Workflow (Edit → Sync → Test) ```bash # 1. Edit your API file locally # Example: hrms/api/employee_clearance.py # 2. Sync to container and clear cache dev.bat sync # 3. Test your API curl http://localhost:8000/api/method/hrms.api.employee_clearance.get_status # 4. When ready, commit and push to production git add . git commit -m "feat: Add employee clearance API" git push origin production ``` ### Helper Commands | Command | Description | |---------|-------------| | `dev.bat start` | Start all containers (first run: 10-15 min) | | `dev.bat stop` | Stop all containers | | `dev.bat restart` | Restart Frappe to pick up code changes | | `dev.bat sync` | Copy API files and clear cache (quick reload) | | `dev.bat shell` | Open bash shell in container | | `dev.bat bench` | Run bench command (e.g., `dev.bat bench migrate`) | | `dev.bat logs` | Follow Frappe logs | | `dev.bat test` | Test hello API endpoint | | `dev.bat migrate` | Run database migrations | | `dev.bat status` | Show container status | | `dev.bat reset` | Delete everything and start fresh (DESTRUCTIVE) | ## File Structure ``` docker-dev/ ├── docker-compose.yml # Container orchestration ├── dev.bat # Windows helper script └── dev.sh # Linux/Mac helper script hrms/api/ # BEI custom API files (synced to container) ├── __init__.py # API exports (CRITICAL - update when adding new APIs) ├── hello.py # Test endpoint ├── employee_clearance.py # Clearance APIs ├── enrichment.py # Data enrichment APIs ├── google_chat.py # Google Chat integration ├── google_drive.py # Google Drive integration ├── google_login.py # Google OAuth ├── oauth_tokens.py # OAuth token management ├── onboarding.py # Employee onboarding └── roster.py # Shift roster APIs ``` ## Adding a New API ### 1. Create your API file ```python # hrms/api/my_new_api.py import frappe @frappe.whitelist(allow_guest=True) def hello(): """Test endpoint.""" return {"message": "Hello from my new API!"} @frappe.whitelist() def get_data(): """Requires authentication.""" return {"user": frappe.session.user} ``` ### 2. Update __init__.py ```python # hrms/api/__init__.py from hrms.api.my_new_api import ( hello, get_data, ) ``` ### 3. Sync and test ```bash dev.bat sync curl http://localhost:8000/api/method/hrms.api.my_new_api.hello ``` ## Container Configuration | Component | Value | |-----------|-------| | Frappe Image | `frappe/bench:v5.25.11` | | Bench Location | `/workspace/frappe-bench` | | API Mount | `/bei-api` (read-only from `hrms/api/`) | | Site Name | `dev.localhost` | | MariaDB Port | 3307 (external), 3306 (internal) | | Web Port | 8000 | | Socket.IO Port | 9000 | ## Volumes | Volume | Purpose | |--------|---------| | `docker-dev_frappe-bench` | Frappe bench directory (apps, sites, etc.) | | `docker-dev_mariadb-data` | Database data | **Note:** Volumes persist data across container restarts. To completely reset, use `docker compose down -v`. ## Troubleshooting ### Container won't start ```bash # Check logs dev.bat logs # Or directly docker logs frappe-dev ``` ### API changes not visible ```bash # Force sync and clear cache dev.bat sync # If still not working, restart Frappe dev.bat restart ``` ### Database connection errors ```bash # Check MariaDB is healthy docker ps # Should show mariadb-dev as (healthy) ``` ### Need fresh start ```bash # WARNING: This deletes all data dev.bat reset # Or manually: docker compose -f docker-dev/docker-compose.yml down -v dev.bat start ``` ### First run taking too long First run downloads and installs: - Frappe Framework (~3 min) - ERPNext (~5 min) - HRMS (~3 min) - Site creation (~2 min) Total: 10-15 minutes. Subsequent starts are fast (~30 seconds). ## Testing APIs ### Without authentication ```bash # APIs with @frappe.whitelist(allow_guest=True) curl http://localhost:8000/api/method/hrms.api.hello.hello ``` ### With authentication ```bash # Get session cookie first curl -c cookies.txt -X POST http://localhost:8000/api/method/login \ -d "usr=Administrator" -d "pwd=admin" # Then use the cookie curl -b cookies.txt http://localhost:8000/api/method/hrms.api.roster.get_roster ``` ### Using bench execute ```bash # Run Python code directly dev.bat bench execute hrms.api.hello.hello # With arguments dev.bat bench execute "hrms.api.employee_clearance.get_status" --args '["HR-EMP-0001"]' ``` ## When to Deploy to Production After testing locally: 1. **Commit changes:** ```bash git add hrms/api/ git commit -m "feat: Add employee clearance API" ``` 2. **Push to production branch:** ```bash git push origin production ``` 3. **Monitor GitHub Actions:** https://github.com/Bebang-Enterprise-Inc/hrms/actions 4. **Verify production:** ```bash curl https://hq.bebang.ph/api/method/hrms.api.hello.hello ``` See `/deploy-frappe` skill for full production deployment options. ## DO NOT DO 1. **NEVER edit files directly in the container** - Changes are lost on restart 2. **NEVER use `docker commit`** - Corrupts the Python environment 3. **NEVER push untested code to production** - Always test locally first 4. **NEVER skip updating `__init__.py`** - API won't be whitelisted 5. **NEVER assume production deploy will pick up code changes** - Use `no_cache=true` (see below) --- ## CRITICAL: Local vs Production Asset Handling ### Why Local Works But Production Breaks **Local development** allows `bench build` because: - Single container environment - No persistent asset volumes (fresh start each time) - Development mode reloads assets on change **Production** prohibits `bench build` because: - Multi-container architecture (frontend + backend) - Persistent volumes don't auto-update - Assets baked into Docker image at build time ### What This Means For You | Action | Local | Production | |--------|-------|------------| | `bench build` | ✅ OK | ❌ NEVER | | `bench migrate` | ✅ OK | ⚠️ Only via isolated container | | Edit Python files | ✅ Sync + restart | ❌ Rebuild image | | Edit CSS/JS | ✅ Sync + restart | ❌ Rebuild image | ### The Production Rule **All code and asset changes MUST go through Docker image rebuild.** When you push to production: 1. GitHub Actions rebuilds the entire Docker image 2. New CSS/JS hashes are baked into image 3. Assets volume should be deleted before deploy 4. Fresh containers get consistent assets **Never "hot-fix" production by running bench commands.** See `/deploy-frappe` for the full CSS 404 root cause analysis and fix. ## Testing Custom WWW Pages Locally ### Creating Custom Pages (like login) 1. Create your page file: ``` hrms/www/bei-login.html # The HTML template hrms/www/bei-login.py # Optional Python context handler ``` 2. If redirecting from an existing route, add to `hrms/hooks.py`: ```python website_redirects = [ {"source": "/login", "target": "/bei-login", "redirect_http_status": 302}, ] ``` 3. Sync to container: ```bash dev.bat sync ``` 4. Test locally: ```bash # Check redirect curl -sI http://localhost:8000/login | grep -i location # Check page renders curl -s http://localhost:8000/bei-login | grep -o "