MAATRIX / Блог / Gitea Actions не запускаются: причины и решение

Gitea Actions не запускаются: причины и решение

Gitea Actions не запускаются: причины и решение

MAATRIX

Пуш прошёл, а во вкладке Actions пусто — или запуск появился и намертво завис в жёлтом «Waiting». Жалоба «gitea actions не работают» покрывает четыре разные поломки: выключенный модуль, ненайденный workflow, раннер без нужной метки и джоб, упавший на первом шаге. Определим, на каком шаге всё встало, и пройдём слои по порядку.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

«Gitea Actions не работают» — это четыре разные поломки

Actions — конвейер из трёх частей: Gitea создаёт запуск, act_runner его забирает, контейнер джоба выполняет шаги. Симптом указывает на звено.

Что видно в интерфейсеГде ломается
Вкладки Actions в репозитории нет вообщеМодуль выключен глобально или в репозитории
Вкладка есть, после пуша список запусков пустWorkflow не найден или не совпал триггер
Запуск создан, но висит в WaitingНет раннера с нужной меткой либо занят capacity
Running висит часами, лог пустойРаннер отвалился, задача ждёт ZOMBIE_TASK_TIMEOUT
Первый шаг падает за 5–20 секундРаннер жив, ломается окружение джоба

Смотрим логи:

sudo journalctl -u gitea -n 200 --no-pager | grep -iE 'actions|workflow'
sudo journalctl -u act_runner -n 100 --no-pager

В норме раннер опрашивает Gitea раз в пару секунд. Тишина или повторяющееся Failed to fetch task — он до Gitea не достучался, и правки в workflow ничего не изменят. Третий источник — админка Site Administration → Actions → Runners: метки раннера и статус, Idle — ждёт работу, Offline — молчит дольше минуты.

Actions выключены: три выключателя, а не один

Уровень 1 — конфиг Gitea. В /etc/gitea/app.ini:

