@@ -478,3 +478,140 @@ jobs:
478478 echo "Waiting for crates.io to index..."
479479 sleep 45
480480 done
481+
482+ # Clean up old canary releases to avoid clutter
483+ # Keeps the last 7 days of releases, or at least the last 10
484+ cleanup :
485+ name : Cleanup
486+ needs : [create-release]
487+ runs-on : ubuntu-latest
488+ permissions :
489+ contents : write
490+ packages : write
491+ env :
492+ REPO : ${{ github.repository }}
493+ OWNER : ${{ github.repository_owner }}
494+ steps :
495+ - name : Harden the runner (Audit all outbound calls)
496+ uses : step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
497+ with :
498+ egress-policy : audit
499+
500+ - name : Clean up old canary releases and tags
501+ env :
502+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
503+ run : |
504+ set -euo pipefail
505+
506+ # Configuration
507+ KEEP_DAYS=7
508+ MIN_KEEP=10
509+
510+ echo "=== Cleaning up old canary releases ==="
511+
512+ # Get all canary releases sorted by date (oldest first)
513+ RELEASES=$(gh api "repos/${REPO}/releases" \
514+ --jq '[.[] | select(.tag_name | test("canary")) | {id: .id, tag: .tag_name, date: .created_at}] | sort_by(.date)')
515+
516+ TOTAL=$(echo "$RELEASES" | jq 'length')
517+ echo "Found $TOTAL canary releases"
518+
519+ if [ "$TOTAL" -le "$MIN_KEEP" ]; then
520+ echo "Only $TOTAL releases exist, keeping all (minimum: $MIN_KEEP)"
521+ exit 0
522+ fi
523+
524+ # Calculate cutoff date (7 days ago)
525+ CUTOFF_DATE=$(date -d "-${KEEP_DAYS} days" -u +%Y-%m-%dT%H:%M:%SZ)
526+ echo "Cutoff date: $CUTOFF_DATE"
527+
528+ # Find releases older than cutoff, but ensure we keep at least MIN_KEEP
529+ OLD_RELEASES=$(echo "$RELEASES" | jq --arg cutoff "$CUTOFF_DATE" \
530+ '[.[] | select(.date < $cutoff)]')
531+ OLD_COUNT=$(echo "$OLD_RELEASES" | jq 'length')
532+
533+ # Calculate how many we can actually delete
534+ CAN_DELETE=$((TOTAL - MIN_KEEP))
535+ if [ "$OLD_COUNT" -gt "$CAN_DELETE" ]; then
536+ TO_DELETE=$CAN_DELETE
537+ else
538+ TO_DELETE=$OLD_COUNT
539+ fi
540+
541+ echo "Releases older than $KEEP_DAYS days: $OLD_COUNT"
542+ echo "Will delete: $TO_DELETE (keeping at least $MIN_KEEP)"
543+
544+ if [ "$TO_DELETE" -eq 0 ]; then
545+ echo "Nothing to delete"
546+ exit 0
547+ fi
548+
549+ # Delete oldest releases (up to TO_DELETE)
550+ echo "$OLD_RELEASES" | jq -r ".[:$TO_DELETE][] | \"\(.id) \(.tag)\"" | while read -r ID TAG; do
551+ echo "Deleting release: $TAG (ID: $ID)"
552+ gh api -X DELETE "repos/${REPO}/releases/$ID" || true
553+
554+ # Also delete the associated tag
555+ echo "Deleting tag: $TAG"
556+ gh api -X DELETE "repos/${REPO}/git/refs/tags/$TAG" || true
557+ done
558+
559+ echo "=== Cleanup complete ==="
560+
561+ - name : Clean up old GHCR images
562+ env :
563+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
564+ run : |
565+ set -euo pipefail
566+
567+ # Configuration
568+ KEEP_DAYS=7
569+ MIN_KEEP=10
570+ PACKAGE_NAME="ledger"
571+
572+ echo "=== Cleaning up old GHCR canary images ==="
573+
574+ # Get all versions of the package, filter to canary tags
575+ VERSIONS=$(gh api "orgs/${OWNER}/packages/container/${PACKAGE_NAME}/versions" \
576+ --jq '[.[] | select(.metadata.container.tags | any(test("^canary"))) | {id: .id, tags: .metadata.container.tags, date: .created_at}] | sort_by(.date)' 2>/dev/null || echo "[]")
577+
578+ TOTAL=$(echo "$VERSIONS" | jq 'length')
579+ echo "Found $TOTAL canary image versions"
580+
581+ if [ "$TOTAL" -le "$MIN_KEEP" ]; then
582+ echo "Only $TOTAL versions exist, keeping all (minimum: $MIN_KEEP)"
583+ exit 0
584+ fi
585+
586+ # Calculate cutoff date
587+ CUTOFF_DATE=$(date -d "-${KEEP_DAYS} days" -u +%Y-%m-%dT%H:%M:%SZ)
588+ echo "Cutoff date: $CUTOFF_DATE"
589+
590+ # Find versions older than cutoff
591+ OLD_VERSIONS=$(echo "$VERSIONS" | jq --arg cutoff "$CUTOFF_DATE" \
592+ '[.[] | select(.date < $cutoff)]')
593+ OLD_COUNT=$(echo "$OLD_VERSIONS" | jq 'length')
594+
595+ # Calculate how many we can delete
596+ CAN_DELETE=$((TOTAL - MIN_KEEP))
597+ if [ "$OLD_COUNT" -gt "$CAN_DELETE" ]; then
598+ TO_DELETE=$CAN_DELETE
599+ else
600+ TO_DELETE=$OLD_COUNT
601+ fi
602+
603+ echo "Versions older than $KEEP_DAYS days: $OLD_COUNT"
604+ echo "Will delete: $TO_DELETE (keeping at least $MIN_KEEP)"
605+
606+ if [ "$TO_DELETE" -eq 0 ]; then
607+ echo "Nothing to delete"
608+ exit 0
609+ fi
610+
611+ # Delete oldest versions
612+ echo "$OLD_VERSIONS" | jq -r ".[:$TO_DELETE][] | \"\(.id) \(.tags | join(\", \"))\"" | while read -r ID TAGS; do
613+ echo "Deleting GHCR version: $TAGS (ID: $ID)"
614+ gh api -X DELETE "orgs/${OWNER}/packages/container/${PACKAGE_NAME}/versions/$ID" || true
615+ done
616+
617+ echo "=== GHCR cleanup complete ==="
0 commit comments