DEV Community

Alex Spinov
Alex Spinov

Posted on

Woodpecker CI Has a Free API: Lightweight Open-Source CI/CD for Git Repositories

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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="")
Enter fullscreen mode Exit fullscreen mode

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']}")
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Resources


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)