05 · Contributing

Making your first change

Same flow across all thirty repos. Small, focused PRs get merged fast; drive-by refactors wait behind them.

The flow

  1. Fork the target repository — or branch within the org if you're a maintainer.
  2. Create a feature branch from main. One concern per branch.
  3. Make the change with tests where applicable. Bug fixes come with a regression test.
  4. Commit with Conventional Commits: feat:, fix:, docs:, chore:, refactor:, test:.
  5. Open a pull request. Describe what changes and why; link issues. CI and CodeQL must pass before merge.
  6. Address review feedback. Signed commits may be required on protected branches.

Local checks before pushing

Python projects run ruff, pylint, gitleaks, shellcheck, and whitespace fixers via pre-commit:

# One-shot: everything configured in .pre-commit-config.yaml
python3 -m pre_commit run --all-files

# Or individually
python3 -m ruff check --fix .
python3 -m ruff format .
python3 -m pylint inverter_control/
shellcheck --exclude=SC2154,SC2164,SC2181,SC2029,SC1091 *.sh
gitleaks detect --source .

# Tests with coverage
python3 -m pytest tests/ -v --cov=solar_forecast

Note: there is no bare python command on dev machines here — always python3. Pre-commit may auto-fix files during push; if it does, retry the push.

Approval gates for control code

Changes touching the write path — anything that ends up commanding an inverter or battery — get extra scrutiny by design:

  • New setpoints or policy rules must preserve the deployed controller's source-validity, limit and watchdog checks and verify D-Bus write acknowledgements. The archived governance project is not an installed gate.
  • Document the command's actual logging and verification path. Do not claim mandatory event-log coverage when that service is not deployed.
  • Default-off. Risky behavior ships disabled until configuration explicitly enables it.

Where to ask

Related: CI standards →