# Woodpecker CI/CD Guide for VAPORA Provisioning

Complete reference for understanding, running, and troubleshooting VAPORA's Woodpecker CI/CD pipelines.

---

## Overview

VAPORA uses five integrated Woodpecker CI/CD pipelines for complete deployment automation. These pipelines are self-hosted alternatives to GitHub Actions, providing full control over infrastructure and execution environment.

### Pipeline Architecture

```
Push to Repository
    ↓
[Validate & Build] - Generates artifacts
    ↓
    ├── Manual Promotion → [Deploy to Docker]
    │                          ↓
    │                    Health checks → Services running locally
    │
    └── Manual Promotion → [Deploy to Kubernetes] with dry-run
                                ↓
                        Review changes
                                ↓
                        Actual deployment
                                ↓
                        [Health Check] (automatic every 15min/6hr)
                                ↓
                        [Rollback] if issues detected
```

---

## Quick Reference

### Pipeline Files

```
.woodpecker/
├── validate-and-build.yml       # Validates configs, generates artifacts
├── deploy-docker.yml            # Deploys to Docker Compose
├── deploy-kubernetes.yml        # Deploys to Kubernetes
├── health-check.yml             # Continuous monitoring (scheduled)
├── rollback.yml                 # Safe deployment rollback
├── SETUP.md                     # Installation and configuration
└── WOODPECKER_GUIDE.md          # This file
```

### Pipeline Triggers

| Pipeline | Trigger | Branch | Manual |
|----------|---------|--------|--------|
| **validate-and-build** | Push, PR | main/develop | Yes |
| **deploy-docker** | Manual promotion | main/develop | Yes |
| **deploy-kubernetes** | Manual promotion | main/develop | Yes |
| **health-check** | Cron (15min, 6hr) | Any | Yes |
| **rollback** | Manual promotion | main/develop | Yes |

### Environment Variables

All pipelines use:
```bash
ARTIFACTS_DIR=provisioning/artifacts    # Generated configs
LOG_DIR=provisioning/logs               # Pipeline logs
VAPORA_NAMESPACE=vapora                 # K8s namespace
```

---

## Workflows in Detail

### 1. Validate & Build (validate-and-build.yml)

**Purpose**: Validate all configurations and generate deployment artifacts

**Triggers**:
- Push to `main` or `develop` branches (if provisioning files change)
- Manual promotion from Woodpecker UI
- Pull requests affecting provisioning

**Execution Flow**:
```
setup
  └─ prepare: Create directories, display info
      ↓
install_dependencies
  └─ install_tools: Install Rust, Nushell, Nickel, jinja2, yq
      ↓
validate_solo/multiuser/enterprise (parallel)
  └─ validate_*: Run mode-specific validation
      ↓
build_artifacts
  ├─ install_tools: Reinstall tools (cached layer)
  ├─ build_artifacts: Run CI pipeline to generate outputs
  ├─ verify_artifacts: Validate JSON, YAML, TOML formats
  └─ generate_manifest: Create README documenting outputs
      ↓
publish
  └─ publish_artifacts: Display artifact summary
```

**Duration**: ~5 minutes

**Outputs**:
```
provisioning/artifacts/
├── config-solo.json
├── config-multiuser.json
├── config-enterprise.json
├── vapora-solo.toml/yaml
├── vapora-multiuser.toml/yaml
├── vapora-enterprise.toml/yaml
├── configmap.yaml
├── deployment.yaml
├── docker-compose.yml
└── README.md
```

**Usage**:
```bash
# Automatic (on push)
git commit -m "Update provisioning config"
git push origin main

# Manual (from Woodpecker UI)
1. Go to repository → Latest build
2. Click "Promote" button
3. Select "validate-and-build" pipeline
4. Click "Promote"
```

**Expected Output**:
```
✓ Solo configuration validated
✓ Multiuser configuration validated
✓ Enterprise configuration validated
✓ JSON outputs validated
✓ YAML outputs validated
✓ TOML outputs validated
✓ Manifests generated
✓ Artifacts ready for deployment
```

---

### 2. Deploy to Docker (deploy-docker.yml)

**Purpose**: Deploy VAPORA to Docker Compose for local/staging testing

**Triggers**:
- Manual promotion from completed validate-and-build build
- Manual promotion from Woodpecker UI

