Thanks for taking an interest. Pull requests are welcome.
This project is open source under the MIT license. You can use, fork, modify, and redistribute it freely. Pull requests are welcome.
For anything larger than a typo, a doc clarification, or a one-line bug fix, open an issue first. Describe what you want to change and why. This avoids wasted work on changes that do not fit the project direction.
A change is in scope if it:
- Fixes a defect against documented behaviour.
- Improves documentation, tests, or build tooling.
- Adds a new sink or source that follows the patterns described in documentation/architecture.md and the project's
AGENTS.md. - Improves observability, performance, or security without breaking existing behaviour.
A change is likely out of scope if it:
- Changes the architectural rules listed in
AGENTS.md(clean architecture, one container per source, fail-fast, etc.). - Adds optional features behind feature flags.
- Vendors large external dependencies.
- Renames public configuration keys without a clear migration path.
No CLA is required. By submitting a pull request, you confirm that you have the right to submit the change, and you agree that your contribution is licensed under the project's MIT license (inbound = outbound). You provide the contribution as is, without warranty.
Requirements:
- Go (version pinned in
go.mod). golangci-lint(version pinned in.github/workflows/ci.yml).make.- Docker, only if you want to build container images.
Common commands:
make build # build binaries into out/
go test ./... # run all tests
golangci-lint run ./... # run the linterThe lint and test suites must both pass with zero issues before a pull request can be merged.
The full set of project rules lives in AGENTS.md. Highlights:
- Services depend only on interfaces in
internal/domain/. Do not import an adapter package frominternal/service/. - Use
log/slog, not the standardlogpackage, outsidecmd/meterlogger/. - Use constructor injection. No globals except the
processKillertest seam. - Every repository call accepts and propagates
context.Context. - Line length is 120 characters, enforced by
golinesthroughgolangci-lint. - Use
net.JoinHostPortfor DSN host/port composition. Usestrconv.Itoafor integer-to-string conversion. - Do not use em dashes anywhere in code, comments, or documentation.
- Keep total coverage at or above 80 percent.
- Use
github.com/DATA-DOG/go-sqlmockfor database tests; do not require a real database. - Hardware-dependent paths (real serial ports, real network endpoints) may stay untested. Add a comment in the test file explaining why.
- Service error paths replace
processKillerwith a no-op to avoid signalling the process during tests. - Prefer table-driven tests for functions with several input variants.
Follow the patterns documented in AGENTS.md and documentation/architecture.md. In short:
- A new sink lives under
internal/adapters/sink/<name>/and registers incmd/meterlogger/config.go,db.go, and the foursource_*.gofiles. Add it to the sink table indocumentation/README.mdand the config examples indocumentation/configuration.md. - A new source lives under
internal/adapters/source/<name>/, defines its reader and repository interfaces ininternal/domain/, ships per-sink store methods, has amultisinkwrapper, and is wired through a newcmd/meterlogger/source_<name>.go.
- Keep commits focused. One logical change per commit.
- Write a short, factual subject line. Describe the change in the body if needed.
- Rebase your branch on
masterbefore opening the PR. - Reference any issue the change closes.
- The PR description must include a clear summary, a test plan, and any breaking change notes.
- Do not push generated artefacts (
out/,bin/,.env, IDE files). The.gitignorecovers these.
master is protected. lint, test, Analyze (go, manual) and Analyze (actions, none)
must pass before a PR can merge, and the branch must be up to date with master first.
Force-pushing and deleting master are blocked. Administrators can override, for
emergencies only.
Two rules the protection cannot enforce on its own:
- Never merge on a red check, including one you believe is stale. A check that is genuinely obsolete still has to be re-run green before the merge. If it cannot re-run, push a commit so the checks re-evaluate on a fresh SHA.
- After changing CI or code scanning configuration, confirm a fresh fully green run
before merging the change that depends on it. Configuration changes on the GitHub
side can take minutes to take effect, so a run started near the change may still
reflect the old setup. CI, Security, Integration and CodeQL all carry a
workflow_dispatchtrigger for exactly this check. Release is driven by its tag and is deliberately not dispatchable.
Open an issue with:
- The version (
meterlogger --versionprints it), or the commit SHA. - The source you ran (
heat,grid,solar,ventilation). - The sinks you had enabled.
- A minimal config that reproduces the problem, with secrets redacted.
- The relevant log output at debug level (
--debug).
Do not file a public issue for a security problem. See SECURITY.md for the disclosure process.