| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
🔓 100% Open Source | 🤖 Bring Your Own LLM | 🚀 Self-Hosted Kubernetes Risk Analysis
Stop preventable production incidents before they happen
After one too many 3am pages from production incidents that could've been caught earlier, I built PatchPulse. It's a self-hosted tool that analyzes your Kubernetes changes before they hit production, combining rule-based guardrails with optional AI analysis to give you explainable risk scores.
Think of it as a safety net for your deployments - it catches the stuff that slips through code review and CI/CD checks.
I've been there - you merge a PR, deploy to production, and suddenly pods are OOMKilled because someone forgot resource limits. Or worse, a security misconfiguration opens up your cluster. PatchPulse catches these issues before they become incidents.
git clone https://github.com/amarkdotdev/patchpulse.git
cd patchpulsePatchPulse supports multiple AI providers. You only need to provide an API key for ONE provider:
# Create .env file
touch .env
# Option 1: OpenAI (recommended for best results)
echo "OPENAI_API_KEY=sk-your-key-here" >> .env
# Option 2: DeepSeek (cost-effective alternative)
# echo "DEEPSEEK_API_KEY=sk-your-key-here" >> .env
# Option 3: Claude (Anthropic)
# echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" >> .env
# Note: Requires: pip install anthropic
# Option 4: Google Gemini
# echo "GEMINI_API_KEY=your-key-here" >> .env
# Note: Requires: pip install google-generativeai
# Optionally specify which provider to use (defaults to first available)
# echo "AI_PROVIDER=openai" >> .env💡 No LLM? No Problem! PatchPulse works perfectly fine without any AI - you'll still get all the rule-based guardrails and risk scoring. The AI stuff is just extra if you want it.
# Start all services
docker compose up -d
# Check logs
docker compose logs -f backend
# Wait for services to be ready (about 10-15 seconds)Once PatchPulse is running, access it at:
Dashboard: http://localhost:8000/dashboard
API Documentation: http://localhost:8000/docs
Health Check: http://localhost:8000/health
API Root: http://localhost:8000/api
Note: The dashboard is the main interface for PatchPulse. The website (patchpulse.dev) is a separate marketing site and not part of this repository.
PatchPulse can be deployed in two ways:
Backend runs separately (Docker Compose, VM, or anywhere):
# 1. Start backend (runs anywhere)
docker compose up -d
# 2. Run agent locally (connects to your cluster via kubeconfig)
cd app/agent
export BACKEND_URL=http://localhost:8000
export KUBECONFIG=$HOME/.kube/config # Points to your cluster
go run cmd/agent/main.goBoth backend and agent run inside Kubernetes:
# Deploy both backend and agent to your cluster
helm install patchpulse-backend ./helm/backend --namespace patchpulse
helm install patchpulse-agent ./helm/agent --namespace patchpulsePatchPulse works in two ways:
# Example: PR with risky deployment.yaml
# PatchPulse detects: "Missing resource limits"
# → Risk score: 50
# → Decision: Advisory (allows, but warns)┌─────────────────┐
│ Developer │
│ Creates PR │
└────────┬────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐
│ Git Integration│────▶│ PatchPulse │
│ (GitHub/GitLab)│ │ Backend │
└─────────────────┘ │ (FastAPI) │
└────────┬─────────┘
│
┌────────▼─────────┐
│ Policy Engine │
│ + AI Analysis │
└────────┬─────────┘
│
┌────────▼─────────┐
│ Risk Score │
│ Decision │
└────────┬─────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Notification │ │ Dashboard │ │ Kubernetes │
│ (Slack/Email) │ │ (Web UI) │ │ Agent │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
▼
┌─────────────────┐
│ Your K8s │
│ Cluster │
└─────────────────┘
# Test cluster access
kubectl get nodes
# If using a remote cluster, make sure kubeconfig is set
export KUBECONFIG=$HOME/.kube/config# The agent will automatically use your kubeconfig
export BACKEND_URL=http://localhost:8000 # Where backend is running
cd app/agent
go run cmd/agent/main.go# Create namespace
kubectl create namespace patchpulse
# Deploy backend
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--set env.DATABASE_URL="postgresql://..."
# Deploy agent (automatically connects to cluster)
helm install patchpulse-agent ./helm/agent \
--namespace patchpulse \
--set env.BACKEND_URL="http://patchpulse-backend:8000"1. Developer creates PR/MR → Git integration detects change 2. Change event sent to backend → Policy engine evaluates 3. AI analysis runs (if configured) → Security scan, recommendations, predictions 4. Risk score calculated (0-100) → Decision made (allow/block) 5. Notification sent to Slack/Teams → Decision stored in database 6. Dashboard updates in real-time via WebSocket
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ GitHub │────▶│ Git Poller │────▶│ Backend │
│ GitLab │ │ │ │ (FastAPI) │
└─────────────┘ └──────────────┘ └──────┬──────┘
│
┌─────────────┐ ┌──────────────┐ │
│ Kubernetes │────▶│ Agent │─────────────┘
│ Cluster │ │ (Go) │
└─────────────┘ └──────────────┘
│
┌─────────────┐ ┌──────────────┐ ┌─────▼──────┐
│ Slack │◀────│ Notifications│◀────│ PostgreSQL │
│ Teams │ │ │ │ Database │
│ PagerDuty │ └──────────────┘ └────────────┘
│ Email │
└─────────────┘
Create a .env file in the root directory:
# Database
DATABASE_URL=postgresql://patchpulse:patchpulse@postgres:5432/patchpulse
# Policy Mode (advisory or enforce)
POLICY_MODE=advisory
# Logging
LOG_LEVEL=INFO
# AI Provider - Choose ONE (see LLM Provider Setup section)
OPENAI_API_KEY=your_openai_api_key
# OR
# DEEPSEEK_API_KEY=your_deepseek_api_key
# OR
# ANTHROPIC_API_KEY=your_anthropic_api_key
# OR
# GEMINI_API_KEY=your_gemini_api_key
# Optional: Specify which provider to use (defaults to first available)
AI_PROVIDER=openai
# Git Integration
GITHUB_TOKEN=your_github_token
GITHUB_REPOS=owner/repo1,owner/repo2
GITLAB_TOKEN=your_gitlab_token
GITLAB_PROJECTS=12345,67890
# JWT Secret (auto-generated if not set)
JWT_SECRET_KEY=your_jwt_secretadvisory: Logs decisions but doesn't block changes (default)
enforce: Blocks high-risk changes (score ≥ 70)
PatchPulse is 100% open source and supports bring your own LLM. You can use any of these providers:
| Provider | Cost | Quality | Setup |
|---|---|---|---|
| OpenAI | $$$ | ⭐⭐⭐⭐⭐ | OPENAI_API_KEY=sk-... |
| DeepSeek | $ | ⭐⭐⭐⭐ | DEEPSEEK_API_KEY=sk-... |
| Claude | $$$ | ⭐⭐⭐⭐⭐ | ANTHROPIC_API_KEY=sk-ant-... |
| Gemini | $$ | ⭐⭐⭐⭐ | GEMINI_API_KEY=... |
export OPENAI_API_KEY=sk-your-key-here
# Or in .env file:
echo "OPENAI_API_KEY=sk-your-key-here" >> .envModels: Uses gpt-4o-mini by default (cost-effective). You can modify ai_analyzer.py to use other models.
export DEEPSEEK_API_KEY=sk-your-key-here
# Or in .env file:
echo "DEEPSEEK_API_KEY=sk-your-key-here" >> .envModels: Uses deepseek-chat by default. OpenAI-compatible API.
# First install the package
pip install anthropic
export ANTHROPIC_API_KEY=sk-ant-your-key-here
# Or in .env file:
echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" >> .envModels: Uses claude-3-5-sonnet-20241022 by default.
# First install the package
pip install google-generativeai
export GEMINI_API_KEY=your-key-here
# Or in .env file:
echo "GEMINI_API_KEY=your-key-here" >> .envModels: Uses gemini-1.5-pro by default.
PatchPulse supports any OpenAI-compatible API endpoint (Ollama, LocalAI, vLLM, etc.):
# Set a dummy API key (not used for local endpoints)
export OPENAI_API_KEY=not-used
# Set your custom endpoint
export OPENAI_BASE_URL=http://localhost:11434/v1 # Ollama example
# Or
export OPENAI_BASE_URL=http://localhost:8080/v1 # LocalAI example
# Or in .env file:
echo "OPENAI_API_KEY=not-used" >> .env
echo "OPENAI_BASE_URL=http://localhost:11434/v1" >> .envExamples:
The system will automatically use your custom endpoint with the OpenAI client.
PatchPulse works perfectly without any LLM! If no API key is provided:
curl -X POST http://localhost:8000/api/v1/change-events \
-H "Content-Type: application/json" \
-d '{
"source": "github",
"repo": "org/repo",
"sha": "abc123",
"pr_number": 42,
"branch": "feature-branch",
"files": ["k8s/deployment.yaml"],
"diff_hunks": [{
"file": "k8s/deployment.yaml",
"hunk": "- limits:\n cpu: 500m"
}],
"timestamp": "2026-01-01T00:00:00Z"
}'curl http://localhost:8000/api/v1/decisions?limit=10curl http://localhost:8000/api/v1/analytics/summarycurl http://localhost:8000/api/v1/decisions/{decision_id}# Filter by risk score
curl "http://localhost:8000/api/v1/decisions?min_risk=50&max_risk=100"
# Filter by source
curl "http://localhost:8000/api/v1/decisions?source=github"
# Filter by date range
curl "http://localhost:8000/api/v1/decisions?start_date=2026-01-01&end_date=2026-01-31"See /docs for interactive API documentation.
docker compose up -dOption 1: Using your .env file (Recommended)
# Create a values file from your .env
# This reads your .env file and creates Helm values
cat > /tmp/patchpulse-values.yaml <<EOF
env:
DATABASE_URL: "postgresql://patchpulse:patchpulse@postgres:5432/patchpulse"
POLICY_MODE: "advisory"
LOG_LEVEL: "INFO"
OPENAI_API_KEY: "$(grep OPENAI_API_KEY .env | cut -d '=' -f2)"
DEEPSEEK_API_KEY: "$(grep DEEPSEEK_API_KEY .env | cut -d '=' -f2 || echo '')"
ANTHROPIC_API_KEY: "$(grep ANTHROPIC_API_KEY .env | cut -d '=' -f2 || echo '')"
GEMINI_API_KEY: "$(grep GEMINI_API_KEY .env | cut -d '=' -f2 || echo '')"
EOF
# Install backend using values from .env
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--create-namespace \
--values /tmp/patchpulse-values.yaml
# Install agent
helm install patchpulse-agent ./helm/agent \
--namespace patchpulse \
--set env.BACKEND_URL=http://patchpulse-backend:8000Option 2: Using --set-file (Alternative)
# Install backend with API key from .env file
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--create-namespace \
--set env.OPENAI_API_KEY="$(grep OPENAI_API_KEY .env | cut -d '=' -f2)" \
--set env.POLICY_MODE=advisory
# Install agent
helm install patchpulse-agent ./helm/agent \
--namespace patchpulse \
--set env.BACKEND_URL=http://patchpulse-backend:8000Option 3: Manual values override
Edit helm/backend/values.yaml and add your API keys to the env section, then install:
helm install patchpulse-backend ./helm/backend \
--namespace patchpulse \
--create-namespace# Backend
cd app/backend
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload
# Agent
cd app/agent
go run cmd/agent/main.go
# Git Integration
cd app/integrations/git
python poller.py# Unit tests
cd app/backend
pytest tests/
# Integration tests
docker compose up -d
./test_api_endpoints.shpatchpulse/ ├── app/ # Application code │ ├── backend/ # FastAPI backend service │ │ ├── main.py # Main application entry point │ │ ├── models.py # Pydantic models and SQLAlchemy ORM │ │ ├── database.py # Database connection and setup │ │ ├── policy_engine.py # Policy evaluation and guardrails │ │ ├── ai_analyzer.py # AI-powered risk analysis (BYO LLM!) │ │ ├── ai_features.py # Advanced AI features │ │ ├── auth.py # Authentication system │ │ └── requirements.txt │ ├── agent/ # Kubernetes agent (Go) │ │ ├── cmd/agent/ # Agent main application │ │ └── Dockerfile │ ├── integrations/ # External integrations │ │ ├── git/ # GitHub/GitLab integration │ │ ├── slack/ # Slack notifications │ │ ├── teams/ # Microsoft Teams integration │ │ ├── pagerduty/ # PagerDuty integration │ │ └── email/ # Email notifications │ └── ui/ # Dashboard UI (served at /dashboard) ├── docs/ # Technical documentation ├── helm/ # Kubernetes Helm charts ├── docker-compose.yml # Local development setup └── README.md # This file
Integrate PatchPulse into your CI/CD pipeline to automatically analyze PRs:
# GitHub Actions example
- name: Analyze with PatchPulse
run: |
curl -X POST $PATCHPULSE_URL/api/v1/change-events \
-H "Content-Type: application/json" \
-d @change-event.jsonValidate Kubernetes manifests before deployment:
# Analyze deployment manifests
kubectl apply --dry-run=client -f deployment.yaml | \
patchpulse analyze --source=manualTrack compliance with Kubernetes best practices:
# Get compliance report
curl http://localhost:8000/api/v1/analytics/compliancePrevent production incidents by catching risky changes:
Use PatchPulse to educate teams on Kubernetes best practices:
See SECURITY.md for detailed security information.
Contributions are welcome! This is a solo project, so any help is genuinely appreciated.
See CONTRIBUTING.md for more details.
What I'd love help with:
This project is licensed under the PatchPulse Non-Commercial License - see the LICENSE file for details.
✅ Permitted Uses:
❌ Prohibited Uses:
💼 Commercial Licensing: For commercial use, please contact us to obtain a commercial license. Commercial licenses are available for:
Contact: amarkdotdev@gmail.com
This license protects the open-source nature of PatchPulse while ensuring commercial use requires proper licensing.
Documentation: http://localhost:8000/docs (when running locally)
Website: https://patchpulse.dev
Issues: https://github.com/amarkdotdev/patchpulse/issues
Email: amarkdotdev@gmail.com
Ways to help:
If PatchPulse has saved you from a late-night incident or just made your life easier, consider buying me a coffee:
It's not required at all, but it's a nice way to say thanks and helps me justify spending more time on this project. Every bit helps! 🙏
I'm a DevOps engineer based in Israel 🇮🇱, and I built PatchPulse because I was tired of preventable production incidents.
You know those moments when you're debugging at 2am and think "we should've caught this earlier"? That's what PatchPulse is for. It's the tool I wish I had when I was managing Kubernetes clusters at scale.
I built this in my spare time, iterating based on real problems I've faced. It's not perfect, but it's useful, and I'm sharing it because I think other teams might find it helpful too.
Want to chat?
This project wouldn't exist without the open source community. Special shoutout to everyone who's contributed, reported bugs, or just used PatchPulse and gave feedback.
Built with:
🔓 Open Source | 🤖 Bring Your Own LLM | 🚀 Self-Hosted
Made with ❤️ in Israel for the Kubernetes community worldwide
⭐ Star on GitHub • 📖 Documentation • ☕ Buy Me a Coffee • 🐛 Report Bug
| Back | FazBrowse Home | New Git URL |