CI/CD: выкладка по коммиту

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

25 минут

Озвучено синтезом речи (Qwen3-TTS), голос не принадлежит человеку.

CI/CD — конвейер, который на каждый коммит сам проверяет, собирает и выкладывает сайт, причём выкладка идёт, только когда все проверки прошли.

Пятница, вечер, FTP

Вспомните, как выкладывали сайт в 2010 году: открыть программу, подключиться к серверу, перетащить файлы из одной папки в другую. Что здесь может пойти не так? Всё. Забыли один файл. Залили не ту версию. Не заметили битую ссылку. Правка уехала на живой сайт без проверки, а прежней версии нигде нет. И знает всё это один человек, который «умеет заливать».

Современный ответ называется CI/CD, и за двумя буквами скрыта простая идея: пусть выкладкой занимается машина, по записанным правилам, каждый раз одинаково.

  • CI (continuous integration, непрерывная интеграция): каждое изменение сразу автоматически собирается и проверяется. Небольшие правки, частые проверки, и ошибка находится, пока свежа.
  • CD (continuous delivery или deployment): проверенная версия автоматически доходит до людей. При доставке (delivery) версия всегда готова, а последнее нажатие «выкатить» делает человек. При развёртывании (deployment) после зелёных проверок сайт обновляется сам. Для небольшого сайта обычно выбирают второе.

Для вас это значит, что правка сайта превращается из ритуала в коммит: сохранили изменение в репозитории (вы знаете Git как способ хранить версии), отправили в основную ветку, и дальше всё идёт само.

Станции конвейера

Конвейер это цепочка станций, и каждая что-то проверяет или делает. Если станция «заклинила» (красная), дальше ничего не идёт.

  1. Запуск: событие, например коммит в ветку main или открытый запрос на изменение.
  2. Проверки: битые ссылки, ошибки разметки, тесты, доступность, наличие нужных страниц.
  3. Сборка: превращает исходники в готовый сайт (о сборке вы читали в части про JavaScript).
  4. Предпросмотр: черновик по временному адресу, чтобы посмотреть глазами. Многие платформы делают его на каждый запрос на изменение.
  5. Выкладка: замена живого сайта, но только когда всё предыдущее зелёное.
  6. Уведомление: сообщение в чат или на почту: «вышло» или «упало на проверке ссылок».

Запустите изменение на схеме. Потом заклините разные станции и сравните с выкладкой вручную: там никто не останавливает плохую правку. Включите «ошибку, которую проверки не видят» и нажмите «Откатить».

Конвейер выкладки: где он останавливается

Нажмите на станцию, чтобы «заклинить» её, потом запустите.

  1. Вы сохранили правку и отправили её в основную ветку (push).

  2. Ссылки, разметка, страница согласия на обработку данных.

  3. Собирает страницы: Главная, Услуги, Контакты.

  4. Выкладывает черновик по временному адресу, чтобы посмотреть глазами.

  5. Заменяет живой сайт новой версией, когда всё выше прошло.

  6. Пишет в чат или на почту: что выложено или что упало.

Результат появится после запуска.

Проверьте себя: почему выкладка стоит после проверок, а не рядом с ними?

Чтобы плохая версия не попала на живой сайт: если любая проверка красная, до выкладки дело не доходит, и сайт остаётся прежним.

Как это выглядит: GitHub Actions

Конвейер записывают в файле. В GitHub Actions это текстовый YAML в папке .github/workflows/. Вот файл для сайта на GitHub Pages (урок про публикацию покажет его в деле):

name: Проверка и выкладка сайта
on:
  push:
    branches: [main]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: Ссылки и разметка
        run: npm run check:links && npm run check:html
      - name: Сборка страниц
        run: npm run build
      - name: Страница политики и согласия на месте
        run: test -f dist/politika/index.html
      - uses: actions/upload-pages-artifact@v5
        with:
          path: dist
  deploy:
    needs: check
    runs-on: ubuntu-latest
    environment: github-pages
    steps:
      - uses: actions/deploy-pages@v5

Прочтите как инструкцию. on: push: branches: [main]: запускать при каждом коммите в main. Два задания: check (проверить и собрать) и deploy. Строка needs: check говорит, что выкладка ждёт успеха проверок, а если проверки красные, она не запустится. Каждый шаг это либо готовое действие (uses:, например получение кода), либо команда (run:). Номера версий действий (@v7, @v5) меняются: актуальные смотрите в документации (она в источниках).

