PullRequest Resources¶
The PullRequest
resource automates the creation and management of pull requests based on Kubernetes cluster data. This guide covers everything you need to know about using PullRequest resources for GitOps workflows and automated change management.
Overview¶
PullRequest resources enable you to: - Automatically create pull requests when cluster resources change - Implement change approval workflows through Git-based review processes - Sync cluster state to Git repositories with proper change tracking - Integrate with CI/CD pipelines triggered by pull request events
Basic PullRequest Resource¶
Minimal Example¶
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: simple-pr
namespace: default
spec:
repository: "https://github.com/myorg/config-repo.git"
baseBranch: "main"
headBranch: "automated-update"
title: "Automated configuration update"
body: "This PR contains automated updates from the Kubernetes cluster"
resourceRef:
apiVersion: v1
kind: ConfigMap
name: app-config
namespace: default
path: "config/app.yaml"
This creates a pull request with the contents of the app-config
ConfigMap.
Complete Example¶
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: comprehensive-pr
namespace: default
labels:
app: myapp
automation: enabled
spec:
# Repository configuration
repository: "https://github.com/myorg/config-repo.git"
baseBranch: "main"
headBranch: "config-update-{{ .timestamp | date "20060102-150405" }}"
# PR metadata
title: "🤖 Automated configuration update from {{ .cluster.name }}"
body: |
# Automated Configuration Update
This pull request contains automated configuration updates from the Kubernetes cluster `{{ .cluster.name }}`.
## Changes Summary
- **Resource**: {{ .resourceRef.kind }}/{{ .resourceRef.name }}
- **Namespace**: {{ .resourceRef.namespace }}
- **Updated**: {{ .timestamp | date "2006-01-02 15:04:05 UTC" }}
## Resource Details
```yaml
{{ .resourceContent | indent 4 }}
```
## Validation Checklist
- [ ] Configuration syntax is valid
- [ ] No sensitive data is exposed
- [ ] Changes are backwards compatible
- [ ] All required fields are present
## Approval Required
This PR requires approval from the configuration management team before merging.
---
*Generated by git-change-operator on {{ .timestamp }}*
# Labels and metadata
labels:
- "automated"
- "configuration"
- "cluster-sync"
- "{{ .cluster.environment }}"
# Review assignments
assignees:
- "config-team"
- "{{ .resourceRef.owner | default "devops-team" }}"
reviewers:
- "senior-engineers"
teamReviewers:
- "platform-team"
# PR options
draft: false
maintainerCanModify: true
# Authentication
credentials:
secretName: github-token
tokenKey: token
# Resource reference (same options as GitCommit)
resourceRef:
apiVersion: v1
kind: ConfigMap
name: app-config
namespace: default
path: "applications/myapp/config.yaml"
strategy: "template"
template: |
# Application Configuration
# Source: {{ .metadata.namespace }}/{{ .metadata.name }}
# Generated: {{ .timestamp }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .metadata.name }}
namespace: {{ .metadata.namespace }}
labels:
{{ range $key, $value := .metadata.labels }}
{{ $key }}: {{ $value }}
{{ end }}
annotations:
generated-by: git-change-operator
source-cluster: {{ .cluster.name }}
sync-timestamp: "{{ .timestamp }}"
data:
{{ range $key, $value := .data }}
{{ $key }}: |
{{ $value | indent 4 }}
{{ end }}
# Write configuration
writeMode: "overwrite"
fileMode: "0644"
createDirs: true
# Reconciliation settings
reconcileInterval: "300s"
suspend: false
# Auto-merge settings (optional)
autoMerge:
enabled: false
strategy: "squash" # merge, squash, rebase
conditions:
- allChecksPass: true
- reviewApproved: true
- upToDate: true
Pull Request Lifecycle¶
Creation Process¶
- Resource Change Detection - Operator detects changes to referenced resources
- Branch Creation - Creates or updates the head branch with new content
- PR Creation - Creates pull request if it doesn't exist
- PR Update - Updates existing PR with new content if needed
- Status Tracking - Monitors PR status and reports back to Kubernetes
Branch Management¶
PullRequest resources can manage branches automatically:
spec:
# Dynamic branch naming
headBranch: "auto-update/{{ .resourceRef.name }}/{{ .timestamp | date "20060102" }}"
# Branch creation options
branchOptions:
createFromBase: true # Create branch from base branch
updateIfExists: true # Update existing branch
deleteAfterMerge: true # Auto-delete branch after PR merge
protectBranch: false # Don't add branch protection
Status Management¶
Monitor PullRequest resource status:
# Check PullRequest status
kubectl get pullrequest mypr -o yaml
# Example status
status:
phase: "Open" # Pending, Open, Merged, Closed, Failed
prNumber: 123
prURL: "https://github.com/myorg/config-repo/pull/123"
headSHA: "abc123def456"
baseSHA: "def456abc123"
conditions:
- type: "Ready"
status: "True"
lastTransitionTime: "2024-01-15T10:30:00Z"
reason: "PRCreated"
message: "Pull request created successfully"
- type: "ReviewsApproved"
status: "False"
reason: "PendingReview"
message: "Waiting for required reviews"
lastUpdateTime: "2024-01-15T10:30:00Z"
observedGeneration: 1
Authentication and Permissions¶
GitHub Token Authentication¶
# GitHub personal access token
apiVersion: v1
kind: Secret
metadata:
name: github-token
namespace: default
type: Opaque
data:
token: Z2hwX3Rva2VuX2hlcmU= # base64 encoded GitHub token
---
# PullRequest using GitHub token
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: github-pr
spec:
repository: "https://github.com/myorg/repo.git"
credentials:
secretName: github-token
tokenKey: token
Required GitHub Token Permissions¶
For public repositories: - public_repo
- Access to public repositories - workflow
- Update GitHub Actions workflows (if needed)
For private repositories: - repo
- Full repository access - workflow
- Update GitHub Actions workflows (if needed)
GitLab Token Authentication¶
# GitLab access token
apiVersion: v1
kind: Secret
metadata:
name: gitlab-token
namespace: default
type: Opaque
data:
token: Z2xwYXRfdG9rZW5faGVyZQ== # base64 encoded GitLab token
---
# PullRequest for GitLab (merge request)
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: gitlab-mr
spec:
repository: "https://gitlab.com/myorg/repo.git"
provider: "gitlab" # Specify GitLab provider
credentials:
secretName: gitlab-token
tokenKey: token
Advanced Features¶
Multiple Resource References¶
Include multiple resources in a single PR:
spec:
resourceRefs: # Note: plural form
- apiVersion: v1
kind: ConfigMap
name: app-config
namespace: default
path: "config/app.yaml"
- apiVersion: v1
kind: Secret
name: app-secrets
namespace: default
path: "secrets/app.yaml"
strategy: "template"
template: |
# Secret metadata (values redacted for security)
apiVersion: v1
kind: Secret
metadata:
name: {{ .metadata.name }}
namespace: {{ .metadata.namespace }}
type: {{ .type }}
data:
{{ range $key, $value := .data }}
{{ $key }}: "[REDACTED-{{ $value | len }}-bytes]"
{{ end }}
- apiVersion: apps/v1
kind: Deployment
name: myapp
namespace: default
path: "deployments/myapp.yaml"
Conditional PR Creation¶
Create PRs based on conditions:
spec:
# Only create PR if conditions are met
conditions:
- field: ".metadata.labels.environment"
operator: "equals"
value: "production"
- field: ".spec.replicas"
operator: "greaterThan"
value: 1
# Template with conditional logic
body: |
# Configuration Update
{{ if eq .metadata.labels.environment "production" }}
⚠️ **PRODUCTION CHANGE** - This change affects the production environment.
Additional review required from:
- Platform Engineering Team
- Security Team
{{ end }}
## Resource Details
- **Name**: {{ .metadata.name }}
- **Namespace**: {{ .metadata.namespace }}
- **Environment**: {{ .metadata.labels.environment }}
Auto-Merge Configuration¶
Configure automatic merging for trusted changes:
spec:
autoMerge:
enabled: true
strategy: "squash" # merge, squash, rebase
# Conditions that must be met before auto-merge
conditions:
- allChecksPass: true
- reviewApproved: true
- upToDate: true
- noConflicts: true
# Additional requirements
requirements:
minApprovals: 2
dismissStaleReviews: true
requireCodeOwnerReviews: true
requiredStatusChecks:
- "continuous-integration"
- "security-scan"
- "config-validation"
# Auto-merge delays
delays:
afterCreation: "30m" # Wait 30 minutes after creation
afterUpdate: "10m" # Wait 10 minutes after updates
afterApproval: "5m" # Wait 5 minutes after final approval
File Encryption¶
Encrypt sensitive files before committing them to the repository using age encryption:
spec:
# Basic encryption setup with SSH public key
encryption:
enabled: true
recipients:
- type: ssh
secretRef:
name: ssh-keys
key: id_rsa.pub
files:
- path: "secrets/database.yaml"
content: |
database:
host: db.example.com
password: super-secret-password
ssl_cert: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJANfKvPOD7JEBMA0GCSqGSIb3DQEBBQUAMBkx...
-----END CERTIFICATE-----
Advanced encryption with multiple recipient types:
spec:
encryption:
enabled: true
fileExtension: ".encrypted" # Custom extension (default: .age)
recipients:
# Age key recipient
- type: age
secretRef:
name: age-keys
key: public-key
# SSH key recipient (uses SSH public key)
- type: ssh
secretRef:
name: ssh-keys
key: id_rsa.pub
# Passphrase recipient
- type: passphrase
secretRef:
name: passwords
key: encryption-passphrase
# YubiKey recipient (hardware security key)
- type: yubikey
secretRef:
name: yubikey-piv
key: public-key
resourceRefs:
- apiVersion: v1
kind: Secret
name: app-secrets
namespace: default
path: "secrets/app-secrets.yaml"
# This will be encrypted as secrets/app-secrets.yaml.encrypted
Encryption secrets setup:
# Create age key secret
apiVersion: v1
kind: Secret
metadata:
name: age-keys
namespace: default
data:
public-key: YWdlMXh4eGJ4eGJ4eGJ4eGJ4eGJ4eGJ4eGJ4eGJ4eGJ4eGJ4...
---
# Create SSH key secret
apiVersion: v1
kind: Secret
metadata:
name: ssh-keys
namespace: default
data:
id_rsa.pub: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCZ1FD...
---
# Create passphrase secret
apiVersion: v1
kind: Secret
metadata:
name: passwords
namespace: default
data:
encryption-passphrase: bXktc2VjdXJlLXBhc3NwaHJhc2U= # my-secure-passphrase
---
# Create YubiKey secret
apiVersion: v1
kind: Secret
metadata:
name: yubikey-piv
namespace: default
data:
public-key: c2stcHV0dHk6QUFBQUIzTnphQzF5YzJFQUFBQURBUUFCQUFBQmdRRHo...
Benefits of encryption: - Security: Sensitive data is encrypted before being stored in Git - Compliance: Meet security requirements for storing secrets in repositories - Flexibility: Support for multiple encryption methods (age keys, SSH keys, passphrases, YubiKeys) - GitOps-ready: Encrypted files can be safely stored in public repositories
Complete Encryption Examples¶
Basic Encrypted PullRequest¶
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: encrypted-config-pr
namespace: default
spec:
repository: "https://github.com/myorg/secure-configs.git"
baseBranch: "main"
headBranch: "encrypted-secrets-update"
title: "Update encrypted application secrets"
body: |
Automated update of encrypted configuration files.
Files are encrypted using age encryption for secure storage.
**Files Updated:**
- Database credentials
- API keys
- TLS certificates
authSecretRef: "git-credentials"
# Encryption Configuration
encryption:
enabled: true
fileExtension: ".encrypted" # Files will be saved as .encrypted
recipients:
- type: ssh
secretRef:
name: ssh-keys
key: id_rsa.pub
files:
- path: "secrets/database.yaml"
content: |
database:
host: "production-db.example.com"
username: "app_user"
password: "super-secret-password-123"
ssl_mode: "require"
- path: "secrets/api-keys.yaml"
content: |
api:
stripe_key: "sk_live_abcdefghijklmnop"
sendgrid_key: "SG.xyz123.abc456"
oauth_secret: "oauth_secret_token_xyz"
Multi-Recipient Encryption with YubiKey¶
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: multi-encryption-pr
namespace: default
spec:
repository: "https://github.com/myorg/enterprise-config.git"
baseBranch: "main"
headBranch: "multi-encrypted-update"
title: "Multi-encrypted configuration update"
authSecretRef: "git-credentials"
# Multiple Encryption Recipients
encryption:
enabled: true
recipients:
# Team SSH keys
- type: ssh
secretRef:
name: team-ssh-keys
key: devops-team.pub
# Hardware security keys
- type: yubikey
secretRef:
name: security-team-yubikeys
key: security-officer.pub
# Emergency age key
- type: age
secretRef:
name: emergency-keys
key: break-glass-key
# Backup passphrase
- type: passphrase
secretRef:
name: backup-auth
key: recovery-passphrase
# Reference existing Kubernetes resources
resourceReferences:
- apiVersion: v1
kind: Secret
name: app-secrets
namespace: production
strategy: dump
output:
path: "production/secrets/app-secrets.yaml"
# Will be encrypted as: production/secrets/app-secrets.yaml.encrypted
- apiVersion: v1
kind: ConfigMap
name: database-config
namespace: production
strategy: fields
output:
path: "production/config/"
# Each field becomes a separate encrypted file
Encrypted Resource Backup¶
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: backup-secrets-pr
namespace: backup-system
spec:
repository: "https://github.com/myorg/cluster-backups.git"
baseBranch: "main"
headBranch: "automated-backup"
title: "Automated encrypted backup of cluster secrets"
authSecretRef: "backup-git-credentials"
encryption:
enabled: true
recipients:
- type: yubikey
secretRef:
name: backup-yubikey
key: backup-officer.pub
# Backup multiple secrets across namespaces
resourceReferences:
# Production secrets
- apiVersion: v1
kind: Secret
name: database-credentials
namespace: production
strategy: dump
output:
path: "backups/production/database-credentials.yaml"
# Staging secrets
- apiVersion: v1
kind: Secret
name: api-tokens
namespace: staging
strategy: dump
output:
path: "backups/staging/api-tokens.yaml"
# Certificate secrets
- apiVersion: v1
kind: Secret
name: tls-certificates
namespace: cert-manager
strategy: fields
output:
path: "backups/certificates/"
# Each certificate becomes a separate encrypted file
Setting Up Encryption Secrets¶
# 1. SSH Key Secret
kubectl create secret generic ssh-keys \
--from-file=id_rsa.pub=~/.ssh/id_rsa.pub \
--namespace=default
# 2. YubiKey Secret (extract public key from YubiKey PIV)
kubectl create secret generic yubikey-piv \
--from-literal=public-key="$(ykman piv keys export 9a - | ssh-keygen -i -m PKCS8 -f /dev/stdin)" \
--namespace=default
# 3. Age Key Secret
age-keygen -o age-key.txt
kubectl create secret generic age-keys \
--from-file=public-key=<(grep 'public key:' age-key.txt | cut -d: -f2 | tr -d ' ') \
--namespace=default
# 4. Passphrase Secret
kubectl create secret generic passwords \
--from-literal=encryption-passphrase="my-secure-recovery-phrase" \
--namespace=default
PR Templates and Customization¶
Dynamic PR Titles¶
spec:
title: |
{{ if eq .resourceRef.kind "Secret" }}🔐{{ else if eq .resourceRef.kind "ConfigMap" }}⚙️{{ else }}📝{{ end }}
{{ .resourceRef.kind }}/{{ .resourceRef.name }} update in {{ .resourceRef.namespace }}
{{- if .metadata.labels.environment }} ({{ .metadata.labels.environment }}){{ end }}
Rich PR Bodies¶
spec:
body: |
# 🤖 Automated Resource Update
## Summary
This PR updates the **{{ .resourceRef.kind }}** `{{ .resourceRef.name }}` in namespace `{{ .resourceRef.namespace }}`.
## Resource Information
| Field | Value |
|-------|-------|
| **Kind** | {{ .resourceRef.kind }} |
| **Name** | {{ .resourceRef.name }} |
| **Namespace** | {{ .resourceRef.namespace }} |
| **Cluster** | {{ .cluster.name }} |
| **Environment** | {{ .metadata.labels.environment | default "unknown" }} |
| **Updated** | {{ .timestamp | date "2006-01-02 15:04:05 UTC" }} |
## Changes
{{ if .diff }}
```diff
{{ .diff }}
```
{{ else }}
New resource - no previous version available.
{{ end }}
## Validation
- [x] Resource syntax is valid
- [x] All required fields are present
- [ ] Manual review completed
- [ ] Security implications assessed
{{ if eq .metadata.labels.environment "production" }}
## ⚠️ Production Impact
This change affects the **production** environment. Please ensure:
1. Change has been tested in staging
2. Rollback plan is ready
3. Monitoring is in place
4. Team is notified
{{ end }}
---
<details>
<summary>🔍 Resource Details</summary>
```yaml
{{ .resourceContent | indent 4 }}
```
</details>
*Automated by git-change-operator • [Documentation](https://github.com/myorg/git-change-operator/docs)*
Provider-Specific Configuration¶
GitHub Configuration¶
spec:
provider: "github" # Default
# GitHub-specific options
github:
# Organization settings
organization: "myorg"
# PR settings
allowMaintainerEdit: true
deleteHeadBranch: true
# Draft PR settings
draft: false
# Issue linking
linkedIssues:
- number: 123
action: "closes" # closes, fixes, resolves
GitLab Configuration¶
spec:
provider: "gitlab"
# GitLab-specific options (merge requests)
gitlab:
# Project settings
projectID: 12345
# Merge request settings
removeSourceBranch: true
squash: true
# Approval settings
approvalsRequired: 2
# Milestone and labels
milestoneID: 5
labels: ["automated", "config-sync"]
Bitbucket Configuration¶
spec:
provider: "bitbucket"
# Bitbucket-specific options
bitbucket:
# Workspace settings
workspace: "myworkspace"
# PR settings
closeSourceBranch: true
# Default reviewers
defaultReviewers:
- "platform-team"
Monitoring and Observability¶
Metrics¶
Monitor PullRequest operations:
# Total PullRequest operations
git_change_operator_pullrequest_operations_total
# PR creation success rate
rate(git_change_operator_pullrequest_operations_total{status="success",operation="create"}[5m])
# Average PR processing time
git_change_operator_pullrequest_duration_seconds
# Open PRs by namespace
git_change_operator_pullrequest_open_total
Events¶
Monitor PullRequest events:
# View PullRequest events
kubectl describe pullrequest mypr
# Example events
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal BranchCreated 5m pullrequest-controller Created branch 'auto-update-20240115'
Normal ResourceFetched 5m pullrequest-controller Successfully fetched resource data
Normal FileCommitted 4m pullrequest-controller Committed file to branch
Normal PRCreated 4m pullrequest-controller Pull request created: #123
Normal PRUpdated 2m pullrequest-controller Pull request updated with latest changes
Alerting¶
Set up alerts for PullRequest issues:
# Prometheus alert rules
groups:
- name: git-change-operator-pullrequest
rules:
- alert: PullRequestCreationFailed
expr: increase(git_change_operator_pullrequest_operations_total{status="failed",operation="create"}[5m]) > 0
for: 0m
labels:
severity: warning
annotations:
summary: "PullRequest creation failed"
description: "Failed to create pull request for {{ $labels.pullrequest }}"
- alert: PullRequestStale
expr: (time() - git_change_operator_pullrequest_last_update_time) > 604800 # 1 week
for: 0m
labels:
severity: info
annotations:
summary: "PullRequest is stale"
description: "PullRequest {{ $labels.pullrequest }} has not been updated for over 1 week"
Security Considerations¶
Token Permissions¶
Minimize required permissions:
# GitHub token with minimal permissions
# For public repos: public_repo
# For private repos: repo
# Additional: workflow (if updating GitHub Actions)
# Store token securely
apiVersion: v1
kind: Secret
metadata:
name: github-token-minimal
namespace: git-change-operator-system
type: Opaque
data:
token: <base64-encoded-token>
Sensitive Data Protection¶
Prevent sensitive data in PRs:
spec:
resourceRef:
apiVersion: v1
kind: Secret
name: app-secrets
path: "secrets/app-secrets.yaml"
strategy: "template"
template: |
# Sanitized secret for PR review
apiVersion: v1
kind: Secret
metadata:
name: {{ .metadata.name }}
namespace: {{ .metadata.namespace }}
type: {{ .type }}
data:
{{ range $key, $value := .data }}
{{ $key }}: "[REDACTED]" # Don't expose actual values
{{ end }}
# Metadata for reviewers
_metadata:
originalKeys: {{ keys .data | join ", " }}
keyCount: {{ len .data }}
lastUpdated: {{ .timestamp }}
RBAC Configuration¶
# Minimal RBAC for PullRequest operations
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pullrequest-operator
rules:
# PullRequest resources
- apiGroups: ["gco.galos.one"]
resources: ["pullrequests"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["gco.galos.one"]
resources: ["pullrequests/status"]
verbs: ["get", "update", "patch"]
# Referenced resources (minimal read access)
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets"]
verbs: ["get", "list", "watch"]
Use Cases and Patterns¶
Configuration Review Workflow¶
Implement a configuration review process:
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: config-review-workflow
spec:
repository: "https://github.com/myorg/k8s-configs.git"
baseBranch: "main"
headBranch: "review/{{ .metadata.namespace }}-{{ .metadata.name }}"
title: "📋 Configuration Review: {{ .metadata.name }}"
body: |
# Configuration Review Required
A configuration change has been detected and requires review before deployment.
## Change Details
- **Resource**: {{ .resourceRef.kind }}/{{ .resourceRef.name }}
- **Namespace**: {{ .resourceRef.namespace }}
- **Environment**: {{ .metadata.labels.environment }}
## Review Checklist
- [ ] Configuration follows security guidelines
- [ ] Resource limits are appropriate
- [ ] No hardcoded secrets or credentials
- [ ] Backwards compatibility maintained
- [ ] Documentation updated (if needed)
## Deployment Plan
1. Merge this PR to update the configuration repository
2. CI/CD pipeline will validate the changes
3. Automatic deployment to {{ .metadata.labels.environment }} environment
4. Monitor deployment and rollback if needed
labels: ["config-review", "{{ .metadata.labels.environment }}"]
reviewers: ["config-team", "security-team"]
draft: false
Multi-Environment Promotion¶
Promote configurations across environments:
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: env-promotion
spec:
repository: "https://github.com/myorg/env-configs.git"
baseBranch: "production"
headBranch: "promote/staging-to-prod"
title: "🚀 Promote {{ .metadata.name }} from staging to production"
body: |
# Environment Promotion
This PR promotes configuration from **staging** to **production**.
## Staging Validation
- [x] Configuration deployed successfully in staging
- [x] All tests passing
- [x] Performance benchmarks met
- [x] Security scan completed
## Production Deployment Checklist
- [ ] Deployment window scheduled
- [ ] Monitoring alerts configured
- [ ] Rollback plan prepared
- [ ] Team notified
## Risk Assessment
**Risk Level**: {{ .metadata.labels.risk | default "Medium" }}
{{ if eq .metadata.labels.risk "High" }}
⚠️ **HIGH RISK CHANGE** - Additional approvals required
{{ end }}
conditions:
- field: ".metadata.labels.environment"
operator: "equals"
value: "staging"
- field: ".metadata.labels.validated"
operator: "equals"
value: "true"
Compliance and Audit Trail¶
Maintain compliance with automated documentation:
apiVersion: gco.galos.one/v1
kind: PullRequest
metadata:
name: compliance-audit
spec:
repository: "https://github.com/myorg/compliance-records.git"
baseBranch: "main"
headBranch: "audit/{{ .timestamp | date "2006-01" }}/{{ .metadata.name }}"
title: "📊 Compliance Record: {{ .metadata.name }} - {{ .timestamp | date "January 2006" }}"
body: |
# Compliance Audit Record
## Change Summary
- **Date**: {{ .timestamp | date "2006-01-02 15:04:05 UTC" }}
- **Resource**: {{ .resourceRef.kind }}/{{ .resourceRef.name }}
- **Namespace**: {{ .resourceRef.namespace }}
- **Change Type**: {{ .changeType | default "Configuration Update" }}
- **Initiated By**: {{ .initiator | default "System Automation" }}
## Compliance Verification
- [x] Change follows organizational policies
- [x] Appropriate approvals obtained
- [x] Security implications assessed
- [x] Data classification reviewed
- [x] Retention policies applied
## Audit Trail
| Field | Before | After |
|-------|--------|-------|
{{ range .changes }}
| {{ .field }} | {{ .before }} | {{ .after }} |
{{ end }}
## Supporting Documentation
- Configuration Repository: [Link]({{ .configRepo }})
- Change Request: {{ .changeRequestID | default "N/A" }}
- Approval Workflow: [Link]({{ .approvalWorkflow }})
resourceRef:
path: "audit-records/{{ .timestamp | date "2006/01" }}/{{ .metadata.name }}.md"
labels: ["compliance", "audit", "{{ .metadata.labels.classification }}"]
assignees: ["compliance-team"]
Troubleshooting¶
Common Issues¶
Authentication Failures¶
# Check token permissions
kubectl get secret github-token -o yaml
# Test token manually
curl -H "Authorization: token $(echo '<base64-token>' | base64 -d)" \
https://api.github.com/user
# Common errors:
# - Token expired
# - Insufficient permissions
# - Invalid repository URL
Branch Creation Failures¶
# Check PullRequest status
kubectl describe pullrequest mypr
# Common errors:
# - Branch already exists (check branchOptions.updateIfExists)
# - Base branch doesn't exist
# - Insufficient repository permissions
PR Creation Failures¶
# Check controller logs
kubectl logs -n git-change-operator-system -l control-plane=controller-manager
# Common errors:
# - API rate limits exceeded
# - Invalid PR template
# - Repository not found
# - Network connectivity issues
Debug Commands¶
# Check PullRequest resources
kubectl get pullrequest -A -o wide
# Get detailed status
kubectl get pullrequest mypr -o jsonpath='{.status}' | jq
# View events
kubectl get events --field-selector involvedObject.name=mypr
# Test resource references
kubectl get configmap app-config -o yaml
Best Practices¶
PR Management¶
- Use descriptive titles that clearly indicate the change
- Provide comprehensive descriptions with context and impact
- Include validation checklists for reviewers
- Link to related issues and documentation
- Set appropriate labels for filtering and automation
Branch Strategy¶
- Use meaningful branch names with consistent patterns
- Clean up branches after PR merge
- Protect important branches from direct pushes
- Use branch prefixes to categorize changes
Review Process¶
- Assign appropriate reviewers based on change impact
- Require approvals for sensitive changes
- Use draft PRs for work-in-progress changes
- Enable auto-merge for trusted automated changes
- Set up status checks to validate changes
Security¶
- Use minimal token permissions required for operations
- Rotate tokens regularly and monitor usage
- Audit PR creation and review processes
- Sanitize sensitive data before including in PRs
- Monitor for unauthorized changes
Next Steps¶
- Authentication Guide - Set up secure Git authentication
- GitCommit Resources - Learn about direct Git commits
- Examples - See real-world PR automation examples
- Advanced Patterns - Complex workflow examples
For enterprise PullRequest patterns, see our Corporate Setup Guide.