**Execution Flow**:
```
setup
  └─ prepare: Display deployment info
      ↓
install_dependencies
  └─ install_tools: Install tools + Docker
      ↓
download_artifacts
  └─ fetch_latest_artifacts: Get configs from workspace
      ↓
validate_docker_config
  └─ validate_compose: Validate docker-compose.yml format
      ↓
deploy_docker_compose
  ├─ pull_images: Download container images
  └─ compose_up: Start services with docker compose
      ↓
health_checks
  ├─ verify_services: Check HTTP endpoints
  └─ collect_logs: Gather service logs
      ↓
verify_endpoints
  └─ test_endpoints: Test API calls to running services
      ↓
generate_report
  └─ create_deployment_report: Generate deployment summary
      ↓
publish
  └─ publish_results & notify_slack
```

**Duration**: ~3 minutes

**Service Endpoints** (after deployment):
```
- Backend API: http://localhost:8001
- Frontend UI: http://localhost:3000
- Agents: http://localhost:8002
- LLM Router: http://localhost:8003
- SurrealDB: http://localhost:8000
- Health: http://localhost:8001/health
```

**Usage**:
```bash
# From Woodpecker UI (after validate-and-build)
1. Go to completed validate-and-build build
2. Click "Promote"
3. Select "deploy-docker"
4. Click "Promote"

# Monitor via Woodpecker UI
1. Go to repository → Active builds
2. Watch deploy-docker build progress
3. Check each stage for logs
```

**Local Testing**:
```bash
# Download artifacts from Woodpecker workspace
# Extract provisioning/artifacts/docker-compose.yml

# Start services
docker compose -f docker-compose.yml up -d

# Check health
curl http://localhost:8001/health

# View logs
docker compose logs -f backend

# Stop services
docker compose down
```

**Verification**:
- ✓ Backend responds at port 8001
- ✓ Frontend accessible at port 3000
- ✓ Agents running at port 8002
- ✓ LLM Router at port 8003
- ✓ SurrealDB at port 8000
- ✓ Health endpoint returns 200 OK

---

### 3. Deploy to Kubernetes (deploy-kubernetes.yml)

**Purpose**: Deploy VAPORA to Kubernetes with dry-run validation

**Triggers**:
- Manual promotion from completed validate-and-build
- Manual promotion from Woodpecker UI

**Execution Flow**:
```
setup
  └─ prepare: Display deployment info
      ↓
install_dependencies
  └─ install_tools: Install kubectl, tools
      ↓
configure_kubernetes
  ├─ setup_kubeconfig_staging/production: Decode kubeconfig
  └─ verify_cluster: Test cluster access
      ↓
validate_manifests
  ├─ validate_kubernetes_manifests: Check manifest validity
  └─ dry_run_validation: Kubernetes dry-run check
      ↓
create_namespace
  ├─ ensure_namespace: Create vapora namespace
  └─ setup_rbac: Configure service accounts
      ↓
deploy_configmap
  └─ apply_configmap: Deploy configuration
      ↓
deploy_services (with monitoring)
  ├─ apply_deployments: Deploy all three services
  ├─ monitor_rollout_backend: Wait for backend ready
  ├─ monitor_rollout_agents: Wait for agents ready
  └─ monitor_rollout_llm_router: Wait for router ready
      ↓
verify_deployment
  ├─ check_pods: Verify pod status
  ├─ check_services: Verify service endpoints
  ├─ collect_logs: Gather deployment logs
  └─ annotate_deployment: Add metadata
      ↓
generate_report
  └─ create_deployment_report: Generate summary
      ↓
publish
  └─ publish_results & notify_slack
```

**Duration**: ~5-10 minutes (includes rollout waits)

**Deployment Options**:
```bash
# Via Woodpecker UI Promotion
1. Select environment: staging or production
2. Select deployment mode: solo, multiuser, enterprise
3. Set dry_run: true (first), then false (actual)
4. Set rollout_timeout: 300 (seconds)
```

**Dry-Run Usage** (Recommended):
```bash
# Step 1: Promote with dry-run enabled
Mode: enterprise
Environment: staging
Dry-run: true
Rollout timeout: 300

# Step 2: Review dry-run output in logs
# Check proposed changes to deployments

# Step 3: If satisfied, promote again with dry-run disabled
Dry-run: false

# Step 4: Monitor rollout
# Watch rollout status and pod health
```

