From cf24c4d47346773fa29e8cf02d8fc5e8a47e2c8e Mon Sep 17 00:00:00 2001 From: migatu Date: Wed, 26 Aug 2026 20:13:27 +0200 Subject: [PATCH] =?UTF-8?q?ci:=20buduj=20tylko=20zmienione=20us=C5=82ugi?= =?UTF-8?q?=20i=20sprz=C4=85taj=20po=20sobie=20na=20runnerze?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rejestr obrazów rósł, bo `build.yaml` budował CZTERY obrazy przy każdym pushu do mastera, niezależnie od tego, co się zmieniło. Zmiana w samej prezentacji dawała nowe wersje data, logic i astrodemo — identyczne co do zawartości, różniące się wyłącznie tagiem. Render i silnik B miały filtry ścieżek od początku (build-render.yaml, build-swisseph.yaml) i budują się tylko przy własnych zmianach. Ta zmiana przenosi tę samą zasadę do głównego pipeline'u, licząc różnicę wobec poprzedniego commita. Kontekstem budowania każdego obrazu jest wyłącznie `./services/`, więc porównanie ścieżek jest dokładne, a nie przybliżone. Sprawdzone na ośmiu ostatnich commitach mastera: dwa refaktory prezentacji dają sam `presentation`, poprawka Dockerfile'a astrodemo daje samo `astrodemo`, a commit ruszający link_crypto w pięciu usługach — komplet. Bez porównania (pierwszy commit, przepisana historia) budujemy wszystko: lepiej zbudować za dużo niż wypuścić obraz ze starym kodem pod nowym tagiem. SKUTEK UBOCZNY DO ŚWIADOMOŚCI: tagi w kustomization mogą się teraz rozjechać między usługami, bo nie każda dostaje nową wersję z każdego commita. Tak ma być — image-updater śledzi każdy obraz osobno i przypina to, co istnieje. ZABEZPIECZENIE PRZED CICHYM POMINIĘCIEM. Usługa, której nie ma na żadnej liście, nigdy się nie zbuduje i nikt tego nie zauważy: brak obrazu wygląda potem na problem z rejestrem albo z siecią. Ten sam mechanizm kosztował nas już raz, przy liście obserwowanych obrazów w image-updaterze. Pętla po `services/*/` zatrzymuje budowanie i mówi wprost, co dopisać. Sprawdzone także od strony negatywnej — podstawiony katalog nowej usługi kończy przebieg kodem 1. SPRZĄTANIE NA RUNNERZE, w build.yaml i w build-render.yaml, z `if: always()` — bo to po NIEUDANYM budowaniu zostaje najwięcej śmieci, a kolejny przebieg zaczyna od mniejszego zapasu miejsca niż poprzedni. Tak zatkał się dysk przy renderze z TeX Live. Filtr `until=168h` zostawia tydzień, więc warstwy bazowe i cache przeżywają i build nie zaczyna od zera. Co-Authored-By: Claude Opus 5 --- .gitea/workflows/build-render.yaml | 11 ++++ .gitea/workflows/build.yaml | 83 ++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/build-render.yaml b/.gitea/workflows/build-render.yaml index 7261c4e..eacbd9e 100644 --- a/.gitea/workflows/build-render.yaml +++ b/.gitea/workflows/build-render.yaml @@ -32,3 +32,14 @@ jobs: docker push $IMG:$TAG docker push $IMG:latest echo "Zbudowano i wypchnieto: $IMG:$TAG (+ latest)" + + # Sprzątanie ZAWSZE, także po nieudanym budowaniu. Ten obraz dźwiga TeX Live + # i to właśnie na nim runner zatkał się kiedyś na „no space left on device" — + # a po nieudanym buildzie zostaje najwięcej śmieci. + - name: Sprzątanie po budowaniu + if: always() + run: | + docker system df || true + docker system prune -af --filter "until=168h" || true + docker builder prune -f --filter "until=168h" || true + docker system df || true diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 8d9d9b0..ecc2ae5 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -1,21 +1,96 @@ name: build + +# Buduje obrazy usług, które dzielą warstwę logiczną i łącze: data, logic, +# presentation, astrodemo. Render i silnik B mają własne pipeline'y, bo są ciężkie +# i rzadko się zmieniają (build-render.yaml, build-swisseph.yaml). on: push: branches: [master] + jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + # Dwa commity, bo porównujemy z poprzednim. Domyślny płytki klon ma + # jeden i `HEAD^` w nim nie istnieje. + fetch-depth: 2 + - name: Login run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login gitea.czernobog.pl -u gitea --password-stdin - # astrodemo dołącza do tej samej pętli: dzieli warstwę logiczną i łącze, - # więc jego obraz ma powstawać z tego samego commita co reszta produktu. - - name: Build & push (data, logic, presentation, astrodemo) + + - name: Build & push (tylko usługi, które się zmieniły) run: | + set -eu TAG=${GITHUB_SHA::8} - for SVC in data logic presentation astrodemo; do + USLUGI="data logic presentation astrodemo" + # Usługi z własnym pipeline'em — celowo poza tą pętlą. + OSOBNE="render engine-swisseph" + + # Usługa, której nie ma na żadnej z list, nigdy się nie zbuduje i NIKT + # tego nie zauważy: brak obrazu wygląda potem na problem z rejestrem. + # Ten sam mechanizm już nas kosztował przy liście obserwowanych obrazów + # w image-updaterze. Lepiej zatrzymać budowanie i powiedzieć wprost. + for KATALOG in services/*/; do + NAZWA=$(basename "$KATALOG") + case " $USLUGI $OSOBNE " in + *" $NAZWA "*) ;; + *) echo "BŁĄD: usługa '$NAZWA' nie jest na żadnej liście budowania." + echo "Dopisz ją do USLUGI w tym pliku albo daj jej własny workflow" + echo "(jak render i engine-swisseph), zależnie od tego, czy ma" + echo "powstawać z każdego commita produktu." + exit 1 ;; + esac + done + + # Kontekstem budowania każdego obrazu jest WYŁĄCZNIE ./services/, + # więc zmiana poza tym katalogiem nie może wpłynąć na jego zawartość. + # Dzięki temu porównanie ścieżek jest dokładne, a nie przybliżone. + if POPRZEDNI=$(git rev-parse --verify HEAD^ 2>/dev/null); then + ZMIENIONE=$(git diff --name-only "$POPRZEDNI" HEAD) + else + # Pierwszy commit albo przepisana historia — nie ma z czym porównać, + # więc budujemy wszystko. Lepiej zbudować za dużo niż wypuścić obraz + # ze starym kodem pod nowym tagiem. + echo "Brak poprzedniego commita — buduję komplet." + ZMIENIONE="" + fi + + # Zmiana w samym pliku workflow dotyczy wszystkich obrazów naraz. + if [ -z "$ZMIENIONE" ] || echo "$ZMIENIONE" | grep -q '^\.gitea/workflows/build\.yaml$'; then + DO_BUDOWY="$USLUGI" + else + DO_BUDOWY="" + for SVC in $USLUGI; do + if echo "$ZMIENIONE" | grep -q "^services/$SVC/"; then + DO_BUDOWY="$DO_BUDOWY $SVC" + fi + done + fi + + if [ -z "$(echo "$DO_BUDOWY" | tr -d ' ')" ]; then + echo "Żadna z usług się nie zmieniła — nie ma czego budować." + echo "Wdrożone tagi zostają na poprzednich wersjach, i tak ma być." + exit 0 + fi + + echo "Buduję:$DO_BUDOWY (tag $TAG)" + for SVC in $DO_BUDOWY; do docker build -t gitea.czernobog.pl/gitea/astrololo-$SVC:$TAG ./services/$SVC docker push gitea.czernobog.pl/gitea/astrololo-$SVC:$TAG done echo "Tag: $TAG" + + # Sprzątanie ZAWSZE, także po nieudanym budowaniu — to właśnie po awarii + # zostaje najwięcej śmieci, a kolejny przebieg zaczyna od mniejszego zapasu + # miejsca niż poprzedni. Tak zatkał się dysk przy budowaniu rendera. + - name: Sprzątanie po budowaniu + if: always() + run: | + docker system df || true + # `until=168h` zostawia tydzień: warstwy bazowe i cache z ostatnich dni + # przeżywają, więc kolejny build nie zaczyna od zera, a stare znikają. + docker system prune -af --filter "until=168h" || true + docker builder prune -f --filter "until=168h" || true + docker system df || true