Post

Git Ollama Tools

Git Ollama Tools

Git Ollama Tools

Purpose

A custom webhook service that runs Ollama-backed automation agents against Gitea pushes. One shared pipeline (webhook → clone → analyze → open PR/issue) feeds five agents:

AgentTriggerAction
Secret scannerany changed fileregex-only, no Ollama call — opens an issue (bot:secrets) with masked values, never edits code
Lint & auto-fixPython, PowerShell, JS, CSS, HTML, YAMLruns each language’s fixer, sends leftovers to Ollama, opens a PR (bot:lint)
Test coverage reviewerchanged .py filesast-parses functions missing a test_<func>, drafts pytest stubs, opens a PR (bot:tests, needs-review)
Docstring/README updaterchanged function signatures/bodiesregenerates docstrings, updates README if the public API changed, opens a PR (bot:docs)
Changelogany push with ≥1 commitone bullet per commit, appended under ## Unreleased in CHANGELOG.md, opens a PR (bot:changelog)

Every code-modifying agent only ever opens a PR — never pushes to main, never auto-merges. The secret scanner is the one exception in the other direction: it never modifies code and never calls Ollama, since sending a matched secret to the model would leak it a second time.

Guardrails: pushes from the bot account or any bot/* branch are ignored outright (loop prevention); idempotency checks against open PRs/issues on Gitea skip repeat work, and a bot branch that exists without an open PR is deleted and retried rather than left stuck; a model fix must pass a parse/compile gate (py_compile, yaml.safe_load, Node’s vm.Script, PowerShell’s Language.Parser — all parse-only, nothing the model writes is ever executed) and show the checker’s error count actually went down before it’s kept.

Deployment

ItemValue
Imagegitea.git.homelab.example/bjones/git_ollama_tools:0.1.190 (private registry)
Namespacedefault
Replicas1 — the app runs a single in-process background worker thread (JobQueue), so extra replicas wouldn’t parallelize agent runs and risk concurrent writes to the same audit log
Node placementx86 k3s LXC nodes (nodeSelector kubernetes.io/arch: amd64 + picluster/lxc: "true"); follows its local-zfs volume
Service typeLoadBalancer (MetalLB, 192.0.2.39), port 8020
Storagegit-ollama-tools-data-zfs PVC, 1Gi, local-zfs storage class

reloader.stakater.com/auto: "true" is set on the Deployment.

Configuration

Non-secret config (gitea.url, ollama.url/model, the repo allowlist, work-dir paths) comes from a mounted ConfigMap at /config/config.yaml. The Gitea bot token and webhook secret are injected as env vars (GITEA_BOT_TOKEN, WEBHOOK_SECRET) from a Secret — never stored in the ConfigMap.

Agents only touch repos explicitly listed in the ConfigMap’s allowlist. Updating the allowlist requires both re-applying the ConfigMap and a manual kubectl rollout restart — this Deployment has no Reloader annotation wired for the ConfigMap specifically, and the app only reads its config file once at startup.

Probes

The app exposes GET /healthz (returns {"status": "ok"}), so liveness and readiness probes hit that path on port 8020 rather than a plain TCP check.

Networking

Ollama backend: https://ollama.intel.homelab.example, model qwen2.5-coder:7b.

Exposed via a LoadBalancer Service (MetalLB pool first-pool, 192.0.2.30–192.0.2.40) rather than an Ingress — Gitea’s system webhook (instance-wide, fires on every push to every repo on the instance, not a per-repo webhook) targets the MetalLB-assigned IP directly on port

  1. The app’s own allowlist config decides which repos it actually acts on; everything else is ignored on receipt, along with pushes from the bot account itself and any bot/* branch.

Resources

 RequestsLimits
CPU100m1
Memory256Mi1Gi
This post is licensed under CC BY 4.0 by the author.