Junior: питання на співбесіді з теми «Хуки, CI й автоматизація»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
5 питань
Хуки - виконувані скрипти, які Git запускає в певні моменти: перед комітом, після checkout, перед push. Лежать у .git/hooks/ (Git створює там приклади з суфіксом .sample) і мають бути виконуваними (chmod +x).
Клієнтські хуки, які використовують найчастіше:
| Хук | Коли | Типове використання |
|---|---|---|
pre-commit |
перед створенням коміту | форматування, лінтер, швидкі перевірки |
prepare-commit-msg |
перед відкриттям редактора повідомлення | підставити номер задачі з назви гілки |
commit-msg |
після введення повідомлення | перевірити формат (Conventional Commits) |
post-checkout |
після checkout/switch |
оновити залежності, очистити кеш |
pre-push |
перед відправкою на сервер | запустити тести |
Ненульовий код виходу скасовує операцію - так pre-commit може заборонити коміт:
#!/bin/sh
# .git/hooks/pre-commit
vendor/bin/pint --test || {
echo "Код не відформатовано. Запустіть vendor/bin/pint"
exit 1
}
Що отримують хуки:
commit-msg- шлях до файла з повідомленням коміту (першим аргументом);pre-push- назву й адресу віддаленого репозиторію в аргументах, а в стандартному вводі - рядки з посиланнями й SHA, які відправляються.
Важливі обмеження:
.git/hooksне потрапляє в репозиторій - хуки не поширюються командою автоматично (для цього -core.hooksPathчи інструменти на кшталт Husky і CaptainHook);- хуки легко обійти:
git commit --no-verify(чи-n) пропускаєpre-commitіcommit-msg,git push --no-verify-pre-push. Тому хуки - зручність для розробника, а гарантію дає CI; - хуки мають бути швидкими:
pre-commitна хвилину - і люди почнуть використовувати--no-verifyпостійно. Повний набір тестів - уpre-pushчи CI.
Каталог .git/ не версіонується, тож хуки, покладені в .git/hooks, живуть лише на вашій машині. Є кілька способів зробити їх спільними.
1. core.hooksPath - вбудований механізм Git:
mkdir .githooks
# покласти туди pre-commit, commit-msg... і зробити виконуваними
chmod +x .githooks/*
git config core.hooksPath .githooks
Хуки лежать у репозиторії й проходять рев'ю, але кожен розробник має один раз виконати git config. Його зручно додати в скрипт налаштування проєкту:
{
"scripts": {
"post-install-cmd": ["git config core.hooksPath .githooks || true"]
}
}
2. CaptainHook - для PHP-проєктів: конфігурація в captainhook.json, хуки встановлюються командою vendor/bin/captainhook install (або автоматично через Composer-плагін):
{
"pre-commit": {
"enabled": true,
"actions": [
{ "action": "vendor/bin/pint --test" },
{ "action": "vendor/bin/phpstan analyse --no-progress" }
]
}
}
3. GrumPHP - інший PHP-інструмент: набір готових задач (phpcs, phpstan, phpunit, перевірка повідомлень комітів), конфігурація в grumphp.yml, хуки ставить сам.
4. Husky - якщо в проєкті є Node: npx husky init створює каталог .husky/ і через скрипт prepare у package.json налаштовує core.hooksPath при кожному npm install. Часто разом з lint-staged, що запускає інструменти лише на змінених файлах.
Як обрати: PHP-бекенд без Node - CaptainHook чи GrumPHP; є фронтенд і npm install - Husky; мінімум залежностей - core.hooksPath.
Пам'ятайте: хуки - зручність, а не гарантія. Будь-хто може їх не встановити чи пропустити через --no-verify, тому ті самі перевірки обов'язково дублюються в CI.
Laravel Pint - форматувальник коду на основі PHP CS Fixer. Корисні режими:
vendor/bin/pint # виправити всі файли
vendor/bin/pint --test # лише перевірити, ненульовий код при помилках
vendor/bin/pint --dirty # лише файли з незакоміченими змінами
vendor/bin/pint --diff=main # лише файли, що відрізняються від гілки main
vendor/bin/pint --repair # виправити, але повернути ненульовий код, якщо було що виправляти
Простий pre-commit хук:
#!/bin/sh
files=$(git diff --cached --name-only --diff-filter=ACMR -- '*.php')
[ -z "$files" ] && exit 0
vendor/bin/pint $files
git add $files
git diff --cached- лише файли, додані в індекс (тобто ті, що потраплять у коміт);--diff-filter=ACMR- додані, скопійовані, змінені й перейменовані; видалені файли форматувати нема чого;git addпісля форматування - щоб виправлення потрапили в коміт.
Пастка частково доданих файлів: якщо у файлі частина змін додана в індекс (git add -p), а частина ні, то git add $files після Pint додасть у коміт і ті зміни, які ви навмисно не додавали. Варіанти:
- лише перевіряти, а не виправляти:
vendor/bin/pint --test $files- коміт блокується, розробник сам запускає Pint; - використати інструмент, що вміє працювати з частковим індексом (lint-staged ховає неіндексовані зміни на час перевірки).
--dirty у хуку - зручно, але він бере файли з будь-якими незакоміченими змінами, а не лише з індексу.
Що варто знати:
- форматування в хуку - зручність; в CI має бути
pint --test, щоб неформатований код не потрапив уmainчерез--no-verify; - конфігурація в
pint.json- однакова для хуку, CI й редактора; - великий одноразовий перехід на Pint краще зробити окремим комітом і додати його SHA у
.git-blame-ignore-revs, щобgit blameне показував форматування як автора всіх рядків.
GitHub Actions - вбудований у GitHub CI/CD. Робочі процеси (workflows) описуються в YAML у .github/workflows/ і запускаються на події: push, pull request, розклад, ручний запуск.
Основні поняття:
- workflow - файл з описом процесу;
- event (
on) - що запускає процес; - job - набір кроків, що виконується на окремій віртуальній машині (runner); jobs ідуть паралельно, якщо не вказано залежність
needs; - step - команда (
run) чи готова дія (uses) з Marketplace.
Мінімальний workflow для Laravel:
# .github/workflows/tests.yml
name: tests
on:
pull_request:
push:
branches: [main]
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
coverage: none
- run: composer install --no-interaction --prefer-dist
- run: cp .env.example .env && php artisan key:generate
- run: vendor/bin/pint --test
- run: php artisan test --compact
Що відбувається: на кожен PR і push у main GitHub піднімає чисту машину з Ubuntu, завантажує код, встановлює PHP і залежності, перевіряє стиль і запускає тести. Результат видно в PR як перевірку - зелену чи червону.
Чому це важливо:
- те, що «працює в мене», перевіряється в чистому середовищі;
- хуки можна пропустити, а CI - ні, особливо з обов'язковими перевірками в захисті гілки;
- рецензент не витрачає час на код, який не проходить тести.
Корисно знати:
- для публічних репозиторіїв стандартні runner-и безкоштовні, для приватних є місячна квота хвилин;
- секрети (ключі API) - у Settings → Secrets і доступні як
${{ secrets.NAME }}; у PR з форків секрети за замовчуванням не передаються; shivammathur/setup-php- де-факто стандарт для PHP: версії, розширення, інструменти.
Dependabot - бот GitHub, що стежить за залежностями й сам відкриває pull request-и з оновленнями. Розробнику лишається переглянути зміни, дочекатися зеленого CI і злити.
Два режими:
- security updates - PR лише для залежностей з відомими вразливостями (на основі GitHub Advisory Database);
- version updates - регулярні PR з новими версіями за розкладом.
Конфігурація для Laravel-проєкту:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: composer
directory: /
schedule:
interval: weekly
groups:
laravel:
patterns: ["laravel/*"]
open-pull-requests-limit: 5
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
Що тут налаштовано:
- екосистеми: Composer, npm і навіть версії дій у workflow GitHub Actions;
groups- кілька оновлень в одному PR (усі пакетиlaravel/*разом), щоб не тонути в десятках дрібних PR;open-pull-requests-limit- скільки PR бот тримає відкритими одночасно;schedule- як часто перевіряти.
Чому це варто робити:
- маленькі регулярні оновлення простіші за одне велике раз на рік, коли накопичилися мажорні версії й breaking changes;
- вразливості закриваються швидко, а не після інциденту;
- оновлення проходять той самий процес, що й код: CI, рев'ю, історія.
Без доброго набору тестів Dependabot корисний наполовину: зелений CI має реально означати «оновлення нічого не зламало». Тому тести - передумова для сміливих оновлень.
Корисні опції: ignore - пропускати певні пакети чи мажорні версії, cooldown - не пропонувати версію одразу після публікації, а почекати кілька днів (захист від зламаних чи скомпрометованих релізів).
Докладніше в документації: GitHub: Dependabot version updates