phase: 89_source_ignore_paths
All verification complete — TODO.md was already cleared in the roadmap commit; the two extra unit-test diffs are necessary fake-signature adaptations for the new keywords. Everything is green, no fixes were needed. ## Phase 89 — final verification pass: ALL GREEN **Verified (all 6 task files present in `complete/`):** - `git_sources.ignore_paths` JSONB column + migration 0013; `alembic downgrade -1 && upgrade head` round-trips (head `0013`) - Importer: `normalize_ignore_path`/`is_ignored`/`_ignore_for_root`, `ignore` in walk + progress pre-walk, `ignore_by_root` in `import_sources` - API: GET/POST carry list; admin-only `PATCH` (replace, 404/422 fixed details, anonymous 403) - Pipelines wired: `_run_sync`, `_run_upload` re-upload, `scripts/import_docs.py` - Sources-page box: dialog, §7.4 save lifecycle, `N ignored` tag, a11y; env rows get no box **Test/lint results:** - `uv run pytest` → 1808 passed - `uv run pytest --cov=app --cov-report=term-missing` → TOTAL **99%** (>90%) - `uv run pytest tests/e2e/test_source_ignore_paths.py -v --no-cov` → 6 passed (isolated, DB up) - Regressions in isolation: `test_git_sources_admin` 6, `test_archive_upload_sources` 5, `test_sync_button` 3, `test_smoke` 3 — all passed - `uv run ruff check . && uv run pyright` → clean (0 errors) **Completion criteria:** box→PATCH 200→count+GET round-trip ✅ · sync excludes `ignore/` (no docs/chunks/embeddings/summaries) + prunes newly-ignored (pruned==2) ✅ · no-mid-path rule E2E ✅ · PATCH 404/422/replace/clear/403 ✅ · full gate green ✅ · commit + phase move left to harness per rules. **Deviations:** none blocking — E2E pins `files == 4` (overview's "5" was an off-by-one vs its own 6-file tree, documented in-test); `tests/unit/test_importer.py` + `test_sync_button.py` test-double fakes extended for the new keywords (needed for the suite to stay green). **Next pending phase:** none — `todo/` holds only this phase.
This commit is contained in:
@@ -6,7 +6,8 @@ on; these tests lock the table/column contract (PLAN §5) without a live DB.
|
||||
from __future__ import annotations
|
||||
|
||||
from pgvector.sqlalchemy import Vector
|
||||
from sqlalchemy import UniqueConstraint
|
||||
from sqlalchemy import TextClause, UniqueConstraint
|
||||
from sqlalchemy.sql.schema import DefaultClause
|
||||
|
||||
import app.models # noqa: F401 (import registers all tables on Base.metadata)
|
||||
from app.db import Base
|
||||
@@ -62,6 +63,44 @@ def test_doc_drafts_token_is_unique_not_null() -> None:
|
||||
assert uq, "doc_drafts must be unique on (token) — the URL credential"
|
||||
|
||||
|
||||
def test_git_sources_ignore_paths_column_contract() -> None:
|
||||
"""Phase 89: every source row carries its ignore list — JSONB, NOT
|
||||
NULL, server default ``'[]'`` (a pre-phase-89 row reads ``[]``, so
|
||||
every existing source imports exactly as before)."""
|
||||
sources = Base.metadata.tables["git_sources"]
|
||||
assert "ignore_paths" in sources.c, (
|
||||
"git_sources must have the ignore_paths column (phase 89)"
|
||||
)
|
||||
col = sources.c["ignore_paths"]
|
||||
assert col.nullable is False, "git_sources.ignore_paths must be NOT NULL"
|
||||
sd = col.server_default
|
||||
assert isinstance(sd, DefaultClause), "ignore_paths needs a server default"
|
||||
assert isinstance(sd.arg, TextClause), (
|
||||
"the server default must be the literal SQL text '[]'"
|
||||
)
|
||||
assert sd.arg.text == "'[]'", "ignore_paths server default must be '[]'"
|
||||
|
||||
|
||||
def test_git_source_python_default_empty_list() -> None:
|
||||
"""A freshly constructed row (no DB) resolves to an empty ignore
|
||||
list via the Python-side default (``default=list``) — the ORM
|
||||
INSERT-time default, so an ORM insert that omits the column inserts
|
||||
``[]`` rather than NULL (the server default ``'[]'`` independently
|
||||
covers non-ORM inserts)."""
|
||||
from app.models import GitSource
|
||||
|
||||
row = GitSource(url="https://example.com/r.git", kind="git")
|
||||
col = row.__table__.c["ignore_paths"]
|
||||
assert col.default is not None, (
|
||||
"ignore_paths needs a Python-side (INSERT-time) default"
|
||||
)
|
||||
# Invoked with the (unused) execution context at INSERT time — a
|
||||
# freshly constructed row that omits the kwarg stores [] rather
|
||||
# than NULL (the real-DB behaviour is pinned against the dev DB
|
||||
# by the git-sources API integration tests).
|
||||
assert col.default.arg(None) == [], "the default must resolve to []"
|
||||
|
||||
|
||||
def test_doc_drafts_column_contract() -> None:
|
||||
"""Phase 59: the editable triple (title/path/body) + status +
|
||||
timestamps are NOT NULL; ``branch`` / ``commit_sha`` are NULL
|
||||
|
||||
Reference in New Issue
Block a user