Советы

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Вот мы и достигли финального шага в нашем пути изучения git — в этой завершающей цикл публикаций статье мы применим на практике все знания из предыдущих публикаций и напишем workflow, который будет создавать VPS на стороне 1cloud, загружать на VM код проекта, настраивать окружение и весь необходимый софт для работы проекта.

Сам workflow и проект можно скачать отсюда. Рекомендуем ознакомиться со всей статьей целиком, так как дальнейшие публикации будут посвящены работе с 1cloud API и материал раздела «Работа с 1cloud API через GitHub Actions» очень пригодится. С преамбулой закончили, переходим к сути — познакомимся со схемой работы автоматизации нашего проекта.

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Упрощенно план работы автоматизации выглядит так: в ручном режиме запускается workflow -> запускается Python-скрипт создания VPS -> на VPS загружается код проекта -> настраивается виртуальное Python-окружение -> устанавливается и настраивается Nginx.

Итого у нас есть 2 сущности:

  • VPS — виртуальный сервер, который мы будем создавать по заранее заданному шаблону с помощью API. К нему будет обращаться Python-скрипт, который будет запускаться на виртуальной машине GitHub. Для работы с API нам нужен API-ключ, который мы будем передавать в скрипт через секреты. После создания VPS на него можно загружать код проекта.
  • Проект — это блог для Python-комьюнити, написанный на Django. Так как это пока альфа-версия, то мы не используем СУБД, поэтому для работы проекта потребуется только развернуть виртуальное окружение Python из requirements.txt, установить и настроить Nginx и Gunicorn.

Хорошо, у нас есть план и понимание с какими сущностями мы будем работать. Можно начинать писать workflow.

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Workflow состоит из четырех джоб, каждый из которых содержит от двух до пяти шагов. Вначале workflow мы опишем его название, триггер срабатывания и переменные, которые будут использоваться далее по коду:

name: Create new VPS and deploy repo on: workflow_dispatch env:   PROJECT_DIR: /var/www/   PROJECT_DIR_app: /var/www/pyoops.com/pyoops   REPO_LINK: https://github.com/Pseudolukian/pyoops.com.git   REPO_NAME: pyoops.com

  vps_ip_file: VPS_IP.txt

Первая джоба — создание VPS. Она состоит их пяти шагов: 1) Checkout the repo — получение доступа к репозиторию; 2) Setup Python — обновление версии Python до 10; 3) Run the VPS create script — запуск Python-скрипта, который создает VPS; 4) Export VPS IP to file and check — сохранение IP-адреса VPS в файл и его проверка; 5) Save VPS IP — сохранение IP-адреса VPS как артефакта.

create_vps: runs-on: ubuntu-latest steps:   — name: «Checkout the repo»     uses: actions/checkout@v3      — name: «Setup Python»     uses: actions/setup-python@v4     with:       python-version: '3.10'       cache: 'pip'      — name: «Run the VPS create script»     run: |       pip install requests       python3 ./1cloud_create_vps.py ${{ secrets.API_KEY }}      — name: Export VPS IP to file and check     run: |       echo «${{ env.VPS }}» > ${{ env.vps_ip_file }}       echo $(tail -1 ${{ env.vps_ip_file }})     — name: Save VPS IP     uses: actions/upload-artifact@v3     with:       name: VPS IP

      path: ${{ env.vps_ip_file }}

