Introduction
Hi there, I’m Yura Zatsepin. This is a tutorial for Woodpecker—a CI/CD system.
This tutorial exists because I’m trying to find a good CI for “non K8S world”, fully locally and which can give me a fresh perspective. This is all about Woodpecker CI, which was formerly a fork of Drone CI. Drone CI I used long time ago on couple projects. It was a real lightweight solution after Jenkins and TeamCity where I had my experience before.
I know Woodpecker CI doesn’t yet offer many battle-tested features from modern commercial CI, but it’s an open source and very niche product. It’s based on ideas already applied in Gitlab CI and GitHub Actions. But the core advantage from Drone is still here: you can start working with CI locally. You don’t need external solutions for this like Gitlab local runner or GitHub Actions - act CLI. Here you can install Woodpecker-cli and write some YAML files and you’re ready. Our workflows can be run locally. If we see a broken pipeline on Woodpecker server, we can download metadata from a failed build and re-run it locally. In general, you can start writing CI workflows when starting a new project from day 0 without any server at all. Yes, GitHub Actions is available. And it’s actually great. But when you need a self-hosted, fully open CI solution for modern world dev experience this is what you probably need Woodpecker CI.
I am writing tutorials here after some personal research about this tool. Actually, I already have production pipelines on this CI and I’ve encountered some problems with hosting it and deploying certain things. The docs are great, but they don’t address all the challenges I faced. I find this book a good place to save my thoughts for the future and anyone who wants to try Woodpecker.
In the current version, this book is written in Russian language.
How to read this tutorial
Пока каждый раздел — это отдельная статья о Woodpecker CI. Можно читать любую в зависимости, что интереснее, пример с rust web app или с мобильным приложением.
Для удобной работы, советую использовать mise. В корне примеров есть файл mise.toml. В нем описано, что нам потребуется woodpecker-cli
По умолчанию нам потребуется woodpecker-cli.
Чтобы установить глобально:
mise use --global aqua:woodpecker-ci/woodpecker/woodpecker-cli
Либо в файле mise.toml должна быть строчка с установкой утилиты. В таком случае при переходе в папку с таким toml у вас будет доступна утилита woodpecker-cli.
[tools]
"aqua:woodpecker-ci/woodpecker/woodpecker-cli" = "latest"
Hello World Woodpecker
Создадим папку нашего проекта, папку для всех сценариев CI/CD и первый сценарий.
mkdir -p woodpecker-test/.woodpecker && touch woodpecker-test/.woodpecker/hello-world-flow.yml
Заполним файл сценария.
when:
- event: manual
steps:
- name: build
image: bash
commands:
- echo "This is the build step"
- sleep 5
И мы уже готовы запустить наш сценарий для будущего CI/CD с помощью CLI woodpecker-cli.
woodpecker-cli exec
# hello-world-flow.yml
[build:L0:0s] + echo "This is the build step"
[build:L1:0s] This is the build step
[build:L2:0s] + sleep 5
Да, да! Таким образом существует в мире возможность начать проект не с инициализации через cargo new или npm create. А с того чтобы описать что вы решили собрать и протестировать и запустить.
Поговорим о yaml нашего workflow для woodpecker. Мы видим язык для определения шагов выполнения. Каждый шаг требует условия для запуска. И обычно условием будет что-то вроде
when:
- event: push
branch: master-of-the-zoo
when:
- event: [push, pull_request]
Мы не можем не указать никакого условия, шаг не будет исполнен. А если мы укажем pull-request или push, woodpecker-cli локально тоже не станет запускать шаги. Есть несколько способов для запуска сразу, это использование условия
- evaluate: "true"
Либо CI_PIPELINE_EVENT=manual, что дает больше информации о том что происходит. Можно передать любую другую env при вызове и сделать проверку. Еще вариант указать event как manual. Собственно то, что и надо использовать.
when:
- event: [push, pull_request]
branch: master
- event: manual
Если сборка завалилась уже на сервере woodpecker, то можно через UI или CLI скачать metadata файл, который, переданный через аргумент при запуске сценария, будет содержать информацию о том, что произошло событие пуша нового коммита, и сценарий также будет выполнен.

