CI/CD на Gitea Actions: рабочая альтернатива GitHub
Gitea Actions появились на стабильном уровне в Gitea 1.21 и за полтора года выросли до варианта, на котором я спокойно держу боевой CI. Расскажу, что это, чем отличается от GitHub Actions и где у меня живёт. Если у тебя есть причина не зависеть от GitHub (импортозамещение, своя инфраструктура, регуляторика) — Gitea это закрывает.
Что такое Gitea Actions
Это встроенная в Gitea система выполнения workflow-файлов в формате, совместимом с GitHub Actions. Те же .github/workflows/*.yml, тот же синтаксис uses, run, steps, matrix. Под капотом — act_runner, форк nektos/act, который умеет запускать GitHub-совместимые workflow в Docker.
Идея простая: ты переносишь репозиторий с GitHub в Gitea, кладёшь рядом .gitea/workflows/ или используешь .github/workflows/ — и CI начинает работать без переписывания.
Что работает
- Все базовые шаги: checkout, setup-node, run, upload-artifact, download-artifact. Это покрывает 90% всех CI.
- Matrix, jobs.needs, concurrency — поддерживается.
- Сервисы (например, Postgres рядом с тестами) через
services:. - Cache (через actions/cache) — поддерживается, есть встроенный сервер кэша.
- Custom actions из marketplace, если они написаны на JS или Docker. Через настройку
fetch_marketplaceможно дотянуться до GitHub-marketplace или поднять свой.
Что не работает или работает иначе
- Часть actions, которые жёстко привязаны к GitHub API (комментарии в PR, релизы). Большинство аналогов есть в виде Gitea-actions, но переписать пару шагов придётся.
- Отчёты о тестах в UI — не такие красивые, как в GitHub. Но артефакты загружаются и скачиваются.
- Reusable workflows и composite actions — поддерживаются, но в новых версиях; на 1.21 ловила баги, на 1.23+ нормально.
- OIDC (federated authentication) пока ограничен. Если тебе нужен short-lived deploy токен через OIDC — пока нет.
Установка act_runner
Минимальный сетап на одной VPS, где уже стоит Gitea. Создаём отдельного пользователя:
sudo useradd --system --create-home --shell /bin/bash actrunnerСкачиваем бинарь act_runner:
cd /opt
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.10/act_runner-0.2.10-linux-amd64
sudo mv act_runner-0.2.10-linux-amd64 /usr/local/bin/act_runner
sudo chmod +x /usr/local/bin/act_runnerРегистрируем runner. На странице админа Gitea (или owner-а репо) идёшь в Site Administration → Actions → Runners → Create new Runner, копируешь токен.
sudo -u actrunner act_runner register \
--no-interactive \
--instance https://git.example.ru \
--token <runner_token> \
--name builder-01 \
--labels ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-latestЛейбл ubuntu-latest:docker://... говорит runner-у: «когда workflow требует ubuntu-latest, используй вот этот образ». Я беру catthehacker/ubuntu — он близок к настоящему ubuntu-runner GitHub-а и содержит большинство нужных пакетов.
systemd-сервис runner-а
# /etc/systemd/system/act-runner.service
[Unit]
Description=Gitea Act Runner
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=actrunner
WorkingDirectory=/home/actrunner
ExecStart=/usr/local/bin/act_runner daemon --config /home/actrunner/config.yaml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetФайл config.yaml у меня — слегка отредактированный дефолт:
log:
level: info
runner:
capacity: 2
timeout: 3h
cache:
enabled: true
dir: /var/cache/actrunner
container:
network: host
privileged: false
options: '--cpus=2 --memory=4g'capacity: 2 — runner будет одновременно держать 2 job-а. Подбирай по CPU/RAM сервера. cache.enabled включает встроенный кэш-сервер для actions/cache. Без него кэш не работает или работает в обходной ветке.
Простой workflow
.gitea/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm test
- run: pnpm buildЭто работает один в один как на GitHub. Если у тебя workflow уже есть — переезд занимает минуты.
Сервисы для тестов
jobs:
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: test
POSTGRES_DB: test
ports: ['5432:5432']
options: --health-cmd 'pg_isready -U postgres' --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v4
- run: pnpm install --frozen-lockfile
- env:
DATABASE_URL: postgres://postgres:test@postgres:5432/test
run: pnpm test:integrationЗдесь обращаю внимание на options: --health-cmd. Без health-check job стартует тесты сразу, до того как Postgres готов. Иногда это работает, иногда — flaky. Health-check экономит часы отладки.
Деплой через workflow
Стандартный паттерн: build → push в registry → ssh-команда на VPS → systemctl restart. На Gitea Actions это собирается так:
jobs:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Build and push
run: |
echo '${{ secrets.REGISTRY_PASSWORD }}' | docker login registry.example.ru -u '${{ secrets.REGISTRY_USER }}' --password-stdin
docker build -t registry.example.ru/myapp/api:${{ github.sha }} .
docker push registry.example.ru/myapp/api:${{ github.sha }}
- name: Deploy
env:
SSH_KEY: ${{ secrets.DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan srv.example.ru >> ~/.ssh/known_hosts
ssh deploy@srv.example.ru "cd /opt/myapp \
&& export VERSION=${{ github.sha }} \
&& docker compose pull api \
&& docker compose up -d --no-deps api"Секреты в Gitea кладутся через UI: Repository Settings → Actions → Secrets. Там же — переменные окружения, которые менее чувствительны.
Сравнение с GitHub Actions
Скорость
На моей VPS act_runner крутится в среднем не быстрее, чем GitHub-runner. Если поставить runner на shared-VPS со слабым CPU, будет ощутимо медленнее. Если выделить отдельную машину с быстрым диском — сравнимо.
Стоимость
На приватных репозиториях GitHub даёт 2000 минут в месяц на free, дальше платно. Gitea Actions полностью бесплатны, ограничены только своим железом. На больших командах с активным CI это разница ощутимая.
Свобода и контроль
Самое главное преимущество. Никакие изменения в политике GitHub не трогают твой CI. Можно ставить runner-ы во внутренней сети, тестировать с доступом к корпоративным сервисам без VPN-туннелей. На частных проектах это бывает решающим фактором.
Экосистема
На GitHub marketplace больше готовых actions, и они часто свежее. На Gitea ты или используешь GitHub-actions через прокси, или пишешь свои. Большинство ходовых (checkout, setup-node, cache, upload-artifact) есть и работают.
Подводные камни
Docker внутри Docker
act_runner запускает workflow в контейнере. Если ты в workflow делаешь docker build, нужен docker-in-docker или docker.sock пробросить. Я делаю так:
# config.yaml act_runner-а
container:
valid_volumes:
- /var/run/docker.sock
options: '-v /var/run/docker.sock:/var/run/docker.sock'В workflow используешь docker как обычно. На security-критичных проектах это нежелательно: контейнер с доступом к docker.sock — фактически root на хосте. Альтернатива — отдельный buildkit или buildx-сервис.
Слишком тяжёлый образ ubuntu
act_runner по умолчанию подтягивает образ catthehacker/ubuntu в полной комплектации (~10 GB). Первый запуск будет долгим. На своём CI я часто использую act-22.04 или slim-вариант.
Кэш на больших артефактах
Встроенный кэш-сервер хранит файлы локально на диске. Если у тебя огромные node_modules или большие артефакты, диск runner-а может неожиданно кончиться. Поставь периодическую очистку через cron или ограничь размер кэша в config.
Версии Gitea
Gitea Actions активно развивается. Проверяй changelog при апгрейдах: на 1.22 кое-какие синтаксические особенности изменились. Если у тебя сложный workflow, после апгрейда прогоняй тестовый прогон.
Когда я беру Gitea Actions
- Внутренние корпоративные проекты, которым нельзя на внешний CI.
- Сервисы с регуляторными требованиями к локализации.
- Команды с большим объёмом CI-минут, которые упёрлись в платный план GitHub.
- Проекты, где разработка идёт в Gitea и переход на GitHub — лишний шаг.
Когда оставляю GitHub Actions
- OSS-проекты с публичной видимостью.
- Команды, которым важна экосистема готовых action-ов.
- Стартапы, у которых нет ресурса поддерживать свой CI-инфраструктуру.
Для меня Gitea Actions сейчас — это альтернатива, к которой я прихожу с конкретной причиной, а не дефолт. Но как опция — рабочая, проверенная и бесплатная. На двух своих сервисах её гоняю год без сюрпризов.