Следующая джоба — загрузка кода проекта на VPS. Эта джоба состоит из двух сложносоставных шагов:

  1. Download VPS IP artifact and check it — на этом шаге мы загружаем IP созданной VPS из артефакта в переменную VPS_IP и проверяем, что переменная создалась и содержит IP-адрес VPS;
  2. Upload repo to VPS — тут мы используем модуль ssh-action@master для подключения к VPS по SSH с использованием SSH-ключа, который мы заранее сгенерировали и добавили в Панель 1cloud. После подключения исполняются shell-команды подготовки окружения и загрузки кода проекта на VPS.
  3. upload_repo_to_vps:     needs: «create_vps»     runs-on: ubuntu-latest          steps:       — name: Download VPS IP artifact and check it         uses: actions/download-artifact@v3         with:           name: VPS IP       — shell: bash         run: |           echo «VPS_IP=$(tail -1 ${{ env.vps_ip_file }})» >> $GITHUB_ENV       — run: |           echo ${{ env.VPS_IP }}       — name: «Upload repo to VPS»         uses: appleboy/ssh-action@master         with:           host: ${{ env.VPS_IP }}           username: ${{ secrets.SSH_USER }}           key: ${{ secrets.SSH_KEY }}           script: |             mkdir ${{ env.PROJECT_DIR }}             cd ${{ env.PROJECT_DIR }}             git clone ${{ env.REPO_LINK }}             echo «REPO_DOWNLOADED=true» >> /etc/profile             echo «SERVER_NAME='$(hostname -I | awk '{print $1}')'» >> /etc/profile             source /etc/profile             chown www-data:www-data ${{ env.PROJECT_DIR_app }}/db.sqlite3                chown www-data:www-data ${{ env.PROJECT_DIR_app }}/static_collections

                chmod 755 ${{ env.PROJECT_DIR_app }}/db.sqlite3

Последняя джоба — установка Nginx. Эта джоба, как и предыдущая джоба состоит из двух шагов: 1) Download VPS IP artifact and check it — чтение артефакта с IP-адресом VPS (мы выполняем этот шаг повторно, так как каждая джоба запускается на отдельной виртуальной машине GitHub); 2) Install Nginx — установка и настройка Nginx.

nginx_install: needs: «upload_repo_to_vps» runs-on: ubuntu-latest     steps:       — name: Download VPS IP artifact and check it         uses: actions/download-artifact@v3         with:           name: VPS IP       — shell: bash         run: |           echo «VPS_IP=$(tail -1 ${{ env.vps_ip_file }})» >> $GITHUB_ENV       — run: |           echo ${{ env.VPS_IP }}              — name: «Install Nginx»         uses: appleboy/ssh-action@master         with:           host: ${{ env.VPS_IP }}           username: ${{ secrets.SSH_USER }}           key: ${{ secrets.SSH_KEY }}           script: |             sudo apt update && sudo apt install -y nginx

            ln -s /var/www/pyoops.com/configs/pyoops.conf /etc/nginx/sites-enabled/pyoops

Вот и всё. В четыре несложные джобы мы смогли уложить весь workflow, который автоматизирует процессы создания VPS, доставки на него кода проекта и настройки рабочего окружения. Ознакомиться с полным кодом workflow и проекта можно по ссылке.

Теперь мы расскажем, о некоторых нюансах реализации подобных workflow при работе с 1cloud API.

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Для работы с 1cloud API нужно получить API-ключ. Генератор API-ключей находится в разделе Настройки -> Настройки проекта -> API-ключ:

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Для подключения к виртуальному серверу по SSH с помощью SSH-ключа нужно создать пару ключей с помощью команды ssh-keygen -t rsa для Linux или с помощью команды ssh-keygen для Windows (CMD). Публичную часть ключа (расширение .pub) необходимо загрузить в Панель 1cloud -> раздел Настройки -> Личные настройки -> SSH-ключи:

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Для добавления нового SSH-ключа нужно нажать на кнопку «Добавить SSH-ключ» и в появившиеся поля ввести: название ключа и скопированное из pub-файла тело ключа. Далее приватную часть SSH-ключа и API-ключ 1cloud нужно сохранить как секреты в GitHub Actions. Оба ключа бессрочные и их можно использовать любое количество раз.

Для создания виртуальной машины через API 1cloud нужно передать в JSON-формате параметры создаваемой машины и ЦОД размещения. Удобнее всего вынести эти параметры в JSON-конфигурацию следующего вида:

{ «Name»: «Test_VPS_to_dep», #Название VM, которое будет отражаться в Панели «DCLocation»: «DsMsk», #Техническое название ЦОДа, где будет создана VM «CPU»: 2, #Кол-во ядер процессора «RAM»: 4096, #Объем оперативной памяти в MB. «HDD»: 20, #Размер диска в GB «ImageID»: 2169, #ID образа OS. 2169 — Ubuntu 18. «HDDType»:»SSD», #Тип диска: SSD или HDD. «isHighPerfomance»:false, #Тип пула ресурсов ЦОДа: стандартный/высокий. «isBackupActive»:false, #Подключен ли бекап: true/false. «SshKeys»:[3145] #ID SSH-ключа.

}

Технические названия ЦОДов, ID образов OS и ID SSH-ключей можно получить через API запросы. Как это сделать описано в нашей базе знаний.

Для реализации API запросов к 1cloud удобно и просто использовать Python и встроенную библиотеку requests. Вот пример реализации API-запроса на создание VPS с мониторингом готовности создания виртуального сервера и сохранением его IP-адреса в переменную окружения:

import requests, json, time, os, subprocess, sys api_key = str(sys.argv[1]) url = «https://api.1cloud.ru/server/» server_id = str() headers = {«Content-Type»:»application/json», «Authorization»: «Bearer » + api_key} server_config = json.load(open(«./configs/vps_config.json»)) def create_server():     create_server = requests.post(url, headers = headers, json = server_config)     server_id = create_server.json()[«ID»]     print(«Server», server_id, «start to create.»)     time.sleep(10)     check_server_status = requests.get(url + str(server_id), headers = headers)     check_server_status.json()     while check_server_status.json()['State'] == «New»:         time.sleep(45)         check_server_status = requests.get(url + str(server_id), headers = headers)         check_server_status.json()         print(«Server», server_id, «creating…»)     server_ip = str(check_server_status.json()[«PrimaryNetworkIp»])          os.system(f'echo VPS={server_ip} >> $GITHUB_ENV')     result = «Server» + str(server_id) + «is created successfully. » + «IP:» + str(server_ip)     return result if __name__ == «__main__»:

    print(create_server())

Пожалуй из нюансов всё. Мы дали общую схему работы workflow по созданию VPS и загрузки на виртуальный сервер кода проекта, а также рассмотрели некоторые особенности работы с 1cloud API. Настало время подвести итог.

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

Сделаем краткую выжимку по всем 6 статьям цикла, чтобы всё самое важно для работы с GitHub Actions у вас было под рукой в одном месте:

  1. Workflow — это поток выполнения задач (джобов) описанный в формате yaml и хранящийся в специальной поддиректории workflows, директории .github. Вначале файла задается название workflow, которое будет отражаться в Панели управления GitHub Actions и триггер срабатывания workflow: name: Create new VPS and deploy repo
    on: workflow_dispatch
  2. Jobs (джобы) — это задачи, логическое объединение шагов, которые выполняются на отдельных виртуальных машинах GitHub. По умолчанию каждая задача запускается независимо от других и не имеет с ними физической связи. Поэтому вначале каждого блока джобы, указываются два параметра:
    • needs: «create_vps» — название задачи после завершения которой будет выполнена текущая задача;
    • runs-on: ubuntu-latest — образ ОС виртуальной машины, на которой выполняется джоба.

    Если параметр «needs» не указан джоба будет выполняться сразу после старта workflow. В базовом виде блок jobs может выглядеть так: name: Create new VPS and deploy repo on: workflow_dispatch jobs:   create_vps: #Название джобы     runs-on: ubuntu-latest #Шаблон OS     steps: #Начало секции шагов

          …

  3. Steps (шаги) — это конкретные инструкции к выполнению действий. Шаг имеет название и опции выполнения действий: контекст выполнения, скрипт действия и т.д. Вот несколько примеров шагов реализующих разную логику выполнения действий:
  4. Actions (экшены) — это готовые части кода (мини-программы), написанные пользователем для выполнения стандартных операций. Например, для получения доступа к репозиторию из виртуальной машины GitHub (actions/checkout@v3) или для подключения по SSH к VPS (appleboy/ssh-action@master). Экшены содержатся в магазине готовых решений GitHub.
  5. Переменные — это хранилища данных, в которые можно что-то класть или что-то доставать по ходу выполнения workflow. Есть 5 уровней переменных:
    • Переменные среды на уровне операционной системы, на которой выполняется рабочий процесс. Эти переменные доступны только в рамках одной джобы;
    • Переменные окружения, которые определены в workflow, в секции env. Эти переменные доступны из любой точки workflow;
    • Переменные репозитория. Это переменные, которые определяются не в workflow, а в панели управления репозиторием, например, секреты;
    • Переменные контекста GitHub Actions. Это переменные, которые автоматически определяются GitHub Actions для каждого запущенного рабочего процесса;
    • Переменные уровня организации. Эти переменные доступны для всех workflow репозиториев в рамках какой-то организации.
  6. Артефакты — это файлы, которые генерируются или используются в рабочем процессе и могут быть сохранены и переданы между различными шагами или джобами. В основном артефакты используются для передачи данных между джобами, так как каждая джоба выполняется на своей виртуальной машине. Для работы с артефактами есть готовые экшены:
Читайте также:  ТОП-7 книг для программистов, которые только начинают свой путь в IT

Итак, теперь вы знаете как работать с базовыми сущностями GitHub Actions, чтобы написать рабочий workflow. Для получения более полной информации рекомендуем ознакомиться с предыдущими публикациями. В них вы найдете много практического материала и некоторые тонкости работы с сущностями GitHub Actions, которые сэкономят много времени при разработке собственных workflow.

Автоматизация рутинных задач с помощью GitHub Actions

Вы будете тратить меньше времени на тестирование приложения, сборку, проверку качества кода, актуальность задач, если автоматизируете рутинные процессы. 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. Некоторые из них созданы известными компаниями, но бóльшая часть создается и публикуется самостоятельными разработчиками. 

Руки прочь: автоматизация ручных задач с помощью GitHub Actions

GitHub Marketplace: actions to improve your workflow

Find the actions that help your team build better, together.

github.com

Также стоит уделить внимание и неофициальному каталогу интересных действий — Awesome Actions.

sdras/awesome-actions

A curated list of awesome actions to use on GitHub — sdras/awesome-actions

github.com

Здесь можно найти много интересных решений и вдохновиться — возможно, у вас есть похожая задача, а вы и не думали, что её можно тоже автоматизировать.

Как написать свой 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

Примеры сценариев, которые используются в проектах CodeX

Автоматизация Projects с помощью Actions — Документация по GitHub

Для автоматизации проектов можно использовать GitHub Actions.

В этой статье показано, как использовать API GraphQL и GitHub Actions для добавления запроса на вытягивание в проект организации. В примерах рабочих процессов, когда запрос на вытягивание помечен как «готов к проверке», в проект добавляется новая задача, для которой в поле «Состояние» указано «Выполнить», а в настраиваемое поле «Дата публикации» добавляется текущая дата.

Вы можете скопировать один из приведенных ниже рабочих процессов и изменить его, как описано в таблице ниже, в соответствии с вашими потребностями.

Проект может охватывать несколько репозиториев, но рабочий процесс зависит от репозитория. Добавьте рабочий процесс в каждый репозиторий, который требуется отслеживать проект. Дополнительные сведения о создании файлов рабочего процесса см. в разделе «Краткое руководство по GitHub Actions».

В этой статье предполагается, что у вас есть базовое представление о GitHub Actions. Дополнительные сведения о GitHub Actionsсм. в разделе «Документация по GitHub Actions».

