Prečo automatizovať nasadenie
Pri manuálnom deploye sa zodpovednosť za poradie krokov (testy, migrácie, cache, restart workerov) presúva na človeka — a človek niekedy krok vynechá. Pipeline v GitHub Actions vykoná rovnaké kroky v rovnakom poradí pri každom push, bez výnimky, a zlyhanie ktoréhokoľvek kroku zastaví celý deploy skôr, než sa rozbitý kód dostane na produkciu.
Architektúra pipeline: od commitu po produkciu
Bežná pipeline pre Laravel appku má štyri fázy, ktoré idú postupne za sebou:
- Checkout a závislosti — stiahnutie kódu,
composer install,npm ci - Testy — Pest alebo PHPUnit testovacia sada proti testovacej databáze
- Build — kompilácia frontend assetov (
npm run build) - Deploy — nahranie kódu na server cez SSH/rsync, migrácie, cache warm-up
Fáza deploy sa spustí len ak fázy testov a buildu prešli bez chyby — to je celý zmysel pipeline.
Workflow YAML
name: Deploy
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, pdo_mysql, redis
coverage: none
- name: Install Composer dependencies
run: composer install --no-interaction --prefer-dist --optimize-autoloader
- name: Copy .env
run: cp .env.testing .env
- name: Generate app key
run: php artisan key:generate
- name: Run Pest tests
run: php artisan test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Node dependencies a build assetov
run: |
npm ci
npm run build
- name: Nasadenie cez SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/myapp
bash deploy.sh
Job deploy má needs: test — GitHub Actions ho nespustí, pokiaľ testovací job neskončí úspechom.
GitHub Secrets: čo do nich patrí
Citlivé hodnoty (SSH klúč, heslá, API tokeny) sa nikdy neukladajú priamo do workflow súboru ani do repozitára. V nastaveniach repozitára (Settings → Secrets and variables → Actions) sa definujú ako zašifrované premenné, dostupné v pipeline cez ${{ secrets.NAZOV }}.
.env sa nikdy nesmie commitnúť do repozitára — obsahuje produkčné heslá k databáze a API klúče. Pre SSH deploy klúč vytvorte samostatný, len na deploy účel, s prístupom len do adresára aplikácie (princíp najmenších oprávnení).
Nasadenie bez výpadku: releases a symlink
Priamy git pull do produkčného adresára znamená, že počas sťahovania zmien môže requester dostať polovičný stav appky. Riešením je nahrávať každú verziu do nového adresára a prepnúť symlink až po dokončení všetkých krokov:
# deploy.sh na serveri
RELEASE=releases/$(date +%Y%m%d%H%M%S)
mkdir -p $RELEASE
cp -r current/. $RELEASE/
cd $RELEASE
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
cd ..
ln -sfn $RELEASE current # Atomické prepnutie symlinku
php artisan queue:restart # Workery zoberú nový kód pri ďalšom jobe
Príkaz ln -sfn prepne symlink atomicky — requesty počas prepínania dostanú buď úplne starú, alebo úplne novú verziu, nikdy zmiešanú.
Migrácie v pipeline — opatrne
migrate --force v automatizovanej pipeline spustí migrácie bez interaktívneho potvrdenia. Pri migráciách, ktoré menia veľké tabuľky (napr. ALTER TABLE na miliónoch riadkov), zvážte spustenie migrácie manuálne mimo pipeline alebo s explicitným maintenance oknom — automatický deploy nie je miesto na experimentovanie s rizikovou zmenou databázovej schémy.
Cache warm-up a queue restart po deployi
Po každom nasadení treba znova vygenerovať cache, ktorá obsahuje skompilovanú konfiguráciu, routy a views z predošlej verzie kódu:
php artisan config:cache— zlúči všetky config súbory do jedného cachovaného PHP súboruphp artisan route:cache— zrýchli registráciu routov, vyžaduje, aby routy neobsahovali closuresphp artisan view:cache— predkompiluje Blade šablónyphp artisan queue:restart— signalizuje queue workerom, aby po dokončení aktuálneho jobu reštartovali a načítali nový kód
Bez queue:restart by queue workery (spustené ako dlhotrvajúci proces, podobne ako pri Octane) ďalej obsluhovali starý kód v pamäti.
Notifikácie o nasadení
Krok navyše v deploy jobe odošle správu do Slacku alebo Discordu po úspešnom (alebo neúspešnom) nasadení — tím okamžite vie, že nová verzia je na produkcii:
- name: Notifikácia do Slacku
if: always()
uses: slackapi/slack-github-action@v1.27.0
with:
payload: |
{
"text": "Deploy ${{ job.status }}: ${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: always() zabezpečí, že notifikácia sa odošle aj pri zlyhaní deploy jobu — to je presne ten prípad, kedy chcete vedieť o probléme najrýchlejšie.
Záver: checklist pred zapnutím pipeline
- Testovacia sada (Pest/PHPUnit) prebieha v CI proti samostatnej testovacej databáze, nie produkčnej
- Žiadny secret ani
.envnie je commitnutý v repozitári - SSH deploy klúč má prístup len do adresára aplikácie, nie root prístup na server
- Deploy používa release adresáre + atomický symlink, nie priamy
git pulldo produkčného adresára - Po deployi sa vždy vykoná cache warm-up a
queue:restart - Tím dostáva notifikáciu o výsledku každého nasadenia