[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = github

С Gitea 1.21 ENABLED включён по умолчанию, но при переезде со старой версии в конфиг едет старый ENABLED = false. Проверка — sudo grep -A5 '^\[actions\]' /etc/gitea/app.ini, дальше обязателен sudo systemctl restart gitea: на лету конфиг не перечитывается. В Docker то же задаётся переменной GITEA__actions__ENABLED=true — правка app.ini внутри контейнера при пересоздании затрётся.

Уровень 2 — юнит репозитория. Settings → Advanced Settings → чекбокс Enable Repository Actions: у репозиториев, созданных до включения модуля, он снят.

Уровень 3 — глобальный запрет юнита. Если в секции [repository] осталось DISABLED_REPO_UNITS = repo.actions, чекбокса из второго уровня в интерфейсе не будет вовсе: настройки выглядят нормально, а включить нечего. Признак, что первый уровень в порядке, — раздел Actions в админке виден только при ENABLED = true.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Gitea

Workflow не найден: каталог, расширение и молчаливый YAML

Gitea ищет файлы в двух каталогах, но не в обоих сразу. Сначала .gitea/workflows/, и если этот каталог непуст, .github/workflows/ не читается вообще. Классика переезда с GitHub: положили .gitea/workflows/lint.yaml для пробы — и старые пайплайны перестали запускаться.

  • Расширение только .yml или .yamlci.yml.disabled игнорируется молча. И файл должен лежать в ветке, куда вы пушите: workflow из feature/ci на пуш в main не сработает.
  • YAML должен парситься. Ошибку Gitea показывает в самом запуске: workflow is not valid. .gitea/workflows/ci.yaml: yaml: line 14: did not find expected key. Табуляция вместо пробелов даёт found character that cannot start any token; ловите это до пуша через actionlint.

Файл на месте и валиден, а запуска нет — не совпал триггер:

  • Ветка и пути. on: push: branches: [main] не поймает ни пуш в master, ни пуш тега — для тегов нужен ключ tags. А фильтр paths: ['src/**'] смотрит на изменённые файлы коммита: правка README.md не запустит ничего.
  • Коммит с [skip ci]. Gitea сверяет сообщение коммита со списком [actions] SKIP_WORKFLOW_STRINGS, где по умолчанию [skip ci], [ci skip], [no ci], [skip actions], [actions skip]. Одна такая строка в сообщении мержа — и «Actions сломались».
  • Пуш, сделанный самим Actions. Коммит, отправленный встроенным GITEA_TOKEN, нового запуска не порождает: защита от рекурсии, настройкой не отключается. Нужна цепочка — заводите токен бота.
  • schedule и workflow_dispatch. Расписания читаются только из ветки по умолчанию. А кнопка Run workflow появилась в Gitea 1.24: на старых сборках workflow с единственным workflow_dispatch запустить нечем.

Раннер не зарегистрирован — или зарегистрирован не туда

Gitea сама ничего не выполняет: без act_runner запуски копятся в очереди вечно. Токен регистрации выпускается в Site Administration → Actions → Runners → Create new Runner, и здесь важна область токена: из админки он даёт раннера всему инстансу, а со страницы репозитория Settings → Actions → Runners — только ему. Зарегистрировали раннера на team/app, а ждёте сборок в team/api — задачи там будут висеть в Waiting вечно.

cd /var/lib/act_runner
sudo -u act_runner /usr/local/bin/act_runner register --no-interactive \
  --instance https://git.example.com \
  --token <REGISTRATION_TOKEN> \
  --labels 'ubuntu-latest:docker://gitea/runner-images:ubuntu-latest'

Команда создаёт файл .runner в текущем каталоге — с идентификатором и постоянным токеном. Отсюда две поломки: systemd стартует демон из другого WorkingDirectory и .runner не находит, либо файл принадлежит root, а сервис ходит от act_runner. Рабочий юнит:

[Service]
User=act_runner
WorkingDirectory=/var/lib/act_runner
ExecStart=/usr/local/bin/act_runner daemon --config /etc/act_runner/config.yaml

Типовые строки в логе раннера:

Строка в логеПричина
Failed to ping the Gitea instance server: connection refusedне тот адрес или закрытый порт
x509: certificate signed by unknown authorityсамоподписанный сертификат Gitea
unknown method ... / Unimplementedact_runner старше, чем Gitea
token is invalid при registerтокен использован или из другой области

Сертификат лечится CA в /usr/local/share/ca-certificates/gitea-ca.crt плюс sudo update-ca-certificates, а не флагом insecure: true: он снимает проверку целиком, а по этому каналу ездит постоянный токен раннера. И держите версии парой: обновили Gitea — обновите act_runner.

Задача висит в Waiting: метки, capacity и мёртвый раннер

Запуск создан, раннер Idle, задача не двигается. Gitea не отдаёт её «любому свободному» — она ищет раннера с меткой, дословно равной значению runs-on. Для планировщика ubuntu-latest и ubuntu-22.04 — разные строки, self-hosted и Self-Hosted тоже. Формат метки — <имя>[:<схема>[:<аргумент>]], схема определяет, где выполнится джоб:

МеткаЧто происходит
ubuntu-latest:docker://gitea/runner-images:ubuntu-latestджоб в контейнере из этого образа
ubuntu-latest:hostджоб прямо на хосте, без изоляции
ubuntu-latest (схема опущена)то же, что :host

Метка без схемы — частая причина «запустилось и сразу упало»: на хосте нет Node.js, а actions/checkout написан на JS, и шаг умирает с exec: "node": executable file not found in $PATH. Ставьте Node 20+ или возвращайте docker://.

Метки правятся в /etc/act_runner/config.yaml — перерегистрация не нужна, конфиг перекрывает записанное при регистрации:

runner:
  capacity: 2
  labels:
    - "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
container:
  network: gitea_default
  docker_host: "-"

После sudo systemctl restart act_runner метки обновятся в админке. Ещё два сценария:

  • capacity: 1. Раннер берёт одну задачу за раз: матрица из четырёх job'ов выглядит как «зависло», хотя всё работает. Ставьте capacity по числу vCPU, не выше.
  • Раннер умер посреди задачи. Статус останется Running до ZOMBIE_TASK_TIMEOUT — по умолчанию 10 минут. Параметр живёт в [actions] рядом с ENDLESS_TASK_TIMEOUT = 3h и ABANDONED_JOB_TIMEOUT = 24h.

Джоб стартовал и упал: checkout, ROOT_URL и docker.sock

Дошло до Running и умерло на первых секундах — проблема в окружении джоба.

Действие не скачивается. actions/checkout@v4 раннер тянет с github.com:

Error: unable to resolve action `actions/checkout@v4`, unable to find version `v4`

Источник задаёт [actions] DEFAULT_ACTIONS_URL: с версии 1.20 у него ровно два значения — github и self (ваш инстанс), произвольный URL не принимается. Обход без правки конфига — полный адрес в uses: https://gitea.com/actions/checkout@v4.

ROOT_URL с localhost. checkout клонирует по адресу, который Gitea сообщает раннеру, — по [server] ROOT_URL. Осталось http://localhost:3000/ — джоб пойдёт в localhost собственного контейнера:

fatal: unable to access 'http://localhost:3000/team/app.git/': Failed to connect to localhost port 3000: Connection refused

Лечение — внешний ROOT_URL = https://git.example.com/ и рестарт Gitea.

Контейнер джоба не видит Gitea. Когда Gitea и раннер живут в одном docker compose, джоб-контейнер поднимается в сети bridge и имя gitea не резолвит: could not resolve host: gitea. Пропишите общую сеть в container.network — её имя покажет docker network ls.

Docker-сокет. Раннеру с меткой docker:// нужен доступ к демону:

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock

Пользователя раннера — в группу, обязательно с перезапуском: sudo usermod -aG docker act_runner && sudo systemctl restart act_runner. Честно: группа docker равносильна root на хосте, поэтому раннер, собирающий чужой код из pull request'ов, лучше держать на отдельной машине.

Реверс-прокси. Раннер держит длинный опрос задач, и Nginx с дефолтными таймаутами рвёт соединение — в логе context deadline exceeded. Нужны proxy_read_timeout 600s;, proxy_buffering off; и client_max_body_size 512m;: без последнего артефакт падает с 413 Request Entity Too Large. А сам actions/upload-artifact@v4 требует Gitea 1.22+.

Какой сервер под Gitea с Actions брать в MAATRIX

Gitea в покое скромна: 150–250 МБ RSS. Всё меняется рядом с act_runner: демон ест 30–50 МБ, но каждый джоб поднимает контейнер, а образ gitea/runner-images:ubuntu-latest занимает около 3 ГБ распакованным — плюс кэш сборки и растущий /var/lib/docker.

Минимум: 2 vCPU, 4 ГБ RAM, 60 ГБ NVMe. Gitea, PostgreSQL и один раннер с capacity: 1. Честное ограничение: на 1 vCPU и 2 ГБ сама Gitea живёт прекрасно, но первая же сборка Node-проекта упирается в память — и вы получаете не ошибку CI, а Killed от OOM-киллера посреди npm ci.

Комфортный вариант: 4 vCPU, 8 ГБ RAM, 120–160 ГБ NVMe. Помещаются capacity: 2–4, параллельная матрица и еженедельный docker system prune -af --filter "until=168h" вместо аврала «no space left on device». Тяжёлые сборки лучше вынести на отдельную машину, чтобы Gitea не подтормаживала на git push. И следите за хранением: логи задач лежат в /var/lib/gitea/data/actions_log, артефакты — в actions_artifacts, а сроки по умолчанию щедрые — LOG_RETENTION_DAYS = 365.

Локация — UK, Лондон. Причина прикладная: раннеру нужен беспрепятственный доступ к github.com, ghcr.io и Docker Hub, иначе вы получите ровно тот unable to resolve action из предыдущего раздела. Из Лондона реестры отвечают штатно, RTT до Москвы — 45–60 мс, для git push незаметно, а до команды в ЕС пинг минимальный, плюс европейская юрисдикция. Если разработчики только в России и внешние реестры не нужны — берите RU-площадку с пингом 5–15 мс.

Gitea из каталога apps.maatrix.io ставится автоматически при заказе: вставлять команды не нужно, автоустановка работает на Ubuntu и Debian, доступы появляются в личном кабинете, в разделе «Доступ». Остаётся выпустить токен регистрации и поднять act_runner под свои метки — этот шаг осознанно ваш, метки зависят от пайплайнов. Выбрать конфигурацию можно сразу под задачу; оплата — картой российского банка, по СБП, криптой или токеном MAAT.

Если Gitea ещё не стоит — установка и настройка; прочие грабли — в частых ошибках Gitea, а память — в требованиях к серверу.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Gitea

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Вкладка Actions есть, раннер Idle, а задача висит в Waiting.

Смотрите метки: откройте раннера в Site Administration → Actions → Runners и сверьте их с runs-on — совпадение должно быть посимвольным. Второй кандидат — capacity: 1, когда предыдущая задача ещё выполняется.

Перенёс репозиторий с GitHub, workflow в .github/workflows не запускаются.

Проверьте, нет ли каталога .gitea/workflows: если он существует и непуст, Gitea читает только его. Либо перенесите все файлы в .gitea/workflows, либо удалите каталог .gitea.

Можно ли обойтись без доступа к github.com с сервера?

Да, но действия придётся зеркалировать: скопируйте actions/checkout и остальные нужные репозитории в организацию actions на своём Gitea и поставьте DEFAULT_ACTIONS_URL = self. Точечный вариант — полный адрес в uses.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.