-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
delete old nightly releases to unpollute our release page #8501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
626530e
2c439bd
3a6092c
6b013da
e8eeec6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,48 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Nightly builds are helpful validation, but useless when old. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # This script deletes any "nightly" titled release older than DAYS_OLD. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Dry run is default, and must be explicitly passed as 'false' to act. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Release cleanup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| schedule: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - cron: "30 3 * * *" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dry_run: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "Dry run (no deletions)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: boolean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cleanup: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Clean up old nightly releases | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DRY_RUN: ${{ github.event_name != 'schedule' && (github.event_name != 'workflow_dispatch' || inputs.dry_run) }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DAYS_OLD=7 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CUTOFF_DATE=$(date -u -d "${DAYS_OLD} days ago" +%Y-%m-%dT%H:%M:%SZ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --yes; then | |
| if ! gh release delete "$tag" -R "$GITHUB_REPOSITORY" --cleanup-tag --yes; then |
Copilot
AI
Feb 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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'.