**Verification Commands** (after deployment):
```bash
# Check deployments
kubectl get deployments -n vapora

# Check pods
kubectl get pods -n vapora -o wide

# Check services
kubectl get services -n vapora

# View logs
kubectl logs -f deployment/vapora-backend -n vapora

# Check events
kubectl get events -n vapora --sort-by='.lastTimestamp'

# Port forward for local testing
kubectl port-forward -n vapora svc/vapora-backend 8001:8001
curl http://localhost:8001/health

# Check rollout history
kubectl rollout history deployment/vapora-backend -n vapora
```

**Deployment Modes**:

| Mode | Replicas | Resources | Use Case |
|------|----------|-----------|----------|
| **solo** | 1 | Minimal | Development, testing |
| **multiuser** | 2 | Standard | Team/staging environments |
| **enterprise** | 3 | Optimized | Production with HA |

---

### 4. Health Check & Monitoring (health-check.yml)

**Purpose**: Continuous health monitoring across Docker and Kubernetes

**Triggers**:
- Schedule: Every 15 minutes (quick check)
- Schedule: Every 6 hours (comprehensive diagnostics)
- Manual promotion from Woodpecker UI

**Execution Flow**:
```
setup
  └─ prepare: Display check info
      ↓
install_dependencies
  └─ install_tools: Install kubectl, Docker tools
      ↓
configure_kubernetes
  └─ setup_kubeconfig: Configure cluster access
      ↓
health_check_docker (if available)
  ├─ check_docker_containers: Container status
  ├─ check_docker_endpoints: HTTP health checks
  └─ collect_docker_diagnostics: System resource info
      ↓
health_check_kubernetes
  ├─ check_k8s_deployments: Deployment replica status
  ├─ check_k8s_services: Service endpoints
  ├─ check_k8s_events: Recent cluster events
  └─ collect_pod_logs: Application logs
      ↓
analyze_health
  ├─ generate_health_report: Create summary
  └─ check_health_status: Determine overall status
      ↓
publish
  └─ publish_reports & notify_slack
```

**Duration**: ~5 minutes

**Checked Resources** (Docker):
- Container status (Up/Down)
- HTTP endpoints (8001, 8002, 8003, 3000, 8000)
- Network connectivity
- Resource usage

**Checked Resources** (Kubernetes):
- Deployment replica status
- Pod readiness conditions
- Service availability
- ConfigMap data
- Recent cluster events
- Pod logs (last 100 lines)

**Reports Generated**:
```
provisioning/logs/health-checks/
├── docker-containers.log
├── docker-endpoints.log
├── docker-diagnostics.log
├── k8s-deployments.log
├── k8s-services.log
├── k8s-events.log
├── k8s-diagnostics.log
├── pods/
│   ├── backend.log
│   ├── agents.log
│   └── llm-router.log
└── HEALTH_REPORT.md
```

**Manual Trigger**:
```bash
# From Woodpecker UI
1. Click "Promote" on any completed build
2. Select "health-check" pipeline
3. Click "Promote"

# View results
1. Wait for build to complete
2. Check "Artifacts" for health reports
3. Review pod logs for errors
```

**Alert Conditions**:
- ❌ Pod in CrashLoopBackOff state
- ❌ Endpoint not responding
- ❌ Service not running
- ❌ Recent error events in cluster

---

### 5. Rollback Deployment (rollback.yml)

**Purpose**: Safe deployment rollback with pre-checks and verification

**Triggers**:
- Manual promotion only (safety feature)

**Execution Flow**:
```
pre_rollback_checks
  └─ verify_environment: Confirm rollback parameters
      ↓
install_dependencies
  └─ install_tools: Install kubectl, tools
      ↓
configure_kubernetes
  └─ setup_kubeconfig: Configure target cluster
      ↓
store_deployment_history
  └─ snapshot_current_state: Backup current deployments
      ↓
kubernetes_rollback
  ├─ perform_rollback: Execute kubectl rollout undo
  ├─ verify_rollback: Check rollback status
  └─ check_pod_health: Verify pod readiness
      ↓
docker_rollback_guide
  ├─ generate_docker_guide: Create manual instructions
  └─ store_docker_state: Backup docker-compose.yml
      ↓
post_rollback_verification
  └─ generate_rollback_report: Create summary
      ↓
publish
  └─ publish_artifacts & notify_slack
```

