Blog

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:

  1. Merge albo push na główną gałąź.
  2. Ręczny build frontu / composer install na serwerze.
  3. Upload plików (FTP, panel hostingu, ad‑hoc SSH).
  4. „Sprawdzę szybko w przeglądarce” — bez powtarzalnego zestawu scenariuszy.
  5. 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):

  1. Na PR: instalacja zależności, lint/format opcjonalnie, testy z bazą w serwisie CI.
  2. Na głównej gałęzi: to samo + deploy po SSH / do platformy (rsync, artifact, container registry — zależnie od hostingu).
  3. Sekrety tylko w CI, nie w repo.
  4. Migracje jako część deployu, nie „dopiszę ręcznie później”.
  5. 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-Proto itd.) generowane URL-e assetów i redirecty potrafią wracać jako zwykłe http://. 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.