mysurik.ru

Git хуки: как я автоматизировал деплой на сервер одной командой

Git хуки как я автоматизировал деплой на сервер одной командой

Вечная проблема «залить файлы на сервер»

Раньше я обновлял сайт так: правил код локально, открывал FileZilla, перетаскивал файлы на сервер. Если забыл какую-то папку — сайт падал с ошибкой. Если заливал не туда — тоже проблема.

Потом я открыл для себя Git хуки. И теперь деплой выглядит так: git push production — и код сам улетает на сервер, обновляется, кеш сбрасывается.

Как это работает

На сервере создаётся bare-репозиторий, в нём вешается post-receive хук. Когда я пушаю в этот репозиторий, хук выполняет три действия:

1. Копирует новые файлы из репозитория в рабочую директорию сайта
2. Запускает composer install, если есть новые зависимости
3. Сбрасывает кеш WordPress через WP-CLI

Всё это занимает секунд 5. Раньше через FTP — минута-две.

Мой хук

Самый простой post-receive хук, который я написал:

#!/bin/bash
git --work-tree=/var/www/site --git-dir=/var/repo/site.git checkout -f
cd /var/www/site && composer install
wp cache flush

Работает безотказно уже год. Если что-то идёт не так — пушаю фикс, через 5 секунд сайт снова работает.

Безопасность

Я не храню пароли в репозитории. Все секреты в .env файле на сервере, а сам .env добавлен в .gitignore. При деплое хук копирует .env.example, если .env не существует.

Также настроил хуки на pre-commit, которые запускают линтер и проверяют синтаксис PHP. Если код кривой — коммит отклоняется. Это спасает от глупых ошибок в продакшне.

Совет

Если вы до сих пор таскаете файлы на сервер через FTP — поставьте Git и настройте деплой через хуки. Это займёт час времени, но сэкономит дни в перспективе.

Продолжу эту тему, потому что Git-хуки — это одна из тех вещей, которая кажется «для программистов», но на самом деле бесценна для любого, кто управляет сайтом или сервером. Я расскажу подробнее, как всё устроено, с какими граблями столкнулся и что в итоге получилось.

Начну с того, как я жил до хуков, чтобы ты прочувствовал разницу. Мой рабочий процесс выглядел так: правлю код на локальной машине, потом открываю FTP-клиент, нахожу нужную папку, перетаскиваю файлы. Если файлов много — процесс затягивается. Если забыл папку или залил не туда — сайт падает. Самое обидное — это когда обновляешь полсайта, а потом понимаешь, что забыл одну картинку или один файл конфигурации. Приходится снова лезть в FTP, искать, заливать. Такой подход отнимает кучу времени и нервирует.

Ещё одна беда FTP — это отсутствие истории. Ты не знаешь, что именно менялось между «работало» и «сломалось». Если что-то поехало, откатываться некуда — только вручную вспоминать, какие файлы трогал. Git решает и эту проблему: каждая правка — это коммит, и всегда можно вернуться на любой из них. Для меня это стало решающим аргументом: не просто «быстрый деплой», а «контролируемый и откатываемый деплой».

Теперь про устройство. Схема такая: на сервере создаётся «голый» (bare) репозиторий — это специальный репозиторий без рабочей копии, который служит приёмником для пуша. В нём живёт папка hooks, где лежат скрипты, срабатывающие на разные события. Нас интересует post-receive — он выполняется после того, как ты запушил коммиты. Вот этот хук и делает всю магию: забирает файлы из репозитория, раскладывает их в рабочую директорию сайта и выполняет постобработку.

Разберу сам хук по шагам, потому что понимать его стоит. Первая строка — checkout: она берёт последний коммит и раскладывает файлы в указанную папку сайта. Это сердце всего процесса. Дальше — дополнительные действия: установка зависимостей, если они изменились, и сброс кеша. У меня это composer install для PHP-зависимостей и wp cache flush для WordPress. Каждое из этих действий можно убрать или добавить под свои нужды. Скрипт простой, но именно в этой простоте его сила.

Про то, как я настраивал это в первый раз, расскажу с деталями. Нужно было: создать bare-репозиторий на сервере, настроить его так, чтобы пуш в него не блокировался (Git по умолчанию отказывается принимать пуш в неbare-репозиторий), написать хук, дать ему права на выполнение. Звучит как много шагов, но на практике — это полчаса. Я набил пару шишек: забыл сделать файл исполняемым (chmod +x) — и хук просто не срабатывал, пуш проходил, а сайт не обновлялся. Эта ошибка сбила меня с толку на вечер, пока я не сообразил проверить права.

Про безопасность — это отдельная важная тема, и я хочу остановиться на ней подробнее. Главное правило, которое я соблюдаю: никаких паролей и ключей в репозитории. Все секреты живут в .env на сервере, а сам .env добавлен в .gitignore, чтобы случайно не закоммитить. В хуке я добавил проверку: если .env нет — копируется шаблон .env.example. Так на новом сервере всё поднимается автоматически, а секреты не утекают. Это базовая гигиена, но именно на ней ломается большинство новичков.

Ещё про безопасность: не оставляй репозиторий доступным извне. Мой сервер слушает Git по SSH, и доступ к нему закрыт ключами. Никакого HTTP-доступа к репозиторию нет. Если бы он был открыт, это был бы потенциальный вектор атаки: кто-то мог бы читать код или даже пушить изменения. Поэтому: SSH + ключи, и всё. Ключи — по одному на каждого участника, доступ — строго по необходимости.

