Make and Update GitHub Releases (Weekly Cleanup + Rebuild) #210
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Make and Update GitHub Releases (Weekly Cleanup + Rebuild) | |
| on: | |
| workflow_dispatch: {} | |
| schedule: | |
| # Weekly (Sunday 00:00 UTC) | |
| - cron: "0 0 * * 0" | |
| concurrency: | |
| group: releases-cleanup-rebuild | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| jobs: | |
| cleanup-github-releases: | |
| name: 🧹 Cleanup Old Managed Releases & Tags (2026*) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Workflow "ownership" prefixes (only these will be touched) | |
| MANAGED_TAG_PREFIXES: >- | |
| AD-SSO-APIs-Integration | |
| All-Repository-Files | |
| BlueTeam-Tools | |
| Core-ScriptLibrary | |
| GPOs-Templates | |
| ITSM-Templates-SVR | |
| ITSM-Templates-WKS | |
| READMEs-Files-Package | |
| SysAdmin-Tools | |
| # Matches your requested "2026xxyyzzwwkk" style (2026 + extra digits). | |
| # Also covers your current pattern: 2026MMDD (8 digits) + optional "-<sha>" | |
| # Examples matched: | |
| # SysAdmin-Tools-20260206-6b43527 | |
| # SysAdmin-Tools-20260206010203-6b43527 | |
| MANAGED_2026_VERSION_REGEX: '^2026[0-9]{4,10}(-[0-9a-f]{7})?$' | |
| steps: | |
| - name: 🧰 Install Dependencies (gh) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y gh | |
| - name: 🔐 Verify GitHub CLI Auth | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| gh auth status | |
| - name: 🗑️ Delete ALL matching Releases (tag prefix + 2026 version) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| owner="${GITHUB_REPOSITORY%/*}" | |
| repo="${GITHUB_REPOSITORY#*/}" | |
| echo "Repository: ${owner}/${repo}" | |
| echo "Managed prefixes:" | |
| for p in ${MANAGED_TAG_PREFIXES}; do | |
| echo " - $p" | |
| done | |
| echo "Version regex: ${MANAGED_2026_VERSION_REGEX}" | |
| deleted=0 | |
| # Stream tag_name for ALL releases (paginated) | |
| mapfile -t release_tags < <( | |
| gh api --paginate "repos/${owner}/${repo}/releases?per_page=100" --jq '.[].tag_name' | |
| ) | |
| if [[ "${#release_tags[@]}" -eq 0 ]]; then | |
| echo "No releases found." | |
| else | |
| for tag in "${release_tags[@]}"; do | |
| for prefix in ${MANAGED_TAG_PREFIXES}; do | |
| # Expected tag formats: | |
| # <prefix>-<version> | |
| # where <version> begins with 2026... | |
| if [[ "$tag" == "${prefix}-"* ]]; then | |
| ver="${tag#${prefix}-}" | |
| if [[ "$ver" =~ ${MANAGED_2026_VERSION_REGEX} ]]; then | |
| echo "Deleting release: ${tag}" | |
| gh release delete "${tag}" -y || true | |
| deleted=$((deleted + 1)) | |
| fi | |
| break | |
| fi | |
| done | |
| done | |
| fi | |
| echo "Deleted releases: ${deleted}" | |
| - name: 🗑️ Delete ALL matching Tags (tag prefix + 2026 version) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| owner="${GITHUB_REPOSITORY%/*}" | |
| repo="${GITHUB_REPOSITORY#*/}" | |
| deleted=0 | |
| # Use git/matching-refs for reliable pagination over tag refs | |
| for prefix in ${MANAGED_TAG_PREFIXES}; do | |
| echo "Scanning tags for prefix: ${prefix}-" | |
| mapfile -t refs < <( | |
| gh api --paginate "repos/${owner}/${repo}/git/matching-refs/tags/${prefix}-" --jq '.[].ref' | |
| ) | |
| for ref in "${refs[@]}"; do | |
| # ref like: refs/tags/<tagname> | |
| tag="${ref#refs/tags/}" | |
| ver="${tag#${prefix}-}" | |
| if [[ "$ver" =~ ${MANAGED_2026_VERSION_REGEX} ]]; then | |
| echo "Deleting tag ref: ${ref}" | |
| gh api -X DELETE "repos/${owner}/${repo}/git/refs/tags/${tag}" >/dev/null 2>&1 || true | |
| deleted=$((deleted + 1)) | |
| fi | |
| done | |
| done | |
| echo "Deleted tags: ${deleted}" | |
| update-github-releases: | |
| name: 🚀 Rebuild Managed Releases | |
| needs: cleanup-github-releases | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| release_name: | |
| - AD-SSO-APIs-Integration | |
| - All-Repository-Files | |
| - BlueTeam-Tools | |
| - Core-ScriptLibrary | |
| - GPOs-Templates | |
| - ITSM-Templates-SVR | |
| - ITSM-Templates-WKS | |
| - READMEs-Files-Package | |
| - SysAdmin-Tools | |
| steps: | |
| - name: 📦 Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| submodules: true | |
| - name: 🧰 Install Dependencies (zip) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y zip | |
| - name: 🏷️ Compute Version Tag | |
| id: tag | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| short_sha="${GITHUB_SHA::7}" | |
| date_tag="$(date -u +%Y%m%d)" | |
| echo "version_tag=${{ matrix.release_name }}-${date_tag}-${short_sha}" >> "$GITHUB_OUTPUT" | |
| - name: 📦 Build Release Artifact | |
| shell: bash | |
| env: | |
| RELEASE_NAME: ${{ matrix.release_name }} | |
| run: | | |
| set -euo pipefail | |
| rm -rf artifacts temp || true | |
| mkdir -p artifacts temp | |
| copy_root_meta() { | |
| [[ -f README.md ]] && cp README.md temp/ || true | |
| [[ -f LICENSE.txt ]] && cp LICENSE.txt temp/ || true | |
| [[ -f LICENSE ]] && cp LICENSE temp/ || true | |
| [[ -f CHANGELOG.md ]] && cp CHANGELOG.md temp/ || true | |
| } | |
| case "$RELEASE_NAME" in | |
| BlueTeam-Tools|Core-ScriptLibrary|ITSM-Templates-SVR|ITSM-Templates-WKS|SysAdmin-Tools) | |
| [[ -d "$RELEASE_NAME" ]] || { echo "::error::Missing dir: $RELEASE_NAME"; exit 1; } | |
| cp -r "$RELEASE_NAME" temp/ | |
| copy_root_meta | |
| ;; | |
| GPOs-Templates) | |
| [[ -d "SysAdmin-Tools/GroupPolicyObjects-Templates" ]] || { echo "::error::Missing dir: SysAdmin-Tools/GroupPolicyObjects-Templates"; exit 1; } | |
| cp -r SysAdmin-Tools/GroupPolicyObjects-Templates/* temp/ | |
| [[ -f SysAdmin-Tools/ActiveDirectory-Management/Export-n-Import-GPOsTool.ps1 ]] && \ | |
| cp SysAdmin-Tools/ActiveDirectory-Management/Export-n-Import-GPOsTool.ps1 temp/ || true | |
| copy_root_meta | |
| ;; | |
| READMEs-Files-Package) | |
| [[ -f README.md ]] && cp README.md temp/main-README.md || true | |
| find . -type f -iname "README.md" ! -path "./README.md" | while read -r file; do | |
| dir="$(dirname "$file")" | |
| name="$(basename "$dir")" | |
| cp "$file" "temp/${name}-README.md" | |
| done | |
| ;; | |
| All-Repository-Files) | |
| for dir in BlueTeam-Tools Core-ScriptLibrary ITSM-Templates-SVR ITSM-Templates-WKS SysAdmin-Tools; do | |
| [[ -d "$dir" ]] && cp -r "$dir" temp/ || echo "::warning::Missing dir (skipped): $dir" | |
| done | |
| copy_root_meta | |
| ;; | |
| AD-SSO-APIs-Integration) | |
| [[ -d "SysAdmin-Tools/ActiveDirectory-SSO-Integrations" ]] || { echo "::error::Missing dir: SysAdmin-Tools/ActiveDirectory-SSO-Integrations"; exit 1; } | |
| cp -r SysAdmin-Tools/ActiveDirectory-SSO-Integrations/* temp/ | |
| copy_root_meta | |
| ;; | |
| *) | |
| echo "::error::Unknown release: $RELEASE_NAME" | |
| exit 1 | |
| ;; | |
| esac | |
| (cd temp && zip -r "../artifacts/${RELEASE_NAME}.zip" .) | |
| sha256sum "artifacts/${RELEASE_NAME}.zip" > "artifacts/${RELEASE_NAME}.sha256.txt" | |
| - name: 📝 Extract Changelog Section | |
| id: changelog | |
| shell: bash | |
| env: | |
| RELEASE_NAME: ${{ matrix.release_name }} | |
| run: | | |
| set -euo pipefail | |
| if [[ ! -f CHANGELOG.md ]]; then | |
| echo "body=No CHANGELOG.md found in repository root." >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| section="## ${RELEASE_NAME}" | |
| body="$(awk -v section="$section" ' | |
| $0 == section {found=1; next} | |
| /^## / && found {exit} | |
| found {print} | |
| ' CHANGELOG.md | sed -e 's/[[:space:]]\+$//' )" | |
| if [[ -z "${body// }" ]]; then | |
| body="No changelog available for ${RELEASE_NAME}." | |
| fi | |
| echo "body<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "$body" >> "$GITHUB_OUTPUT" | |
| echo "EOF" >> "$GITHUB_OUTPUT" | |
| - name: 🚀 Create/Update GitHub Release (upload assets) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.version_tag }} | |
| name: ${{ steps.tag.outputs.version_tag }} | |
| body: ${{ steps.changelog.outputs.body }} | |
| draft: false | |
| prerelease: false | |
| files: | | |
| artifacts/${{ matrix.release_name }}.zip | |
| artifacts/${{ matrix.release_name }}.sha256.txt | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: 📦 Upload Build Artifacts (Actions) | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-${{ matrix.release_name }} | |
| path: | | |
| artifacts/${{ matrix.release_name }}.zip | |
| artifacts/${{ matrix.release_name }}.sha256.txt | |
| retention-days: 30 |