chore: ignore graphify-out, add .dockerignore (#1255)

Ignore graphify-out and add a root .dockerignore for the Docker build
context (COPY . .).

Contributed by @komsikov; maintainer fixups after triad+scope review:
root-anchored ignore entries, secrets/host envs/runtime and review state
kept out of image layers while .git, tests/ and sources stay in (CI runs
pytest inside the image), pinned by TestDockerignore and mapped in
docs/architecture/08.

Squash-merged so the PR's rewritten copy of the #1250 merge commit
(6972dea6) does not enter history.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
This commit is contained in:
bogeyboy 2026-09-24 19:14:54 +03:00 • committed by GitHub
parent b6008efafc
commit bc9482b081
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 88 additions and 2 deletions

47
.dockerignore Normal file
View file

@ -0,0 +1,47 @@
# Build context for `docker build -t ouroboros-web .` (Dockerfile: COPY . .).
# Keep secrets, host environments and local runtime/operator state out of image
# layers. Do NOT exclude .git, tests/ or sources: CI builds this image and
# runs pytest inside it, and the agent needs its own Git history.
# tests/test_build_scripts.py::TestDockerignore pins both halves.
# Secrets (mirrors .gitignore)
**/.env
**/.env.*
**/*.key
**/*.pem
# Host environments, IDE state and caches
.venv/
venv/
env/
**/node_modules/
**/__pycache__/
**/*.pyc
.pytest_cache/
.mypy_cache/
.ruff_cache/
.cursor/
.vscode/
.idea/
# Local runtime, review and operator state (never tracked; see .gitignore)
/data/
/logs/
/.tmp-data-*/
/.review-drive/
/.claudexor/
/.adversarial-review/
/.review-evidence-iter2/
# Build output and bundled runtimes
/dist/
/build/
/python-standalone/
/node-standalone/
/ripgrep-standalone/
/betterleaks-standalone/
/claudexor-runtime/
# Other
/.devcontainer
/graphify-out

4
.gitignore vendored
View file

@ -103,4 +103,6 @@ MagicMock/
devtools/benchmarks/editbench/fixtures_v2/
# Other
.devcontainer
# Anchored to the repo root, like /logs/ and /ocr_pages/ above.
/.devcontainer
/graphify-out

View file

@ -58,4 +58,6 @@ Public installer naming and links ride the same projection: `release_sync.py::RE
Docker runs the web and server runtime without PyWebView. The image binds `0.0.0.0` and sets no network password by default: a missing password only warns, and `NetworkAuthGate` permits requests when no password is configured — publishing the container port without setting `OUROBOROS_NETWORK_PASSWORD` therefore exposes the owner surface. Set the password (or keep the port unpublished); packaging adds no stronger boundary of its own.
The root `.dockerignore` filters `COPY . .`: secrets, host virtualenvs, `node_modules`, caches and runtime/review/operator state stay out of image layers; `.git`, `tests/` and sources stay in, because CI runs pytest inside the image.
---

View file

@ -511,6 +511,38 @@ class TestBuildWindowsPs1:
# Dockerfile (Docker / web runtime)
# ---------------------------------------------------------------------------
class TestDockerignore:
"""The root .dockerignore owns the build context of Dockerfile's COPY . .
Both halves matter: private local state must stay out of image layers,
and the paths CI needs inside the image (Git history, tests, sources)
must stay in."""
def _patterns(self):
lines = _read(".dockerignore").splitlines()
return {ln.strip() for ln in lines if ln.strip() and not ln.lstrip().startswith("#")}
def test_private_state_is_excluded(self):
patterns = self._patterns()
required = {
"**/.env", "**/.env.*", "**/*.key", "**/*.pem",
".venv/", "venv/", "env/", "/data/",
"/.review-drive/", "/.claudexor/", "/.adversarial-review/",
}
missing = sorted(required - patterns)
assert not missing, f".dockerignore must exclude private local state: {missing}"
def test_ci_needed_paths_stay_in_context(self):
patterns = self._patterns()
for kept in (".git", "tests", "ouroboros", "web", "prompts", "docs",
"supervisor", "pyproject.toml", "uv.lock", "server.py"):
for spelling in (kept, kept + "/", "/" + kept, "/" + kept + "/", "**/" + kept):
assert spelling not in patterns, (
f".dockerignore must not exclude {kept}: CI runs pytest inside the image"
)
assert "*" not in patterns and "**" not in patterns
class TestDockerfile:
"""Dockerfile must install Playwright Chromium/WebKit binaries so browser tools work
out of the box in the container without additional setup."""

View file

@ -141,7 +141,10 @@ CHAPTER_BYTE_BUDGETS: dict[str, int] = {
# `ouroboros` push included), the per-checkout static/VERSION provenance a boot
# and a restart prove, and the scrubbed roots plus the single dependency-sync
# chokepoint. The `ui-smoke` row it replaces was rewritten, not appended to.
"docs/architecture/08-git-branching-ci-and-build.md": 20560,
# 20560 -> 20800 (PR #1255; measured 20768): the Docker subsection maps the new root
# .dockerignore (what it keeps out of image layers and why .git/tests/ must stay in),
# a config BIBLE P6 requires on the map.
"docs/architecture/08-git-branching-ci-and-build.md": 20800,
# 12405 -> 14400 (issue #1142): the ordinary-close paragraph gains the mechanism the chapter had
# no text for — graceful stop signals the server PID only, the server half (stop event at the
# signal, bounded uvicorn drain) is self-sufficient against an old group-SIGTERM launcher.