857 lines
20 KiB
Markdown
857 lines
20 KiB
Markdown
|
|
# Woodpecker CI Setup Guide for VAPORA
|
||
|
|
|
||
|
|
Comprehensive guide for setting up and using Woodpecker CI/CD pipelines for VAPORA provisioning.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Woodpecker is a self-hosted, container-based CI/CD platform compatible with Docker Compose and Kubernetes. This guide covers VAPORA's 5 production-ready Woodpecker pipelines as an alternative to GitHub Actions.
|
||
|
|
|
||
|
|
### Key Features
|
||
|
|
|
||
|
|
- **Self-Hosted**: Deploy on your own infrastructure (Docker, Kubernetes, VMs)
|
||
|
|
- **Container-Based**: Runs pipeline steps in isolated Docker containers
|
||
|
|
- **YAML Pipelines**: Simple YAML syntax for defining workflows
|
||
|
|
- **Flexible Triggers**: Git webhooks, cron schedules, manual promotions
|
||
|
|
- **Secret Management**: Built-in secret storage with environment variable injection
|
||
|
|
- **Artifact Handling**: Workspace persistence across stages
|
||
|
|
- **Multi-Pipeline Support**: Run multiple pipelines in parallel
|
||
|
|
|
||
|
|
### VAPORA Woodpecker Pipelines
|
||
|
|
|
||
|
|
| Pipeline | Purpose | Trigger | Duration |
|
||
|
|
|----------|---------|---------|----------|
|
||
|
|
| **validate-and-build.yml** | Validate configs, generate artifacts | Push, PR, manual | ~5 min |
|
||
|
|
| **deploy-docker.yml** | Deploy to Docker Compose | Manual, after validation | ~3 min |
|
||
|
|
| **deploy-kubernetes.yml** | Deploy to Kubernetes | Manual with dry-run | ~5-10 min |
|
||
|
|
| **health-check.yml** | Continuous monitoring | Cron (15min, 6hr), manual | ~5 min |
|
||
|
|
| **rollback.yml** | Safe rollback with verification | Manual only | ~3-5 min |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Prerequisites
|
||
|
|
|
||
|
|
### Infrastructure Requirements
|
||
|
|
|
||
|
|
**Minimum**:
|
||
|
|
- Linux server (Ubuntu 20.04+, Debian 11+, CentOS 8+)
|
||
|
|
- Docker 20.10+ installed and running
|
||
|
|
- 2 CPU cores, 4GB RAM, 20GB disk
|
||
|
|
|
||
|
|
**Recommended for Production**:
|
||
|
|
- Kubernetes cluster (v1.24+)
|
||
|
|
- 4+ CPU cores, 8GB+ RAM, 50GB+ disk
|
||
|
|
- Separate storage for workspace/artifacts
|
||
|
|
- SSL/TLS for Woodpecker UI
|
||
|
|
|
||
|
|
### Prerequisites to Install
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Ubuntu/Debian
|
||
|
|
sudo apt-get update
|
||
|
|
sudo apt-get install -y docker.io docker-compose git curl wget jq
|
||
|
|
|
||
|
|
# Start Docker daemon
|
||
|
|
sudo systemctl start docker
|
||
|
|
sudo systemctl enable docker
|
||
|
|
|
||
|
|
# Add current user to docker group (after logout/login required)
|
||
|
|
sudo usermod -aG docker $USER
|
||
|
|
```
|
||
|
|
|
||
|
|
### Git Repository
|
||
|
|
|
||
|
|
- GitLab, GitHub, Gitea, or Gogs repository
|
||
|
|
- Repository webhook URL accessible from Woodpecker server
|
||
|
|
- OAuth token for repository access (for most Git services)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
### Option 1: Docker Compose Installation (Recommended for Testing)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create Woodpecker directory
|
||
|
|
mkdir -p ~/woodpecker && cd ~/woodpecker
|
||
|
|
|
||
|
|
# Create docker-compose.yml
|
||
|
|
cat > docker-compose.yml << 'EOF'
|
||
|
|
version: '3.8'
|
||
|
|
|
||
|
|
services:
|
||
|
|
woodpecker-server:
|
||
|
|
image: woodpeckerci/woodpecker-server:latest
|
||
|
|
ports:
|
||
|
|
- "80:8000"
|
||
|
|
- "443:443"
|
||
|
|
environment:
|
||
|
|
- WOODPECKER_ADMIN_USER=admin
|
||
|
|
- WOODPECKER_ADMIN_PASSWORD=admin123
|
||
|
|
- WOODPECKER_GITHUB_SERVER=https://github.com
|
||
|
|
- WOODPECKER_GITHUB_CLIENT_ID=<YOUR_GITHUB_CLIENT_ID>
|
||
|
|
- WOODPECKER_GITHUB_CLIENT_SECRET=<YOUR_GITHUB_CLIENT_SECRET>
|
||
|
|
- WOODPECKER_RPC_SECRET=<GENERATE_WITH: head -c 32 /dev/urandom | base64>
|
||
|
|
- WOODPECKER_LOG_LEVEL=info
|
||
|
|
volumes:
|
||
|
|
- woodpecker-data:/var/lib/woodpecker
|
||
|
|
restart: always
|
||
|
|
|
||
|
|
woodpecker-agent:
|
||
|
|
image: woodpeckerci/woodpecker-agent:latest
|
||
|
|
environment:
|
||
|
|
- WOODPECKER_SERVER=http://woodpecker-server:9000
|
||
|
|
- WOODPECKER_AGENT_SECRET=<SAME_AS_RPC_SECRET>
|
||
|
|
- WOODPECKER_LOG_LEVEL=info
|
||
|
|
volumes:
|
||
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
||
|
|
restart: always
|
||
|
|
depends_on:
|
||
|
|
- woodpecker-server
|
||
|
|
|
||
|
|
volumes:
|
||
|
|
woodpecker-data:
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# Generate RPC secret
|
||
|
|
RPC_SECRET=$(head -c 32 /dev/urandom | base64)
|
||
|
|
echo "RPC_SECRET=$RPC_SECRET"
|
||
|
|
|
||
|
|
# Start services
|
||
|
|
docker-compose up -d
|
||
|
|
|
||
|
|
# Logs
|
||
|
|
docker-compose logs -f
|
||
|
|
```
|
||
|
|
|
||
|
|
### Option 2: Kubernetes Deployment
|
||
|
|
|
||
|
|
Create `woodpecker-deployment.yaml`:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
apiVersion: v1
|
||
|
|
kind: Namespace
|
||
|
|
metadata:
|
||
|
|
name: woodpecker
|
||
|
|
|
||
|
|
---
|
||
|
|
apiVersion: apps/v1
|
||
|
|
kind: Deployment
|
||
|
|
metadata:
|
||
|
|
name: woodpecker-server
|
||
|
|
namespace: woodpecker
|
||
|
|
spec:
|
||
|
|
replicas: 1
|
||
|
|
selector:
|
||
|
|
matchLabels:
|
||
|
|
app: woodpecker-server
|
||
|
|
template:
|
||
|
|
metadata:
|
||
|
|
labels:
|
||
|
|
app: woodpecker-server
|
||
|
|
spec:
|
||
|
|
containers:
|
||
|
|
- name: server
|
||
|
|
image: woodpeckerci/woodpecker-server:latest
|
||
|
|
ports:
|
||
|
|
- containerPort: 8000
|
||
|
|
- containerPort: 9000
|
||
|
|
env:
|
||
|
|
- name: WOODPECKER_ADMIN_USER
|
||
|
|
value: "admin"
|
||
|
|
- name: WOODPECKER_ADMIN_PASSWORD
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: woodpecker-secrets
|
||
|
|
key: admin-password
|
||
|
|
- name: WOODPECKER_RPC_SECRET
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: woodpecker-secrets
|
||
|
|
key: rpc-secret
|
||
|
|
- name: WOODPECKER_GITHUB_CLIENT_ID
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: woodpecker-secrets
|
||
|
|
key: github-client-id
|
||
|
|
- name: WOODPECKER_GITHUB_CLIENT_SECRET
|
||
|
|
valueFrom:
|
||
|
|
secretKeyRef:
|
||
|
|
name: woodpecker-secrets
|
||
|
|
key: github-client-secret
|
||
|
|
volumeMounts:
|
||
|
|
- name: woodpecker-data
|
||
|
|
mountPath: /var/lib/woodpecker
|
||
|
|
volumes:
|
||
|
|
- name: woodpecker-data
|
||
|
|
persistentVolumeClaim:
|
||
|
|
claimName: woodpecker-pvc
|
||
|
|
|
||
|
|
---
|
||
|
|
apiVersion: v1
|
||
|
|
kind: Service
|
||
|
|
metadata:
|
||
|
|
name: woodpecker-server
|
||
|
|
namespace: woodpecker
|
||
|
|
spec:
|
||
|
|
selector:
|
||
|
|
app: woodpecker-server
|
||
|
|
ports:
|
||
|
|
- name: ui
|
||
|
|
port: 8000
|
||
|
|
targetPort: 8000
|
||
|
|
- name: rpc
|
||
|
|
port: 9000
|
||
|
|
targetPort: 9000
|
||
|
|
type: LoadBalancer
|
||
|
|
```
|
||
|
|
|
||
|
|
Deploy:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create secrets
|
||
|
|
kubectl create secret generic woodpecker-secrets \
|
||
|
|
-n woodpecker \
|
||
|
|
--from-literal=admin-password=YOUR_PASSWORD \
|
||
|
|
--from-literal=rpc-secret=$(head -c 32 /dev/urandom | base64) \
|
||
|
|
--from-literal=github-client-id=YOUR_CLIENT_ID \
|
||
|
|
--from-literal=github-client-secret=YOUR_CLIENT_SECRET
|
||
|
|
|
||
|
|
# Apply deployment
|
||
|
|
kubectl apply -f woodpecker-deployment.yaml
|
||
|
|
|
||
|
|
# Check status
|
||
|
|
kubectl get pods -n woodpecker
|
||
|
|
kubectl port-forward -n woodpecker svc/woodpecker-server 8000:8000
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## GitHub Integration Setup
|
||
|
|
|
||
|
|
### Step 1: Create GitHub OAuth App
|
||
|
|
|
||
|
|
1. Go to GitHub → Settings → Developer settings → OAuth Apps
|
||
|
|
2. Click "New OAuth App"
|
||
|
|
3. Fill in:
|
||
|
|
- **Application name**: `VAPORA Woodpecker`
|
||
|
|
- **Homepage URL**: `https://woodpecker.your-domain.com`
|
||
|
|
- **Authorization callback URL**: `https://woodpecker.your-domain.com/authorize`
|
||
|
|
4. Copy `Client ID` and `Client Secret`
|
||
|
|
|
||
|
|
### Step 2: Configure Woodpecker
|
||
|
|
|
||
|
|
For Docker Compose:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Update docker-compose.yml environment variables
|
||
|
|
WOODPECKER_GITHUB_CLIENT_ID=your_client_id_here
|
||
|
|
WOODPECKER_GITHUB_CLIENT_SECRET=your_client_secret_here
|
||
|
|
WOODPECKER_RPC_SECRET=$(head -c 32 /dev/urandom | base64)
|
||
|
|
```
|
||
|
|
|
||
|
|
For Kubernetes:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
kubectl patch secret woodpecker-secrets -n woodpecker \
|
||
|
|
--type=merge \
|
||
|
|
-p '{"data":{"github-client-id":"'$(echo -n YOUR_CLIENT_ID | base64)'","github-client-secret":"'$(echo -n YOUR_CLIENT_SECRET | base64)'"}}'
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 3: Repository Setup
|
||
|
|
|
||
|
|
1. Access Woodpecker UI: `http://localhost:8000` (or your domain)
|
||
|
|
2. Login with admin credentials
|
||
|
|
3. Go to Admin → Repositories
|
||
|
|
4. Authorize your VAPORA repository
|
||
|
|
5. Enable webhooks by visiting `http://your-github.com/settings/hooks`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Secret Management
|
||
|
|
|
||
|
|
### Adding Secrets
|
||
|
|
|
||
|
|
#### Via Woodpecker UI
|
||
|
|
|
||
|
|
1. Go to repository → Settings → Secrets
|
||
|
|
2. Click "Add secret"
|
||
|
|
3. Name: `SECRET_NAME`
|
||
|
|
4. Value: Your secret value
|
||
|
|
5. Save
|
||
|
|
|
||
|
|
#### Via CLI
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Install woodpecker-cli
|
||
|
|
go install github.com/woodpeckerci/woodpecker/cmd/woodpecker-cli@latest
|
||
|
|
|
||
|
|
# Login
|
||
|
|
woodpecker-cli login -s http://woodpecker-server:8000 \
|
||
|
|
-u admin \
|
||
|
|
-p admin_password
|
||
|
|
|
||
|
|
# Add secret
|
||
|
|
woodpecker-cli secret add \
|
||
|
|
-r owner/repo \
|
||
|
|
-n KUBE_CONFIG_STAGING \
|
||
|
|
-v "$(cat ~/.kube/config | base64)"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Required VAPORA Secrets
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Kubernetes kubeconfigs (base64 encoded)
|
||
|
|
KUBE_CONFIG_STAGING # Staging cluster kubeconfig
|
||
|
|
KUBE_CONFIG_PRODUCTION # Production cluster kubeconfig
|
||
|
|
|
||
|
|
# Optional: Slack notifications
|
||
|
|
SLACK_WEBHOOK # General notifications webhook
|
||
|
|
SLACK_WEBHOOK_ALERTS # Critical alerts webhook
|
||
|
|
|
||
|
|
# Optional: Docker registry
|
||
|
|
DOCKER_USERNAME # Docker Hub username
|
||
|
|
DOCKER_PASSWORD # Docker Hub access token
|
||
|
|
```
|
||
|
|
|
||
|
|
### Encoding Kubeconfig
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Get kubeconfig and encode as base64
|
||
|
|
cat ~/.kube/config | base64 > kube_config_base64.txt
|
||
|
|
|
||
|
|
# Use the output in Woodpecker secret UI
|
||
|
|
cat kube_config_base64.txt
|
||
|
|
|
||
|
|
# Verify locally before adding to Woodpecker
|
||
|
|
echo "$(cat kube_config_base64.txt)" | base64 -d | kubectl cluster-info
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Pipeline Triggers
|
||
|
|
|
||
|
|
### Automatic Triggers
|
||
|
|
|
||
|
|
Pipelines trigger automatically when:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# On push to main/develop branches (if provisioning files change)
|
||
|
|
trigger:
|
||
|
|
event: [push]
|
||
|
|
branch: [main, develop]
|
||
|
|
paths:
|
||
|
|
include:
|
||
|
|
- provisioning/schemas/**
|
||
|
|
- provisioning/scripts/**
|
||
|
|
|
||
|
|
# On pull requests
|
||
|
|
trigger:
|
||
|
|
event: [pull_request]
|
||
|
|
branch: [main, develop]
|
||
|
|
```
|
||
|
|
|
||
|
|
### Manual Triggers (Promotions)
|
||
|
|
|
||
|
|
Manually trigger from UI:
|
||
|
|
|
||
|
|
1. Go to repository → Active builds
|
||
|
|
2. Find a completed build
|
||
|
|
3. Click "Promote"
|
||
|
|
4. Select pipeline: `deploy-docker`, `deploy-kubernetes`, etc.
|
||
|
|
5. Set deployment parameters:
|
||
|
|
- Mode: `solo`, `multiuser`, `enterprise`
|
||
|
|
- Environment: `staging`, `production`
|
||
|
|
- Dry-run: `true`/`false`
|
||
|
|
6. Click "Promote"
|
||
|
|
|
||
|
|
### Scheduled Triggers (Cron)
|
||
|
|
|
||
|
|
Health check pipeline runs on schedule:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
trigger:
|
||
|
|
cron:
|
||
|
|
- "*/15 * * * *" # Every 15 minutes
|
||
|
|
- "0 */6 * * *" # Every 6 hours
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Deployment Workflows
|
||
|
|
|
||
|
|
### Workflow 1: Local Development
|
||
|
|
|
||
|
|
```
|
||
|
|
Developer pushes to feature branch
|
||
|
|
↓
|
||
|
|
[Validate & Build] runs automatically
|
||
|
|
↓
|
||
|
|
Review artifacts in workspace
|
||
|
|
↓
|
||
|
|
[Deploy to Docker] manually for local testing
|
||
|
|
↓
|
||
|
|
Test with docker compose
|
||
|
|
↓
|
||
|
|
Create PR
|
||
|
|
```
|
||
|
|
|
||
|
|
### Workflow 2: Staging Deployment
|
||
|
|
|
||
|
|
```
|
||
|
|
Merge PR to develop
|
||
|
|
↓
|
||
|
|
[Validate & Build] runs automatically
|
||
|
|
↓
|
||
|
|
Download artifacts from workspace
|
||
|
|
↓
|
||
|
|
Manually run [Deploy to Kubernetes]
|
||
|
|
- Mode: multiuser
|
||
|
|
- Environment: staging
|
||
|
|
- Dry-run: true
|
||
|
|
↓
|
||
|
|
Review dry-run output
|
||
|
|
↓
|
||
|
|
Run again with dry-run: false
|
||
|
|
↓
|
||
|
|
[Health Check] verifies deployment
|
||
|
|
↓
|
||
|
|
Staging live
|
||
|
|
```
|
||
|
|
|
||
|
|
### Workflow 3: Production Deployment
|
||
|
|
|
||
|
|
```
|
||
|
|
Code review approved
|
||
|
|
↓
|
||
|
|
Merge to main
|
||
|
|
↓
|
||
|
|
[Validate & Build] runs automatically
|
||
|
|
↓
|
||
|
|
Manually run [Deploy to Kubernetes]
|
||
|
|
- Mode: enterprise
|
||
|
|
- Environment: production
|
||
|
|
- Dry-run: true
|
||
|
|
↓
|
||
|
|
Carefully review changes
|
||
|
|
↓
|
||
|
|
Run with dry-run: false
|
||
|
|
↓
|
||
|
|
[Health Check] monitoring (auto every 6 hours)
|
||
|
|
↓
|
||
|
|
Production deployment complete
|
||
|
|
```
|
||
|
|
|
||
|
|
### Workflow 4: Emergency Rollback
|
||
|
|
|
||
|
|
```
|
||
|
|
Production issue detected
|
||
|
|
↓
|
||
|
|
[Health Check] alerts in Slack
|
||
|
|
↓
|
||
|
|
Manually run [Rollback Deployment]
|
||
|
|
- Environment: production
|
||
|
|
↓
|
||
|
|
Services restored
|
||
|
|
↓
|
||
|
|
Investigate root cause
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Configuration Environment Variables
|
||
|
|
|
||
|
|
### For validate-and-build.yml
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ARTIFACTS_DIR=provisioning/artifacts # Output directory for configs
|
||
|
|
LOG_DIR=provisioning/logs # Output directory for logs
|
||
|
|
```
|
||
|
|
|
||
|
|
### For deploy-docker.yml
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ARTIFACTS_DIR=provisioning/artifacts
|
||
|
|
LOGS_DIR=provisioning/logs
|
||
|
|
```
|
||
|
|
|
||
|
|
### For deploy-kubernetes.yml
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ARTIFACTS_DIR=provisioning/artifacts
|
||
|
|
LOGS_DIR=provisioning/logs
|
||
|
|
VAPORA_NAMESPACE=vapora # Kubernetes namespace
|
||
|
|
```
|
||
|
|
|
||
|
|
### For health-check.yml
|
||
|
|
|
||
|
|
```bash
|
||
|
|
LOGS_DIR=provisioning/logs
|
||
|
|
VAPORA_NAMESPACE=vapora
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Monitoring & Logs
|
||
|
|
|
||
|
|
### Via Woodpecker UI
|
||
|
|
|
||
|
|
1. Go to repository → Active/Previous builds
|
||
|
|
2. Click a build to see full pipeline execution
|
||
|
|
3. Click a stage to see detailed logs
|
||
|
|
4. Download logs or artifacts
|
||
|
|
|
||
|
|
### Via CLI
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# List recent builds
|
||
|
|
woodpecker-cli build list -r owner/repo
|
||
|
|
|
||
|
|
# View build details
|
||
|
|
woodpecker-cli build view -r owner/repo -b <BUILD_NUMBER>
|
||
|
|
|
||
|
|
# Watch build in real-time
|
||
|
|
woodpecker-cli build watch -r owner/repo -b <BUILD_NUMBER>
|
||
|
|
|
||
|
|
# Get build logs
|
||
|
|
woodpecker-cli build logs -r owner/repo -b <BUILD_NUMBER>
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logs Location
|
||
|
|
|
||
|
|
All logs stored in workspace:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
provisioning/logs/
|
||
|
|
├── validate-solo.log
|
||
|
|
├── validate-multiuser.log
|
||
|
|
├── validate-enterprise.log
|
||
|
|
├── build.log
|
||
|
|
├── docker/
|
||
|
|
│ ├── backend.log
|
||
|
|
│ ├── frontend.log
|
||
|
|
│ └── all-services.log
|
||
|
|
├── kubernetes/
|
||
|
|
│ ├── backend.log
|
||
|
|
│ ├── agents.log
|
||
|
|
│ ├── llm-router.log
|
||
|
|
│ └── events.log
|
||
|
|
└── health-checks/
|
||
|
|
├── docker-endpoints.log
|
||
|
|
├── k8s-deployments.log
|
||
|
|
└── HEALTH_REPORT.md
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Slack Integration
|
||
|
|
|
||
|
|
### Setup Webhook
|
||
|
|
|
||
|
|
1. Go to Slack workspace → Apps → Custom Integrations
|
||
|
|
2. Create Incoming Webhook
|
||
|
|
3. Select channel: `#deployments`
|
||
|
|
4. Copy Webhook URL
|
||
|
|
5. Add to Woodpecker secret: `SLACK_WEBHOOK`
|
||
|
|
|
||
|
|
### Slack Messages
|
||
|
|
|
||
|
|
**Build Success**:
|
||
|
|
```
|
||
|
|
✅ VAPORA Artifact Build Complete
|
||
|
|
Artifacts ready for deployment
|
||
|
|
```
|
||
|
|
|
||
|
|
**Docker Deploy Success**:
|
||
|
|
```
|
||
|
|
✅ VAPORA Docker deployment successful!
|
||
|
|
Mode: multiuser | Environment: staging
|
||
|
|
```
|
||
|
|
|
||
|
|
**Kubernetes Deploy Success**:
|
||
|
|
```
|
||
|
|
✅ VAPORA Kubernetes deployment successful!
|
||
|
|
Mode: enterprise | Environment: production
|
||
|
|
```
|
||
|
|
|
||
|
|
**Health Check Alert**:
|
||
|
|
```
|
||
|
|
❌ VAPORA Health Check Failed
|
||
|
|
Target: kubernetes
|
||
|
|
```
|
||
|
|
|
||
|
|
**Rollback Alert**:
|
||
|
|
```
|
||
|
|
🔙 VAPORA Rollback Executed
|
||
|
|
Environment: production
|
||
|
|
Verify service health immediately
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Pipeline Not Triggering
|
||
|
|
|
||
|
|
**Problem**: Push doesn't trigger validate-and-build
|
||
|
|
|
||
|
|
**Solution**:
|
||
|
|
1. Check repository is authorized in Woodpecker
|
||
|
|
2. Verify webhook exists in GitHub settings
|
||
|
|
3. Check file paths in `trigger.paths.include` match your changes
|
||
|
|
4. Enable debug logging: `WOODPECKER_LOG_LEVEL=debug`
|
||
|
|
|
||
|
|
### Secret Not Found
|
||
|
|
|
||
|
|
**Problem**: `Secret not found` error in logs
|
||
|
|
|
||
|
|
**Solution**:
|
||
|
|
1. Verify secret exists in repository settings
|
||
|
|
2. Check exact spelling (case-sensitive)
|
||
|
|
3. Ensure secret value is not empty
|
||
|
|
4. Test secret value locally before adding
|
||
|
|
|
||
|
|
### Kubeconfig Decode Error
|
||
|
|
|
||
|
|
**Problem**: `base64: invalid input` during kubectl setup
|
||
|
|
|
||
|
|
**Solution**:
|
||
|
|
```bash
|
||
|
|
# Test locally first
|
||
|
|
echo "$(cat kube_config_base64.txt)" | base64 -d | kubectl cluster-info
|
||
|
|
|
||
|
|
# If it fails, re-encode
|
||
|
|
cat ~/.kube/config | base64 | pbcopy # macOS
|
||
|
|
|
||
|
|
# Update secret in Woodpecker UI
|
||
|
|
```
|
||
|
|
|
||
|
|
### Docker Connection Failed
|
||
|
|
|
||
|
|
**Problem**: `Cannot connect to Docker daemon` in deploy-docker stage
|
||
|
|
|
||
|
|
**Solution**:
|
||
|
|
1. Ensure Docker socket mounted in agent: `-v /var/run/docker.sock:/var/run/docker.sock`
|
||
|
|
2. Verify Docker daemon running: `docker ps`
|
||
|
|
3. Check volume permissions: `sudo chmod 666 /var/run/docker.sock`
|
||
|
|
|
||
|
|
### Deployment Hangs
|
||
|
|
|
||
|
|
**Problem**: Pipeline stage times out waiting for rollout
|
||
|
|
|
||
|
|
**Solution**:
|
||
|
|
1. Check pod logs: `kubectl logs -n vapora <pod>`
|
||
|
|
2. Describe pod: `kubectl describe pod -n vapora <pod>`
|
||
|
|
3. Increase timeout in pipeline stage
|
||
|
|
4. Check resource requests/limits
|
||
|
|
5. Verify cluster has sufficient resources
|
||
|
|
|
||
|
|
### Workspace Persistence Issues
|
||
|
|
|
||
|
|
**Problem**: Files from one stage not available in next stage
|
||
|
|
|
||
|
|
**Solution**:
|
||
|
|
1. Create file in correct location (workspace root or subdirectory)
|
||
|
|
2. Use absolute paths: `${LOGS_DIR}/output.log`
|
||
|
|
3. Check artifact uploads in "publish" stages
|
||
|
|
4. Verify docker volumes: `docker volume ls`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Advanced Configuration
|
||
|
|
|
||
|
|
### Multi-Agent Setup
|
||
|
|
|
||
|
|
For distributed build execution:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# Agent 1 (Docker builds)
|
||
|
|
environment:
|
||
|
|
- WOODPECKER_FILTER_LABELS=type:docker
|
||
|
|
|
||
|
|
# Agent 2 (Kubernetes operations)
|
||
|
|
environment:
|
||
|
|
- WOODPECKER_FILTER_LABELS=type:kubernetes
|
||
|
|
|
||
|
|
# Agent 3 (Health checks)
|
||
|
|
environment:
|
||
|
|
- WOODPECKER_FILTER_LABELS=type:monitoring
|
||
|
|
```
|
||
|
|
|
||
|
|
### Pipeline Concurrency Control
|
||
|
|
|
||
|
|
Limit concurrent executions:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
concurrency:
|
||
|
|
limit: 2 # Max 2 concurrent builds
|
||
|
|
timeout_minutes: 60 # Timeout after 60 minutes
|
||
|
|
```
|
||
|
|
|
||
|
|
### Conditional Stage Execution
|
||
|
|
|
||
|
|
Run stage only if conditions met:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
when:
|
||
|
|
evaluate: 'return build.Deploy_Environment == "production"'
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Comparison: Woodpecker vs GitHub Actions
|
||
|
|
|
||
|
|
| Feature | Woodpecker | GitHub Actions |
|
||
|
|
|---------|-----------|---|
|
||
|
|
| **Hosting** | Self-hosted | GitHub-hosted |
|
||
|
|
| **YAML Format** | Similar | Familiar |
|
||
|
|
| **Manual Dispatch** | Promotion UI | workflow_dispatch |
|
||
|
|
| **Scheduled Workflows** | Cron syntax | schedule syntax |
|
||
|
|
| **Artifact Storage** | Workspace persistence | upload-artifact action |
|
||
|
|
| **PR Comments** | Limited | ✓ Native |
|
||
|
|
| **Slack Integration** | Via webhooks | Actions |
|
||
|
|
| **Secret Management** | Built-in UI | Built-in |
|
||
|
|
| **Free for Public** | Self-hosted cost | ✓ Free |
|
||
|
|
| **Concurrency Control** | ✓ Advanced | ✓ Concurrency groups |
|
||
|
|
| **Deployment Safety** | Dry-run support | Deployment protection |
|
||
|
|
|
||
|
|
### When to Use Woodpecker
|
||
|
|
|
||
|
|
- ✓ You want full control over CI/CD infrastructure
|
||
|
|
- ✓ You need to run on-premise for compliance
|
||
|
|
- ✓ You prefer self-hosted solutions
|
||
|
|
- ✓ You have multiple repositories needing unified CI/CD
|
||
|
|
- ✓ You want to avoid vendor lock-in
|
||
|
|
|
||
|
|
### When to Use GitHub Actions
|
||
|
|
|
||
|
|
- ✓ You want GitHub-hosted runners (no infrastructure)
|
||
|
|
- ✓ You prefer tight GitHub integration
|
||
|
|
- ✓ You want PR comments and GitHub UI integration
|
||
|
|
- ✓ You're already using GitHub workflow syntax
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## First Deployment with Woodpecker
|
||
|
|
|
||
|
|
### Step 1: Enable Woodpecker for Repository
|
||
|
|
|
||
|
|
1. Access Woodpecker UI
|
||
|
|
2. Click "Administration" → "Repositories"
|
||
|
|
3. Find VAPORA repository
|
||
|
|
4. Click to enable
|
||
|
|
5. Grant webhook access
|
||
|
|
|
||
|
|
### Step 2: Create Test Branch
|
||
|
|
|
||
|
|
```bash
|
||
|
|
git checkout -b test/woodpecker-setup
|
||
|
|
echo "# Woodpecker Test" >> README.md
|
||
|
|
git add README.md
|
||
|
|
git commit -m "test: trigger Woodpecker"
|
||
|
|
git push origin test/woodpecker-setup
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 3: Monitor Pipeline
|
||
|
|
|
||
|
|
1. Go to Woodpecker → repository
|
||
|
|
2. See "Validate & Build" trigger automatically
|
||
|
|
3. Monitor pipeline execution
|
||
|
|
4. Check logs for each stage
|
||
|
|
|
||
|
|
### Step 4: Download Artifacts
|
||
|
|
|
||
|
|
1. In completed build, find "Files" section
|
||
|
|
2. Access workspace artifacts:
|
||
|
|
- `provisioning/artifacts/` - Generated configs
|
||
|
|
- `provisioning/logs/` - Pipeline logs
|
||
|
|
|
||
|
|
### Step 5: Test Docker Deployment
|
||
|
|
|
||
|
|
1. Download artifacts
|
||
|
|
2. Go to Woodpecker → repository
|
||
|
|
3. Click "Promote" on validated build
|
||
|
|
4. Select "deploy-docker"
|
||
|
|
5. Set:
|
||
|
|
- Mode: `multiuser`
|
||
|
|
- Environment: `staging`
|
||
|
|
- Dry-run: `true`
|
||
|
|
6. Monitor deployment
|
||
|
|
|
||
|
|
### Step 6: Create Pull Request
|
||
|
|
|
||
|
|
```bash
|
||
|
|
git push origin test/woodpecker-setup
|
||
|
|
# Create PR on GitHub
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Security Best Practices
|
||
|
|
|
||
|
|
✅ **Do**:
|
||
|
|
- Use environment-specific kubeconfigs
|
||
|
|
- Rotate secrets regularly
|
||
|
|
- Run health checks after deployments
|
||
|
|
- Enable dry-run by default
|
||
|
|
- Keep logs for audit trail
|
||
|
|
- Use RBAC in Kubernetes
|
||
|
|
- Monitor Slack alerts
|
||
|
|
- Test on staging first
|
||
|
|
|
||
|
|
❌ **Don't**:
|
||
|
|
- Commit secrets to repository
|
||
|
|
- Deploy directly to production without testing
|
||
|
|
- Disable dry-run validation
|
||
|
|
- Skip health checks
|
||
|
|
- Use same credentials for all environments
|
||
|
|
- Share Woodpecker admin credentials
|
||
|
|
- Keep old pipelines around
|
||
|
|
- Ignore Slack alerts
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Support & Resources
|
||
|
|
|
||
|
|
- **Woodpecker Docs**: https://woodpecker-ci.org/docs/intro
|
||
|
|
- **VAPORA Docs**: See `./../docs/` directory
|
||
|
|
- **GitHub Actions Guide**: `./../.github/GITHUB_ACTIONS_GUIDE.md`
|
||
|
|
- **Nushell Scripts**: `provisioning/scripts/*.nu`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Files Created
|
||
|
|
|
||
|
|
```
|
||
|
|
.woodpecker/
|
||
|
|
├── validate-and-build.yml (410 lines)
|
||
|
|
├── deploy-docker.yml (340 lines)
|
||
|
|
├── deploy-kubernetes.yml (380 lines)
|
||
|
|
├── health-check.yml (290 lines)
|
||
|
|
├── rollback.yml (330 lines)
|
||
|
|
└── SETUP.md (This file)
|
||
|
|
|
||
|
|
Total: 5 pipelines + comprehensive documentation
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Next Steps
|
||
|
|
|
||
|
|
1. ✅ Install and configure Woodpecker server
|
||
|
|
2. → Integrate with GitHub repository
|
||
|
|
3. → Add secrets for Kubernetes kubeconfigs
|
||
|
|
4. → Configure Slack webhooks (optional)
|
||
|
|
5. → Run first validation pipeline
|
||
|
|
6. → Test Docker deployment
|
||
|
|
7. → Test Kubernetes deployment
|
||
|
|
8. → Configure health checks
|
||
|
|
9. → Document team runbooks
|
||
|
|
10. → Deploy to production
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Generated**: 2026-01-12
|
||
|
|
**Status**: Production-ready
|
||
|
|
**Pipelines**: 5 (validate-and-build, deploy-docker, deploy-kubernetes, health-check, rollback)
|
||
|
|
**Documentation**: Complete
|