GitHub Actions як CI/CD для сайта на статычным генератары і GitHub Pages
Трохі прашарсціў Habr здзівіўся таму, што вельмі мала апублікавана артыкулаў на тэму (beta-)фічы GitHub'а - Actions.
Здавалася б, можна растлумачыць такую недаказанасць тым, што функцыянал яшчэ ў тэсціраванні, няхай і «beta». Але менавіта карысная асаблівасць бэты дазваляе выкарыстоўваць гэтую прыладу ў прыватных рэпазітарах. Менавіта пра працу з дадзенай тэхналогіяй я раскажу ў гэтым артыкуле.
Перадгісторыя
Калі пачынаць па парадку, то варта, мусіць, згадаць той момант, што падчас пошуку хуткага, зручнага, лёгкага і бясплатнага варыянту захоўвання персанальнага сайта «Пра мяне» прыйшлося выдаткаваць некалькі начэй і прошерстить мноства артыкулаў.
Хтосьці на выбірае хостынг, хтосьці хмарны сервер, а тым, каму не хочацца разбірацца ў працы, узаемадзеянні і аплаце ўсяго гэтага - прыходзіцца па душы выгрузка статычных сайтаў у рэпазітар, балазе цяпер гэта можна зрабіць і на GitHub, і на GitLab .
Канешне, гэта асабісты выбар кожнага.
Мой канчатковы выбар быў у карысць GitHub Pages.
Пра Pages
Хто не ў курсе, gh-pages - гэта такі варыянт захоўвання дакументацыі ў выглядзе сайта і прадастаўляецца ён бясплатна, а акрамя дакументацыі прапануецца захоўваць таксама персанальныя сайты. Гэты функцыянал падаецца GitHub'ом усім карыстачам і даступны ў наладах рэпазітара.
Для рэпазітара праекта выкарыстоўваецца галінка. gh-pages, для карыстацкага сайта - асобны рэпазітар з назвай username.github.io з зыходнікамі сайта ў master галінцы.
Падрабязней можна паглядзець у дакументацыі, Але адзначу толькі тое, што GitHub з дзіўнай шчодрасцю дазваляе кожнаму прывязаць уласны дамен да такога сайта, проста дадаўшы файл CNAME c назвай дамена і наладзіўшы DNS свайго дамен-правайдэра на серверы GitHub.
Упэўнены, што артыкулаў аб тым як разгарнуць такі сайт тут знойдзецца мноства, таму далей не пра гэта.
Узнікненне праблемы
Праблема складалася ў тым, што пры выкарыстанні статычнага генератара ёсць неабходнасць складаць дадатковыя мыліцы скрыпты і выкарыстоўваць бібліятэкі для спрашчэння працэсу генерацыі старонак і іх загрузкі ў рэпазітар. Папросту, калі захоўваць зыходнікі ў асобным прыватным рэпазітары, то кожны раз пры любой змене на сайце было неабходна разгортваць лакальнае асяроддзе для наступнай генерацыі статычных старонак і публікацыі ў асноўным рэпазітары сайта.
Існуе багацце статычных генератараў і ўсе яны маюць такую ж праблему. Гэтыя дзеянні займаюць занадта шмат часу і сіл, а па выніку стопорят працу над сайтам, асабліва пасля некалькіх міграцый з АС на АС або інцыдэнтаў са стратай дадзеных на цвёрдых дысках. (так было ў маім выпадку).
Літаральна нядаўна, ці то ва ўсплываючым апавяшчэнні на сайце, ці то ў рассыланні ад GitHub было заўважана новаўбудаваны CI/CD, які дазволіў праводзіць гэтыя дзеянні з мінімальнымі намаганнямі.
Пра генератары статычных старонак
Не буду завастраць на гэтым падпункце асаблівую ўвагу, але падзялюся парай тэзісаў да якіх прыйшоў за час выбару і выкарыстання такіх:
1) выбіраць генератар стаіць пад сваю мову праграмавання, ці такі які быў максімальна зразумелы. Да гэтай ідэі я прыйшоў у той момант, калі самому прыйшлося дапісваць некаторы функцыянал для працы сайта, прастаўляць мыліцы для яго большай устойлівасці і аўтаматызацыі. Акрамя таго, гэта добрая нагода самому напісаць дадатковы функцыянал у выглядзе плагінаў;
2) на якім менавіта генератары спыняцца гэта асабісты выбар, але варта ўлічваць, што для пачатковага апускання ў працу функцыяналу GitHub Pages неабходна спачатку паставіць сабе Джэкіл. Балазе, ён дазваляе генераваць сайт з зыходнікаў прама ў рэпазітары (гэта я і паўтару са сваім выбарам).
Мой выбар генератара засноўваецца на першым пункце. пелікан які напісаны на Python з лёгкасцю замяніў чужы для мяне Jekyll (карыстаўся амаль год). У выніку нават стварэнне і рэдагаванне артыкулаў, робата над сайтам дае дадатковы досвед у цікавай для мяне мове.
__
Пастаноўка задачы
Галоўная задача будзе - напісаць такі скрыпт (на самай справе файл канфігурацыі), які дазволіў бы аўтаматычна генераваць статычныя старонкі з прыватнага рэпазітара. У рашэнні будзе задзейнічаны функцыянал віртуальнага асяроддзя. Скрыпт сам будзе дадаваць гатовыя старонкі ў публічны рэпазітар.
Інструменты для вырашэння
Інструменты, якія будзем выкарыстоўваць для вырашэння задачы:
GitHub Actions;
Python 3.7;
пелікан;
Git;
GitHub Pages.
Рашэнне праблемы
Разам, пазнаёміўшыся крыху з дакументацыяй і разабраўшыся як пішуцца скрыпты для Actions стала зразумела што гэты механізм цалкам вырашыць узніклую праблему. На момант напісання артыкула для выкарыстання дадзенага функцыяналу неабходна падпісаццана бэта-тэставанне!
Апісанне новага функцыяналу самім Github
Пачынаецца напісанне Actions-скрыпту са стварэння найменнага файла ў тэчцы .github і яе падтэчку workflows. Зрабіць гэта можна як уручную, так і з рэдактара ва ўкладцы Actions на старонцы рэпазітара.
Прыклад пустога бланка скрыпту
Коратка адкаментую бланк
name: CI # название скрипта: будет отображаться во вкладке Actions
on: [push] # действие, по которому запускается данный скрипт
jobs: # роботы, которые будут выполняться
build: # сборка, которая..
runs-on: ubuntu-latest # ..будет запущена на основе этого образа
steps: # шаги которые будут проделаны после запуска образа
- uses: actions/checkout@v1 # переход в самую актуальную ветку
- name: Run a one-line script # имя работы номер 1
run: echo Hello, world! # суть работы номер 1 (bash-команда записана в одну строку)
- name: Run a multi-line script # имя работы номер 2
run: | # суть работы номер 2 (многострочная)
echo Add other actions to build,
echo test, and deploy your project.
Напішам свой на аснове шаблону:
0) Імя можна пакінуць і "CI". Тут справа густаўшчыны.
1) Далей неабходна абраць тое дзеянне/трыгер, якое прывядзе да запуску скрыпту, у нашым выпадку гэта звычайны пуш новага комміта ў рэпазітар.
on:
push
2) Выява на аснове якога будзе запускацца скрыпт таксама пакінем з прыкладу, бо Ubuntu суцэль уладкоўвае па неабходным функцыянале. Гледзячы на даступныя інструменты становіцца зразумела, што гэта можа быць любы неабходны ці проста зручны вобраз (або докер кантэйнер на яго аснове).
build:
runs-on: ubuntu-latest
3) У кроках спачатку наладзім асяроддзе для падрыхтоўкі да асноўнай працы.
3.1) пераходзім у неабходную нам галінку (стандартны крок checkout):
- uses: actions/checkout@v1
3.2) усталёўваны Python:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.7
3.4) ствараем дырэкторыю, у якую будуць генеравацца старонкі сайта:
- name: Make output folder
run: mkdir output
4) Для таго, каб праца над сайтам была паслядоўная, а менавіта не выдаляла папярэднія змены і можна было без канфліктаў дадаваць змены ў рэпазітар сайта, наступным крокам будзем кожны раз кланаваць рэпазітар сайта:
зменную GITHUB_ACTOR GitHub усталёўвае сам, і гэтае імя карыстальніка, па віне якога запусціўся дадзены скрыпт;
пераменная secrets.ACCESS_TOKEN гэта згенераваны токен для кіравання Github'ом, яго ў выглядзе зменнай асяроддзя мы можам перадаць усталяваўшы ва ўкладцы Secrets налад нашага рэпазітара. Прашу заўважыць, пры генерацыі токен падасца нам аднойчы, больш доступу да яго не будзе. Таксама як і значэння пунктаў Secrets.
Параметры, перададзеныя генератару, адказваюць за дырэкторыю, куды будзе адпраўлены згенераваныя файлы (-o output) і канфігурацыйны файл, які выкарыстоўваем для генерацыі (-s publishconf.py; пра падыход да падзелу лакальнага канфіга і канфіга для публікацыі можна пачытаць у дакументацыі Pelican).
Нагадаю, што ў нас у тэчку output ужо схіляецца рэпазітар сайта.
6) Наладзім git і праіндэксуем нашы змененыя файлы:
У гэтым пункце выкарыстоўваецца ўжо вядомая пераменная, і ўказваецца рабочая дырэкторыя, у якой будзе адбывацца запуск каманд з гэтага кроку. Каманда пераходу ў працоўную дырэкторыю інакш выглядала б як. cd output.
7) Згенеруем паведамленне комміта, закамміцім змены і запушым іх у рэпазітар. Каб коміт не быў марна, і адпаведна не выдаў памылку ў bash (вынік на выхадзе не 0) - спачатку праверым ці неабходна наогул нешта каміціць і пушыць. Для гэтага выкарыстоўваем каманду git diff-index --quiet --cached HEAD -- якая на выхадзе ў тэрмінал выдасць 0 калі няма зменаў адносна папярэдняй версіі сайта, і 1 такія змены ёсць. Пасля чаго апрацоўваем вынік гэтай каманды. Такім чынам, мы ў інфармацыі аб выкананні скрыпту запішам карысную інфармацыю аб стане сайта на гэтым этапе, замест аўтаматычнага падзення і адпраўкі нам справаздачы аб падзенні скрыпту.
Гэтыя дзеянні таксама праводзім у нашай дырэкторыі з гатовымі старонкамі.
- name: Push and send notification
run: |
COMMIT_MESSAGE="Update pages on $(date +'%Y-%m-%d %H:%M:%S')"
git diff-index --quiet --cached HEAD -- && echo "No changes!" && exit 0 || echo $COMMIT_MESSAGE
# Only if repo have changes
git commit -m "${COMMIT_MESSAGE}"
git push https://${{ secrets.ACCESS_TOKEN }}@github.com/${GITHUB_ACTOR}/${GITHUB_ACTOR}.github.io.git master
working-directory: ./output
Вынік
У выніку такі скрыпт дазваляе не думаць аб стварэнні статычных старонак. Дадаючы змены напроста ў прыватны рэпазітар, няхай гэта будзе працай з git з-пад любой сістэмы ці стварэннем файла праз web-інтэрфейс GitHub'а, Actions зробяць усё самі. У выпадку нечаканага падзення скрыпту на пошту прыйдзе апавяшчэнне.
Поўны код
Пакіну свой працоўны варыянт, у ім у апошні крок дададзена адпраўка апавяшчэння аб тым, што коміт быў запушаны ў асноўны рэпазітар.
Выкарыстоўваюцца вышэйапісаныя Secrets куды дададзены токен бота і ідэнтыфікатар карыстальніка якому трэба адправіць паведамленне.