itdepends
эссе
🚧 Это заметка в работе, выводы могут измениться

Как CI/CD три дня молчал в Telegram, а я не замечал

3 мин чтения 402 слов зависит

Идеальная автоматизация — та, которую ты проверяешь только когда что-то пошло не так.

Сегодняшняя история про то, как я настроил пайплайн деплоя блога, добавил отправку уведомлений о новых постах в Telegram-канал, увидел в логах [notify-telegram] No new blog posts found. и подумал: «Ну нет новых постов, значит всё ок».

Прошло три дня.. Два поста опубликованы на сайте. В канале — тишина.

Как это работало (в теории)

После каждого пуша в main GitHub Actions делал следующее:

  1. Проверял типы и картинки
  2. Собирал Docker-образ и пушил в GHCR
  3. Деплоил на VPS
  4. Запускал node scripts/notify-telegram.js

Скрипт нотификации брал git diff --name-only --diff-filter=A HEAD~1 HEAD, искал .md файлы в src/content/blog/, парсил frontmatter и отправлял пост в канал.

Выглядит логично, правда?

Как это работало (на практике)

А на практике HEAD~1 HEAD смотрит только на последний коммит. Если я запушил три коммита — с постом, с фиксом типографики и с обновлением зависимостей — то скрипт проверял diff только между фиксом и обновлением зависимостей. Пост оставался невидимым.

Ещё веселее: GitHub Actions с fetch-depth: 2 грузил всего два последних коммита. Если в них не было .md — скрипт благополучно ничего не находил и завершался с кодом 0. CI был зелёным. Всё хорошо. Никаких ошибок.

Самый опасный баг — тот, который не ломается, а просто молча не работает.

Отладка

Я обратил внимание только когда логи внезапно стали слишком короткими. Зашёл в Actions, открыл последний ран — notify-telegram отработал за 2 секунды и вывел:

[notify-telegram] No new blog posts found.

При этом на сайте уже висели два свежих поста.

Проблема оказалась в двух местах:

  1. Логика range: HEAD~1 HEAD вместо range от предыдущего пуша до текущего
  2. Shallow clone: fetch-depth: 2 не давал истории для нормального diff

Что починил

Вместо HEAD~1 HEAD — использую GITHUB_EVENT_BEFORE и GITHUB_SHA:

git diff --name-only --diff-filter=A \
  ${GITHUB_EVENT_BEFORE}..${GITHUB_SHA} \
  -- src/content/blog/

Вместо fetch-depth: 2 — поставил fetch-depth: 0 в checkout-шаге. Для небольшого репозитория разницы во времени нет, а diff работает корректно.

Ещё добавил возможность ручной отправки через FORCE_POST_FILE, на случай если нужно запостить что-то без коммита.

Что в итоге

Сейчас пайплайн видит все новые посты во всём range пуша, а не только в последнем коммите. И отправляет их все, если вдруг кто-то решит запушить несколько постов разом.

Проверяйте автоматизацию не по цвету галочки, а по результату. Зелёный CI — это хорошо, но зелёный CI с пустым каналом — это просто красиво оформленное молчание.

Поделиться: Telegram