**Duration**: ~3-5 minutes

**Rollback Parameters**:
```yaml
Target:
  - kubernetes    # Automatic K8s rollback
  - docker        # Guided Docker rollback

Environment:
  - staging       # Staging cluster
  - production    # Production cluster

Deployment:
  - all           # Rollback all services
  - backend       # Rollback specific service
  - agents
  - llm-router

Revision:
  - 0             # Previous revision (default)
  - 1, 2, 3...    # Specific revision number
```

**Usage**:
```bash
# Kubernetes Rollback (Automatic)
1. Go to Woodpecker UI
2. Click "Promote"
3. Select "rollback" pipeline
4. Set:
   - Target: kubernetes
   - Environment: production
   - Deployment: all
   - Revision: 0 (previous)
5. Click "Promote"
6. Monitor rollout status

# Docker Rollback (Manual Guide)
1. Follow generated DOCKER_ROLLBACK_GUIDE.md
2. Execute git/docker commands as instructed
3. Verify services running with health checks
```

**Verification After Rollback**:
```bash
# Kubernetes
kubectl get pods -n vapora
kubectl logs -f deployment/vapora-backend -n vapora
kubectl rollout history deployment/vapora-backend -n vapora

# Docker
docker compose ps
docker compose logs -f
curl http://localhost:8001/health
```

**Rollback History**:
```bash
# View deployment revisions
kubectl rollout history deployment/vapora-backend -n vapora

# Output example:
REVISION  CHANGE-CAUSE
1         <initial>
2         Deployment rolled out
3         Deployment rolled out

# Find the working revision and use that number
```

---

## Integration Patterns

### Pattern 1: Automatic Validation on Every Push

```
Developer pushes feature branch
    ↓
Git webhook triggers Woodpecker
    ↓
[Validate & Build] runs automatically
    ↓
Artifacts generated in workspace
    ↓
Build completes (visible in Woodpecker UI)
```

### Pattern 2: Staging Deployment

```
1. Merge PR to develop branch
    ↓
2. [Validate & Build] runs automatically
    ↓
3. In Woodpecker UI → Promote to deploy-kubernetes
    - Mode: multiuser
    - Environment: staging
    - Dry-run: true
    ↓
4. Review dry-run output
    ↓
5. Promote again with dry-run: false
    ↓
6. [Health Check] runs (automatic in 15min)
    ↓
7. Staging live
```

### Pattern 3: Production Deployment

```
1. Code review approved
    ↓
2. Merge PR to main branch
    ↓
3. [Validate & Build] runs automatically
    ↓
4. In Woodpecker UI → Promote to deploy-kubernetes
    - Mode: enterprise
    - Environment: production
    - Dry-run: true
    ↓
5. **CAREFULLY** review all changes
    ↓
6. Promote again with dry-run: false
    ↓
7. [Health Check] monitoring starts (every 6 hours)
    ↓
8. Production deployment complete
```

### Pattern 4: Emergency Rollback

```
1. Production issue detected
    ↓
2. [Health Check] alerts in Slack (if configured)
    ↓
3. In Woodpecker UI → Promote to rollback
    - Target: kubernetes
    - Environment: production
    - Deployment: all
    - Revision: 0 (previous)
    ↓
4. Monitor rollout status
    ↓
5. Services restored
    ↓
6. Investigate root cause
    ↓
7. Plan corrected deployment
```

---

## Configuration & Secrets

### Secrets Required

```bash
# Kubernetes kubeconfigs (base64 encoded)
KUBE_CONFIG_STAGING         # For staging deployments

KUBE_CONFIG_PRODUCTION      # For production deployments

# Optional: Slack notifications
SLACK_WEBHOOK               # General notifications

SLACK_WEBHOOK_ALERTS        # Critical alerts only
```

### Adding Secrets in Woodpecker UI

1. Go to repository → Settings → Secrets
2. Click "Add secret"
3. Enter name: `KUBE_CONFIG_STAGING`
4. Paste base64-encoded kubeconfig value
5. Click "Add"
6. Repeat for other secrets

### Encoding Kubeconfig

```bash
# Get kubeconfig and encode
cat ~/.kube/config | base64

# Verify locally before adding
echo "base64_value_here" | base64 -d | kubectl cluster-info
```

### Environment Variables Available in Pipelines

