Files
LMS/deploy/WOODPECKER.md
Vladislav Kopnin 685916c4bd ci: перевести merge gate на Gitea + Woodpecker
- .woodpecker/check.yaml, smoke.yaml, release.yaml
- local-backend агент: Java 21, Docker Compose v2, Python 3, Node/Playwright
- concurrency lms-ci, чтобы smoke/release не занимали порты одновременно
- deploy/WOODPECKER.md: server, OAuth Gitea, systemd-агент, security note
- удалён .gitlab-ci.yml
2026-10-29 12:01:44 +03:00

165 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CI на Gitea + Woodpecker
Репозиторий использует **Woodpecker CI 3.x**. Конфигурация лежит в
`.woodpecker/`:
| Workflow | Событие | Что делает |
|---|---|---|
| `check` | push, pull_request | `ci-preflight.sh`, `test ktlintCheck detekt evidenceCheck` |
| `smoke` | push, pull_request | после `check`: полный стек, health, вход админа, один курс |
| `release` | tag, manual | `npm ci`, preflight, полный `ldd-release.sh` (миграции, mutation, load, Chromium/Firefox/WebKit) |
Все три workflow используют `concurrency: {limit: 1, group: lms-ci}`: smoke и
release поднимают реальный стек на портах 8080–8090, параллельный запуск занял
бы порты.
## Почему local backend
`check` может работать в Docker-бэкенде, но `smoke`/`release` запускают
`docker compose` и Java-процессы на `localhost`, поэтому им нужен доступ к
Docker и портам хоста. Проще всего один агент с **local backend** на том же
сервере, где стоит Docker.
> **Безопасность.** Local backend выполняет пайплайн прямо на хосте без
> изоляции. Он допустим только для **приватного** репозитория с доверенными
> авторами. Не включайте публичные форки/PR от недоверенных пользователей на
> этом агенте: код пайплайна сможет прочитать окружение агента. Если появится
> публичный контур — вынесите `check` на отдельный Docker-backend агент, а
> smoke/release оставьте на изолированной машине.
## 1. Требования к серверу агента
- Java 21 в `PATH` (не Java 25 — см. README).
- Docker Engine + Compose v2, пользователь агента в группе `docker`.
- Python 3, bash, git, curl, `ss` (`iproute2`), Node.js 22 + npm.
- Системные библиотеки для Chromium/Firefox/WebKit. На Fedora проще один раз
выполнить `sudo npx playwright install-deps`; WebKit при их отсутствии
автоматически запускается в Docker-образе Playwright.
- Свободные порты 8080–8090 на время smoke/release.
- Достаточно места: Gradle-кэш, Docker-образы, Playwright-браузеры.
Проверка окружения:
```bash
./scripts/ci-preflight.sh # для smoke/check
./scripts/ci-preflight.sh --release
```
## 2. Woodpecker server
Удобно запустить server в Docker рядом с Gitea. Пример
`docker-compose.woodpecker.yml` (не коммитьте секреты):
```yaml
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:v3
restart: unless-stopped
ports:
- "127.0.0.1:8000:8000" # UI за nginx
- "127.0.0.1:9000:9000" # gRPC для агента
environment:
WOODPECKER_OPEN: "false"
WOODPECKER_HOST: ${WOODPECKER_HOST:?https://ci.example.ru}
WOODPECKER_GITEA: "true"
WOODPECKER_GITEA_URL: ${GITEA_URL:?https://git.example.ru}
WOODPECKER_GITEA_CLIENT: ${GITEA_CLIENT:?}
WOODPECKER_GITEA_SECRET: ${GITEA_SECRET:?}
WOODPECKER_AGENT_SECRET: ${WOODPECKER_AGENT_SECRET:?}
WOODPECKER_ADMIN: ${WOODPECKER_ADMIN:?admin}
volumes:
- woodpecker-data:/var/lib/woodpecker
volumes:
woodpecker-data:
```
1. В Gitea создайте OAuth2-приложение:
redirect URI `https://ci.example.ru/authorize`.
2. Заполните `GITEA_CLIENT`, `GITEA_SECRET`, `WOODPECKER_AGENT_SECRET`
(например, `openssl rand -hex 32`), `WOODPECKER_HOST`, `GITEA_URL`.
3. Если Gitea и Woodpecker на одном хосте, разрешите webhook на loopback в
`/etc/gitea/conf/app.ini`:
```ini
[webhook]
ALLOWED_HOST_LIST = external,loopback
```
Также проверьте, что Gitea отдаёт API-страницы не меньше 50 элементов
(значение по умолчанию подходит).
4. Поднимите server и зайдите в UI через Gitea-аккаунт.
5. Включите репозиторий LMS в Woodpecker (Settings → Repositories).
## 3. Агент на хосте
Server в контейнере, агент — **на хосте**, иначе local backend не увидит
Java/Docker/Node хоста.
```bash
sudo useradd --system --create-home --shell /bin/bash woodpecker
sudo usermod -aG docker woodpecker
sudo install -m 0755 woodpecker-agent /usr/local/bin/woodpecker-agent
```
`woodpecker-agent` скачивается из релизов Woodpecker (Linux amd64):
`https://github.com/woodpecker-ci/woodpecker/releases`.
`/etc/woodpecker-agent.env` (права `0600`, владелец `root`):
```dotenv
WOODPECKER_SERVER=localhost:9000
WOODPECKER_AGENT_SECRET=тот-же-секрет-что-у-server
WOODPECKER_BACKEND=local
WOODPECKER_MAX_WORKFLOWS=1
# Кэш Gradle и браузеров Playwright переживает запуски. Допустимо только для
# приватного репозитория с доверенными авторами (см. предупреждение выше).
WOODPECKER_BACKEND_LOCAL_ISOLATED_HOME=false
```
`/etc/systemd/system/woodpecker-agent.service`:
```ini
[Unit]
Description=Woodpecker CI agent (LMS)
After=network-online.target docker.service
Wants=network-online.target
[Service]
User=woodpecker
EnvironmentFile=/etc/woodpecker-agent.env
ExecStart=/usr/local/bin/woodpecker-agent
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now woodpecker-agent
journalctl -u woodpecker-agent -f
```
В UI агент появится через несколько секунд. Репозиторий должен быть помечен
как trusted, если вы захотите использовать volumes/privileged (текущему
конфигу они не нужны).
## 4. Первый прогон
1. Push в ветку или MR → pipeline `check` → `smoke`.
2. Убедиться, что зелёные оба workflow.
3. Проверить ручной запуск: UI → Run pipeline → event `manual` → workflow
`release`.
4. Для релиза: `git tag vX.Y.Z && git push origin vX.Y.Z` → workflow
`release`; полный отчёт печатается в лог, файлы остаются в
`build/evidence/` рабочей копии агента.
Если pipeline не появляется:
- проверьте, что репозиторий включён в Woodpecker;
- проверьте `WOODPECKER_SERVER` и общий `WOODPECKER_AGENT_SECRET`;
- проверьте, что агент видит Docker (`docker compose version` от пользователя
`woodpecker`) и Java 21;
- проверьте, что путь конфигурации в настройках проекта — `.woodpecker/`
(по умолчанию).