- M7.1-M7.10: Extensible SourceConnector trait, Obsidian/paperless/git/S3 connectors, sync framework, CLI, HTTP endpoints, health monitoring, gate - M3.5.10: Auth integration with Authentik OIDC → Vault token validation - DESIGN.md: Add source connectors architecture, update auth to Authentik/Vault (Kong removed from cluster) - INDEX.md: 75 tasks, 11 gates - Fix all Kong references in M3.5.1 task
4.9 KiB
M7.4 — Git repository connector
| Field | Value |
|---|---|
| Phase | M7 — Source connectors |
| Size | M — 1–3 days |
| Status | ⬜ Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | M7.10 |
| Depends | M7.1 |
Goal
Implement a SourceConnector that clones or pulls a git repository and exposes
its documents for ingestion — so documentation repos, wikis, and runbook
collections tracked in git become searchable through the memory service.
Facts (inlined — no spec read needed)
Many knowledge sources are already in git: internal wikis, Forgejo repos, infrastructure documentation, README collections. This connector pulls them without requiring manual export.
Configuration:
connectors:
- kind: git_repo
name: infra-docs
config:
repo_url: https://forgejo.riotpiao.com/rock/homelab-docs.git
branch: main
clone_dir: /tmp/mem-connectors/infra-docs # local checkout
paths: [docs/, runbooks/] # only scan these dirs
extensions: [md, txt, rst]
auth_secret: forgejo-token # k8s secret for private repos
sync_depth: 1 # shallow clone
Clone-then-walk model. The connector clones (or pulls) the repo to a local
directory, then walks the filesystem like the Obsidian connector. This reuses
DocCorpusSource internals and avoids git-specific content access APIs.
Change detection uses git. git diff --name-only HEAD@{1}..HEAD after a pull
tells the sync framework exactly which files changed — more efficient than
re-hashing every file.
Branch tracking. Connector watches one branch. Branch changes (main → prod) require config update. No multi-branch support — each branch is a separate connector instance.
Steps
- Implement
GitRepoConnectorinmem-ingest/src/connectors/git_repo.rs. - On first sync:
git clone --depth N --branch B <url> <clone_dir>. - On subsequent syncs:
git -C <clone_dir> pull --ff-only. list_documents()— walkclone_dirfiltered bypathsandextensions, compute sha256 per file.fetch_document()— read file fromclone_dir, return content with git metadata (last commit sha, author, date for that file viagit log -1).health_check()— verifyclone_diris a valid git repo, check remote connectivity viagit ls-remote.- Handle auth for private repos (token from k8s secret → git credential helper or URL embedding).
- Register
"git_repo"kind in connector registry factory. source_type()returnsReference.
Acceptance
- Clone + walk produces correct document list for fixture repo.
- Pull detects changed files without re-processing unchanged ones.
- Path filtering limits scan to configured subdirectories.
- Private repo auth works (token in URL or credential helper).
- Health check distinguishes: valid repo, invalid remote, auth failure.
Verify
Harness: fixture git repo created in temp dir with known content.
Integration test — tests/it_git_repo_connector.rs:
a1_clone_and_list— init fixture repo, connector clones it; assertlist_documents()returns expected files.a2_path_filtering— fixture withdocs/andsrc/; config sayspaths: [docs/]; assert onlydocs/files returned.a3_extension_filtering— fixture with .md, .rs, .txt; assert only .md/.txt.a4_fetch_returns_content— fetch a doc; assert content matches fixture file.a5_pull_detects_changes— add a commit to fixture repo; pull; assert changed file appears in list with new hash.a6_health_check_valid_repo— valid clone_dir; assertreachable: true.a7_health_check_no_clone— no clone_dir; assertreachable: falsewith message indicating clone needed.a8_shallow_clone— assert clone depth matches config (git rev-list --count HEAD).a9_config_from_yaml— parse connector from YAML; assert fields match.
Command: cargo test --test it_git_repo_connector
False pass:
- Testing with a local repo path instead of a clone. The clone/pull machinery is the whole point — a connector that reads a pre-existing checkout is just the Obsidian connector.
- Not testing pull-after-change. First sync always works; second sync is where change detection matters.
Traps
- Running
git cloneon every sync. Check ifclone_diralready has a valid checkout first; clone only on first run. - Not cleaning up failed clones. A partial clone leaves a directory that is neither valid nor absent — subsequent runs fail on both clone (dir exists) and pull (not a repo).
- Force-push upstream breaks
--ff-only. Detect non-fast-forward, deleteclone_dir, re-clone. Log a warning — this means all docs are re-processed. - Symlinks across the repo boundary.
walkdirfollows symlinks by default; a symlink to/etc/passwdis a real concern in a cluster-wide service.
Background: DESIGN.md — source connectors section