Дополнительные сведения о других изменениях, которые можно внести в проект через API, см. в разделе «Использование API для управления Projects».

Вы также можете использовать рабочий процесс actions/add-to-project, который поддерживается GitHub и добавит текущую проблему или запрос на вытягивание в указанный проект. Дополнительные сведения см. в репозитории actions/add-to-project и файле сведений.

Примечание. GITHUB_TOKEN ограничен уровнем репозитория и не может получить доступ к проекты. Для доступа к проекты можно создать GitHub App (рекомендуется для проектов организации) или personal access token (рекомендуется для пользовательских проектов). Ниже приведены примеры рабочих процессов для обоих подходов.

Читайте также:  Вузы для программистов в России

Пример проверки подлинности рабочего процесса при использовании GitHub App

Дополнительные сведения о проверке подлинности в рабочем процессе GitHub Actions с помощью GitHub Appсм. в разделе «Выполнение запросов API с проверкой подлинности с помощью приложения GitHub в рабочем процессе GitHub Actions».

  1. Создайте GitHub App или выберите существующий GitHub App, принадлежащий вашей организации. Дополнительные сведения см. в разделе «AUTOTITLE».

  2. Предоставьте для GitHub App разрешения на чтение и запись в проектах организации. В этом конкретном примере для GitHub App также потребуются разрешения на чтение запросов на вытягивание репозитория и проблемы с репозиторием. Дополнительные сведения см. в разделе «AUTOTITLE».

    Примечание. Вы можете управлять разрешением приложения в проектах организации и проектах репозитория. Необходимо предоставить разрешение на чтение и запись в проектах организации; разрешений на чтение и запись в проектах репозитория будет недостаточно.

  3. Установите GitHub App в вашей организации. Установите его для всех репозиториев, к которым проект должен получать доступ. Дополнительные сведения см. в разделе «AUTOTITLE».

  4. Храните идентификатор GitHub App как секрет в репозитории или организации. В следующем рабочем процессе замените APP_ID именем секрета. Идентификатор приложения можно найти на странице параметров приложения или через API приложений. Дополнительные сведения см. в разделе «AUTOTITLE».

  5. Создайте закрытый ключ для приложения. Сохраните содержимое итогового файла в виде секрета в репозитории или организации. (Сохраните все содержимое файла, включая ——BEGIN RSA PRIVATE KEY—— и ——END RSA PRIVATE KEY——.) В следующем рабочем процессе замените APP_PEM именем секрета. Дополнительные сведения см. в разделе «AUTOTITLE».

  6. В следующем рабочем процессе замените YOUR_ORGANIZATION названием организации. Например, octo-org. Замените YOUR_PROJECT_NUMBER номером проекта. Чтобы найти номер проекта, просмотрите URL-адрес проекта. Например, https://github.com/orgs/octo-org/projects/5 имеет номер проекта 1. Чтобы этот конкретный пример работал, проект также должен иметь поле даты публикации даты.

Пример проверки подлинности рабочего процесса с помощью personal access token

  1. Создайте personal access token (classic) с project помощью и repo область. Дополнительные сведения см. в разделе «AUTOTITLE».
  2. Сохраните personal access token в качестве секрета в репозитории или организации.
  3. В следующем рабочем процессе замените YOUR_TOKEN именем секрета. Замените YOUR_ORGANIZATION названием организации. Например, octo-org. Замените YOUR_PROJECT_NUMBER номером проекта. Чтобы найти номер проекта, просмотрите URL-адрес проекта. Например, у https://github.com/orgs/octo-org/projects/5 номер 5.

Непрерывное развертывание и автоматизация рабочих процессов с помощью Github Actions

Github Actions

Github Actions облегчает разработчикам автоматизацию рабочих процессов.

До появления Github Actions нам приходилось использовать CI/CD инструменты, такие как Jenkins, для запуска сборки каждый раз, когда код публиковался в репозитории. Мы также использовали интеграцию этих сборок с плагинами для проверки качества кода, такими как Sonar.

