R2 cleanup (purge beta + prune old stable) #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: R2 cleanup (purge beta builds) | |
| # 一次性运维:清掉 Cloudflare R2 (bucket: openspeech) 里所有 beta 版本的二进制归档 | |
| # (首段前缀含 -beta,如 v0.2.49-beta.6/),保留全部正式版归档与顶层滚动 manifest | |
| # (latest*.json / download*.json)。复用 release.yml 同一套 R2_* secrets。 | |
| # | |
| # 分组不依赖 S3 delimiter/CommonPrefixes(R2 上为空),而是 aws s3 ls --recursive 拉全部 | |
| # key 后按首段路径聚合。报告写成 artifact(report.txt / beta_prefixes.txt / totals.txt)。 | |
| # delete step 对每个待删前缀二次校验必须含 -beta;删完自校验,若仍有 -beta key 残留则 exit 1。 | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| mode: | |
| description: 'dry-run = 只列清单不删;delete = 真正删除 beta 归档' | |
| required: true | |
| type: choice | |
| default: dry-run | |
| options: | |
| - dry-run | |
| - delete | |
| permissions: | |
| contents: read | |
| jobs: | |
| cleanup: | |
| runs-on: ubuntu-latest | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} | |
| AWS_ENDPOINT_URL: ${{ secrets.R2_ENDPOINT }} | |
| AWS_DEFAULT_REGION: auto | |
| R2_BUCKET: ${{ secrets.R2_BUCKET }} | |
| MODE: ${{ inputs.mode }} | |
| steps: | |
| - name: List & classify objects | |
| run: | | |
| set -euo pipefail | |
| echo "Mode: $MODE | Bucket: $R2_BUCKET" | |
| aws s3 ls "s3://$R2_BUCKET" --recursive > all_objects.txt | |
| total_all=$(wc -l < all_objects.txt) | |
| # 按 key 首段路径聚合;不含 / 的顶层文件归到 (root) | |
| awk '{ | |
| key=$4; size=$3; | |
| n=index(key,"/"); | |
| grp=(n>0)?substr(key,1,n-1):"(root)"; | |
| objs[grp]++; bytes[grp]+=size; | |
| } END { for (g in objs) printf "%s\t%d\t%d\n", g, objs[g], bytes[g] }' \ | |
| all_objects.txt | sort > groups.txt | |
| : > beta_prefixes.txt | |
| : > report.txt | |
| del_objs=0; del_bytes=0; beta_count=0; keep_objs=0; keep_bytes=0 | |
| while IFS=$'\t' read -r g o b; do | |
| if [[ "$g" == *-beta* ]]; then | |
| printf '%-34s objs=%-4s bytes=%s [BETA -> DELETE]\n' "$g" "$o" "$b" >> report.txt | |
| echo "$g/" >> beta_prefixes.txt | |
| del_objs=$((del_objs+o)); del_bytes=$((del_bytes+b)); beta_count=$((beta_count+1)) | |
| else | |
| printf '%-34s objs=%-4s bytes=%s [KEEP]\n' "$g" "$o" "$b" >> report.txt | |
| keep_objs=$((keep_objs+o)); keep_bytes=$((keep_bytes+b)) | |
| fi | |
| done < groups.txt | |
| { | |
| echo "total_all_objects=$total_all" | |
| echo "beta_prefix_count=$beta_count" | |
| echo "delete_objects=$del_objs" | |
| echo "delete_bytes=$del_bytes" | |
| echo "keep_objects=$keep_objs" | |
| echo "keep_bytes=$keep_bytes" | |
| } > totals.txt | |
| # job summary(Actions 页可视) | |
| { | |
| echo "## R2 cleanup ($MODE)" | |
| echo '```' | |
| cat totals.txt | |
| echo '```' | |
| echo "### prefixes" | |
| echo '```' | |
| cat report.txt | |
| echo '```' | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| cat totals.txt | |
| - name: Upload report artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: r2-cleanup-report | |
| path: | | |
| report.txt | |
| beta_prefixes.txt | |
| totals.txt | |
| retention-days: 7 | |
| - name: Delete beta prefixes | |
| if: ${{ inputs.mode == 'delete' }} | |
| run: | | |
| set -euo pipefail | |
| if [[ ! -s beta_prefixes.txt ]]; then | |
| echo "No beta prefixes to delete." | |
| exit 0 | |
| fi | |
| while IFS= read -r p; do | |
| [[ -z "$p" ]] && continue | |
| case "$p" in | |
| *-beta*) ;; | |
| *) echo "ABORT: non-beta prefix in delete list: $p"; exit 1 ;; | |
| esac | |
| echo ">>> deleting s3://$R2_BUCKET/$p" | |
| aws s3 rm "s3://$R2_BUCKET/$p" --recursive --only-show-errors | |
| done < beta_prefixes.txt | |
| echo "Delete done." | |
| - name: Verify after delete | |
| if: ${{ inputs.mode == 'delete' }} | |
| run: | | |
| set -euo pipefail | |
| remaining=$(aws s3 ls "s3://$R2_BUCKET" --recursive | awk '{print $4}' | grep -c -- '-beta' || true) | |
| summ=$(aws s3 ls "s3://$R2_BUCKET" --recursive --summarize | tail -2) | |
| bytes=$(printf '%s\n' "$summ" | awk '/Total Size/{print $NF}') | |
| { | |
| echo "## R2 cleanup verify" | |
| echo "remaining_beta_keys=$remaining" | |
| echo "bucket_total_bytes=${bytes:-0}" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| echo "remaining_beta_keys=$remaining" | |
| echo "bucket_total_bytes=${bytes:-0}" | |
| if [[ "$remaining" -ne 0 ]]; then | |
| echo "ERROR: still $remaining beta keys left"; exit 1 | |
| fi | |
| echo "OK: no beta keys remain." |