mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-09-17 07:41:53 -04:00
201 lines
9.2 KiB
YAML
201 lines
9.2 KiB
YAML
name: Post-Release Cleanup
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
base_version:
|
|
description: 'The base version to clean up (e.g., 2.3.0)'
|
|
required: true
|
|
type: string
|
|
confirm_deletion:
|
|
description: 'WARNING: This is a destructive action. Set to true to perform deletion. Defaults to a dry run.'
|
|
required: true
|
|
type: boolean
|
|
default: false
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
# Destructive (deletes releases + tags): serialize dispatches so two cleanups
|
|
# can never interleave.
|
|
concurrency:
|
|
group: ${{ github.workflow }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
cleanup_prereleases:
|
|
# ubuntu-slim: gh + git + jq + stdlib python is the whole toolchain, and the gh-pages
|
|
# worktree needs no privileges. Slim is single-CPU (the full-history clone below is slower
|
|
# than on a VM) and its 15-minute platform cap is hard, matching the timeout already set
|
|
# here. Each step is independently re-runnable, so a capped run is retryable.
|
|
runs-on: ubuntu-slim
|
|
timeout-minutes: 15
|
|
# Dispatch inputs reach the shell as environment variables rather than being
|
|
# interpolated into the script text: base_version is free-form and feeds a
|
|
# regex that drives `rm -rf` and tag deletion, so a value containing quotes,
|
|
# $(...) or a newline must not be able to break out of the assignment.
|
|
env:
|
|
BASE_VERSION: ${{ github.event.inputs.base_version }}
|
|
CONFIRM_DELETION: ${{ github.event.inputs.confirm_deletion }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
# Shared by every step below: reject anything that is not a bare X.Y.Z
|
|
# before it reaches a regex, a tag deletion or an rm -rf.
|
|
- name: Validate base_version
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ ! "$BASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
echo "base_version must be a bare X.Y.Z version (got '$BASE_VERSION')." >&2
|
|
exit 1
|
|
fi
|
|
echo "Cleaning up pre-releases for $BASE_VERSION."
|
|
|
|
- name: Cleanup pre-releases and their tags
|
|
id: cleanup_releases
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
# Internal/open/closed pre-releases are cut continuously across the whole
|
|
# dev cycle, including before the version-bump commit lands — so some of
|
|
# them still carry the PRIOR release's version number (e.g. a
|
|
# v2.7.14-internal.N draft built while working toward 2.8.0). Scoping this
|
|
# sweep to "v${BASE_VERSION}-*" misses exactly those, leaving stale drafts
|
|
# behind forever. Once base_version has shipped as a stable release, every
|
|
# numbered internal/open/closed pre-release — regardless of which version
|
|
# it was tagged under — is superseded, so match on the pre-release SHAPE
|
|
# instead of a version prefix.
|
|
TAG_PATTERN='^v[0-9]+\.[0-9]+\.[0-9]+-(internal|open|closed)\.[0-9]+$'
|
|
echo "Searching for pre-releases matching pattern '$TAG_PATTERN'."
|
|
RELEASES_TO_DELETE=$(gh release list --json tagName,isPrerelease,isDraft --limit 1000 | jq -r --arg pattern "$TAG_PATTERN" '.[] | select((.isPrerelease == true or .isDraft == true) and .tagName != null and (.tagName | test($pattern))) | .tagName')
|
|
|
|
if [ -z "$RELEASES_TO_DELETE" ]; then
|
|
echo "No stale internal/open/closed pre-releases found."
|
|
else
|
|
if [[ "$CONFIRM_DELETION" == "true" ]]; then
|
|
echo "!!! DELETING RELEASES AND TAGS !!!"
|
|
echo "The following pre-releases and their tags will be deleted:"
|
|
echo "$RELEASES_TO_DELETE"
|
|
echo "$RELEASES_TO_DELETE" | xargs -n 1 gh release delete --cleanup-tag --yes
|
|
else
|
|
echo "DRY RUN: The following pre-releases and their tags would be deleted:"
|
|
echo "$RELEASES_TO_DELETE"
|
|
fi
|
|
fi
|
|
|
|
# The docs site keeps a per-tag snapshot for every open/closed testing tag
|
|
# in a version cycle (see docs-release.yml). Once vX.Y.Z ships, /vX.Y.Z/
|
|
# supersedes them all, so reap them to stop gh-pages growing without bound.
|
|
- name: Cleanup pre-release docs snapshots on gh-pages
|
|
run: |
|
|
set -euo pipefail
|
|
DRY_RUN=true
|
|
[[ "$CONFIRM_DELETION" == "true" ]] && DRY_RUN=false
|
|
|
|
if ! git ls-remote --exit-code --heads origin gh-pages >/dev/null 2>&1; then
|
|
echo "No gh-pages branch; nothing to clean."
|
|
exit 0
|
|
fi
|
|
|
|
work="$(mktemp -d)"
|
|
rmdir "$work"
|
|
git fetch --quiet origin gh-pages
|
|
git worktree add --quiet -B gh-pages "$work" FETCH_HEAD
|
|
trap 'git worktree remove --force "$work" 2>/dev/null || true' EXIT
|
|
|
|
# Reaping is only sound because /vX.Y.Z/ supersedes these snapshots.
|
|
# If it is missing, the production docs never published (or this was
|
|
# dispatched for the wrong version) and deleting the snapshots would
|
|
# destroy the only docs for this version — and whatever the site root
|
|
# currently falls back to. Fail closed instead.
|
|
if [ ! -d "$work/v${BASE_VERSION}" ]; then
|
|
echo "Refusing to reap docs snapshots: /v${BASE_VERSION}/ is not published on gh-pages." >&2
|
|
echo "Run Docs Release against the v${BASE_VERSION} tag first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Open/closed test-track snapshots are cut continuously across the whole
|
|
# dev cycle, including before the version-bump commit lands, so some may
|
|
# still be named after the PRIOR release (e.g. v2.7.14-open.3 built while
|
|
# working toward 2.8.0). Once /v${BASE_VERSION}/ is confirmed published
|
|
# above, every numbered open/closed snapshot is superseded regardless of
|
|
# which version it was tagged under — so match the snapshot-dir SHAPE
|
|
# instead of a version prefix.
|
|
mapfile -t stale < <(
|
|
find "$work" -maxdepth 1 -mindepth 1 -type d \
|
|
-regextype posix-extended \
|
|
-regex ".*/v[0-9]+\.[0-9]+\.[0-9]+-(open|closed)\.[0-9]+" -printf '%f\n' | sort
|
|
)
|
|
|
|
if [ ${#stale[@]} -eq 0 ]; then
|
|
echo "No pre-release docs snapshots found."
|
|
exit 0
|
|
fi
|
|
|
|
printf 'Pre-release docs snapshots to reap:\n'
|
|
printf ' %s\n' "${stale[@]}"
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
echo "DRY RUN: the directories above would be removed from gh-pages."
|
|
exit 0
|
|
fi
|
|
|
|
for d in "${stale[@]}"; do
|
|
rm -rf "${work:?}/$d"
|
|
done
|
|
|
|
# Rebuild versions.json (and the root placeholder) from what remains,
|
|
# using the same generator the publisher runs.
|
|
python3 scripts/docs/regenerate-versions.py "$work"
|
|
|
|
cd "$work"
|
|
git add -A
|
|
if git diff --cached --quiet; then
|
|
echo "gh-pages already clean."
|
|
exit 0
|
|
fi
|
|
git -c user.name='github-actions[bot]' \
|
|
-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
|
|
commit -q -m "docs: reap pre-release snapshots for ${BASE_VERSION}"
|
|
git push --quiet origin HEAD:gh-pages
|
|
echo "Removed ${#stale[@]} pre-release docs snapshot(s) from gh-pages."
|
|
|
|
- name: Cleanup dangling pre-release tags
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
# Same rationale as the release-cleanup step above: match the
|
|
# internal/open/closed pre-release tag SHAPE across all versions, not just
|
|
# tags prefixed with this dispatch's base_version.
|
|
TAG_PATTERN='^v[0-9]+\.[0-9]+\.[0-9]+-(internal|open|closed)\.[0-9]+$'
|
|
echo "Searching for any remaining remote pre-release tags matching pattern '$TAG_PATTERN'."
|
|
|
|
# This finds all remote tags. Look them up on their own first so a
|
|
# failure here (e.g. a network blip) fails the step loudly, instead of
|
|
# being swallowed by the trailing `|| true` a downstream grep needs
|
|
# (grep exits non-zero on zero matches, which is not itself an error).
|
|
REMOTE_TAGS=$(git ls-remote --tags origin "refs/tags/v*" | awk '{print $2}' | sed 's|refs/tags/||')
|
|
|
|
# Some tags may have been deleted already by the previous 'release delete' step.
|
|
TAGS_TO_DELETE=$(grep -E "$TAG_PATTERN" <<<"$REMOTE_TAGS" || true)
|
|
|
|
if [ -z "$TAGS_TO_DELETE" ]; then
|
|
echo "No dangling pre-release tags found."
|
|
else
|
|
if [[ "$CONFIRM_DELETION" == "true" ]]; then
|
|
echo "!!! DELETING DANGLING TAGS !!!"
|
|
echo "The following pre-release tags will be deleted:"
|
|
# We pipe to xargs which will run the command for each tag.
|
|
# If a tag was already deleted by the previous 'release delete' step, this will fail for that tag.
|
|
# We add '|| true' to ignore any errors and ensure the workflow doesn't fail.
|
|
echo "$TAGS_TO_DELETE" | xargs -n 1 -I {} sh -c 'git push --delete origin {} || true'
|
|
else
|
|
echo "DRY RUN: The following dangling pre-release tags would be deleted:"
|
|
echo "$TAGS_TO_DELETE"
|
|
fi
|
|
fi
|