#!/usr/bin/env bash # Shared functions for retention-cleanup.sh # Can be sourced by tests for unit testing age_days() { local published="$1" epoch_pub now epoch_pub=$(date -d "$published" +%s 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%SZ" "$published" +%s 2>/dev/null || echo 0) [ "$epoch_pub" -eq 0 ] && echo 99999 && return now=$(date -u +%s) echo $(( (now - epoch_pub) / 86400 )) } parse_path() { local rel="$1" OWNER="${rel%%/*}" rest="${rel#*/}" REPO="${rest%%/*}" } read_rule() { local config="$1" branch="$2" key="$3" default="$4" v=$(jq -r --arg b "$branch" --arg k "$key" '.branches[$b][$k] // empty' "$config") [ -n "$v" ] && echo "$v" || echo "$default" } # Phase 3: apply retention rules to KEEP array, populate TO_DELETE # Reads from global KEEP array # Populates global TO_DELETE array # Usage: apply_retention apply_retention() { local config="$1" local default_max_age default_keep_min local max_age keep_min key count seen_key commit_dir report_type path local entry dir owner repo branch days default_max_age=$(jq -r '.branches.default.maxAgeDays // 90' "$config") default_keep_min=$(jq -r '.branches.default.keepMin // 5' "$config") TO_DELETE=() declare -A BRANCH_COUNTS declare -A SEEN_COMMITS declare -A DELETED_COMMITS if [ "${#KEEP[@]}" -eq 0 ]; then return fi IFS=$'\n' for entry in $(printf '%s\n' "${KEEP[@]}" | sort -t'|' -k4,4 -k5,5n); do IFS='|' read -r dir owner repo branch days <<< "$entry" max_age=$(read_rule "$config" "$branch" "maxAgeDays" "$default_max_age") keep_min=$(read_rule "$config" "$branch" "keepMin" "$default_keep_min") # Age check — per-report-type deletion if [ "$days" -gt "$max_age" ]; then echo " DELETE: ${dir} (age ${days}d > maxAge ${max_age}d, branch ${branch})" TO_DELETE+=("$dir") continue fi # keepMin — per-commit counting commit_dir=$(dirname "$dir") key="$branch" seen_key="${key}|${commit_dir}" if [ -z "${SEEN_COMMITS[$seen_key]:-}" ]; then SEEN_COMMITS["$seen_key"]=1 count="${BRANCH_COUNTS[$key]:-0}" count=$((count + 1)) BRANCH_COUNTS["$key"]=$count else count="${BRANCH_COUNTS[$key]:-0}" fi if [ "$count" -gt "$keep_min" ]; then if [ -z "${DELETED_COMMITS[$commit_dir]:-}" ]; then DELETED_COMMITS[$commit_dir]=1 report_type="${dir##*/}" echo " DELETE: ${commit_dir} (kept ${keep_min}/${count} commits, exceeds keepMin, branch ${branch})" TO_DELETE+=("$commit_dir") fi fi done unset IFS }