Эти действия обычно выполняются специально назначенной командой DevOps. С другой стороны, если взять проект с открытым исходным кодом, который работает исключительно за счет поддержки участников, то как бы вы могли убедиться, что качество кода не ухудшится, если в проект внесет вклад слишком много людей, или что функциональность не будет нарушена новым исправлением?

Github Actions помогает нам решить эту проблему. Мы можем предпринимать действия на основе событий, происходящих в репозитории, таких как push, PR и т.д.

Давайте посмотрим, как настроить рабочий процесс в нашем проекте.

Фото Roman Synkevych on Unsplash

Конечная цель каждого рабочего процесса зависит от сценария использования, но наиболее часто используемым рабочим процессом является CI/CD. Вы также можете определить несколько рабочих процессов: один для развертывания, другой для отправки приветствия и так далее.

Каждый рабочий процесс записывается в собственный файл и соответствует синтаксису yml. Расширение файла может быть yml или yaml, а имя файла может быть любым, которое решит разработчик.

Все yml-файлы рабочих процессов должны быть размещены в каталоге «.github/workflows» вашего репозитория.

Элементы файлов рабочего процесса

Давайте начнем с самых основных элементов, которые входят в состав файлов рабочего процесса.

name: Deployment
on:
push:
branches:
— main
pull_request:
branches:
— main

имя: Это поле дает название рабочему процессу, которое будет отображаться на вкладке действий GitHub после запуска рабочего процесса. (См. изображение ниже)

  • on: В этом поле мы определяем события, которые должны инициировать запуск рабочего процесса.
  • В приведенном выше примере файла мы определили два события, push и pull_request, которые должны запустить рабочий процесс.
  • Если мы хотим, чтобы рабочий процесс развертывания запускался только при изменении исходного кода, мы можем явно указать это, как показано ниже.

on:
push:
branches:
— main
paths:
— '**.java'

Явно указав пути в виде ‘**.java’ в нашем yml-файле, мы можем быть уверены, что только когда файл «.java» в ветке «main» будет зафиксирован, наш рабочий процесс будет запущен.

Еще один способ определения каталогов, которые необходимо избегать и включать, приведен ниже. «!» указывает, что мы хотим избежать этого пути.

on:
push:
paths:
— 'sub-project/**'
— '!sub-project/docs/**'

В приведенной выше конфигурации рабочий процесс будет запущен, если файл фиксации находится в каталоге «sub-project», но не будет запущен, если файл находится в каталоге «sub-project/docs».

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
— uses: actions/checkout@v1
— name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: '8'

Еще один элемент, который обычно следует за «on» — это «jobs».

События, определенные под клавишей «on», будут вызывать элементы, определенные под клавишей «jobs».

Одно или несколько заданий обычно перечисляются в рабочем процессе, каждое из которых имеет свой уникальный идентификатор задания. В приведенном выше примере yml-файла «build» — это идентификатор задания.

Далее мы определяем имя этого конкретного задания, которое будет отображаться на вкладке GitHub Actions при запуске рабочего процесса, как показано ниже.

runs-on: Каждое задание запускается на виртуальном сервере, который называется runner environment. Мы можем выбрать среду, на которой мы хотим запустить эти задания, из macOS, Ubuntu и Window Servers.

шаги: Это последовательность задач в рамках задания. Это может запускать действия, доступные в публичных репозиториях (так что нам не придется писать их снова), или устанавливать задачи, например, запуск сборки приложения.

Если мы используем существующее действие в качестве одного из шагов, мы можем объявить это с помощью ключевого слова «uses», если мы определяем команду, то ее можно объявить с помощью ключевого слова «run». Посмотрите пример файла ниже.

Мы можем найти предопределенные действия в репозитории github.com/actions и использовать их по мере необходимости.

