Вы будете тратить меньше времени на тестирование приложения, сборку, проверку качества кода, актуальность задач, если автоматизируете рутинные процессы. GitHub Actions — это сервис, который позволит описать сценарии любой сложности и условия для его запуска.
Сервис бесплатен для проектов с открытым исходным кодом. Для приватных проектов количество бесплатных минут работы сценариев ограничено. Ознакомиться с ценами и лимитами можно на странице сервиса.
Что такое GitHub Actions
Actions — это готовые наборы команд, которыми описывается порядок действий при срабатывании определенного триггера: коммита в ветку, созданной задачи, публикации нового релиза и так далее. Также сценарии можно запускать по времени, как это делается с помощью утилиты cron.
Actions могут взаимодействовать с кодом приложения и историей его изменений, с рабочим окружением репозитория(задачи, проекты, документация, релизы), со сторонними сервисами для развертывания приложения или отправки каких-то запросов с уведомлениями. Это мощный инструмент, который будет вместе с вами работать над проектом.
Как описать сценарий
Файлы сценариев — workflow — хранятся в директории .github/workflow
в репозитории вашего проекта. Это конфигурационные файлы формата YAML.
У каждого сценария есть имя, условия для выполнения и задачи. В каждой задаче описывается набор отдельных шагов.
name: ...
on: ...
jobs: ...
Каждая задача может иметь имя, указание операционной системы, зависимость от других задач и список шагов.
Каждый шаг может быть как набором bash-команд, так и готовым action.
Для примера рассмотрим сценарий, который собирает фронтенд для сайта codex.so в режиме production и добавляет сборку в пулл-реквест.
# Имя сценария
name: Build frontend
# Условия для выполнения: любые действия с пулл-реквестом
on: [pull_request]
# Список задач
jobs:
build:
# Название задачи
name: Build frontend
# Выполнить на вирутальной машине с Ubuntu
runs-on: ubuntu-latest
# Список шагов
steps:
# Использовать код проекта из определенного коммита
# По умолчанию используется ветка, изменения которой вызвали выполнение сценария
- uses: actions/checkout@v2
# Настройка Node.js 15 для работы на виртуальной машине
- name: Use Node.js 15
uses: actions/setup-node@v1
with:
node-version: 15
# Установка node-пакетов проекта и сборка фронтенда
# Выполнятся описанные bash-команды
- name: Go to app dir, Install Node.js packages, Build static files
run: cd www && yarn && yarn build
# Попытка закоммитить обновления сборки фронтенда в ветку от имени бота github-actions (указываем его имя и почту с идентификатором официального бота от гитхаба)
- uses: EndBug/add-and-commit@v7
with:
author_name: github-actions
author_email: 41898282+github-actions[bot]@users.noreply.github.com
message: 'Build frontend'
Ознакомьтесь с документацией от GitHub по работе со сценариями для того, чтобы узнать подробнее о возможностях workflow файлов.
Локальное тестирование правильности работы сценариев не предусмотрено.
Где искать экшены
Попробуйте найти нужное действие в каталогах, перед тем, как создавать и публиковать свое собственное.
В GitHub Marketplace есть отдельный раздел, посвященный Actions. Некоторые из них созданы известными компаниями, но бóльшая часть создается и публикуется самостоятельными разработчиками.
Также стоит уделить внимание и неофициальному каталогу интересных действий — Awesome Actions.
Здесь можно найти много интересных решений и вдохновиться — возможно, у вас есть похожая задача, а вы и не думали, что её можно тоже автоматизировать.
Как написать свой Action
Допустим, вы не нашли готовое решение для нужного шага, а описать весь набор команд в виде bash-скрипта неудобно или не представляется возможным. В таком случае Вы можете воспользоваться инструкцией от GitHub. Код action может быть написан на JavaScript, собран в виде готового Docker-образа с любым содержимым. Также набор шагов может быть описан в файле в виде списка консольных команд.
Однако надо помнить, что actions на основе докер-контейнеров могут быть запущены только на виртуальной машине с Linux.
Для нового действия вам потребуется создать отдельный репозиторий с описанием-настройками, исходным кодом и сборкой.
В качестве примера разберем codex-team/action-nodejs-package-info — действие, которое получает информацию о названии приложения и его версии из package.json
файла.
Настройки хранятся в файле action.yml
в корне проекта.
# Мета-информация об action используется для формирования карточки в маркетплейсе
# Имя действия
name: 'Get package info'
# Описание
description: 'Action for getting information from package.json file'
# Иконка и ее цвет фона
branding:
icon: 'box'
color: 'red'
# Параметры, которое могут или должны быть переданы на вход
inputs:
path:
description: 'Path to package.json file'
required: false
default: ./
# Параметры, которые будут доступны по результатам выполнения шага
outputs:
name:
description: 'Package name'
version:
description: 'Package version'
npmjs-link:
description: 'Link to npmjs.com package page'
# Условия запуска кода
runs:
# Описание среды и ее версии
using: 'node12'
# Пусть к собранному скрипту
main: 'dist/index.js'
Далее, для работы кода вам потребуется установить пару практически обязательных node-зависимостей:
- @actions/core — базовые функции для работы с настройкой переменных, логированием и экспортом значений;
- @vercel/ncc — утилита для сборки кода проекта в единственный js-файл со всеми зависимостями.
Добавим скрипт build
для сборки исходного кода index.js
со всеми зависимостями (например, @actions/core
) в единый файл dist/index.js
.
{
"name": "action-nodejs-package-info",
"scripts": {
"build": "ncc build index.js --minify"
},
"devDependencies": {
"@actions/core": "^1.2.6",
"@vercel/ncc": "^0.25.1"
}
}
И сам исходный файл с простой логикой. Получаем путь к package.json
файлу, считываем его и экспортируем некоторые параметры.
import fs from 'fs';
import { join } from 'path';
const core = require('@actions/core');
/**
* Read package.json file
* @param {string} path
* @returns {object}
*/
const readPackageJson = function (path) {
const packageJson = fs.readFileSync(join(path, 'package.json')).toString();
return JSON.parse(packageJson);
};
try {
/**
* Path to directory with package.json file
* @type {string}
*/
const path = core.getInput('path');
/**
* Get data from package.json file
* @type {object}
*/
const packageInfo = readPackageJson(path);
core.setOutput("name", packageInfo.name);
core.setOutput("version", packageInfo.version);
core.setOutput("npmjs-link", `https://www.npmjs.com/package/${packageInfo.name}`);
} catch (error) {
core.setFailed(error.message);
}
Команда core.getInput()
получает значения импортированных переменных, а core.setOutput()
экспортирует значения обратно в сценарий. Подробная информация о ключевых методах для работы с действиями доступна в описании пакета @actions/core.
Также, не забудьте добавить README.md
файл с описанием работы действия и всех параметров. А перед коммитом изменений выполните команду yarn build
для актуализации файла со сборкой или настройте сценарий, который будет делать это за вас.
Для того, чтобы использовать ваш Action в сценариях, необходимо создать версию с тегом. Для этого перейдите в раздел "Релизы" в репозитории проекта и создайте новый релиз. На этой же странице вам будет предложено опубликовать действие в маркетплейс, после чего оно появится в поиске.
Проверьте действие, использовав его в каком-нибудь сценарии. На момент написания заметки это единственный вариант тестирования корректности работы кода.
Полезные ссылки
Официальная документация по Actions от GitHub
Список доступных иконок и цветов для иконки действия
Примеры самодельных действий
- codex-team/action-nodejs-package-info — информация об имени и версии node-пакета
- codex-team/action-check-domain — проверка срока регистрации домена и действия SSL
- codex-team/action-codexbot-notify — отправка уведомлений в чат Telegram или Slack