Про pre-commit хуки тоже хочу рассказать подробнее, потому что они спасают от глупых ошибок. pre-commit выполняется до создания коммита, и если он завершится с ошибкой — коммит не создастся. Я повесил туда линтер и проверку синтаксиса PHP. То есть если я написал код с ошибкой синтаксиса, Git просто не даст мне его закоммитить. Это защищает от ситуации, когда кривой код улетает в продакшн и роняет сайт. Проверки занимают секунду, а нервов экономят кучу.

Теперь про то, как этот деплой вписался в мою жизнь. Раньше обновление сайта — это ритуал с FTP, волнениями и откатами вручную. Теперь — это одна команда: git push production. Я поправил код, проверил локально, запушил — и через пять секунд сайт уже работает с новым кодом. Если что-то не так — я вижу это сразу, пушаю фикс, и всё снова работает. Никаких «понедельников, когда всё сломалось ночью». Всё прозрачно и контролируемо.

Про автоматизацию дальше: я поднял на CI-сервере проверки, которые прогоняются на каждый пуш до того, как код уйдёт в продакшн. Это, правда, уже выходит за рамки «хуков», но логически продолжает тему. Линтеры, тесты, сборка — всё это гоняется автоматически. И только если проверки прошли — пуш уходит в прод. Это можно настроить попроще, но принцип тот же: машина проверяет за тебя, а ты только пушишь.

Что бы я посоветовал новичку, который хочет перейти с FTP на Git. Не пытайся освоить всё сразу. Начни с простого: bare-репозиторий на сервере, один post-receive хук с checkout, и команда git push. Это уже даст 90% пользы: быстрый деплой и история изменений. Потом добавишь pre-commit с линтером, потом — CI. Каждый шаг простой, а вместе они превращают хаос в порядок. Не надо ждать «идеального» решения с первого раза — начни с малого.

Ещё одна деталь, которая меня приятно удивила: хуки — это просто скрипты. Ты не ограничен языком и инструментами. В постобработке можно делать что угодно: перезапустить сервис, сгенерировать документы, отправить уведомление в Telegram, сделать бэкап. Я, например, добавил в хук отправку сообщения себе, когда деплой прошёл успешно. Это удобно: прилетает подтверждение, что всё ок, и не нужно лезть на сервер проверять. Скрипт — это просто твой код, и ограничен ты только фантазией.

Про откаты скажу отдельно, потому что это то, что FTP дать не мог. Если новый код сломал сайт, я делаю git revert последнего коммита и пушаю — сайт возвращается к рабочей версии. Всё. Никакого «вспомнить, какие файлы я менял» и «поискать вчерашнюю копию». История Git — это машина времени, которая всегда под рукой. Именно этот аспект я ценю больше всего: не скорость деплоя, а спокойствие, что всегда можно откатиться.

Подведу итог. Git-хуки превратили мой деплой из рутины с FTP в одну команду. Плюсы: скорость, история, контроль, безопасность, автоматизация. Минусы — только время на первоначальную настройку, но оно окупается за первую неделю. Если ты до сих пор таскаешь файлы на сервер через FTP — очень советую попробовать. Настройка займёт вечер, зато потом ты будешь только удивляться, как жил без этого раньше.

Добавлю ещё несколько практических деталей, которые вылезли уже в процессе эксплуатации. Первое — про ветки. Сначала я пушил прямо в основную ветку, и если я торопился, кривой код иногда улетал в прод. Потом я привык работать через ветки: в отдельной ветке правлю, проверяю, потом мёржу в основную и пушу. Хук срабатывает только на пуш в основную ветку — это фильтр, который не даёт случайному экспериментальному коду попасть на сайт. Небольшая привычка, а защита серьёзная.

Второе — про скорость. Я часто слышу «деплой через хуки — это сложно». На деле сложнее объяснить, чем сделать. Весь хук — это полтора десятка строк bash. Никакого магического фреймворка. Если ты умеешь писать команды в терминале — ты умеешь писать хуки. И не обязательно делать всё сразу: можно начать с одного git checkout, а остальное добавлять по мере необходимости. Git тебе не запрещает — он просто исполняет твой скрипт.

Третье — про логирование. Я добавил в хук запись в лог: когда был пуш, какой коммит, какая ветка. Это оказалось очень полезно при разборе инцидентов: видишь, что именно и когда улетело на сервер. На FTP у меня такой картины не было вообще — только «что-то сломалось, не знаю когда». Сейчас я всегда могу посмотреть историю деплоев и понять, что изменилось.

Четвёртое — про команду в паре. Если сайтом занимаются двое, Git решает проблему конфликтов. Оба пушат в один репозиторий, и Git сам следит, кто что менял. Конфликты, конечно, случаются, но они решаются осознанно, а не «последний заливший — виноват». Это снимает кучу напряжения между участниками проекта. Для одиночки это тоже полезно, но в команде эффект особенно заметен.

И последнее — не бойся, что это «для серьёзных проектов». Хуки отлично работают и для небольшого сайта, и для личного блога. Я как раз пришёл к ним через маленький проект. Сложность не в инструменте, а в привычке. Как только ты раз переживёшь «git push — и сайт обновился», назад к FTP уже не хочется. Попробуй на тестовом проекте — и решай сам.

Ваш комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *