Kategoria: Automatyzacja i autonomia
Najtrudniejsze pytanie po awarii automatyki w domu nie brzmi „co się zepsuło”, tylko: „co się zmieniło?”.
Wszystkie liczby w tym tekście są policzone, nie szacowane, na jednej maszynie, czyli tej, która prowadzi mój dom: dziewięć projektów docker compose i 32 kontenery, stan z października 2026. W tym miesiącu nie wypuściłem ani jednej nowej funkcji. Cztery tygodnie poszły na to, czego w domu nikt nie wymaga: kontrolę wersji, testy i bramki wokół każdej zmiany.
Co trafiło do repozytorium
Rok pracy, który istniał tylko na jednej maszynie
Pierwsze zadanie było najprostsze w całym miesiącu: skomitować rok pracy. Drzewo robocze działało od miesięcy ze zmianami, które istniały wyłącznie na tym jednym dysku: bez historii, bez drogi powrotnej, bez odpowiedzi na pytanie z pierwszego akapitu.
Repozytorium od razu pokazało coś o moim porządkowaniu: reguły ignorowania kłamały. Jedna linia wykluczała katalog core/ i po cichu wykluczała razem z nim prawdziwy, śledzony kod. Ogólna reguła na *.json ukrywała śmieci, a w tym samym ruchu dziewięć dashboardów i dwa eksporty przepływów, które chciałem zachować. Na repozytorium, które ukrywa przed autorem pliki, nie da się postawić żadnej bramki. Automatyzacje, które zostały w eksploatacji, zebrałem osobno: 10 automatyzacji, które faktycznie działają.
Jeden plik, z którego odtworzę maszynę
112 paczek i jedna przypięta wersja Pythona
System instaluje się dziś z jednego pliku: 112 paczek w dokładnych wersjach i jedna przypięta wersja Pythona. Maszyna prowadząca dom da się więc odbudować z pliku, zamiast pozostawać jedyną, na której kiedykolwiek dała się uruchomić.
Dla projektu hobbystycznego to przesada. Dla czegoś, co ma działać za pięć lat, to różnica między aktywem a pamiątką. Tę samą zasadę zastosowałem wcześniej do danych: osiem baz danych za jedną drogą dostępu.
Osiem bramek, przez które przechodzi zmiana
Integrację ciągłą uruchamiam na własnym runnerze, na tej samej maszynie co system, bo moje dane nie wychodzą z domu. Pracuje osiem zadań i wszystkie osiem blokuje zmianę:
- analiza statyczna kodu,
- skan sekretów,
- walidacja wstępna,
- testy jednostkowe,
- kontrola kontraktu API,
- skan bezpieczeństwa zależności,
- walidacja plików YAML,
- budowa obrazu Docker.
Pipeline wykrył najpierw nie błąd w automatyzacji, a błąd w moim własnym teście. Test czytał prawdziwy plik z tokenem opaski, obecny na mojej maszynie i nieobecny w czystym klonie repozytorium. U mnie przechodził, w czystym środowisku nie przeszedł, a przy okazji okazało się, że zapisuje ten token dwukrotnie. Pipeline potrzebował dziesięciu minut, żeby pokazać błąd, który trwał miesiącami.
Żadnej reguły nie ustawiłem od razu jako blokującej: najpierw czyszczę mechanicznie, potem włączam regułę. Zanim weszła bramka odrzucająca białe znaki na końcu linii, znormalizowałem 418 plików jednym commitem. Audyt objął też dokumentację, bo dokumentacja jest testem, którego nikt nie uruchamiał: opisywała błędny model domyślny i błędne nazwy baz danych.
Droga powrotna i to, czego nie automatyzuję
Wdrożenie nadal wykonuję ręcznie
Drogą powrotną jest historia w repozytorium: każdą zmianę da się dziś wskazać i cofnąć do commita, o którym wiem, że działał. Wcześniej takiej drogi nie było, więc zepsutą zmianę naprawiałem na żywo, na działającym budynku. Siedem lat tej instalacji pokazało, że awarie fizyczne potrafię przewidzieć; zmiana w logice to inna klasa ryzyka.
Ciągłego wdrażania nadal nie ma i jest to decyzja, nie zaległość. Obrazy wgrywam ręcznie, bo automatyzowanie wdrożenia, zanim pipeline zasłuży na zaufanie, oznacza tylko szybsze psucie. Projekt tej części, obejmujący wersjonowane tagi obrazów, odtworzenie kontenera z kontrolą stanu zdrowia i wycofanie zmiany, jest gotowy i czeka. Gdzie przebiega granica między zgodą a samodzielnym działaniem, opisałem przy okazji miesiąca, w którym system przestał pytać.
Co kupiły te cztery tygodnie
„Zweryfikowane” w miejsce „wygląda dobrze”
| Pozycja (policzona, październik 2026) | Stan |
| Blokujące bramki w pipeline | 8, wcześniej 0 |
| Paczki zablokowane w jednym pliku | 112 |
| Testy w zestawie | 75 |
| Czas zestawu jednostkowego | z 54 s do około 2 s |
| Skrypty sprawdzone składniowo / uruchomione na próbę | 435 / 375 |
| Pliki znormalizowane przed bramką | 418 |
| Kontenery / stacki / niezdrowe | 32 / 9 / 0 |
Na koniec miesiąca przeprowadziłem pełną aktualizację wszystkich stacków. Przypięte wersje baz danych zostawiłem świadomie bez zmian, bo bezpieczeństwo danych jest ważniejsze niż ich świeżość. Wynik: 32 kontenery działające, 14 obrazów faktycznie zmienionych, zero niezdrowych, zero nieoczekiwanych zatrzymań, każda usługa sprawdzona funkcjonalnie, skróty obrazów porównane przed i po.
Te cztery tygodnie nie kupiły żadnej nowej możliwości. Kupiły prawo do napisania „zweryfikowane” tam, gdzie wcześniej pisałem „wygląda dobrze”. Nie mam liczby oszczędzonego czasu i nie zamierzam jej szacować. Zwrotem jest zdjęte ryzyko, które nie pokazuje się na żadnym wykresie.
Restart nie naprawi aplikacji, która po prostu zużywa pamięć
Bramka sprawdza kształt zmiany, nie jej sens. Najlepszy przykład z tego miesiąca nie przeszedł przez żadną z ośmiu: mój strażnik zasobów restartuje kontenery przy wysokiej presji na pamięć. Przez kilka dni restartował co godzinę jedną usługę Javy, bo ta jest zawsze największym konsumentem pamięci. Żaden restart nie zwalniał niczego, a usługa była wyłączana na minutę. Heurystyka była poprawna, a działanie bezużyteczne, i żadna analiza statyczna tego nie wyłapie.
Reszta otwartych pozycji jest tej samej klasy. Pięć obrazów kontenerów buduje się bez pliku blokad, więc przebudowa jest odtwarzalna tylko częściowo. Dwa ostrzeżenia o zależnościach ignoruję świadomie, ponieważ oba są przechodnie i nie mają poprawki u źródła. Zabezpieczenie gałęzi nie jest u mnie regułą, a konwencją, bo tej opcji nie ma w moim planie.
Najważniejszego pipeline nie rozstrzyga wcale: czy dana automatyzacja powinna w ogóle istnieć i ile wolno jej robić bez pytania. Na to odpowiada poziom, na którym dopuszczam ją do działania, opisany w tekście pięć poziomów od automatyzacji do autonomii.