Skip to content

Make and Update GitHub Releases (Weekly Cleanup + Rebuild) #209

Make and Update GitHub Releases (Weekly Cleanup + Rebuild)

Make and Update GitHub Releases (Weekly Cleanup + Rebuild) #209

name: Make and Update GitHub Releases (Cleanup + Rebuild)
on:
workflow_dispatch: {}
schedule:
- cron: "0 0 * * *" # daily 00:00 UTC
# Prevent overlapping runs (schedule + manual, or long matrices)
concurrency:
group: releases-cleanup-rebuild
cancel-in-progress: false
permissions:
contents: write
jobs:
cleanup-github-releases:
name: 🧹 Cleanup ALL Old Managed Releases & Tags
runs-on: ubuntu-latest
timeout-minutes: 25
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# These prefixes define what this workflow "owns".
# Anything whose tag starts with one of these prefixes will be deleted.
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
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 (all pages)
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
# List releases via API (paginate), extract tag_name, delete if prefix matches.
# This deletes releases regardless of how many you have (no fixed limit).
page=1
deleted=0
while :; do
# 100 per page (max)
json="$(gh api --paginate "repos/${owner}/${repo}/releases?per_page=100&page=${page}" || true)"
# If empty array or empty response -> stop
if [[ -z "${json}" ]] || [[ "${json}" == "[]" ]]; then
break
fi
# Extract "tag_name" lines safely
mapfile -t tags < <(printf '%s' "${json}" | gh api --silent --input - --jq '.[].tag_name' 2>/dev/null || true)
# If no tags returned, stop
if [[ "${#tags[@]}" -eq 0 ]]; then
break
fi
for tag in "${tags[@]}"; do
for prefix in ${MANAGED_TAG_PREFIXES}; do
if [[ "$tag" == "${prefix}"* ]]; then
echo "Deleting release: $tag"
gh release delete "$tag" -y || true
deleted=$((deleted + 1))
break
fi
done
done
page=$((page + 1))
done
echo "Deleted releases: ${deleted}"
- name: 🗑️ Delete ALL matching Tags (all pages)
shell: bash
run: |
set -euo pipefail
owner="${GITHUB_REPOSITORY%/*}"
repo="${GITHUB_REPOSITORY#*/}"
deleted=0
# List all tags via API (paginate). Delete any tag that matches our prefixes.
gh api --paginate "repos/${owner}/${repo}/tags?per_page=100" --jq '.[].name' | while read -r tag; do
[[ -z "${tag}" ]] && continue
for prefix in ${MANAGED_TAG_PREFIXES}; do
if [[ "$tag" == "${prefix}"* ]]; then
echo "Deleting tag ref: refs/tags/${tag}"
# Delete tag reference
gh api -X DELETE "repos/${owner}/${repo}/git/refs/tags/${tag}" >/dev/null 2>&1 || true
deleted=$((deleted + 1))
break
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
}
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/
;;
*)
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