woodpecker-cli exec --metadata-file Partysun-napatam-pipeline-2-metadata.json
Вернемся к нашему yaml для сценария, там есть еще одна магия, которую надо понять. Local Backend
Агент Woodpecker может запустить код в контейнерах Docker, k8s и запускать сценарии в среде bash/fish локально на системе, где установлен агент Woodpecker. Локальный запуск опасен, и стоит понимать возможные риски для системы.
Когда мы используем локальный backend для запуска сценария, параметр image используется для выбора того, какой shell (Bash или Fish) будет использован для запуска команд.
Full Example 1: Rust web app
Итак разберемся как сделать сценарии woodpecker CI для простого веб приложения на Rust. Само веб приложение можно скачать с github. Это фактически hello world на axum, с двумя endpoints / и /health.
Написание веб приложения на Rust не является предметом нашего разговора.
Для удобной работы, советую использовать mise. В корне проекта есть файл mise.toml. В нем описано, что нам потребуется woodpecker-cli и hurl. Hurl это утилита для запуска http запросов по файлу сценария. Мы будем его использовать для имитации интеграционных тестов. С помощью mise нужные утилиты будут установлены автоматически и будут доступны только когда вы находитесь в папке проекта.
curl https://mise.run | sh
mise trust mise.toml
mise install
Мы будем работать с docker и docker должен быть установлен в системе. И это проект на Rust, так что установить Rust тоже необходимо.
Проверим, что проект запускается и тесты в main модуле на Rust работают.
cargo check && cargo test
Также проверим, можем ли мы поднять docker с помощью compose и запустим hurl тесты:
docker compose up -d && mise test-hurl
Если в обоих случаях все работает и веб сервер поднимается, то перейдем к пониманию сценариев или workflow для Woodpecker CI. Для того чтобы запустить сценарии Woodpecker, вам не надо даже настраивать сервер CI, можно начать без всего, но woodpecker-cli потребуется.
Структура наших сценариев на Woodpecker CI:
❯ tree .woodpecker
/.woodpecker
├── deploy.yaml
├── docker.yaml
└── test.yaml
test.yaml
matrix:
RUST: [stable, nightly]
when:
- event: [push, pull_request]
branch: master
- event: manual
labels:
backend: docker
platform: linux/amd64
steps:
- name: build
image: rust
environment:
CARGO_TERM_COLOR: always
commands:
- rustup default $RUST
- echo "Building Cargo Demo Project"
- cargo build
- name: test
image: rust
environment:
CARGO_TERM_COLOR: always
commands:
- rustup default $RUST
- cargo test
Запустить этот сценарий можно абсолютно без проблем локально.
woodpecker-cli exec .woodpecker/test.yaml --repo-path .
Нужно обязательно указать “–repo-path .” если вы запускаете команду в корне проекта. Иначе CLI попробует запустить сценарий из папки .woodpecker Или воспользоваться тасками прописанными в mise.toml.
mise test
Чтобы посмотреть все возможные таски:
mise tasks
Name Description
build Build Docker image, run integration tests, and push to registry using Woodpecker CI
lint Format and lint Rust code
test Run tests using Woodpecker CI
test-hurl Run integration tests using Hurl against local server (http://localhost:4000)
Интересным в этом простом pipeline отмечу matrix
Matrix позволяет запустить билды для разных версий images, зависимостей, компиляторов.
Условия When
Для того чтобы сценарий можно было запустить локально, мы должны указать event: manual. Мы можем гибко организовать условия запуска для определенных веток репозитория и событиях на этих ветках, можно также проверять переменные окружения на определенные значения.
Теперь о Labels
Это тоже условия для запуска билда, но они выполняются не при локальном запуске, а на сервере woodpecker CI. Их цель определить на какой ноде агента будет выполнена сборка. Можно к примеру указать:
labels:
node: production
И если в конфигурации ноды агента есть
WOODPECKER_AGENT_LABELS: "node=production"
То сценарий запустится только на этой одной ноде.