Woodpecker CI is a community fork of Drone that provides a simple, container-native CI/CD system. It integrates with Gitea, Forgejo, GitHub, GitLab, and Bitbucket with minimal configuration.
What Is Woodpecker CI?
Woodpecker is a lightweight CI/CD engine with a powerful pipeline syntax. Every step runs in a Docker container, making builds reproducible and isolated. It is designed for simplicity and ease of self-hosting.
Key Features:
- Container-native pipelines
- Multi-platform (Linux, ARM, Windows)
- Multi-backend (Docker, Local, Kubernetes)
- Git forge integration (Gitea, GitHub, GitLab)
- Matrix builds
- Secrets management
- Cron jobs
- REST API
Installation
# Docker Compose with Gitea
version: '3'
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:latest
ports:
- 8000:8000
environment:
- WOODPECKER_OPEN=true
- WOODPECKER_HOST=http://localhost:8000
- WOODPECKER_GITEA=true
- WOODPECKER_GITEA_URL=http://gitea:3000
- WOODPECKER_GITEA_CLIENT=your-client-id
- WOODPECKER_GITEA_SECRET=your-client-secret
volumes:
- woodpecker-data:/var/lib/woodpecker
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=your-agent-secret
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Pipeline Configuration
# .woodpecker.yml
steps:
- name: install
image: node:20-alpine
commands:
- npm ci
- name: lint
image: node:20-alpine
commands:
- npm run lint
- name: test
image: node:20-alpine
commands:
- npm test
- name: build
image: node:20-alpine
commands:
- npm run build
- name: docker
image: plugins/docker
settings:
repo: registry.example.com/myapp
tags: latest
when:
branch: main
event: push
Woodpecker API: Pipeline Management
import requests
WP = "http://localhost:8000/api"
HEADERS = {"Authorization": "Bearer your-token"}
# List repositories
repos = requests.get(f"{WP}/user/repos", headers=HEADERS).json()
for repo in repos:
print(f"Repo: {repo['full_name']}, Active: {repo['active']}")
# Get recent pipelines
pipelines = requests.get(f"{WP}/repos/1/pipelines", headers=HEADERS).json()
for p in pipelines:
print(f"Pipeline #{p['number']}: {p['status']} ({p['event']}) - {p['message'][:50]}")
# Trigger a pipeline
new_pipeline = requests.post(f"{WP}/repos/1/pipelines", headers=HEADERS, json={
"branch": "main"
}).json()
print(f"Triggered: #{new_pipeline['number']}")
# Get pipeline logs
logs = requests.get(f"{WP}/repos/1/pipelines/1/logs/1/1", headers=HEADERS).json()
for entry in logs:
print(entry.get("data", ""), end="")
Secrets Management
# Add a secret
requests.post(f"{WP}/repos/1/secrets", headers=HEADERS, json={
"name": "docker_password",
"value": "supersecret",
"events": ["push", "tag"]
})
# List secrets
secrets = requests.get(f"{WP}/repos/1/secrets", headers=HEADERS).json()
for s in secrets:
print(f"Secret: {s['name']}, Events: {s['events']}")
Matrix Builds
# .woodpecker.yml
matrix:
NODE_VERSION:
- 18
- 20
- 22
DATABASE:
- postgres
- mysql
steps:
- name: test
image: node:${NODE_VERSION}-alpine
commands:
- npm ci
- npm test
services:
- name: db
image: ${DATABASE}:latest
Resources
- Woodpecker Docs
- Woodpecker GitHub — 4K+ stars
- Plugin Index
Need to scrape web data for your CI pipelines? Check out my web scraping tools on Apify — production-ready actors for Reddit, Google Maps, and more. Questions? Email me at spinov001@gmail.com
Top comments (0)