Полный пример: lint, test, build, deploy
Собираем всё изученное в один настоящий пайплайн от пуша до прода.
Цель курса — автоматизировать всё от пуша до прода: один файл проверяет код, собирает артефакт и катит его на сервер по правилам.
Что должен делать пайплайн
- на каждый PR и push в main — прогнать
lintиtest(барьер качества); - если проверки прошли — собрать артефакт (
build); - деплоить
deployтолько изmain, с защищённым окружениемproduction; - не запускать два деплоя разом и отменять устаревшие прогоны CI.
Полный workflow
name: CI/CD
on:
push:
branches: [main]
pull_request:
concurrency:
group: cicd-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint:
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 run lint
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: "npm"
- run: npm ci
- run: npm test
build:
needs: [lint, 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 run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Деплой
run: |
echo "Выкатываю dist/ на прод"
# здесь реальная команда деплоя (ssh/облачный экшен)
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
Как это читается
lintиtestидут параллельно;testещё и размножен матрицей по версиям Node.buildждёт оба (needs: [lint, test]) и выгружает артефактdist.deployзависит отbuild, выполняется только из main (if) и привязан кproduction— здесь сработают required reviewers и секреты окружения.concurrencyотменяет устаревшие прогоны;permissions: contents: readзадаёт минимальные права по умолчанию.
Граф выполнения
Вывод:
lint ─┐
├─> build ─> deploy (только main, с апрувом)
test ─┘
Итог
- Один файл реализует полный путь: проверка → сборка → условный деплой.
- Ключевые приёмы курса работают вместе: matrix, needs, if, environment, concurrency, permissions, артефакты.
- Это и есть автоматизация «от пуша до прода» — её можно адаптировать почти под любой проект.
Проверьте себя
1. Почему job deploy в примере имеет условие if: github.ref == 'refs/heads/main'?
AЧтобы деплоить из любой ветки
BЧтобы выкатывать на прод только изменения из основной ветки main, а не из веток PR
CЧтобы ускорить сборку
DЧтобы отключить тесты
2. Почему build объявлен с needs: [lint, test]?
AЧтобы build стартовал раньше них
BЧтобы build начинался только после успешных lint и test (барьер качества перед сборкой)
CЧтобы отключить матрицу
DЭто случайная настройка
3. Что обеспечивает блок concurrency в этом пайплайне?
AШифрует артефакт
BОтменяет устаревшие прогоны той же ветки, чтобы не тратить минуты на неактуальные сборки
CСоздаёт несколько окружений
DЗапускает deploy без апрува