delete old nightly releases to unpollute our release page#8501
Conversation
3e73e5d to
626530e
Compare
…in permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces an automated cleanup mechanism to remove old nightly releases from the GitHub releases page. The workflow runs on a daily schedule and can also be manually triggered with a dry-run option for testing.
Changes:
- Added a new GitHub Actions workflow that identifies and deletes nightly releases older than 7 days
- Implements a dry-run mode by default for manual executions, with automatic deletion enabled for scheduled runs
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| description: "Dry run (no deletions)" | ||
| type: boolean | ||
| default: true | ||
|
|
There was a problem hiding this comment.
The workflow is missing explicit permissions declaration. All other workflows in this repository explicitly declare permissions (e.g., release.yml has 'contents: write', update-issue-status.yml has 'contents: write', etc.). This workflow needs 'contents: write' permission to delete releases. Add a 'permissions:' section at the workflow level after the 'on:' section, before 'jobs:', with 'contents: write'.
| permissions: | |
| contents: write |
| if [[ "$DRY_RUN" == "true" ]]; then | ||
| echo "DRY-RUN: $tag" | ||
| else | ||
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --yes; then |
There was a problem hiding this comment.
The 'gh release delete' command only deletes the GitHub release but leaves the git tag intact. For nightly builds with timestamp-based tags (e.g., v9.0.12-abc1234-20260227T040000Z), this will result in orphaned tags accumulating in the repository over time. Consider adding the '--cleanup-tag' flag to also delete the associated tag, or document this as intentional behavior if you want to preserve the tag history.
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --yes; then | |
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --cleanup-tag --yes; then |
| push: | ||
| branches: | ||
| - jay/release-cleanup # TODO: remove after testing | ||
|
|
There was a problem hiding this comment.
The test branch trigger should be removed before merging to production. This TODO comment indicates this is a temporary testing configuration that will cause the workflow to run on every push to the 'jay/release-cleanup' branch, which is not intended for production use.
| push: | |
| branches: | |
| - jay/release-cleanup # TODO: remove after testing |
| gh release list -R "$GITHUB_REPOSITORY" \ | ||
| --limit 1000 \ | ||
| --json tagName,publishedAt,name \ | ||
| --jq ".[] | select(.name | test(\"nightly\"; \"i\")) | select(.publishedAt < \"${CUTOFF_DATE}\") | .tagName" | | ||
| while read -r tag; do | ||
| if [[ "$DRY_RUN" == "true" ]]; then | ||
| echo "DRY-RUN: $tag" | ||
| else | ||
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --yes; then | ||
| echo "Error: release deletion: $tag" >&2 | ||
| exit 1 | ||
| else | ||
| echo "Release deleted: $tag" | ||
| fi | ||
| fi |
There was a problem hiding this comment.
The limit of 1000 releases may not be sufficient if the repository has more than 1000 total releases. Since 'gh release list' returns releases in reverse chronological order by default, older nightly releases beyond the 1000th release would never be deleted. Consider either using pagination to fetch all releases, or documenting this limitation. However, given that nightly builds are created daily and kept for 7 days, this limit should be adequate for most cases unless the repository has hundreds of non-nightly releases per day.
| gh release list -R "$GITHUB_REPOSITORY" \ | |
| --limit 1000 \ | |
| --json tagName,publishedAt,name \ | |
| --jq ".[] | select(.name | test(\"nightly\"; \"i\")) | select(.publishedAt < \"${CUTOFF_DATE}\") | .tagName" | | |
| while read -r tag; do | |
| if [[ "$DRY_RUN" == "true" ]]; then | |
| echo "DRY-RUN: $tag" | |
| else | |
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --yes; then | |
| echo "Error: release deletion: $tag" >&2 | |
| exit 1 | |
| else | |
| echo "Release deleted: $tag" | |
| fi | |
| fi | |
| PAGE=1 | |
| PAGE_SIZE=100 | |
| while :; do | |
| TAGS=$(gh release list -R "$GITHUB_REPOSITORY" \ | |
| --limit "$PAGE_SIZE" \ | |
| --page "$PAGE" \ | |
| --json tagName,publishedAt,name \ | |
| --jq ".[] | select(.name | test(\"nightly\"; \"i\")) | select(.publishedAt < \"${CUTOFF_DATE}\") | .tagName") | |
| # If no tags were returned on this page, we're done. | |
| if [[ -z "$TAGS" ]]; then | |
| break | |
| fi | |
| while read -r tag; do | |
| # Skip empty lines just in case | |
| [[ -z "$tag" ]] && continue | |
| if [[ "$DRY_RUN" == "true" ]]; then | |
| echo "DRY-RUN: $tag" | |
| else | |
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --yes; then | |
| echo "Error: release deletion: $tag" >&2 | |
| exit 1 | |
| else | |
| echo "Release deleted: $tag" | |
| fi | |
| fi | |
| done <<< "$TAGS" | |
| PAGE=$((PAGE + 1)) |
Deletes old (+7 days) nightly builds from the "releases" page.
internalorbetaor production build on the front page.