Wpisy
CI/CD w praktyce — jak automatyzacja testów i deployu odciąża codzienną robotę
Po co pipeline od pusha do produkcji, gdy „wgrać ręcznie” zajmuje kilka minut — i które elementy automatyzacji realnie skracają cykl, a które tylko robią hałas.
Przy małych i średnich projektach CI/CD często brzmi jak luksus z korporacji. Tymczasem największy koszt nie leży w setupie pipeline’u — tylko w powtarzalnej ręcznej pracy i w regresjach, które wychodzą dopiero u klienta. Poniżej opisuję, jak myślę o automatyzacji testów i wdrożeń w praktyce: ogólnie, bez przywiązania do jednego domeny czy hostingu.
Co boli bez pipeline’u
Typowy rytm bez CI/CD wygląda znajomo:
- Merge albo push na główną gałąź.
- Ręczny build frontu /
composer installna serwerze. - Upload plików (FTP, panel hostingu, ad‑hoc SSH).
- „Sprawdzę szybko w przeglądarce” — bez powtarzalnego zestawu scenariuszy.
- Gdy coś pada, cofanie zmian też jest ręczne i stresujące.
Kilka minut na jeden deploy nie brzmi źle. Problem pojawia się przy częstotliwości: kilka iteracji dziennie × zapominanie o migracji, cache’u assetów albo teście krytycznej ścieżki. Koszt to nie czas uploadu — to czas na debug produkcji i utrata zaufania do releasów.
Co ma robić sensowny CI/CD
Dla mnie pipeline ma trzy roboty, nie jedną:
1. Weryfikacja przed merge / przed deployem
Automatyczny przebieg testów (unit + feature / integracja) na czystym środowisku CI. Cel: ten sam werdykt niezależnie od tego, czy lokalnie „działało na moim Dockerze”. Typowe rzeczy, które warto złapać wcześnie: walidacja formularzy, reguły cenowe, uprawnienia, migracje schematu, regresje API.
2. Powtarzalny deploy
Jedna ścieżka: build → artefakt / sync → migracje → przełączenie. Bez checklisty w Notatniku. Im mniej decyzji w trakcie wdrożenia, tym mniej „a, zapomniałem o .env / Vite / cache”.
3. Szybki feedback dla autora zmian
CI ma krzyczeć w PR, nie dopiero gdy klient zgłosi ticket. Zielony check to nie biurokracja — to kontrakt: „ta zmiana nie rozwaliła znanych ścieżek”.
Co automatyzacja realnie ułatwia
- Mniej kontekstu w głowie. Nie musisz pamiętać kolejności kroków wdrożenia — pipeline ją egzekwuje.
- Krótszy cykl poprawka → produkcja. Po setupie push na właściwą gałąź uruchamia testy i (przy zielonym wyniku) deploy.
- Bezpieczniejsze refaktory. Gdy logika biznesowa siedzi w testach, możesz ruszać strukturę kodu bez strachu „coś gdzieś pęknie po cichu”.
- Wspólny standard środowiska. PHP, rozszerzenia, baza w jobie CI — mniej „u mnie działa, na serwerze nie”.
- Historia decyzji. Logi jobów zostają: co poszło, która migracja, który commit. Przy awarii to pierwsza linia śledztwa.
Czego nie warto automatyzować na siłę
Nie każdy check musi blokować produkcję. Długie soak / endurance, skany zależne od żywego internetu albo flaki z zewnętrznych API lepiej trzymać obok twardego gate’u — jako sygnał, nie jako veto każdego merge’a.
Podobnie: deploy przy celowo pominiętych testach (np. job skipnięty przez brak sekretów) nie powinien udawać, że „wszystko sprawdzone”. Lepiej mieć jawną regułę: skipped ≠ green.
Minimalny kształt, który zwykle się sprawdza
Dla typowej aplikacji web (np. PHP/Laravel + front build):
- Na PR: instalacja zależności, lint/format opcjonalnie, testy z bazą w serwisie CI.
- Na głównej gałęzi: to samo + deploy po SSH / do platformy (rsync, artifact, container registry — zależnie od hostingu).
- Sekrety tylko w CI, nie w repo.
- Migracje jako część deployu, nie „dopiszę ręcznie później”.
- Jasny rollback: poprzedni release / poprzedni commit da się przywrócić bez archeologii.
Szczegóły narzędzi (GitHub Actions, GitLab CI, Forge, własny runner) są wymienne. Ważny jest kontrakt: push → dowód → wdrożenie.
Typowe pułapki
- Testy zależne od Vite / assetów frontu w środowisku bez builda — trzeba je odciąć albo zbudować w jobie.
- Różnice silnika bazy (np. wyrażenia default w MySQL 8) — migracja „działa lokalnie”, pada w CI.
- HTTPS za reverse proxy. Gdy TLS kończy nginx / Cloudflare / Caddy przed aplikacją, a nie sama appka, bez zaufania do nagłówków proxy (
X-Forwarded-Protoitd.) generowane URL-e assetów i redirecty potrafią wracać jako zwykłehttp://. Często wychodzi dopiero na pierwszym deployu za CDN — zepsute CSS/JS albo pętla przekierowań. - Zbyt szeroki scope pierwszego pipeline’u. Lepiej zacząć od testów + deployu z
main/master. Dopiero potem: cache zależności w CI, testy na kilku wersjach PHP naraz, środowiska preview pod PR.
Rezultat, którego szukam
Nie „idealny DevOps”. Szukam stanu, w którym:
- codzienna zmiana nie wymaga ręcznego rytuału wdrożenia,
- regresja krytycznej ścieżki wpada w CI, zanim zobaczy ją użytkownik,
- releasy są nudne — a nudne releasy to dobry znak.
CI/CD nie zastępuje myślenia o produkcie. Zabiera z talerza powtarzalną, podatną na pomyłki robotę i zostawia czas na to, co faktycznie trzeba zaprojektować: model danych, UX, reguły biznesowe.