Skip to content

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

Make and Update GitHub Releases (Weekly Cleanup + Rebuild)

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

name: Make and Update GitHub Releases
on:
workflow_dispatch: {}
release:
types: [published]
schedule:
- cron: "0 0 * * *" # daily at 00:00 UTC
concurrency:
group: make-update-releases-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write
jobs:
cleanup-github-releases:
name: 🧹 Cleanup Managed Releases & Tags
runs-on: ubuntu-latest
timeout-minutes: 20
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Tags/releases managed by this workflow must start with one of these prefixes
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 + jq)
shell: bash
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y jq gh
- name: 🔐 Authenticate GitHub CLI
shell: bash
run: |
set -euo pipefail
gh auth status
- name: 🗑️ Delete Managed Releases and Tags (server-side)
shell: bash
run: |
set -euo pipefail
owner="${GITHUB_REPOSITORY%/*}"
repo="${GITHUB_REPOSITORY#*/}"
# Fetch release tag names once (limit 200; increase if you have more)
mapfile -t all_release_tags < <(gh release list --limit 200 --json tagName -q '.[].tagName' || true)
if [[ "${#all_release_tags[@]}" -eq 0 ]]; then
echo "No releases found."
exit 0
fi
echo "Managed prefixes:"
echo "${MANAGED_TAG_PREFIXES}" | tr ' ' '\n' | sed '/^\s*$/d'
for prefix in ${MANAGED_TAG_PREFIXES}; do
echo "Processing prefix: ${prefix}"
for tag in "${all_release_tags[@]}"; do
if [[ "$tag" == "${prefix}"* ]]; then
echo "Deleting release: $tag"
gh release delete "$tag" -y || true
# Delete tag ref via API (avoids git checkout/push)
# Endpoint expects: tags/<tag-name> (without refs/)
echo "Deleting tag ref: tags/$tag"
gh api -X DELETE "repos/${owner}/${repo}/git/refs/tags/${tag}" >/dev/null 2>&1 || true
fi
done
done
update-github-releases:
name: 🚀 Build & Publish Managed Releases
needs: cleanup-github-releases
runs-on: ubuntu-latest
timeout-minutes: 30
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 + jq)
shell: bash
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y zip jq
- 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
id: build
shell: bash
env:
RELEASE_NAME: ${{ matrix.release_name }}
run: |
set -euo pipefail
mkdir -p artifacts temp
# Always start clean
rm -rf temp/*
mkdir -p temp
# Helper: copy root metadata if present
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)
if [[ ! -d "$RELEASE_NAME" ]]; then
echo "::error::Directory not found: $RELEASE_NAME"
exit 1
fi
cp -r "$RELEASE_NAME" temp/
copy_root_meta
;;
GPOs-Templates)
if [[ ! -d "SysAdmin-Tools/GroupPolicyObjects-Templates" ]]; then
echo "::error::Directory not found: SysAdmin-Tools/GroupPolicyObjects-Templates"
exit 1
fi
cp -r SysAdmin-Tools/GroupPolicyObjects-Templates/* temp/
# Optional helper tool (keep tolerant)
[[ -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)
# Collect all README.md files across repo (including root as main-README.md)
[[ -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
if [[ -d "$dir" ]]; then
cp -r "$dir" temp/
else
echo "::warning::Directory missing (skipped): $dir"
fi
done
copy_root_meta
;;
AD-SSO-APIs-Integration)
if [[ ! -d "SysAdmin-Tools/ActiveDirectory-SSO-Integrations" ]]; then
echo "::error::Directory not found: SysAdmin-Tools/ActiveDirectory-SSO-Integrations"
exit 1
fi
cp -r SysAdmin-Tools/ActiveDirectory-SSO-Integrations/* temp/
;;
*)
echo "::error::Unknown RELEASE_NAME: $RELEASE_NAME"
exit 1
;;
esac
(cd temp && zip -r "../artifacts/${RELEASE_NAME}.zip" .)
sha256sum "artifacts/${RELEASE_NAME}.zip" > "artifacts/${RELEASE_NAME}.sha256.txt"
echo "zip_path=artifacts/${RELEASE_NAME}.zip" >> "$GITHUB_OUTPUT"
echo "sha_path=artifacts/${RELEASE_NAME}.sha256.txt" >> "$GITHUB_OUTPUT"
- 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}"
# Extract lines between "## RELEASE_NAME" and next "## "
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
# Multi-line output
echo "body<<EOF" >> "$GITHUB_OUTPUT"
echo "$body" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: 🧾 Upload Build Artifacts (Actions)
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
- name: 🚀 Create/Update GitHub Release (and 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 }}