```bash
# Woodpecker System Variables
CI_BUILD_LINK              # Link to build in UI
CI_COMMIT_SHA              # Full commit hash
CI_COMMIT_BRANCH           # Branch name
CI_COMMIT_AUTHOR           # Commit author

# Pipeline-Defined Variables
ARTIFACTS_DIR              # provisioning/artifacts
LOG_DIR                    # provisioning/logs
VAPORA_NAMESPACE           # vapora (K8s namespace)
```

---

## Monitoring & Troubleshooting

### Checking Build Status

**Via Woodpecker UI**:
1. Go to repository page
2. See "Active builds" and "Previous builds"
3. Click a build to see pipeline execution
4. Click a stage to see detailed logs

**Via Terminal**:
```bash
# If using woodpecker-cli
woodpecker-cli build list -r owner/repo

# View specific build
woodpecker-cli build view -r owner/repo -b <BUILD_NUMBER>

# Watch build live
woodpecker-cli build watch -r owner/repo -b <BUILD_NUMBER>
```

### Accessing Logs

**From Woodpecker UI**:
1. Click build → see stages
2. Click stage → see full logs
3. Scroll through logs or search

**From Workspace**:
```bash
# Logs persisted in workspace (visible as artifacts)
provisioning/logs/
├── validate-solo.log
├── build.log
├── docker/
├── kubernetes/
└── health-checks/
```

### Common Issues

#### Issue 1: "Pipeline not triggering"

**Symptoms**: Push doesn't start validate-and-build

**Diagnose**:
1. Check webhook in GitHub settings
2. Verify repository authorized in Woodpecker
3. Check file paths match `trigger.paths.include`
4. Review Woodpecker logs: `WOODPECKER_LOG_LEVEL=debug`

**Fix**:
```bash
# Manually re-authorize in Woodpecker UI
# Settings → Repositories → VAPORA → Activate

# Test webhook
curl -X POST https://your-woodpecker/hook \
  -H "X-GitHub-Event: push" \
  -d '{"ref":"refs/heads/main"}'
```

#### Issue 2: "Secret not found"

**Symptoms**: Stage fails with "secret not found"

**Diagnose**:
1. Go to repository → Settings → Secrets
2. Verify secret exists and name matches exactly
3. Check secret value is not empty

**Fix**:
```bash
# Re-add secret in UI
# Make sure spelling is exact (case-sensitive)

# Test secret locally
echo "secret_value" | base64 -d
```

#### Issue 3: "Kubeconfig decode error"

**Symptoms**: `base64: invalid input` during kubectl setup

**Diagnose**:
1. Check if base64 value is valid
2. Test decode locally

**Fix**:
```bash
# Test locally first
echo "kube_config_base64_value" | base64 -d | kubectl cluster-info

# If invalid, re-encode
cat ~/.kube/config | base64

# Add to Woodpecker secret
```

#### Issue 4: "Deployment timeout"

**Symptoms**: Waiting for pod readiness timeout

**Diagnose**:
1. Check pod logs: `kubectl logs -n vapora <pod>`
2. Check pod events: `kubectl describe pod -n vapora <pod>`
3. Check resource constraints

**Fix**:
```bash
# Increase timeout in deploy-kubernetes.yml
rollout_timeout: 600  # 10 minutes

# Check pod logs for errors
kubectl logs -n vapora deployment/vapora-backend --tail=50

# Check resource availability
kubectl top nodes
kubectl top pods -n vapora
```

#### Issue 5: "Docker connection failed"

**Symptoms**: `Cannot connect to Docker daemon` in deploy-docker

**Diagnose**:
1. Check Docker socket mounted
2. Verify Docker daemon running

**Fix**:
```bash
# Verify socket mounted in agent
docker exec woodpecker-agent ls -la /var/run/docker.sock

# Test Docker access
docker ps

# Restart Docker if needed
sudo systemctl restart docker
```

---

## Performance Tuning

### Parallel Validation

Validation stages run in parallel (solo, multiuser, enterprise):

```yaml
validate_solo:
  depends_on: [install_dependencies]
  # Runs while multiuser and enterprise also run

validate_multiuser:
  depends_on: [install_dependencies]
  # All three in parallel, not sequential
```

**Impact**: Reduces validation time by ~3x

### Caching

Tool installation caches automatically:
```bash
# First run: downloads and installs
- cargo install nu --locked

# Subsequent runs: uses cached Docker layer
```

