This document covers development workflow specific to wlanpi-core. For general Git workflow and contribution guidelines, see the WLAN Pi contributing guide.
- Quick setup
- Setup development environment
- Developing
- Authentication and testing
- Troubleshooting
- Versioning and releases
- Code quality
- Building the package
Run ./init from the base folder of this repo to install system depends, create the virtual environment (venv), install Python depends, and run the wlanpi_core module directly on the default port.
After you've done ./init, you can use ./run to skip all the staging. This should work. If it doesn't, please open an issue so we can get it resolved for future use. Note that you may need to run ./init again if depends are updated in the future.
- Clone repo
- Create your feature or fix branch from the
devbranch - Create virtualenv
- Install wheel and setuptools in virtualenv
- Install package into virtualenv with extras
git clone git@github.com:WLAN-Pi/wlanpi-core.git
cd wlanpi-core
python3 -m venv venv && source venv/bin/activate
pip install -U pip pip-tools wheel setuptools
# developers should install test depends also like so
pip install .[testing]Once you've 1) setup the virtualenv, 2) installed Python requirements, and 3) setup OS and package requirements, you can start developing by running wlanpi_core directly.
There are two options to run directly:
Run with auto-reload for development:
sudo venv/bin/python -m wlanpi_core --debug --reloadThis will start the server on http://localhost:8000 with automatic reloading when code changes.
When running directly, you can interact with these URLs:
- API frontend: http://localhost:8000
- Swagger UI documentation: http://localhost:8000/documentation
Use this to test your development code using the production service configuration:
-
Verify the current working directory symlink:
ls -l /opt/wlanpi-core/workingdirectory
-
Link to your development location: In this case, I have
wlanpi-corecloned to~. Adjust accordingly.sudo ln -sfn /home/wlanpi/wlanpi-core/wlanpi_core /opt/wlanpi-core/workingdirectory
-
Restart the service:
sudo systemctl restart wlanpi-core.service sudo systemctl status wlanpi-core.service
-
When done testing, restore the original symlink:
sudo ln -sfn /opt/wlanpi-core/lib/python3.9/site-packages/wlanpi_core /opt/wlanpi-core/workingdirectory sudo systemctl restart wlanpi-core.service
For testing with the exact production setup:
-
Elevate to root and activate the venv:
sudo su -- source venv/bin/activate -
Stop the installed services:
systemctl stop wlanpi-core.service && systemctl stop wlanpi-core.socket -
Start your development copy with socket binding:
gunicorn --workers 1 --reload -k uvicorn.workers.UvicornWorker --bind unix:/run/wlanpi_core.sock wlanpi_core.asgi:app
-
For direct API access (safe networks only):
ufw allow 31415
Then access at
http://wlanpi-###.local:31415/orhttp://<ip>:31415/ -
When done, restart original services:
systemctl stop wlanpi-core.socket && systemctl stop wlanpi-core.service
The getjwt helper script generates JSON Web Tokens (JWTs) for bootstrapping authentication:
# Basic usage
getjwt my-device-123
# With custom port
getjwt my-device-123 8000canonical_string="POST\n/api/v1/auth/token\n\n{\"device_id\": \"testing\"}"
signature=$(printf "$canonical_string" | openssl dgst -sha256 -hmac "$(cat /home/wlanpi/.local/share/wlanpi-core/secrets/shared_secret.bin)" -binary | xxd -p -c 256)
curl -X 'POST' \
-H "X-Request-Signature: $signature" \
'localhost:31415/api/v1/auth/token' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"device_id": "testing"}'The ./install/usr/bin/lhapitest.sh script demonstrates localhost API interaction using HMAC signatures:
# Default port (31415)
./install/usr/bin/lhapitest -X POST -e /auth/token -P '{"device_id": "testing"}'
./install/usr/bin/lhapitest -e /system/device/model
# Custom port (8000)
./install/usr/bin/lhapitest -X POST -e /auth/token -P '{"device_id": "testing"}' -p 8000
./install/usr/bin/lhapitest -e /system/device/model -p 8000Note: Localhost applications use HMAC signatures. External applications must authenticate using JWT tokens.
# View service logs
journalctl -u wlanpi-core
# Follow logs in real-time
journalctl --follow --unit wlanpi-core
journalctl -f -b -u wlanpi-core
journalctl -f -n 10 -u wlanpi-core# Last 20 lines with follow
tail -n 20 -f /var/log/wlanpi_core/app.log
tail -n 20 -f /var/log/wlanpi_core/debug/debug.logCheck the debug log tmpfs mount:
systemctl status var-log-wlanpi_core-debug.mount
mount | grep wlanpi_core/debug
df -h /var/log/wlanpi_core/debug
ls -la /var/log/wlanpi_core/debugExample output:
$ systemctl status var-log-wlanpi_core-debug.mount
● var-log-wlanpi_core-debug.mount - Debug log tmpfs mount for wlanpi-core
Loaded: loaded (/lib/systemd/system/var-log-wlanpi_core-debug.mount; enabled; vendor preset: enabled)
Active: active (mounted) since Tue 2025-01-14 09:25:03 CST; 2min 44s ago
Where: /var/log/wlanpi_core/debug
What: tmpfs
$ mount | grep wlanpi_core/debug
tmpfs on /var/log/wlanpi_core/debug type tmpfs (rw,relatime,size=25600k,mode=750,uid=1000)
$ df -h /var/log/wlanpi_core/debug
Filesystem Size Used Avail Use% Mounted on
tmpfs 25M 12K 25M 1% /var/log/wlanpi_core/debug
Merge strategy between dev (development) and main (release branch)
NEVER use squash merges when merging between dev and main.
Please always use regular merge commits (git merge --no-ff).
Why? Squash merging between permanent branches destroys the shared commit history, making it impossible for Git to track which commits exist in both branches.
This leads to:
- Inability to merge main back into dev without massive conflicts
- Branch divergence that cannot be reconciled
- Loss of detailed commit history on the release branch
Regular merge commits preserve the full history and keep both branches properly synchronized.
Summary:
- ✅ Squash merge OK:
feature/branch→dev(keeps dev clean of the many commits a feat/fix may take) - ❌ Regular merge REQUIRED:
dev→main(preserves shared history) - ❌ Regular merge REQUIRED:
main→dev(preserves shared history)
Each release requires versions to be updated in two locations:
-
Debian changelog:
debian/changelogviadch(devscripts)dch -i # Create new changelog entry -
Python package:
wlanpi_core/__version__.py(manual edit)
Python package versioning should follow PEP 440.
Create annotated tags for releases:
git tag -a v1.2.3 -m "Release 1.2.3"
git push origin v1.2.3For complete release procedures, see Release Process.
Before committing, run the quality checks:
# Format code
tox -e format
# Lint code
tox -e lint
# Run tests
toxInstall dependencies with either:
pip install .[testing]- Or use
./initwhich handles this
From the root directory:
dpkg-buildpackage -us -uc -bSee PACKAGING.md for detailed packaging information.
- Contributing guide - General Git workflow and contribution guidelines
- Release process - Detailed release procedures
- PACKAGING.md - Packaging standards for this repo
- Gunicorn settings documentation