#!/usr/bin/env bash # # Wdrozenie na serwer produkcyjny. # # Wolane przez Gitea Actions (`.gitea/workflows/deploy.yml`) po kazdym pushu # na `main`, ale dziala takze recznie. Kopia na serwerze lezy w # `/opt/akademia/deploy-prod.sh` i musi byc zgodna z ta wersja. # # NAZWA PROJEKTU JEST OBOWIAZKOWA # ----------------------------------------------------------------------------- # `-p akademia` NIE jest ozdobnikiem. Katalog aplikacji nazywa sie # `/opt/akademia/app`, wiec bez tej flagi compose bierze nazwe projektu # z katalogu i staje sie projektem `app`. Na tym serwerze `app` to **inna # aplikacja tego samego wlasciciela**, a komenda bez `-p` tworzy w niej obce # kontenery albo restartuje cudze uslugi. Zdarzylo sie to realnie. # set -euo pipefail APP_DIR=/opt/akademia/app LOG=/opt/akademia/deploy.log COMPOSE="docker compose -p akademia -f docker-compose.prod.yml --env-file .env.production" # Dwa deploye naraz przebudowywalyby ten sam obraz i restartowaly kontener # w polowie pracy drugiego. Blokada jest nieblokujaca: drugi przebieg konczy # sie od razu, zamiast czekac w kolejce z nieaktualnym juz kodem. exec 9>/opt/akademia/deploy.lock flock -n 9 || { echo "$(date '+%F %T') inny deploy trwa - pomijam"; exit 0; } exec >>"$LOG" 2>&1 echo "===== $(date '+%F %T') deploy start =====" cd "$APP_DIR" # Lokalne zmiany zatrzymuja wdrozenie, i to jest swiadome: `--ff-only` nizej # i tak by je odrzucil, ale robil to CICHO. Deploy konczyl sie wtedy statusem # "sukces", a kod nie wchodzil na serwer: rozjazd wykrywalo sie dopiero # recznym `git log` na produkcji. Lepiej zaswiecic na czerwono i nazwac pliki. if [ -n "$(git status --porcelain)" ]; then echo "PRZERWANE: repozytorium na serwerze ma lokalne zmiany." echo "Wdrozenie nie ruszy, dopoki ktos ich nie przeniesie albo nie odrzuci:" git status --short echo echo "Zmiana warta zachowania: przenies ja do repozytorium." echo "Zmiana do wyrzucenia: git checkout -- " exit 1 fi git fetch --prune origin LOCAL=$(git rev-parse @) REMOTE=$(git rev-parse '@{u}') if [ "$LOCAL" = "$REMOTE" ]; then echo "Brak zmian ($LOCAL) - koniec." exit 0 fi echo "Aktualizacja $LOCAL -> $REMOTE" # --ff-only: nigdy nie scalamy na produkcji. Merge z konfliktem zostawilby # repozytorium w stanie polowicznym, a rozwiazywanie go przez SSH na zywej # instancji jest ostatnia rzecza, ktora ktokolwiek chce robic. git merge --ff-only origin/main $COMPOSE up -d --build echo "===== $(date '+%F %T') deploy OK (v $REMOTE) ====="