Строки с npm run check:links и подобные это ваши команды: они определены в проекте. Что делает каждая, зависит от выбранных вами инструментов: проверяльщика ссылок, проверяльщика разметки, сборщика. Этот учебник проверяется так же: на каждое изменение запускаются проверки типов, тесты, проверка доступности, проверка ссылок и проверка содержимого, и только потом основная ветка выкладывается на Pages. Если на сайте есть форма, добавьте проверку, что страница политики и согласия существует (шаг в примере): так важное не потеряется при очередной правке.

GitLab записывает то же самое в файл .gitlab-ci.yml, платформы вроде Netlify, Vercel и Cloudflare Pages обходятся без файла вообще: подключили репозиторий, и они сами собирают и выкладывают на каждый коммит. Это самый простой конвейер, и для многих сайтов его хватает.

Секреты

Конвейеру нужны права: выложить на хостинг, написать в чат. Эти права записаны в токенах и ключах. Главное правило такое же, как в Docker: секреты не лежат в репозитории. Ни в файле конвейера, ни в коде, ни в README. Репозиторий читают коллеги, подрядчики, а иногда весь мир, а история Git хранит всё навсегда: удалённый файл остаётся в старых коммитах.

Секреты кладут в настройки сервиса (у GitHub это раздел Secrets and variables в настройках репозитория). В файле пишут только имя, например secrets.NOTIFY_URL, и платформа подставляет значение при запуске, скрывая его в журнале. Ещё три привычки: давать токену минимальные права (только выкладка), закреплять версии чужих действий (чужой код запускается с вашими правами) и помнить, что запросы на изменение из чужих копий репозитория секретов не получают.

Проверьте себя: почему нельзя просто удалить токен из репозитория после того, как он туда попал?

Он остаётся в истории коммитов, и любой, кто её читал или скопировал, мог его увидеть. Токен, попавший в репозиторий, считают утёкшим: его отзывают и выпускают новый.

Откат

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

  • Через Git. Команда git revert создаёт новый коммит, отменяющий плохой. Вы отправляете его в main, и тот же конвейер выкладывает прежнее поведение. Историю основной ветки не переписывают принудительной отправкой: так теряют чужую работу.
  • Через панель хостинга. Статические платформы хранят прошлые выкладки, и одну из них можно сделать живой кнопкой.
  • Сначала вернуть, потом разбираться. Минуты простоя ценнее, чем красивое понимание причины.

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

Практика

Перед вами сайт вашего проекта и под ним файл конвейера с пропусками. Допишите его: запуск по push в main, задание check со сборкой и проверками (ссылки, разметка и, если в проекте есть форма, страница политики), задание deploy с needs: check, секрет как secrets.ИМЯ. Потом напишите, что проверяет сборка для каждого раздела из брифа, и как вы будете откатывать.

Файл здесь только читается и проверяется, запустить Actions в песочнице нельзя. В следующем уроке вы выложите настоящий сайт, и этот файл вам пригодится.

Что было не так раньше

В 2010 году слова «релиз» боялись: раз в месяц, ночью, с чек-листом на шесть страниц, и один человек, у которого «всё настроено». После релиза неделя уходила на исправление найденного. Идея постоянной интеграции появилась раньше (в конце 1990-х), но обычным делом для небольших сайтов стала только когда появились бесплатные конвейеры при репозиториях. Теперь релиз скучен, и это как раз то, чего добивались.

Практика

Готовлю вашу страницу…

Тест

Вопрос 1 из 5

Расставьте станции конвейера по порядку

Расставьте по порядку кнопками «выше» и «ниже».

Карточки

Эти карточки попадут в повторение, когда вы завершите урок.

  • Что такое CI и CD?

    Ответ

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

  • Из чего состоит конвейер сайта?

    Ответ

    Запуск по коммиту, проверки (ссылки, разметка, согласие), сборка, предпросмотр, выкладка только после зелёных проверок, уведомление. Упала любая станция: дальше ничего не идёт.

  • Где хранить токены и ключи конвейера?

    Ответ

    В настройках секретов сервиса (secrets). Файл конвейера ссылается на имя, значение в репозиторий не попадает. Кто-то прочитал репозиторий, значит прочитал и всё, что в нём.

  • Как откатить плохую версию?

    Ответ

    Вернуть предыдущее: git revert плохого коммита и push (конвейер выложит прошлое) или выбрать прошлую выкладку в панели хостинга. Историю main не переписывают.

Источники

Дальше

Теперь вы знаете: CI/CD: проверка и выкладка по коммиту.