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:
+30
-2
@@ -327,11 +327,18 @@ class GitSourceIn(BaseModel):
|
||||
Trimmed here; the API layer then ``expanduser()``s it and requires an
|
||||
absolute existing directory (else 422 naming the path — the path is
|
||||
not a secret, unlike a git URL) and no ``url``.
|
||||
|
||||
``ignore_paths`` (phase 89) is optional at create time (absent →
|
||||
``[]``) and carries the RAW box lines — trimming/normalization happens
|
||||
in the API layer, not the schema, so the A4 422 details stay fixed
|
||||
strings (the router's credential-safety discipline, applied for
|
||||
consistency).
|
||||
"""
|
||||
|
||||
kind: Literal["git", "local"] = "git"
|
||||
url: str | None = Field(default=None, min_length=1, max_length=500)
|
||||
path: str | None = Field(default=None, min_length=1, max_length=2000)
|
||||
ignore_paths: list[str] | None = Field(default=None)
|
||||
|
||||
@field_validator("url", mode="before")
|
||||
@classmethod
|
||||
@@ -352,12 +359,14 @@ class GitSourceOut(BaseModel):
|
||||
``kind=local`` rows, the stored (expanded) directory path — the
|
||||
phase-35 response shape is unchanged by phase 38, so a local 201
|
||||
reports its path in ``url`` and the full row (``kind`` + ``path``)
|
||||
via ``GET``.
|
||||
via ``GET``. ``ignore_paths`` (phase 89) is the stored, normalized
|
||||
list — non-null (a row created without it reports ``[]``).
|
||||
"""
|
||||
|
||||
id: uuid.UUID | None
|
||||
url: str
|
||||
added_at: datetime | None
|
||||
ignore_paths: list[str]
|
||||
|
||||
|
||||
class GitSourceRow(BaseModel):
|
||||
@@ -369,7 +378,9 @@ class GitSourceRow(BaseModel):
|
||||
``path: null``; local rows carry ``path`` (the absolute directory,
|
||||
expanded) and the same string in ``url`` (the table's NOT-NULL
|
||||
location column). ``id`` / ``added_at`` are nullable: env-fallback
|
||||
rows (table empty) carry neither.
|
||||
rows (table empty) carry neither. ``ignore_paths`` (phase 89) is the
|
||||
row's stored, normalized list — env-fallback rows (no DB row to
|
||||
store a list on) report ``[]``.
|
||||
"""
|
||||
|
||||
id: uuid.UUID | None
|
||||
@@ -377,6 +388,23 @@ class GitSourceRow(BaseModel):
|
||||
url: str
|
||||
path: str | None
|
||||
added_at: datetime | None
|
||||
ignore_paths: list[str]
|
||||
|
||||
|
||||
class GitSourceIgnoreIn(BaseModel):
|
||||
"""``PATCH /api/git-sources/{source_id}`` body (phase 89, A5).
|
||||
|
||||
``ignore_paths`` is REQUIRED — the box's lines in REPLACE semantics:
|
||||
the body list (normalized + A4-validated in the API layer, with the
|
||||
fixed-detail 422s) becomes the row's whole list — an empty list
|
||||
clears all; an absent field is a 422 with the model's own detail.
|
||||
Entries are RAW box lines: normalization + the A4 limits are
|
||||
enforced in the API layer so the 422 details stay fixed strings
|
||||
(the router's credential-safety discipline, applied for
|
||||
consistency).
|
||||
"""
|
||||
|
||||
ignore_paths: list[str]
|
||||
|
||||
|
||||
class GitSourceList(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user