#!/usr/bin/env bash # Weekly housekeeping — root cron on the VPS (docs/40-DEPLOYMENT.md §4): # 0 4 * * 0 /opt/erpcore/prune.sh >> /var/log/erpcore/prune.log 2>&1 # Keeps the newest KEEP backend releases and frontend images (anything currently deployed in # either environment is always kept), prunes build cache, old database backups and E2E reports. # shellcheck source=common.sh source "$(dirname "${BASH_SOURCE[0]}")/common.sh" KEEP="${KEEP:-5}" with_build_lock # never delete a release or image that a running job is producing live=() for e in test release; do load_env "$e" live+=("$(read_state backend)" "$(read_state frontend)") if [[ -L "$CURRENT_LINK" ]]; then live+=("$(basename "$(readlink "$CURRENT_LINK")")"); fi done is_live() { local h for h in "${live[@]}"; do if [[ -n "$h" && "$h" == "$1" ]]; then return 0; fi done return 1 } if [[ -d "$RELEASES_DIR" ]]; then n=0 while IFS= read -r dir; do name="$(basename "$dir")" if [[ "$name" == *.tmp ]]; then log "removing abandoned build $name" rm -rf "$dir" continue fi n=$((n + 1)) if ((n > KEEP)) && ! is_live "$name"; then log "removing backend release $name" rm -rf "$dir" fi done < <(find "$RELEASES_DIR" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' | sort -rn | cut -d' ' -f2-) fi n=0 while IFS= read -r tag; do if [[ -z "$tag" || "$tag" == "" ]]; then continue; fi n=$((n + 1)) if ((n > KEEP)) && ! is_live "$tag"; then log "removing image $WEB_IMAGE_REPO:$tag" docker rmi "$WEB_IMAGE_REPO:$tag" >/dev/null || warn "could not remove $WEB_IMAGE_REPO:$tag" fi done < <(docker image ls "$WEB_IMAGE_REPO" --format '{{.Tag}}') # newest first docker image prune -f >/dev/null docker builder prune -f --filter until=168h >/dev/null find "$BACKUP_DIR" -maxdepth 1 -name 'test-*.dump' -mtime +7 -delete 2>/dev/null || true find "$BACKUP_DIR" -maxdepth 1 -name 'release-*.dump' -mtime +30 -delete 2>/dev/null || true find "$E2E_REPORTS_DIR" -mindepth 1 -maxdepth 1 -type d -mtime +14 -exec rm -rf {} + 2>/dev/null || true log "prune complete"