Skip to main content
Browse docs
By Audience
Getting Started
Configuration
Use Cases
IDE Integration
Third-Party Integrations
Engineering Cache
Console
API Reference
Gateway
Workflow Guides
Templates
Providers and SDKs
Industry Guides
Advanced Guides
Browse by Role
Deployment Guides
In-Depth Guides
Tutorials
FAQ

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 lint validation 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

  1. Developer opens a PR changing policy configs
  2. CI validates with kt policy lint and runs policy behavior tests
  3. PR merges to main after review
  4. Keeptrusts API polls the linked repo and detects the change
  5. Updated config propagates to all bound gateways

Pipeline Summary

StageToolPurpose
PR validationkt policy lintSyntax and semantic checks
Policy testingkt gateway run + curlBehavioral assertions
Deployment gateCI job dependencyBlock deploy on failure
Drift detectionScheduled CI + APIDetect runtime divergence
GitOps syncGit-linked reposAutomated propagation

Key Takeaways

  • Run kt policy lint on 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.yaml in every PR that touches policy files — exit code 0 = 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-repos with auto_create_configuration: true and poll_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