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