From a7dfc803b7b609a996044227a3dfe05c4786faed Mon Sep 17 00:00:00 2001 From: Jonathan Miller <230051081+jmiller-moko@users.noreply.github.com> Date: Thu, 26 Mar 2026 18:11:43 -0500 Subject: [PATCH] chore: add .github/workflows/repository-cleanup.yml from MokoStandards --- .github/workflows/repository-cleanup.yml | 244 +++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 .github/workflows/repository-cleanup.yml diff --git a/.github/workflows/repository-cleanup.yml b/.github/workflows/repository-cleanup.yml new file mode 100644 index 0000000..33c9864 --- /dev/null +++ b/.github/workflows/repository-cleanup.yml @@ -0,0 +1,244 @@ +# Copyright (C) 2026 Moko Consulting +# +# This file is part of a Moko Consulting project. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: GitHub.Workflow +# INGROUP: MokoStandards.Maintenance +# REPO: https://github.com/mokoconsulting-tech/MokoStandards +# PATH: /templates/workflows/shared/repository-cleanup.yml +# VERSION: 04.01.00 +# BRIEF: One-time repository cleanup — reset labels, strip issue template headers, delete old branches +# NOTE: Synced via bulk-repo-sync to .github/workflows/repository-cleanup.yml in all governed repos. +# Run manually via workflow_dispatch. Safe to re-run — all operations are idempotent. + +name: Repository Cleanup + +on: + workflow_dispatch: + inputs: + reset_labels: + description: 'Delete ALL existing labels and recreate the standard 54-label set' + type: boolean + default: true + clean_branches: + description: 'Delete old chore/sync-mokostandards-* branches (keeps current versioned branch only)' + type: boolean + default: true + fix_templates: + description: 'Strip copyright comment blocks from issue templates' + type: boolean + default: true + +permissions: + contents: write + issues: write + +jobs: + cleanup: + name: Repository Cleanup + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + token: ${{ secrets.GH_TOKEN || github.token }} + + - name: Check actor permission + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + ACTOR="${{ github.actor }}" + AUTHORIZED_USERS="jmiller-moko github-actions[bot]" + for user in $AUTHORIZED_USERS; do + if [ "$ACTOR" = "$user" ]; then + echo "✅ ${ACTOR} authorized" + exit 0 + fi + done + PERMISSION=$(gh api "repos/${{ github.repository }}/collaborators/${ACTOR}/permission" \ + --jq '.permission' 2>/dev/null) + case "$PERMISSION" in + admin|maintain) echo "✅ ${ACTOR} has ${PERMISSION}" ;; + *) echo "❌ Admin or maintain required"; exit 1 ;; + esac + + # ── LABEL RESET ────────────────────────────────────────────────────── + - name: Reset labels to standard set + if: inputs.reset_labels == true + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + REPO="${{ github.repository }}" + echo "## 🏷️ Label Reset" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Delete all existing labels + echo "Deleting existing labels..." + DELETED=0 + gh api "repos/${REPO}/labels?per_page=100" --paginate --jq '.[].name' | while read -r label; do + ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$label', safe=''))") + gh api -X DELETE "repos/${REPO}/labels/${ENCODED}" --silent 2>/dev/null && DELETED=$((DELETED+1)) || true + done + echo "Deleted existing labels" >> $GITHUB_STEP_SUMMARY + + # Create the standard 54-label set + echo "Creating standard labels..." + CREATED=0 + while IFS='|' read -r name color description; do + [ -z "$name" ] && continue + gh api "repos/${REPO}/labels" \ + -f name="$name" -f color="$color" -f description="$description" \ + --silent 2>/dev/null && CREATED=$((CREATED+1)) || true + done << 'LABELS' + joomla|7F52FF|Joomla extension or component + dolibarr|FF6B6B|Dolibarr module or extension + generic|808080|Generic project or library + php|4F5D95|PHP code changes + javascript|F7DF1E|JavaScript code changes + typescript|3178C6|TypeScript code changes + python|3776AB|Python code changes + css|1572B6|CSS/styling changes + html|E34F26|HTML template changes + documentation|0075CA|Documentation changes + ci-cd|000000|CI/CD pipeline changes + docker|2496ED|Docker configuration changes + tests|00FF00|Test suite changes + security|FF0000|Security-related changes + dependencies|0366D6|Dependency updates + config|F9D0C4|Configuration file changes + build|FFA500|Build system changes + automation|8B4513|Automated processes or scripts + mokostandards|B60205|MokoStandards compliance + needs-review|FBCA04|Awaiting code review + work-in-progress|D93F0B|Work in progress, not ready for merge + breaking-change|D73A4A|Breaking API or functionality change + priority: critical|B60205|Critical priority, must be addressed immediately + priority: high|D93F0B|High priority + priority: medium|FBCA04|Medium priority + priority: low|0E8A16|Low priority + type: bug|D73A4A|Something isn't working + type: feature|A2EEEF|New feature or request + type: enhancement|84B6EB|Enhancement to existing feature + type: refactor|F9D0C4|Code refactoring + type: chore|FEF2C0|Maintenance tasks + status: pending|FBCA04|Pending action or decision + status: in-progress|0E8A16|Currently being worked on + status: blocked|B60205|Blocked by another issue or dependency + status: on-hold|D4C5F9|Temporarily on hold + status: wontfix|FFFFFF|This will not be worked on + size/xs|C5DEF5|Extra small change (1-10 lines) + size/s|6FD1E2|Small change (11-30 lines) + size/m|F9DD72|Medium change (31-100 lines) + size/l|FFA07A|Large change (101-300 lines) + size/xl|FF6B6B|Extra large change (301-1000 lines) + size/xxl|B60205|Extremely large change (1000+ lines) + health: excellent|0E8A16|Health score 90-100 + health: good|FBCA04|Health score 70-89 + health: fair|FFA500|Health score 50-69 + health: poor|FF6B6B|Health score below 50 + standards-update|B60205|MokoStandards sync update + standards-drift|FBCA04|Repository drifted from MokoStandards + sync-report|0075CA|Bulk sync run report + sync-failure|D73A4A|Bulk sync failure requiring attention + push-failure|D73A4A|File push failure requiring attention + health-check|0E8A16|Repository health check results + version-drift|FFA500|Version mismatch detected + deploy-failure|CC0000|Automated deploy failure tracking + template-validation-failure|D73A4A|Template workflow validation failure + LABELS + + echo "✅ Standard labels created" >> $GITHUB_STEP_SUMMARY + + # ── BRANCH CLEANUP ─────────────────────────────────────────────────── + - name: Delete old sync branches + if: inputs.clean_branches == true + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + REPO="${{ github.repository }}" + CURRENT="chore/sync-mokostandards-v04.01.00" + echo "## 🌿 Branch Cleanup" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + DELETED=0 + gh api "repos/${REPO}/branches?per_page=100" --jq '.[].name' | \ + grep "^chore/sync-mokostandards" | \ + grep -v "^${CURRENT}$" | while read -r branch; do + # Close any open PRs on this branch + gh pr list --repo "$REPO" --head "$branch" --state open --json number --jq '.[].number' 2>/dev/null | while read -r pr; do + gh pr close "$pr" --repo "$REPO" --comment "Superseded by \`${CURRENT}\`" 2>/dev/null || true + echo " Closed PR #${pr}" >> $GITHUB_STEP_SUMMARY + done + # Delete the branch + gh api -X DELETE "repos/${REPO}/git/refs/heads/${branch}" --silent 2>/dev/null || true + echo " Deleted: \`${branch}\`" >> $GITHUB_STEP_SUMMARY + DELETED=$((DELETED+1)) + done + + if [ "$DELETED" -eq 0 ] 2>/dev/null; then + echo "✅ No old sync branches found" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Cleanup complete" >> $GITHUB_STEP_SUMMARY + fi + + # ── ISSUE TEMPLATE FIX ────────────────────────────────────────────── + - name: Strip copyright headers from issue templates + if: inputs.fix_templates == true + run: | + echo "## 📋 Issue Template Cleanup" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + FIXED=0 + for f in .github/ISSUE_TEMPLATE/*.md; do + [ -f "$f" ] || continue + if grep -q '^$/d' "$f" + echo " Cleaned: \`$(basename $f)\`" >> $GITHUB_STEP_SUMMARY + FIXED=$((FIXED+1)) + fi + done + + if [ "$FIXED" -gt 0 ]; then + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git add .github/ISSUE_TEMPLATE/ + git commit -m "fix: strip copyright comment blocks from issue templates [skip ci]" \ + --author="github-actions[bot] " + git push + echo "✅ ${FIXED} template(s) cleaned and committed" >> $GITHUB_STEP_SUMMARY + else + echo "✅ No templates need cleaning" >> $GITHUB_STEP_SUMMARY + fi + + # ── SELF-DELETE ───────────────────────────────────────────────────── + - name: Delete this workflow (one-time use) + if: success() + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + echo "## 🗑️ Self-Cleanup" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + WORKFLOW_FILE=".github/workflows/repository-cleanup.yml" + if [ -f "$WORKFLOW_FILE" ]; then + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git rm "$WORKFLOW_FILE" + git commit -m "chore: remove repository-cleanup.yml after successful run [skip ci]" \ + --author="github-actions[bot] " + git push + echo "✅ Workflow file deleted — it will not appear in future syncs" >> $GITHUB_STEP_SUMMARY + else + echo "ℹ️ Workflow file already removed" >> $GITHUB_STEP_SUMMARY + fi + + - name: Summary + if: always() + run: | + echo "" >> $GITHUB_STEP_SUMMARY + echo "---" >> $GITHUB_STEP_SUMMARY + echo "*Run by @${{ github.actor }} via workflow_dispatch*" >> $GITHUB_STEP_SUMMARY