Automatic PR preview deployments for Kubernetes.
When a pull request opens, kube-gitops creates a live preview environment for it. When the PR closes, the environment is torn down. No manual steps. No leftover resources.
It sits on top of kube-deploy
and delegates all build, image, and deployment work to it. kube-gitops only
handles the git platform side — watching for PRs, enforcing trust policy,
generating the right kube-deploy App CR, and posting status back to the PR.
Testing phase 2:
https://github.com/centerionware/kube-gitops-testing
Index:
- ⬜ - Untested
- ✅ - Tested Working
- ☑️ - Partially Tested
- ✅ - Poll mode
- ✅ - PR from unauthorized user (fork)
- ✅ - PR from project owner (branch)
- ☑️ - Webhook mode
- ☑️ - PR from unauthorized user (fork)
- ✅ - PR from project owner (branch)
- ⬜ - Broken build error reporting
- ⬜ - Poll
- ⬜ - Webhook
- ⬜ - Comment trigger (
/deploy) - ⬜ -
requireLabeltrust gate
- ⬜ - Poll mode
- ⬜ - MR from unauthorized user
- ⬜ - MR from project owner
- ⬜ - Webhook mode
- ⬜ - MR from unauthorized user
- ⬜ - MR from project owner
- ⬜ - Broken build error reporting
- ⬜ - Poll mode
- ⬜ - PR from unauthorized user (fork)
- ⬜ - PR from project owner (branch)
- ⬜ - Webhook mode
- ⬜ - PR from unauthorized user (fork)
- ⬜ - PR from project owner (branch)
- ⬜ - Broken build error reporting
- ⬜ - Poll mode
- ⬜ - PR from unauthorized user (fork)
- ⬜ - PR from project owner (branch)
- ⬜ - Webhook mode
- ⬜ - PR from unauthorized user (fork)
- ⬜ - PR from project owner (branch)
- ⬜ - Broken build error reporting
- kube-deploy must be installed and running in the cluster. kube-gitops
generates
AppCRs for kube-deploy to act on. Without it nothing deploys.
1. Edit deploy.yaml — set your ingress host and external URL:
ingress:
enabled: true
host: gitops.your-domain.com # where kube-gitops is reachable
className: nginx
env:
LOG_DEV_MODE: "false"
EXTERNAL_URL: "https://gitops.your-domain.com" # same as ingress host2. Apply it:
kubectl apply -f deploy.yamlkube-deploy builds and runs the operator. CRDs, RBAC, and the ServiceAccount are all created automatically as part of the same manifest.
3. Create a GitRepo to start watching a repository:
# Create credentials
kubectl create secret generic myapp-git-secret \
-n kube-deploy \
--from-literal=username=myuser \
--from-literal=password=<your-token>
# Apply a GitRepo
kubectl apply -f - <<YAML
apiVersion: kube-gitops.centerionware.app/v1alpha1
kind: GitRepo
metadata:
name: myapp
namespace: kube-deploy
spec:
platform: github # github | gitlab | gitea | forgejo
repo: https://github.com/myorg/myapp
gitSecret: myapp-git-secret
trigger:
mode: poll
pollInterval: 2m
prDeploy:
namespace: pr-previews
baseDomain: previews.your-domain.com
run:
port: 3000
ingress:
enabled: true
className: nginx
YAML4. Check status:
kubectl get gr -n kube-deploy
kubectl get prd -n kube-deployOpen a PR. A preview environment will appear within one poll cycle.
PR opened
└── kube-gitops detects it (webhook or poll)
└── trust policy passes
└── kube-deploy App CR created (branch pinned to PR head)
└── kube-deploy builds, deploys, exposes the preview
└── PR receives comment with preview URL
PR closed
└── App CR deleted
└── kube-deploy tears down everything it owns
This project and all documentation at public release was entirely written by Claude at the direction of one poor and silly engineer.