diff --git a/.github/workflows/cleanup-pre-releases.yaml b/.github/workflows/cleanup-pre-releases.yaml index 8aa6dbfa89..41af556e60 100644 --- a/.github/workflows/cleanup-pre-releases.yaml +++ b/.github/workflows/cleanup-pre-releases.yaml @@ -2,6 +2,12 @@ name: Cleanup Obsolete Releases (PRs and RCs) on: workflow_dispatch: + inputs: + dry_run: + description: "Dry run mode - show what would be deleted without actually deleting" + required: false + default: "false" + type: boolean schedule: - cron: "0 2 * * *" # Optional: runs daily at 2am UTC pull_request_target: @@ -24,6 +30,16 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + # Set dry run mode + DRY_RUN="${{ inputs.dry_run || 'false' }}" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "🔍 DRY RUN MODE: Will show what would be deleted without actually deleting" + else + echo "🗑️ DELETION MODE: Will actually delete obsolete tags and releases" + fi + echo "" + # This script cleans up pre-release tags and releases in two ways: # # 1. PR Prereleases (e.g., v1.2.3-pr123): @@ -34,18 +50,42 @@ jobs: # - These are deleted if the corresponding final release (e.g., v1.2.3) exists and is not a prerelease. # # Final release tags (e.g., v1.2.3) are NEVER deleted by this script. - echo "Fetching all prereleases..." + echo "Fetching all prereleases and orphaned pre-release tags..." + + # Get pre-release GitHub releases releases=$(gh release list --limit 1000 --json tagName,isPrerelease --jq '.[] | select(.isPrerelease) | .tagName') - for tag in $releases; do + # Get all git tags that look like pre-releases but may not have GitHub releases + git fetch --tags + orphaned_tags=$(git tag -l | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+-(pr[0-9]+|rc[0-9]+|alpha[0-9]*|beta[0-9]*|dev[0-9]*)' || true) + + # Combine both lists and remove duplicates + all_prerelease_tags=$(echo -e "$releases\n$orphaned_tags" | sort | uniq | grep -v '^$' || true) + + # Initialize counters and lists + total_tags=0 + would_delete=0 + would_keep=0 + tags_to_delete="" + tags_to_keep="" + + for tag in $all_prerelease_tags; do + total_tags=$((total_tags + 1)) if [[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-pr([0-9]+)$ ]]; then pr_number="${BASH_REMATCH[1]}" echo "Checking PR #$pr_number for tag $tag" pr_info=$(gh pr view "$pr_number" --json state,isDraft 2>/dev/null || echo "NOT_FOUND") if [[ "$pr_info" == "NOT_FOUND" ]]; then - echo "PR #$pr_number not found. Deleting prerelease tag $tag" - gh release delete "$tag" --yes --cleanup-tag + would_delete=$((would_delete + 1)) + tags_to_delete="$tags_to_delete$tag (PR #$pr_number not found)\n" + if [[ "$DRY_RUN" == "true" ]]; then + echo "🔍 [DRY RUN] Would delete: PR #$pr_number not found. Tag $tag would be deleted" + else + echo "🗑️ PR #$pr_number not found. Deleting prerelease tag $tag" + # Try to delete as release first, then as tag if no release exists + gh release delete "$tag" --yes --cleanup-tag 2>/dev/null || git push --delete origin "$tag" 2>/dev/null || echo "Failed to delete $tag" + fi continue fi @@ -53,10 +93,19 @@ jobs: pr_draft=$(echo "$pr_info" | jq -r '.isDraft') if [[ "$pr_state" != "OPEN" || "$pr_draft" == "true" ]]; then - echo "PR #$pr_number is $pr_state${pr_draft:+ (draft)}. Deleting prerelease tag $tag" - gh release delete "$tag" --yes --cleanup-tag + would_delete=$((would_delete + 1)) + tags_to_delete="$tags_to_delete$tag (PR #$pr_number is $pr_state${pr_draft:+ (draft)})\n" + if [[ "$DRY_RUN" == "true" ]]; then + echo "🔍 [DRY RUN] Would delete: PR #$pr_number is $pr_state${pr_draft:+ (draft)}. Tag $tag would be deleted" + else + echo "🗑️ PR #$pr_number is $pr_state${pr_draft:+ (draft)}. Deleting prerelease tag $tag" + # Try to delete as release first, then as tag if no release exists + gh release delete "$tag" --yes --cleanup-tag 2>/dev/null || git push --delete origin "$tag" 2>/dev/null || echo "Failed to delete $tag" + fi else - echo "PR #$pr_number is open and not draft. Keeping tag $tag" + would_keep=$((would_keep + 1)) + tags_to_keep="$tags_to_keep$tag (PR #$pr_number is open)\n" + echo "✅ PR #$pr_number is open and not draft. Keeping tag $tag" fi elif [[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-.+ ]]; then # Exclude -pr* tags @@ -66,12 +115,77 @@ jobs: base_tag="${tag%%-*}" final_release=$(gh release view "$base_tag" --json isPrerelease -q '.isPrerelease' 2>/dev/null || echo "NOT_FOUND") if [[ "$final_release" == "false" ]]; then - echo "Final release $base_tag exists. Deleting obsolete prerelease $tag" - gh release delete "$tag" --yes --cleanup-tag + would_delete=$((would_delete + 1)) + tags_to_delete="$tags_to_delete$tag (final release $base_tag exists)\n" + if [[ "$DRY_RUN" == "true" ]]; then + echo "🔍 [DRY RUN] Would delete: Final release $base_tag exists. Tag $tag would be deleted" + else + echo "🗑️ Final release $base_tag exists. Deleting obsolete prerelease $tag" + # Try to delete as release first, then as tag if no release exists + gh release delete "$tag" --yes --cleanup-tag 2>/dev/null || git push --delete origin "$tag" 2>/dev/null || echo "Failed to delete $tag" + fi else - echo "Final release $base_tag not found or is a prerelease. Keeping $tag" + would_keep=$((would_keep + 1)) + tags_to_keep="$tags_to_keep$tag (final release $base_tag not found)\n" + echo "✅ Final release $base_tag not found or is a prerelease. Keeping $tag" fi else echo "Skipping non-pre-release tag $tag" fi done + + echo "" + echo "📊 SUMMARY:" + echo "Total pre-release tags found: $total_tags" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "Tags that would be deleted: $would_delete" + echo "Tags that would be kept: $would_keep" + echo "" + + if [[ $would_delete -gt 0 ]]; then + echo "🗑️ Tags that WOULD BE DELETED:" + echo -e "$tags_to_delete" | while IFS= read -r line; do + if [[ -n "$line" ]]; then + tag_name=$(echo "$line" | cut -d' ' -f1) + reason=$(echo "$line" | cut -d'(' -f2- | sed 's/)$//') + echo " • $tag_name - $reason" + echo " 🔗 https://github.com/doodlum/skyrim-community-shaders/releases/tag/$tag_name" + fi + done + echo "" + fi + + if [[ $would_keep -gt 0 ]]; then + echo "✅ Tags that would be KEPT:" + echo -e "$tags_to_keep" | while IFS= read -r line; do + if [[ -n "$line" ]]; then + tag_name=$(echo "$line" | cut -d' ' -f1) + reason=$(echo "$line" | cut -d'(' -f2- | sed 's/)$//') + echo " • $tag_name - $reason" + fi + done + echo "" + fi + + echo "🔍 This was a DRY RUN - no tags were actually deleted." + echo "To perform actual deletion, run this workflow with dry_run=false" + else + echo "Tags deleted: $would_delete" + echo "Tags kept: $would_keep" + echo "" + + if [[ $would_delete -gt 0 ]]; then + echo "🗑️ Tags that were DELETED:" + echo -e "$tags_to_delete" | while IFS= read -r line; do + if [[ -n "$line" ]]; then + tag_name=$(echo "$line" | cut -d' ' -f1) + reason=$(echo "$line" | cut -d'(' -f2- | sed 's/)$//') + echo " • $tag_name - $reason" + fi + done + echo "" + fi + + echo "🗑️ Cleanup completed successfully!" + fi