fix(docker): document a proven CPU-priority pattern for --profile runners - #2449
Conversation
…ners A box running --profile runners (self-hosted GitHub Actions runners) alongside the main gittensory app has no CPU limits set by default -- every container competes for the host's CPUs on equal footing. Under a burst of CI jobs, this can starve the app itself of the CPU it needs to do the review work it exists for. Discovered running exactly this pattern in production on an 8-vCPU box: uncapped runner containers left the app starved under load, fixed live via `docker update --cpu-shares`/`--cpus`, but that tuning only ever existed as an uncommitted host file and shell history -- lost if the box were ever rebuilt, and invisible to anyone else running this same pattern. Add docker-compose.override.yml.example (gitignored `docker-compose.override.yml` stays the operator's actual file, mirroring the existing .env/.env.example split) documenting the fix: cpu_shares is a relative weight that only matters once the host is genuinely contended, so setting the app's shares high and the runner's low means review work wins a race for CPU when both want it at the same instant, without ever blocking CI from running merely because the app exists. cpus is a separate, absolute per-container ceiling, sized to the sizing guide in the file's own comments for a different host/replica count. Verified `docker compose config` (merging both files) accepts the syntax with no errors. Added test/unit/docker-compose-override-example.test.ts (pure YAML parsing, no `docker` CLI invocation -- the self-hosted runner container this would actually run on doesn't have Docker-in-Docker access, so shelling out to `docker compose config` inside a test would be unreliable) to pin: the example's service names match the real docker-compose.yml, the app's cpu_shares is set higher than the runner's, and .gitignore keeps a real override file out of version control while tracking the example.
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-02 03:37:55 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2449 +/- ##
=======================================
Coverage 95.91% 95.91%
=======================================
Files 224 224
Lines 25235 25235
Branches 9177 9177
=======================================
Hits 24205 24205
Misses 417 417
Partials 613 613 🚀 New features to boost your workflow:
|
…u_shares The prior commit's test only protected the relative cpu_shares contract (app > runner) -- the documented cpus: "4.0" ceiling had no assertion at all, so it could silently drift from the example's own sizing guide with nothing to catch it. Verified this addition actually catches a regression: dropping it to "2.0" fails the new assertion before restoring the real value.
Summary
--profile runners(self-hosted GitHub Actions runners) alongside the maingittensoryapp has no CPU limits set by default — every container competes for the host's CPUs on equal footing. Under a burst of CI jobs, this can starve the app itself of the CPU it needs to do the review work it exists for.docker update --cpu-shares/--cpus, but that tuning only ever existed as an uncommitted host file (docker-compose.override.yml, never committed) and shell history — invisible to anyone else running this pattern, and lost if the box were ever rebuilt from the repo alone.docker-compose.override.yml.example(a realdocker-compose.override.ymlstays gitignored and operator-owned, mirroring the existing.env/.env.examplesplit) documenting the fix:cpu_sharesis a relative weight that only matters once the host is genuinely contended — setting the app's shares high and the runner's low means review work wins a race for CPU when both want it at the same instant, without ever blocking CI from running merely because the app exists.cpusis a separate, absolute per-container ceiling; the file's own comments include a sizing guide for a different host/replica count.docker-compose.yml's ownrunner:service comment block, where anyone enabling that profile would already be looking.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.md.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coverage— full unsharded run green on Node 22.23.1 (matching CI's pinned.nvmrc): 315 passed / 2 skipped, 5930 tests passed, 0 failures.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderatedocker compose -f docker-compose.yml -f docker-compose.override.yml.example config --quiet— validates the merged config parses with no errors (confirmscpus/cpu_sharesare valid top-level compose-spec keys honored outside Swarm mode, not the Swarm-onlydeploy.resources.limitsblock).docker-compose.yml(selfhost-image-deploy.test.ts,selfhost-observability-config.test.ts,path-matchers.test.ts) all pass unchanged.If any required check was skipped, explain why:
Safety
Notes
.examplefile to a realdocker-compose.override.yml.