build:
name: Build
runs-on: ubuntu-latest
steps:
— uses: actions/checkout@v1
— name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: '8'
— name: Build with Maven
run: mvn -B package -DskipTests —file pom.xml

Каждое задание запускается на виртуальном сервере и по умолчанию выполняется параллельно. Если одно задание зависит от другого, например, развертывание или сборка, то нам придется выполнять их последовательно. Это достигается путем объявления зависимости от задания с помощью ключевого слова «needs».

deploy:
needs: build
name: Deploy

Обратитесь к официальной документации GitHub Actions, чтобы узнать обо всех функциях, которые могут быть включены в рабочий процесс, и найти правильное ключевое слово, используемое в различных случаях.

Заключение

Github Actions дал большой толчок сообществу разработчиков программного обеспечения с открытым исходным кодом и разработчикам, работающим над различными побочными проектами, чтобы автоматизировать множество потоков без дополнительной настройки и загрузки.

Даже проект autocluck, над которым я работал для планирования своих твитов, теперь использует Github Actions для развертывания приложения на AWS. Если вы хотите посмотреть файл рабочего процесса для этого проекта для справки, он доступен на Github.

GitHub Actions — Инструменты — Дока

В этой статье мы говорим про инструменты CI/CD (Continuous Integration и Continuous Delivery). Под этими терминами понимается итерационный процесс сопровождения кода: тестирование и отладка кода, автоматизация рутинных действий, сборка приложений, размещение приложений в магазинах приложений и так далее. Подробно об этом говорится в статье «Что такое CI/CD».

Существует большое количество инструментов для сборки кода и публикации его для пользователей. У каждого свои особенности и тонкости использования. Но есть и конкурирующие между собой инструменты. Среди конкурирующих платформ стоит говорить о 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

Читайте также:  Мультиязычность на Typescript и React

Файл можно назвать произвольно, указать расширение .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..types. Подробно перечень событий и их типы описаны в соответствующем разделе официальной документации. Самые распространённые:

  • push;
  • pull_request;
  • schedule.

В случае с push и pull_request можно указать ветку или тег, тем самым отфильтровав нужное событие для запуска экшена (формат — on..). Есть возможность исключить какие-то ветки, а для всех остальных запускать экшен.

В секции schedule используется формат записи времени, аналогичный cron:

on: schedule: — cron: '20/15 9-18 1,10,20 * *' on: schedule: — cron: '20/15 9-18 1,10,20 * *'

Позиции в строке очень важны: cron: '* * * * *'

  1. * минуты (0—59)
  2. * часы (0—23)
  3. * номер дня в месяце (1—31)
  4. * номер месяца или сокращение на английском языке (1—12 или JAN—DEC)
  5. * номер дня недели или сокращение на английском языке (0—6 или SUN—SAT)

Если значений несколько, они могут быть перечислены через запятую ,. Знак дефиса — можно использовать для указания диапазона.

Если нужно начать, например, с какой-то определённой минуты, часа, дня, месяца, дня недели и запускать что-то периодически можно использовать символ /.

Например, запись '20/15 9-18 1,10,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-on:

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-on необходимо использовать переменную ${{ matrix.os }}. Существует довольно много переменных, которые можно использовать в экшенах.

Например, чтобы получить имя экшена нужно использовать переменную github.action, а чтобы получить хэш коммита — github.sha. Список всех доступных для использования переменных в контексте 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, и в проекте поддерживается проверка линтерами EditorConfig, stylelint и ESLint, которые выполняют функцию тестирования текстов и кода. Список скриптов в файле конфигурации package.json будет примерно таким:

«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/»
}

Тогда можно реализовать такую схему работы:

  1. Загрузка репозитория.
  2. Установка Node.js нужных версий.
  3. Установка зависимостей.
  4. Тестирование кодовой базы и контента на соответствие правилам линтеров.
  5. Сборка приложения.
  6. Публикация приложения.

Наложим дополнительные условия: будет отслеживаться пуш только в ветку 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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *