GitHub Actions — CI/CD рецепты
Для кого эта статья
Готовые примеры GitHub Actions с пошаговым разбором каждой строки YAML — как в галерее Turtle для Python и curl / fetch для API. Можно скопировать workflow, вставить в репозиторий и понять, зачем нужна каждая строка.
Подойдёт, если вы:
- делаете курсовую, лабораторную, диплом или pet-проект на GitHub;
- гуглите «github actions пример», «github actions yaml», «ci cd github actions», «github actions node js», «github actions python», «деплой на github pages actions», «как настроить github actions»;
- знаете
git push, но вкладка Actions пока пустая; - хотите зелёную галочку в pull request и badge «CI passing» в README.
Как применять:
| Шаг | Действие |
|---|---|
| 1 | Создайте папку .github/workflows/ в корне репозитория |
| 2 | Сохраните YAML в файл, например ci.yml |
| 3 | git add, git commit, git push |
| 4 | Откройте вкладку Actions — там появится run |
| 5 | При ошибке кликните красный step и читайте лог |
Бесплатного лимита GitHub Actions хватает для учебных репозиториев. Подробности — в документации GitHub.
Системное введение — GitHub Actions. Полный справочник по ключам YAML — Справочник по GitHub Actions. Связка Git и триггеров — Git и GitFlow в DevOps. Пошаговый деплой сайта — кейс GitHub Pages.
Как пользоваться статьёй
- Прочитайте блок «Что такое GitHub Actions» — там смысл CI/CD без жаргона.
- Сделайте первый workflow за 5 минут — минимальный рабочий файл.
- Найдите свой стек (Node, Python, деплой, PR).
- Скопируйте YAML целиком.
- Прочитайте Разбор и Разбор построчно под кодом.
- Выполните Попробуйте — одна маленькая правка закрепляет тему.
- Для отчёта по лабораторной можно скриншотить вкладку Actions и зелёный step.
Что такое GitHub Actions простыми словами
Вы делаете git push — код попадает на GitHub. GitHub Actions — это робот на сервере GitHub, который автоматически выполняет команды из вашего репозитория: установить Node.js, запустить тесты, собрать сайт, залить на GitHub Pages.
Инструкции роботу лежат в файле YAML (текст с отступами) в папке .github/workflows/.
| Без CI | С GitHub Actions |
|---|---|
| «У меня локально всё работает» | На каждый push проверка на чистой Linux-ВМ |
| Преподаватель клонирует и мучается с версией Node | В YAML зафиксирована версия 20 |
| Забыли запустить тесты перед сдачей | Тесты стартуют сами, результат виден в PR |
| Деплой — копировать папку руками | npm run build + публикация на Pages одной кнопкой |
CI (Continuous Integration) — «каждое изменение кода автоматически проверяется». CD (Continuous Delivery/Deployment) — «после проверок артефакт выкладывается на сервер или Pages».
Словарь за 30 секунд
| Термин | Простыми словами |
|---|---|
| Workflow | Один YAML-файл = один сценарий автоматизации |
| Job | Блок работы на одной виртуальной машине |
| Step | Один шаг внутри job — команда или готовый action |
| Runner | Временная ВМ, где выполняются step (ubuntu-latest = Linux) |
| Action | Чужой готовый step из каталога (actions/checkout@v4) |
on: | Когда запускать — push, PR, расписание, кнопка |
uses: | Подключить action |
run: | Выполнить shell-команду (npm test, pytest) |
with: | Параметры для action (версия Node, путь к папке) |
${{ … }} | Подстановка переменной GitHub (секрет, matrix, ref) |
| Secret | Пароль/токен в Settings, в код не пишется |
| Artifact | Zip с build/ или dist/ — скачать из UI run |
| Matrix | Один job × много версий (Node 18 и 20 параллельно) |
Первый workflow за 5 минут
Задача: с нуля получить зелёный run во вкладке Actions.
Шаг 1 — создать файл локально
В корне репозитория (там же, где README.md):
my-project/
.github/
workflows/
hello.yml ← ваш первый workflow
README.md
Папки .github и workflows с точкой — это стандарт GitHub, не опечатка.
Шаг 2 — минимальный YAML
Файл .github/workflows/hello.yml:
name: Hello CI
on:
push:
branches: [main]
workflow_dispatch:
jobs:
greet:
runs-on: ubuntu-latest
steps:
- run: echo "GitHub Actions работает"
Шаг 3 — отправить на GitHub
git add .github/workflows/hello.yml
git commit -m "ci: первый workflow GitHub Actions"
git push origin main
Если основная ветка называется master, в YAML замените main на master.
Шаг 4 — посмотреть результат
- Откройте репозиторий на github.com.
- Вкладка Actions → слева Hello CI → сверху последний run.
- Клик по job greet → step с
echo→ в логе строкаGitHub Actions работает. - Зелёная галочка ✓ — workflow успешен.
Что увидите в UI:
| Элемент | Значение |
|---|---|
| Жёлтый кружок | Run ещё выполняется |
| Зелёная галочка | Все step прошли |
| Красный крест | Какой-то step упал — откройте его лог |
| Re-run jobs | Повторить без нового коммита |
Попробуйте: на вкладке Actions нажмите Run workflow (работает, потому что в YAML есть workflow_dispatch).
Анатомия YAML-файла workflow
Любой workflow — это четыре уровня вложенности. Отступы только пробелами (обычно 2), табы ломают парсер.
name ← имя в UI
on ← триггеры
jobs ← список job
job_id ← имя job (вы придумываете)
runs-on ← ОС runner
steps ← список шагов
- run ← команда
- uses ← action
Разбор минимального hello.yml построчно
name: Hello CI
Разбор:
name:— подпись workflow во вкладке Actions. Можно по-русски:name: Моя первая CI.- Без
nameGitHub покажет имя файлаhello.yml.
on:
push:
branches: [main]
workflow_dispatch:
Разбор построчно:
| Строка | Смысл |
|---|---|
on: | Блок «когда запускать» |
push: | При отправке коммитов (git push) |
branches: [main] | Только push в ветку main, push в feature/login этот workflow не тронет |
workflow_dispatch: | Ручной запуск кнопкой Run workflow в UI |
Короткая запись того же триггера: on: [push, workflow_dispatch] — без фильтра по ветке (сработает на любой push).
jobs:
greet:
runs-on: ubuntu-latest
steps:
- run: echo "GitHub Actions работает"
Разбор построчно:
| Строка | Смысл |
|---|---|
jobs: | Начало списка job. Можно несколько: test, deploy, … |
greet: | ID job — латиница, без пробелов. В логах и в needs: greet |
runs-on: ubuntu-latest | GitHub выдаёт свежую Ubuntu с bash, curl, git |
steps: | Шаги выполняются сверху вниз на одной и той же ВМ |
- run: echo "…" | Минус + пробел = элемент списка. run — команда в shell |
echo | Печать текста в лог (как в терминале Linux) |
Почему - перед step: в YAML это массив. Каждый step — новый элемент списка.
Основы — checkout и actions
Checkout — скачать код на runner
Задача: понять, зачем почти везде первый step — actions/checkout.
Без checkout на runner пустая папка. Команда npm ci упадёт — нет package.json.
steps:
- uses: actions/checkout@v4
- run: ls -la
- run: cat package.json
Разбор построчно:
| Строка | Смысл |
|---|---|
- uses: actions/checkout@v4 | uses = взять готовый action. actions/checkout — официальный, клонирует репо |
@v4 | Версия action. Пишите @v4, @v5, не @main — иначе завтра action может сломаться |
ls -la | Список файлов в рабочей папке — в логе увидите исходники |
cat package.json | Печать файла — проверка, что checkout сработал |
Где лежит код на runner: переменная $GITHUB_WORKSPACE — обычно /home/runner/work/ИМЯ_РЕПО/ИМЯ_РЕПО.
Попробуйте: добавьте под checkout:
- uses: actions/checkout@v4
with:
fetch-depth: 0
Разбор fetch-depth: 0:
- По умолчанию checkout качает 1 последний коммит (
fetch-depth: 1) — быстрее. 0= вся история Git. Нужно для release notes,git describe, Docusaurus «last updated».
uses: и run: — в чём разница
uses: | run: | |
|---|---|---|
| Что это | Готовый action (чужой YAML+скрипт) | Ваша команда в shell |
| Пример | actions/setup-node@v4 | npm test |
| Когда | Стандартные задачи (git, node, cache) | Ваши скрипты проекта |
Один step — либо uses, либо run (иногда оба через run внутри action).
Синтаксис ${{ }} — подстановка значений
GitHub подставляет значения до выполнения step:
node-version: ${{ matrix.node-version }}
github_token: ${{ secrets.GITHUB_TOKEN }}
if: github.ref == 'refs/heads/main'
| Выражение | Откуда значение |
|---|---|
${{ matrix.node-version }} | Из блока strategy.matrix |
${{ secrets.API_TOKEN }} | Settings → Secrets |
${{ github.ref }} | Текущая ветка или тег |
${{ github.event_name }} | push, pull_request, … |
${{ runner.os }} | Linux, Windows, macOS |
В логах секреты заменяются на ***. Писать echo ${{ secrets.TOKEN }} бессмысленно — увидите звёздочки.
Стартовые рецепты
Простые сценарии для отчёта, курсовой и первого badge в README.
Node.js — установка и тесты (самый частый запрос)
Задача: на каждый push и pull request установить зависимости и запустить npm test.
Файл .github/workflows/node-ci.yml:
name: Node CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test
Разбор блоков:
| Блок | Зачем |
|---|---|
pull_request + push | PR проверяется до merge; push в main — после слияния |
setup-node@v4 | Ставит Node.js 20 на runner (локально у вас может быть 22 — в CI всегда 20) |
cache: 'npm' | Кэш скачанных пакетов — второй run быстрее на 30–60 секунд |
npm ci | clean install строго по package-lock.json. Для CI предпочтительнее npm install |
npm test | Вызывает скрипт "test" из package.json |
Разбор построчно — блок on::
on:
push:
branches: [main]
pull_request:
branches: [main]
pushна веткуfeature/xбез открытого PR — только если добавитеpushбез фильтра или отдельный workflow.pull_requestсbranches: [main]— когда PR влит в main или открыт в main (target branch = main).
Связь с package.json — в проекте должен быть скрипт "test":
{
"scripts": {
"test": "jest"
}
}
Другие варианты той же строки: "node --test", "vitest run", "mocha". Главное — чтобы npm test находил команду.
Без "test" команда npm test упадёт с missing script: test.
Что увидите в логе step npm test:
> my-app@1.0.0 test
> jest
PASS src/app.test.js
Tests: 3 passed, 3 total
Красный step — прокрутите вверх до первой строки FAIL или Error:.
Попробуйте:
- Добавьте step
- run: npm run lintпослеnpm ci. - Добавьте в README badge (замените
USERиREPO):

Python — pytest
Задача: прогнать unit-тесты на Python 3.12 в CI.
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- run: pip install -r requirements.txt
- run: pip install pytest
- run: pytest -q
Разбор построчно:
| Строка | Смысл |
|---|---|
on: [push, pull_request] | Короткая форма — любой push и любой PR |
setup-python@v5 | Python 3.12 на runner |
cache: 'pip' | Кэш wheel-файлов pip |
pip install -r requirements.txt | Зависимости проекта из файла |
pip install pytest | Тестовый раннер (если нет в requirements) |
pytest -q | quiet — меньше строк в логе, только итог и ошибки |
Структура тестов для pytest:
project/
src/
calc.py
tests/
test_calc.py
Пример tests/test_calc.py:
def test_add():
assert 1 + 1 == 2
Попробуйте: замените pytest -q на pytest -v — в логе будет имя каждого теста (удобно для отчёта).
Если зависимости в pyproject.toml:
- run: pip install -e ".[dev]"
- run: pytest -q
Только pull request — проверки без деплоя
Задача: на каждый PR в main — lint и test; деплой этот файл не трогает.
name: PR checks
on:
pull_request:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run lint
- run: npm test
Разбор:
- Триггер только
pull_request— обычный push в feature-ветку без PR workflow не запустит. - В карточке PR появится секция Checks — зелёный или красный статус.
- Если в Settings → Branches → Branch protection включено «Require status checks», merge без зелёного CI невозможен.
Что увидите в PR:
All checks have passed
✓ verify / test (pull_request)
Попробуйте: намеренно сломайте тест, откройте PR — преподаватель увидит красный крест до исправления.
Java — Maven (сборка и тесты)
Задача: типичный CI для учебного Java-проекта с pom.xml.
name: Java CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven
- run: mvn -B verify
Разбор построчно:
| Строка | Смысл |
|---|---|
setup-java@v4 | JDK на runner |
distribution: temurin | Сборка Eclipse Temurin (бывший AdoptOpenJDK) |
java-version: '21' | Версия языка — как в вашем pom.xml |
cache: maven | Кэш ~/.m2 — не качать одни и те же jar каждый раз |
mvn -B verify | Batch mode (без интерактива) + compile + test + package checks |
Попробуйте: Gradle вместо Maven — cache: gradle и run: ./gradlew test.
CI/CD рецепты
1. Matrix — Node 18 и 20 параллельно
Задача: убедиться, что проект работает на двух LTS-версиях Node.
name: Node matrix
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Разбор построчно:
| Строка | Смысл |
|---|---|
strategy: | Настройки параллельного запуска |
matrix: | Таблица параметров → GitHub создаёт отдельный run на каждую комбинацию |
node-version: [18, 20] | Два job: один с Node 18, второй с 20 |
fail-fast: false | Упал тест на 18 — проверка на 20 всё равно дойдёт до конца |
${{ matrix.node-version }} | В первом job подставится 18, во втором 20 |
Что увидите в UI: два под-job test (18) и test (20) внутри одного workflow run.
Попробуйте — кросс-платформа:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [20]
runs-on: ${{ matrix.os }}
Получится 2 job: Linux + Windows.
2. Кэш npm вручную (actions/cache)
Задача: ускорить CI в монорепо, когда встроенного cache: 'npm' мало.
Фрагмент steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
id: npm-cache
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- run: npm ci
Разбор построчно:
| Строка | Смысл |
|---|---|
actions/cache@v4 | Сохранить/восстановить папку между run |
id: npm-cache | Имя step — можно сослаться в if: steps.npm-cache.outputs.cache-hit |
path: ~/.npm | Что кэшируем — каталог npm на Linux |
hashFiles('**/package-lock.json') | Хэш lock-файла в ключе: изменился lock → новый кэш |
restore-keys: | Если точного ключа нет — взять ближайший префикс ${{ runner.os }}-npm- |
| после restore-keys: | Многострочный YAML — вторая строка с отступом |
Что увидите в логе cache step:
Cache restored from key: Linux-npm-a1b2c3d4...
или при первом run:
Cache not found for input keys: Linux-npm-...
Попробуйте: второй push без изменения package-lock.json — время step npm ci обычно падает.
3. Секреты — API-токен без утечки в Git
Задача: вызвать внешний API из CI, токен хранится только в Settings.
Шаг 1 — в GitHub UI:
Settings → Secrets and variables → Actions → New repository secret
| Поле | Значение |
|---|---|
| Name | API_TOKEN |
| Secret | ваш токен (строка) |
Шаг 2 — в YAML:
- name: Deploy with token
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
run: |
curl -sf -H "Authorization: Bearer $API_TOKEN" \
https://api.example.com/deploy
Разбор построчно:
| Строка | Смысл |
|---|---|
name: Deploy with token | Подпись step в UI (необязательно, но удобно) |
env: | Переменные окружения только для этого step |
API_TOKEN: ${{ secrets.API_TOKEN }} | GitHub подставит секрет перед запуском shell |
run: | | Многострочный shell-скрипт |
curl -sf | -s тихо, -f exit code ≠ 0 при HTTP 4xx/5xx — step станет красным |
$API_TOKEN | Shell-переменная из env (без ${{ }} внутри run) |
GITHUB_TOKEN — секрет создаётся автоматически на каждый run. Нужен для push в тот же репозиторий (ветка gh-pages, releases). Пишут ${{ secrets.GITHUB_TOKEN }}.
Токен в коммите остаётся в истории навсегда. Отзовите ключ, очистите историю (git filter-repo / BFG), создайте секрет заново. В YAML — только ${{ secrets.NAME }}.
Попробуйте: step run: echo "token length is ${#API_TOKEN}" с секретом в env — в логе число символов, сам токен скрыт ***.
4. Артефакты — сохранить папку build/
Задача: после сборки положить dist/ в zip — скачать из UI без повторной сборки локально.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: web-dist
path: dist/
retention-days: 7
Разбор построчно:
| Строка | Смысл |
|---|---|
npm run build | Создаёт папку dist/ (Vite, Vue CLI) или build/ (CRA, Docusaurus) |
upload-artifact@v4 | Упаковывает папку и загружает в хранилище GitHub |
name: web-dist | Имя zip в UI run → Artifacts |
path: dist/ | Что положить в zip |
retention-days: 7 | Удалить через 7 дней (экономия квоты) |
Что увидите: внизу страницы run ссылка Artifacts → web-dist — скачать zip.
Передача между job:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: site
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: site
path: dist/
- run: ls -la dist/
Разбор связки:
needs: build— jobdeployстартует после успешногоbuild.download-artifact— распаковывает zip вdist/на новой ВМ (у каждого job свой runner).
5. Условный деплой только с main
Задача: тесты на всех ветках и PR; выкладка на Pages — только push в main.
name: Test and deploy
on:
push:
branches: [main, develop]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci && npm test
deploy:
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci && npm run build
- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
publish_branch: gh-pages
Разбор построчно — job deploy:
| Строка | Смысл |
|---|---|
needs: test | Ждём зелёный job test |
if: github.event_name == 'push' && github.ref == 'refs/heads/main' | PR и push в develop → job пропускается (skipped) |
permissions: contents: write | Без этого GITHUB_TOKEN только читает репо — push в gh-pages упадёт |
peaceiris/actions-gh-pages@v4 | Community action: коммитит содержимое publish_dir в ветку gh-pages |
publish_dir: ./dist | Откуда брать HTML/CSS/JS |
publish_branch: gh-pages | Куда пушить (GitHub Pages читает эту ветку) |
Что увидите при PR: job test зелёный, deploy серый Skipped.
Попробуйте: Vite/React часто пишет в dist, Docusaurus — в build. Проверьте локально npm run build и подставьте правильную папку.
6. Официальный деплой GitHub Pages
Задача: опубликовать статику через официальные action deploy-pages (без peaceiris).
name: Deploy Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: .
- id: deployment
uses: actions/deploy-pages@v4
Разбор построчно — верх файла:
| Строка | Смысл |
|---|---|
permissions: pages: write | Право публиковать на Pages |
id-token: write | OIDC-токен для безопасной авторизации |
concurrency: group: pages | Один deploy Pages одновременно |
cancel-in-progress: true | Новый push отменяет старый незавершённый deploy |
environment: github-pages | Связь с Settings → Environments (опционально protection rules) |
url: ${{ steps.deployment.outputs.page_url }} | Ссылка на сайт в UI run |
configure-pages@v5 | Подготовка Pages |
upload-pages-artifact | Zip для Pages |
id: deployment | Имя step — ссылка steps.deployment.outputs.page_url |
deploy-pages@v4 | Финальная публикация |
path: . | Корень репо = готовый HTML. После сборки укажите path: build |
В Settings → Pages источник должен быть GitHub Actions, не «Deploy from a branch».
Попробуйте: перед upload добавьте npm ci, npm run build, смените path на build.
7. Расписание cron — ночной smoke test
Задача: раз в сутки проверить, что API отвечает 200.
name: Nightly smoke
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch:
jobs:
ping:
runs-on: ubuntu-latest
steps:
- run: |
code=$(curl -s -o /dev/null -w "%{http_code}" https://httpbin.org/status/200)
echo "HTTP code: $code"
test "$code" = "200"
Разбор построчно:
| Строка | Смысл |
|---|---|
schedule: | Запуск по cron (UTC!) |
cron: '0 6 * * *' | Каждый день в 06:00 UTC (= 09:00 МСК зимой) |
curl -s -o /dev/null | Тело ответа выбросить |
-w "%{http_code}" | Напечатать только код статуса |
test "$code" = "200" | Shell: если не 200 — exit 1 → красный step |
Формат cron (5 полей): минута час день_месяца месяц день_недели
| Пример | Значение |
|---|---|
'0 6 * * *' | Каждый день 06:00 UTC |
'0 */4 * * *' | Каждые 4 часа |
'30 8 * * 1-5' | Пн–Пт в 08:30 UTC |
Расписание работает только на default branch (main).
Попробуйте: workflow_dispatch + Run workflow — отладка без ожидания ночи.
8. Concurrency — отмена старых run
Задача: десять push подряд в PR — не ждать десять одинаковых CI, отменять устаревшие.
Добавьте на уровне workflow (рядом с on:, не внутри job):
name: Fast CI
on: [push, pull_request]
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
Разбор построчно:
| Строка | Смысл |
|---|---|
group: ci-${{ github.workflow }}-${{ github.ref }} | Одна «очередь» на пару workflow + ветка/PR |
cancel-in-progress: true | Новый run убивает предыдущий незавершённый |
Что увидите: первый run со статусом Cancelled, последний — актуальный результат.
9. Reusable workflow — один шаблон для всех студентов
Задача: преподаватель держит эталон CI, студенты подключают одной строкой.
Репозиторий org/ci-templates/.github/workflows/node-test.yml:
name: Reusable Node test
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '20'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm test
Разбор:
| Ключ | Смысл |
|---|---|
workflow_call | Этот workflow не стартует от push — только когда его вызвали |
inputs.node-version | Параметр от вызывающего workflow |
${{ inputs.node-version }} | Значение параметра внутри reusable |
В проекте студента .github/workflows/ci.yml:
name: CI
on: [push, pull_request]
jobs:
call-shared:
uses: org/ci-templates/.github/workflows/node-test.yml@main
with:
node-version: '20'
Разбор вызова:
uses: org/repo/path@main—@main= ветка шаблона (можно@v1tag).- Один репозиторий — локально:
uses: ./.github/workflows/node-test.yml.
10. Docker — проверить сборку Dockerfile
Задача: убедиться, что образ собирается на CI (для отчёта по DevOps).
name: Docker build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
push: false
tags: myapp:ci
Разбор построчно:
| Строка | Смысл |
|---|---|
setup-buildx-action | Современный движок сборки Docker |
build-push-action | docker build внутри action |
context: . | Dockerfile и контекст — корень репо |
push: false | Не пушить в registry — только проверка сборки |
tags: myapp:ci | Локальное имя образа на runner |
Попробуйте: push: true + docker/login-action + GHCR — для продвинутых проектов; теория — контейнеризация. Сначала убедитесь, что локальный Dockerfile собирается — примеры Node, Python, Go с построчным разбором.
Реальный пример — деплой этого сайта
Workflow it-knowledge-base — Docusaurus на GitHub Pages.
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: rm -rf .docusaurus .cache build
- run: npm run build
- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
publish_branch: gh-pages
force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
Разбор построчно — каждый step:
| Step | Что делает | Зачем |
|---|---|---|
checkout + fetch-depth: 0 | Клон с полной историей | Docusaurus показывает дату последнего изменения страницы |
setup-node 20 | Node LTS на runner | Совпадает с engines проекта |
npm ci | Установка по lock-файлу | Воспроизводимая сборка |
rm -rf .docusaurus .cache build | Удалить старый кэш сборки | Лечит «залипший» битый build на runner |
npm run build | Docusaurus → папка build/ | Готовый статический сайт |
peaceiris/actions-gh-pages | Push build/ в gh-pages | GitHub Pages отдаёт сайт читателям |
force_orphan: true | Ветка gh-pages без истории | Только HTML, без исходников |
user_name / user_email | Автор коммита — bot | В history видно github-actions[bot] |
Цепочка для отчёта:
push main → Actions deploy.yml → npm run build → ветка gh-pages → spirzen.ru
Подробнее с DNS и Settings — кейс GitHub Pages.
Badge «CI passing» в README
Задача: в README красивая картинка статуса последнего run.

Разбор URL:
| Часть | Замените на |
|---|---|
USER | ваш логин GitHub |
REPO | имя репозитория |
node-ci.yml | имя файла workflow без пути |
Пример для этого репозитория:

Статус обновляется после каждого run. Красный badge = последний run упал.
Частые ошибки — симптом и лечение
| Симптом в логе | Частая причина | Что сделать |
|---|---|---|
| Workflow не появился в Actions | Файл не в .github/workflows/ | Проверьте путь и расширение .yml |
yaml syntax error | Табы вместо пробелов | Переведите отступы на 2 пробела |
npm ERR! Missing script: "test" | Нет "test" в package.json | Добавьте скрипт или замените команду |
npm ci can only install with package-lock | Нет lock-файла | npm install локально, закоммитьте lock |
Permission denied при gh-pages | Нет permissions: contents: write | Добавьте блок permissions |
No such file or directory: dist | Неверная папка сборки | Локально npm run build, посмотрите имя папки |
| Secret пустой | Опечатка secrets.API_TOKEN | Имя = как в Settings, регистр важен |
| Сайт без CSS на Pages | Неверный base / homepage | Для project site нужен /repo-name/ в конфиге |
| Два deploy подряд | Нет concurrency | cancel-in-progress: true |
| PR без Checks | Только push в workflow | Добавьте pull_request в on: |
Откройте упавший step → прокрутите вверх от ##[error] → найдите первую строку с Error:, FAIL или exit code 1. Часто ошибка в step выше, чем кажется (например, npm ci упал из-за lock-файла).
Шпаргалка — что вставить в отчёт по лабораторной
Краткий текст для пояснительной записки (адаптируйте под свой проект):
В репозитории настроен CI на GitHub Actions. Файл
.github/workflows/node-ci.ymlописывает pipeline: при push и pull request запускается job на виртуальной машинеubuntu-latest, выполняется checkout кода, установка Node.js 20, командаnpm ciдля установки зависимостей иnpm testдля автоматического тестирования. Результат отображается во вкладке Actions и в статусах pull request. Это обеспечивает непрерывную интеграцию (CI) — проверку кода на каждое изменение без ручного запуска тестов на машине разработчика.
Куда дальше
| Задача | Материал |
|---|---|
| Теория CI/CD, runner, events | GitHub Actions |
| Все ключи YAML, contexts | Справочник |
| E2E в браузере | Playwright и Actions |
| Git, PR, branch protection | Основы Git |
| Деплой сайта с нуля | Кейс GitHub Pages |
| HTTP в job (curl) | curl / fetch — примеры |
| Bash-скрипты в step | Bash — однострочники, production |
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Практическая карта типовых IT-задач: термины, пошаговое внедрение, проверка качества и типичные ошибки. Простой консольный чат на C# — учебное приложение с сокетами: TCP между клиентом и сервером, многопоточность и обмен сообщениями в консоли. Примеры вёрстки на HTML и CSS с разбором: центрирование, Flexbox, Grid, формы, шапка, подвал и адаптив для учебы и портфолио. Перед началом работы обязательно изучите главу Turtle . Галерея 3D-фигур на Panda3D — карточки, куб, пирамида, сфера, сетки и составные сцены; код для локального запуска. Готовые docker-compose.yml с разбором каждой строки — nginx, PostgreSQL, Redis, WordPress, MongoDB. Примеры для школьников и студентов: postgres example, поднять базу локально, app + db. Примеры nginx.conf для статики, reverse proxy, React/Vue SPA, PHP, SSL и балансировки — построчный разбор директив, проверка curl и типичные ошибки для лабораторных и VPS. dockerfile example — 10 готовых Dockerfile с построчным разбором: node, python, golang, react nginx, spring boot, php, dotnet. Для студентов, лабораторных и docker build с нуля. PromQL example — готовые запросы Prometheus и Grafana с построчным разбором: up, rate, node_exporter cpu, memory, disk, http_requests_total, histogram_quantile p99, алерты. Для студентов, лабораторных и devops docker compose. Готовые манифесты Kubernetes с разбором каждой строки — Pod, Deployment, Service, ConfigMap, Secret, Ingress. Примеры для Minikube, kind и kubectl apply. Примеры графиков Matplotlib на Python для школьников и студентов — sin, cos, парабола, столбцы, scatter, гистограмма, подграфики; код с подробным разбором. Примеры pandas на Python для школьников и студентов — DataFrame, фильтрация, groupby, очистка, merge, сводные таблицы и экспорт; код с подробным разбором каждой строки.Готовые решения
Простой консольный чат на CSharp
HTML + CSS — готовые макеты
Примеры фигур Turtle на Python
Примеры фигур Panda3D на Python
Docker Compose — готовые стеки
Nginx — конфиги под задачу
Dockerfile — 10 типовых образов
Prometheus + Grafana — запросы
Kubernetes YAML — минимальные манифесты
Matplotlib — графики
Pandas — типовые операции