Как понять
Секция статьи "Как понять"Существует большое количество инструментов для сборки кода и публикации его для пользователей. У каждого свои особенности и тонкости использования. Но есть и конкурирующие между собой инструменты. Среди конкурирующих платформ стоит говорить о GitLab CI/CD, Bitbucket Pipelines, Jenkins, Netlify, JetBrains TeamCity, GitHub Actions и прочие.
GitHub Actions — это инструмент для автоматизации рутины в области разработки программного обеспечения, автоматического тестирования, сборки и публикации приложений, который глубоко интегрирован в экосистему инструментов GitHub.
Например, нужна проверка кодовой базы проекта на Node.js или контента на соответствие правилам линтера EditorConfig, установленного в проекте как дев-зависимость. Разработчики, открывая проект локально с помощью IDE или запуская специальный скрипт, смогут проверить код, поскольку в проекте уже присутствует файл .editorconfig. А что делать в том случае, если разработчик открыл файл в блокноте или в веб-интерфейсе? Вот тут можно использовать экшен, который, например, будет срабатывать всякий раз, когда файлы попадают в репозиторий с помощью git push
:
name: EditorConfigon: pushjobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: '14' - run: npm ci - run: npm run editorconfig
name: EditorConfig on: push jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: '14' - run: npm ci - run: npm run editorconfig
Файл можно назвать произвольно, указать расширение .yml и поместить в папку .github/workflows. Экшен автоматически запустится и выдаст результаты проверки на отдельной вкладке «Actions».
Как пользоваться
Секция статьи "Как пользоваться"GitHub Actions — средство автоматизации, конфигурация которого описывается в формате YAML.
В первой секции name
устанавливается название экшена, которое будет использоваться в интерфейсе GitHub. Для названия можно использовать как английский язык, так и, например, русский. Вообще эта секция не является обязательной. Давайте создадим экшен для тестирования приложения на Node.js и назовём его так:
name: Тестирование
name: Тестирование
В секции on
перечисляются триггеры, то есть действия пользователей в репозитории, при возникновении которых будет запускаться экшен. Например, можно настроить экшен так, что он будет запускаться при определённых операциях, связанных с основной веткой:
on: push: branches: [ main ] pull_request: branches: [ main ]
on: push: branches: [ main ] pull_request: branches: [ main ]
В качестве событий можно использовать разные события в репозитории в формате on
. Подробно перечень событий и их типы описаны в соответствующем разделе официальной документации. Самые распространённые:
push
;pull
;_ request schedule
.
В случае с push
и pull
можно указать ветку или тег, тем самым отфильтровав нужное событие для запуска экшена (формат — on
). Есть возможность исключить какие-то ветки, а для всех остальных запускать экшен.
В секции schedule
используется формат записи времени, аналогичный cron
:
on: schedule: - cron: '20/15 9-18 1,10,20 * *'
on: schedule: - cron: '20/15 9-18 1,10,20 * *'
Позиции в строке очень важны: cron
*
минуты (0—59)*
часы (0—23)*
номер дня в месяце (1—31)*
номер месяца или сокращение на английском языке (1—12 или JAN—DEC)*
номер дня недели или сокращение на английском языке (0—6 или SUN—SAT)
Если значений несколько, они могут быть перечислены через запятую
. Знак дефиса
можно использовать для указания диапазона. Если нужно начать, например, с какой-то определённой минуты, часа, дня, месяца, дня недели и запускать что-то периодически можно использовать символ
. Например, запись '20
означает, что событие будет запускаться 1-го, 10-го и 20-го числа каждого месяца с 9 часов утра до 18 часов вечера на 20-й, 35-й и 5-й минуте каждого часа.
Секция jobs
(джобы) предназначена для описания действий, которые должен произвести экшен.
jobs:
jobs:
Каждый джоб имеет свой вывод, которым можно управлять. Вывод той или иной информации можно использовать в зависимых джобах, которые указываются в секции needs
. Вот пример зависимых джобов:
jobs: job1: job2: needs: job1 job3: needs: [job1, job2]
jobs: job1: job2: needs: job1 job3: needs: [job1, job2]
Джоб job2
зависит от job1
, а джоб job3
ещё и от job2
. Название джоба — это фактически название последовательности действий. Название может содержать буквы латинского алфавита, цифры и дефисы. В джобе необходимо прописать, на какой операционной системе экшен должен запускаться в секции runs
:
first-test: runs-on: ubuntu-latest
first-test: runs-on: ubuntu-latest
Доступны следующие операционные системы:
- Windows Server 2019 — для этого нужно использовать
windows
или- latest windows
- 2019 - Windows Server 2016 — для этого нужно использовать
windows
- 2016 - Ubuntu 20.04 — для этого нужно использовать
ubuntu
или- latest ubuntu
- 20 . 04 - Ubuntu 18.04 — для этого нужно использовать
ubuntu
- 18 . 04 - macOS Big Sur 11 — для этого нужно использовать
macos
- 11 - macOS Catalina 10.15 — для этого нужно использовать
macos
или- latest macos
- 10 . 15
Для проведения тестирования или сборки приложения иногда важно использовать разные версии платформ или операционных систем. Например, в случае с Node.js можно использовать несколько версий для тестирования веб-приложения, библиотеки или фреймворка. В экшенах это возможно и реализовано как стратегия запуска на списке (матрице) образов. Слово «образ» употреблено не случайно, поскольку используется Docker-образ для запуска той или иной платформы на базе нужной операционной системы. Кроме Node.js в экшенах поддерживается большой список других платформ, инструкции по настройке которых можно посмотреть в соответствующем разделе официальной документации. В примере используется две операционных системы, на каждой из которых запускается три версии Node.js:
runs-on: ${{ matrix.os }}strategy: matrix: os: [ubuntu-18.04, ubuntu-20.04] node: [10, 12, 14]
runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04, ubuntu-20.04] node: [10, 12, 14]
Если вам не очень понятно, зачем Docker нужен и как работает, прочитайте статью «Что такое Docker».
Чтобы можно было запустить экшен на нескольких операционных системах, в секции runs
необходимо использовать переменную ${{ matrix
. Существует довольно много переменных, которые можно использовать в экшенах. Например, чтобы получить имя экшена нужно использовать переменную github
, а чтобы получить хэш коммита — github
. Список всех доступных для использования переменных в контексте github
есть в официальной документации. В экшенах есть и другие контексты:
env
— содержит переменные окружения;job
— хранит информацию о текущем джобе, которую можно использовать внутри джоба;steps
— хранит информацию о последовательности действий в джобе;runner
— хранит информацию о контейнере, в котором запущен текущий джоб;needs
— хранит вывод всех джобов, зависимых от текущего джоба.
Кроме переменных в экшенах можно пользоваться переменными окружения в операционной системе напрямую для работы команд, скриптов и программ. Иногда это удобнее, чем контексты и переменные. Список переменных окружения находится на соответствующей странице документации.
Список конкретных действий указывается в секции steps
. Такое название используется не случайно, подчёркивается, что это не просто список, это — строгая последовательность действий. Можно использовать заранее готовые экшены с помощью секции uses
, которые находятся в публичном или приватном репозитории. На GitHub есть даже специальный раздел для тех экшенов, о которых авторы решили заявить максимально широкой аудитории. Процесс создания и публикации экшенов описан в официальной документации. В качестве очередного действия можно пользоваться и обычными командами терминала с помощью секции run
. Если необходимо выполнить несколько команд подряд, их можно расположить построчно, используя вертикальную черту |
.
steps: - uses: actions/checkout@v2 - name: Использование Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: | npm run build npm test
steps: - uses: actions/checkout@v2 - name: Использование Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: | npm run build npm test
Подробнее об использовании терминала можно почитать в статье «Интерфейс командной строки». Полностью пример конфигурации для тестирования приложения Node.js будет выглядеть так:
name: Тестированиеon: push: branches: [ main ] pull_request: branches: [ main ]jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04, ubuntu-20.04] node: [10, 12, 14] steps: - uses: actions/checkout@v2 - name: Использование Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: | npm run build npm test
name: Тестирование on: push: branches: [ main ] pull_request: branches: [ main ] jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04, ubuntu-20.04] node: [10, 12, 14] steps: - uses: actions/checkout@v2 - name: Использование Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: | npm run build npm test
На практике
Секция статьи "На практике"Публикация для сайта на 11ty
Секция статьи "Публикация для сайта на 11ty"Попробуем сделать экшен для своего репозитория. Например, мы работаем с движком генератора статики 11ty, и в проекте поддерживается проверка линтерами EditorConfig, stylelint и ESLint, которые выполняют функцию тестирования текстов и кода. Список скриптов в файле конфигурации package
будет примерно таким:
"scripts": { "start": "eleventy --serve --quiet", "test": "editorconfig-checker && stylelint \"src/styles/**/*.css\" && eslint src/**/*.js", "build": "eleventy", "deploy": "cd dist && rsync --archive --compress --delete . user@example.com:/var/www/example.com/html/"}
"scripts": { "start": "eleventy --serve --quiet", "test": "editorconfig-checker && stylelint \"src/styles/**/*.css\" && eslint src/**/*.js", "build": "eleventy", "deploy": "cd dist && rsync --archive --compress --delete . user@example.com:/var/www/example.com/html/" }
Тогда можно реализовать такую схему работы:
- Загрузка репозитория.
- Установка Node.js нужных версий.
- Установка зависимостей.
- Тестирование кодовой базы и контента на соответствие правилам линтеров.
- Сборка приложения.
- Публикация приложения.
Наложим дополнительные условия: будет отслеживаться пуш только в ветку main
и все ветки, названия которых будет начинаться с releases
.
Конфигурация для экшена будет выглядеть так:
name: Публикация сайтаon: push: branches: - main - 'releases/**' pull_request: branches: - mainjobs: deploy: runs-on: ubuntu-latest strategy: matrix: node-version: [ 12.x ] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: | npm ci npm run test npm run build npm run deploy
name: Публикация сайта on: push: branches: - main - 'releases/**' pull_request: branches: - main jobs: deploy: runs-on: ubuntu-latest strategy: matrix: node-version: [ 12.x ] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: | npm ci npm run test npm run build npm run deploy