Содержание
Проблематика
У нас есть какой-то проект, возможно даже с тестами, линтерами, возможно над ним работает 2, а то даже и 3(!) человека. И вся эта радость у нас лежит на Github.
В какой-то момент мы хотим, чтобы какие-то проверки производились автоматически, какие-то артефакты сами магически собирались и ложились куда нужно. Да и вообще приятно смотреть на зелененькие галочки в интерфейсах…

Но процесс этот небыстрый: надо проверить, что все команды ходят в нужные папки, все флаги проставлены, все зависимости нужных версий…
Конечно, самый просто вариант - это создать новую ветку, в которую мы будем пушить изменения, в надежде, что вот-вот, сейчас то оно заработает. Это все прекрасно, но можно же и не ждать, а просто запустить нужную утилитку.
Act

По сути своей - это лишь обертка над существующими образами github-action-ов.
Единственный пререквизит - запущенный docker (или podman).
По сути своей все просто - ставите Вашими любимым пакетным менеджером
brew install act
sudo pacman -S act
или просто качаем готовый бинарь
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
Первый запуск
При первом запуске act
Вам будет предложено на базе какого образа будет производиться запуск всех workflow. Пока рекомендую выбирать Medium
, в дальнейшем все можно будет поменять.

Это может занять длительное время в зависимости от размера образа и Вашего интернета.
Как только образ будет скачан, act
произведет прогон Action-а для события pull_request
(в данном примере).
Работа
Рассмотрим на примере простого приложения nodeJs, в котором просто прогоняются линтеры на Pull Request-ах:
name: Lintingon: push: branches: - main pull_request: branches: - main
jobs: lint: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4 with: node-version: "lts/*" - name: Install dependencies run: npm install - name: Run Astro checks run: npm run check - name: Run ESLint run: npm run lint
Флоу стандартный: создаем новую ветку, в .github/workflows/rust.yml
пишем наши правки. Далее начинается самое интересное.
Act
локально запускает те workflow, для которых при запуске ему были переданы аргументы. Так в нашем случае будем проверять создание Pull Request-а, а значит запустим
act pull_request
И получим

Action прошел все хорошо, Вы великолепны! Так можно локально прогонять практически любые Action-ы перед их деплоем в сам Github.
Кастомные образа
Теперь рассмотрим немного неожиданный, но интересный пример. В репе с Rust кодом нам предлагют простенькие Action-ы:

Самый банальный workflow - проверяет, что приложение собирается и тесты проходят. Тригерится неа все пуши в main
и на Pull Request-ы в него же.
name: Rust
on: push: branches: - main pull_request: branches: - main
env: CARGO_TERM_COLOR: always
jobs: build:
runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4 - name: Build run: cargo build --verbose - name: Run tests run: cargo test --verbose
Попробуем запустить его как и раньше, но получим ошибку:
[Rust/build] ⭐ Run Main Build[Rust/build] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/1] user= workdir=| /var/run/act/workflow/1: line 2: cargo: command not found[Rust/build] ❌ Failure - Main Build[Rust/build] exitcode '127': command not found, please refer to https://github.com/nektos/act/issues/107 for more information[Rust/build] ⭐ Run Complete job[Rust/build] ✅ Success - Complete job[Rust/build] 🏁 Job failedError: Job 'build' failed
Это связано с тем, что в самих образах, на которых Github гоняет Action-ы куда больше установлено, и весят они соотвественно. Можно попробовать выбрать более жирный образ, но с ним тоже могут быть проблемы (как пишут в issue)
Выход есть - можно при запуске указать образ, который будет использоваться вместо того, который указывается в конфиге.
Сам необходимый образ был нарыт в DockrHub-е автора
Так команда становится уже
act -P ubuntu-latest=catthehacker/ubuntu:rust-latest pull_request
И в итоге видим заветное:
[Rust/build] ✅ Success - Main Run tests[Rust/build] ⭐ Run Complete job[Rust/build] Cleaning up container for job build[Rust/build] ✅ Success - Complete job[Rust/build] 🏁 Job succeeded
Аналогичным образом можно подговить образ локально и указать его.
За основу я решил взять базовый образ Ubuntu:
FROM catthehacker/ubuntu:act-latest
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
Здесь мы просто ставим последнюю версию утилит для Rust-а и билдим образ:
docker build -t test .
Готово, можем убедиться, что в образе есть все необходимое:

Теперь для того, чтобы act
не скачивал образа, а брал только локальные, добавим параметр --action-offline-mode
и наш локальный образ (в данном случае test
):
act --action-offline-mode -P ubuntu-latest=test pull_request
После этого Action-ы тоже работают:
[Rust/build] ✅ Success - Main Run tests[Rust/build] ⭐ Run Complete job[Rust/build] Cleaning up container for job build[Rust/build] ✅ Success - Complete job[Rust/build] 🏁 Job succeeded
Таким образом можно накручивать любой необходимый функционал, которого нет в образах автора.
Заключение
Автор позиционирует свое творение как аналог Makefile-а
, чтобы единым источником правды была папка .workflows
с более воспроизводимым окружением. Тут уже больше на цвет и вкус.
Больше примеров использования и параметров можно найти в документации.
Еще можете заглянуть и попробовать расширение для Vs Code.
По мере возможности буду добавлять что-то новое.
Всего доброго!