### Workspace Cleanup

Between builds, workspace persists. To reclaim space:

1. Delete old workspace volumes
2. Configure retention policy in Woodpecker
3. Use `docker volume prune` carefully

---

## Security Considerations

### Secret Management

✅ **Best Practices**:
- Store all sensitive values as secrets
- Use environment-specific secrets (staging vs prod)
- Rotate secrets quarterly
- Never log secret values
- Use unique kubeconfigs per environment

❌ **Anti-Patterns**:
- Hardcoding secrets in YAML
- Using same secret for all environments
- Storing secrets in git history
- Logging secret values during debug

### RBAC & Access Control

```bash
# Kubernetes: Limit service account permissions
kubectl create serviceaccount vapora-deployer -n vapora

# Assign minimal necessary permissions
kubectl create role vapora-deployer \
  --verb=get,list,watch,create,update,patch \
  --resource=deployments,configmaps,pods

# Bind role to service account
kubectl create rolebinding vapora-deployer \
  --role=vapora-deployer \
  --serviceaccount=vapora:vapora-deployer
```

### Pipeline Execution

- Pipelines run in isolated Docker containers
- Limited to workspace directory
- No access to host filesystem (unless mounted)
- Network isolation between stages possible

---

## Advanced Topics

### Custom Pipeline Parameters

Use Woodpecker promotions to pass parameters:

```yaml
deploy-kubernetes.yml:
  environment:
    - Deploy_Environment    # Read from promotion UI
    - Rollback_Target
    - Rollback_Revision
```

### Multi-Agent Setup

Deploy multiple agents for distributed execution:

```bash
# Agent 1: Docker builds
- WOODPECKER_FILTER_LABELS=type:docker

# Agent 2: Kubernetes operations
- WOODPECKER_FILTER_LABELS=type:kubernetes

# In pipeline, require specific agent
labels:
  - type:kubernetes
```

### Conditional Execution

Skip stages based on conditions:

```yaml
deploy-production:
  when:
    evaluate: 'return build.Deploy_Environment == "production"'
    # Only runs if Deploy_Environment is production
```

---

## Comparison with GitHub Actions

### Feature Comparison

| Feature | Woodpecker | GitHub Actions |
|---------|-----------|---|
| **Hosting** | Self-hosted | GitHub-hosted |
| **Infrastructure Control** | ✓ Full control | Limited |
| **YAML Syntax** | Similar but different | GitHub-specific |
| **PR Integration** | Limited | Native |
| **Manual Dispatch** | Via promotions | workflow_dispatch |
| **Secrets Management** | Built-in UI | GitHub secrets |
| **Artifact Storage** | Workspace + volumes | Actions API |
| **Cost (self-hosted)** | Infrastructure only | GitHub minutes quota |
| **Dry-run Support** | ✓ First-class | Manual pattern |

### When to Choose Woodpecker

✓ Want to self-host CI/CD
✓ Need full infrastructure control
✓ Prefer to avoid vendor lock-in
✓ Have compliance/data residency requirements
✓ Want to run multiple repos unified CI/CD

### When to Choose GitHub Actions

✓ Want GitHub-hosted runners
✓ Prefer tight GitHub integration
✓ Want PR comments and status checks
✓ Don't want infrastructure overhead

---

## Support & Resources

- **Woodpecker Documentation**: https://woodpecker-ci.org/docs
- **VAPORA Repository**: https://github.com/your-org/vapora
- **GitHub Actions Guide**: `./../.github/GITHUB_ACTIONS_GUIDE.md`
- **Nushell Scripts**: `provisioning/scripts/*.nu`

---

## Quick Start Checklist

- [ ] Install Woodpecker server
- [ ] Configure GitHub OAuth app
- [ ] Authorize VAPORA repository
- [ ] Add `KUBE_CONFIG_STAGING` secret
- [ ] Add `KUBE_CONFIG_PRODUCTION` secret
- [ ] Test: Push to feature branch
- [ ] Verify: validate-and-build completes
- [ ] Test: Promote to deploy-docker
- [ ] Test: Promote to deploy-kubernetes (dry-run)
- [ ] Configure: Slack webhooks (optional)
- [ ] Document: Team runbooks

---

**Generated**: 2026-01-12
**Status**: Production-ready
**Pipelines**: 5 comprehensive workflows
**Documentation**: Complete reference guide
