-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing and Testing
Keelarr has been proven on two hosts: a QNAP with a real library, and a Mac with nothing on it. That is not "runs anywhere", and every feature added before that gap closes is one nobody has confirmed works elsewhere.
A report that it worked closes an issue as well as a bug report does. Right now nobody can say either way about Linux.
Nine more scenarios are listed in docs/testing.md, each written to be closeable without a conversation first.
npm install
npm testNo framework, no build step, no transpiler. Plain ES modules, node:test, and
dependency injection through *Impl constructor parameters. 432 tests, and the
whole suite runs without Docker.
npm run dev # watch mode
npm run demo # simulated stack, no Docker socket, no authsrc/server.js listens, then initialises — in that order, deliberately
create-http-app.js routes, and the auth gate over /api/*
keelarr-app-service composes seven app services, one concern each
host-profile detection, validation, settings, deploy/.env
dashboard the state the UI renders
import read-only scan of foreign containers
managed-stack install, deploy, upgrade, update checks
cutover adoption cutover and revert
removal removal with retention options
wiring what should be connected, and connecting it
Underneath: runtime.js (Docker and Compose), generator.js (Compose files),
status.js (the dashboard row), jobs.js, store.js, health.js, logger.js.
wiring/ splits further — topology.js classifies networks, attach.js
resolves addresses, reconcile.js compares what is against what should be,
payloads.js builds writes from each app's schema, prerequisites.js reports
what only the operator can supply.
If it cannot be determined, say so. Reachability is tri-state. A prerequisite
check returning null means "no opinion", never "none". A job's status is
derived from its steps rather than from the handler returning normally.
Nearly every guard in this codebase exists because a cheerful default hid a real failure, and the unit suite stayed green through all of them.
Stubbing one layer is not enough if a layer underneath still reaches the real machine.
One test stubbed the settings layer but left the controller-env layer real.
Running npm test inspected the developer's actual Docker, found their running
controller, and overwrote that controller's deploy/.env with QNAP paths from a
test fixture — silently, because the write happened in the test process and never
reached the app's log.
If the reason a line exists is a defect found the hard way, the comment says so. That is what stops it being "simplified" back:
// A total deadline and a silence deadline answer different questions, so a
// command uses one or the other rather than both: bounded work gets
// `timeoutMs`, open-ended transfers get `idleTimeoutMs`.A test that cannot fail proves nothing. When adding one, check it fails against the bug it describes — break the code deliberately and watch it go red.
Two examples worth copying:
-
modules-load.test.jsimports every module undersrc/. It was added after a rename left an orphaned file and 380 tests passed while the app could not boot. Verified by moving a module away and watching it fail. - The job registry's
settled()tests fail ifsettledresolves early. Checked by making it resolve immediately: three tests went red.
Do not poll for a number of event-loop ticks. It is not a measure of how long work takes — it measures how fast the loop spins, which gets worse the busier the machine is.
A helper that gave up after 500 setImmediate ticks passed locally every time
and failed on CI 19 milliseconds into a healthy job. Use
jobs.settled(jobId), which waits on the work itself.
-
npm testpasses - New behaviour has a test, and you have watched that test fail
- Comments explain the reasoning behind anything non-obvious
- If it changes what is proven, update docs/testing.md — and keep automated coverage and live evidence in their separate columns
PolyForm Shield 1.0.0. Use, modify and redistribute freely, including at work. The one restriction is selling a product that competes with Keelarr. Source-available, not OSI-approved open source — worth knowing before you invest time.
Getting started
How it works
Reference