Contributing
Billbird is open source and contributions are welcome.
Development setup
Prerequisites
- Go 1.25+
- Docker and Docker Compose (for PostgreSQL)
- A GitHub App for testing (see setup.md)
Get started
git clone https://github.com/mwesterweel/billbird.git
cd billbird
# Start PostgreSQL
docker compose up db -d
# Set environment variables
export DATABASE_URL="postgres://billbird:billbird@localhost:5432/billbird?sslmode=disable"
export GITHUB_APP_ID="your-app-id"
export GITHUB_PRIVATE_KEY="$(cat path/to/private-key.pem)"
export GITHUB_WEBHOOK_SECRET="your-secret"
# Run the application
go run ./cmd/billbird
# Or run tests
go test ./...
Webhook testing
For local webhook testing, use smee.io to forward GitHub webhooks to your machine:
# Install smee client
npm install -g smee-client
# Create a channel at https://smee.io and forward to localhost
smee -u https://smee.io/your-channel-id -t http://localhost:8080/webhook
Set your GitHub App's webhook URL to the smee.io channel URL.
Project structure
cmd/billbird/ main entrypoint
internal/
api/ REST API handlers
admin/ HTMX admin panel
auth/ OAuth and sessions
client/ Client attribution
commands/ Slash command parser
config/ Environment config
cycletime/ Cycle time tracking
db/ Database layer
github/ GitHub API client
timeentry/ Time entry logic
webhook/ Webhook handler
migrations/ SQL migration files
templates/ HTML templates
docs/ Documentation
Running tests
# All tests
go test ./...
# Specific package
go test ./internal/commands/ -v
# With race detection
go test -race ./...
Adding a migration
Migrations use golang-migrate. To add a new migration:
# Create migration files
migrate create -ext sql -dir migrations -seq description_of_change
This creates two files: NNNNNN_description_of_change.up.sql and NNNNNN_description_of_change.down.sql. Write the forward migration in the .up.sql file and the rollback in the .down.sql file.
Migrations run automatically on application startup.
Code style
- Standard Go formatting (
gofmt) - No ORM --- raw SQL with
pgx - No web framework --- standard library
net/http - Keep dependencies minimal
- Write tests for parser logic and business rules
Architecture principles
- API-first: Every feature must be accessible through the REST API. The admin panel is a thin consumer.
- No physical deletes: All state changes through status fields and correction chains.
- UTC everywhere: Never store local time without offset.
- Boring and auditable: Prefer well-understood approaches over clever ones.
De documentatie beweegt mee met de code
Twee gates, omdat er twee manieren zijn om code binnen te krijgen:
- Elke PR loopt langs
docs-gates(.github/workflows/docs-gates.yml), die de checker uit de hub (MWest2020/handbook) aanroept, op commit-SHA gepind. - Elke push naar main loopt langs de pre-push-guard. Installeren:
bash scripts/install_hooks.sh. In deze repo gaat lang niet alles via een PR, en wat rechtstreeks naar main gaat komt nooit langs die workflow — precies daar loopt documentatie stilletjes achter.
Raakt een wijziging cmd/, internal/ of migrations/ zonder dat er iets onder
docs/ meebeweegt, dan is hij rood. Kan het echt niet: DOCS_DRIFT_OK=1 git push
lokaal, of het label docs-drift-ok op de PR. Allebei zichtbaar.