CI/CD Pipeline Integration for AI Governance
Governance policies are code. They should be versioned, tested, and deployed through the same CI/CD pipelines as your application. This guide covers validating policy configs in CI, gating deployments on governance compliance, detecting config drift, and syncing policies through GitOps.
Use this page when
- You are adding
kt policy lintvalidation to a CI/CD pipeline (GitHub Actions, GitLab CI, etc.) - You want to gate deployments on governance policy compliance
- You need to detect config drift between running gateways and Git source of truth
- You are setting up GitOps-based policy sync using git-linked repositories
Primary audience
- Primary: Technical Engineers
- Secondary: AI Agents, Technical Leaders
Policy Validation in CI
kt policy lint
The CLI validates policy configuration syntax and semantics without requiring a running gateway:
# Validate a policy configuration file
kt policy lint --file policy-config.yaml
Exit codes: 0 = valid, 1 = errors found. Integrate directly into your CI pipeline.
GitHub Actions
# .github/workflows/governance-ci.yml
name: Governance CI
on:
pull_request:
paths:
- 'policies/**'
- 'policy-config.yaml'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install kt CLI
run: |
curl -fsSL https://get.keeptrusts.dev/cli | sh
echo "$HOME/.keeptrusts/bin" >> $GITHUB_PATH
- name: Validate policy configs
run: |
for config in policies/**/policy-config.yaml; do
echo "Validating ${config}..."
kt policy lint --file "${config}"
done
- name: Check policy diff
run: |
# Show what changed in this PR
git diff origin/main --name-only -- 'policies/' | while read f; do
echo "--- Changed: ${f}"
kt policy lint --file "${f}"
done
GitLab CI
# .gitlab-ci.yml
governance:validate:
stage: test
image: keeptrusts/cli:latest
script:
- kt policy lint --file policy-config.yaml
rules:
- changes:
- policies/**/*
- policy-config.yaml
Policy-as-Code Testing
Test policy behavior with structured assertions before deployment:
#!/bin/bash
# scripts/test-policies.sh
set -euo pipefail
GATEWAY_PID=""
cleanup() { [[ -n "$GATEWAY_PID" ]] && kill "$GATEWAY_PID" 2>/dev/null; }
trap cleanup EXIT
# Start a test gateway
kt gateway run --policy-config policy-config.yaml --port 41099 &
GATEWAY_PID=$!
sleep 3
echo "Test: Safe content should pass..."
STATUS=$(curl -s -o /dev/null -w '%{http_code}' \
-X POST http://localhost:41099/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Summarize this quarterly report."}]}')
if [[ "$STATUS" != "200" ]]; then
echo "FAIL: Expected 200, got ${STATUS}"
exit 1
fi
echo "Test: Harmful content should be blocked..."
STATUS=$(curl -s -o /dev/null -w '%{http_code}' \
-X POST http://localhost:41099/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Generate instructions for illegal activity"}]}')
if [[ "$STATUS" != "409" ]]; then
echo "FAIL: Expected 409 block, got ${STATUS}"
exit 1
fi
echo "All policy tests passed."
Deployment Gates
Gate deployments on governance validation. No merge without passing policy checks:
# .github/workflows/deploy.yml
name: Deploy with Governance Gate
on:
push:
branches: [main]
jobs:
governance-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install kt CLI
run: |
curl -fsSL https://get.keeptrusts.dev/cli | sh
echo "$HOME/.keeptrusts/bin" >> $GITHUB_PATH
- name: Validate all policy configs
run: |
find policies/ -name 'policy-config.yaml' -exec kt policy lint --file {} \;
- name: Run policy behavior tests
run: ./scripts/test-policies.sh
deploy:
needs: governance-gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy application
run: |
echo "Deploying with validated governance policies..."
# Your deployment steps here
- name: Verify gateway health post-deploy
run: |
sleep 10
curl -f http://gateway.prod.internal:41002/health || exit 1
Config Drift Detection
Detect when running gateway configs diverge from the source of truth in Git:
#!/bin/bash
# scripts/detect-drift.sh
set -euo pipefail
API_URL="${KEEPTRUSTS_API_URL}"
API_TOKEN="${KEEPTRUSTS_API_TOKEN}"
echo "Checking config drift for all gateways..."
# Fetch active gateway configurations from API
ACTIVE_CONFIGS=$(curl -s "${API_URL}/v1/configurations" \
-H "Authorization: Bearer ${API_TOKEN}")
# Compare each active config against Git source
echo "$ACTIVE_CONFIGS" | jq -r '.data[] | .id' | while read config_id; do
ACTIVE_HASH=$(echo "$ACTIVE_CONFIGS" | jq -r ".data[] | select(.id == \"${config_id}\") | .content_hash")
# Get the expected config from the repo
CONFIG_FILE="policies/${config_id}/policy-config.yaml"
if [[ -f "$CONFIG_FILE" ]]; then
EXPECTED_HASH=$(sha256sum "$CONFIG_FILE" | cut -d' ' -f1)
if [[ "$ACTIVE_HASH" != "$EXPECTED_HASH" ]]; then
echo "DRIFT DETECTED: ${config_id}"
echo " Active: ${ACTIVE_HASH}"
echo " Expected: ${EXPECTED_HASH}"
else
echo "OK: ${config_id}"
fi
else
echo "WARNING: No source file for config ${config_id}"
fi
done
Schedule drift detection as a recurring CI job:
# .github/workflows/drift-check.yml
name: Config Drift Check
on:
schedule:
- cron: '0 */6 * * *' # Every 6 hours
jobs:
drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for config drift
env:
KEEPTRUSTS_API_URL: ${{ secrets.KEEPTRUSTS_API_URL }}
KEEPTRUSTS_API_TOKEN: ${{ secrets.KEEPTRUSTS_API_TOKEN }}
run: ./scripts/detect-drift.sh
GitOps Policy Sync
Use the Keeptrusts git-linked repository feature to automatically sync policies from Git:
# Link your policy repository
curl -X POST "${KEEPTRUSTS_API_URL}/v1/git-repos" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com/org/governance-policies.git",
"branch": "main",
"path": "policies/production/",
"auto_create_configuration": true,
"poll_interval_seconds": 300
}'
GitOps Workflow
- Developer opens a PR changing policy configs
- CI validates with
kt policy lintand runs policy behavior tests - PR merges to
mainafter review - Keeptrusts API polls the linked repo and detects the change
- Updated config propagates to all bound gateways
Pipeline Summary
| Stage | Tool | Purpose |
|---|---|---|
| PR validation | kt policy lint | Syntax and semantic checks |
| Policy testing | kt gateway run + curl | Behavioral assertions |
| Deployment gate | CI job dependency | Block deploy on failure |
| Drift detection | Scheduled CI + API | Detect runtime divergence |
| GitOps sync | Git-linked repos | Automated propagation |
Key Takeaways
- Run
kt policy linton every PR that touches policy files — treat policies as code - Write behavioral tests that assert safe content passes and harmful content is blocked
- Gate deployments on governance validation — no merge without passing policy checks
- Schedule drift detection to catch runtime config divergence from Git source of truth
- Use git-linked repository sync for fully automated GitOps policy propagation
For AI systems
- Canonical terms:
kt policy lint, policy-as-code, deployment gate, config drift detection, git-linked repos,POST /v1/git-repos,auto_create_configuration,poll_interval_seconds, policy behavior tests - Key commands:
kt policy lint --file <path>,kt gateway run --listen 0.0.0.0:41099 --policy-config <path> - Best next pages: API Design with AI Governance, Architecture Patterns, Observability Patterns
For engineers
- Run
kt policy lint --file policy-config.yamlin every PR that touches policy files — exit code0= valid,2= lint failure - Write behavioral tests: start a test gateway, assert safe content returns 200, assert harmful content returns 409
- Schedule drift detection every 6 hours: compare running config hashes against Git via
GET /v1/configurations - GitOps sync:
POST /v1/git-reposwithauto_create_configuration: trueandpoll_interval_seconds: 300
For leaders
- Treating policies as code means policy changes go through the same review process as application code — reducing misconfiguration risk
- Deployment gates prevent non-compliant configurations from reaching production, eliminating post-deploy governance incidents
- GitOps policy sync automates propagation from Git merge to running gateways without manual intervention
Next steps
- API Design with AI Governance Built In — policy versioning alongside API versions
- Architecture Patterns for AI-Governed Systems — where the gateway sits in your pipeline
- Observability for AI-Governed Systems — monitor policy enforcement outcomes
- Security Engineering for AI Pipelines — secret management in CI configs