From b76e3a37183d536690f1ca090c7d8818f7a527b3 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Mon, 15 Jun 2026 02:50:41 +0800 Subject: [PATCH] fix(nightly): publish latest.json via directory rclone copy (#4588) The assemble-manifest job promoted the manifest with single-file `rclone copyto` + `moveto`. Before a single-file upload rclone issues a CreateBucket probe (PUT /), which the object-scoped RELEASE_R2_* token can't satisfy -> 403 AccessDenied, so nightly/latest.json was never published (the build legs and the stable release flow were fine because they use a directory `rclone copy`, which PUTs the object directly without that probe). Mirror the release flow (upload-to-r2.yml): copy a one-file directory into nightly/. R2 PutObject is atomic, so the .tmp + server-side move added nothing. Verified against the live bucket with the current token: directory copy -> 200 OK; single-file copyto -> CreateBucket 403. Co-authored-by: Claude Opus 4.8 (1M context) --- .github/workflows/nightly.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a8d64b26..1e0a783d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -428,10 +428,14 @@ jobs: echo "Assembled latest.json:" jq '{version, platforms: (.platforms | keys)}' latest.json - # Atomic promote: upload to a temp key, then server-side move so - # readers never observe a half-written latest.json. - rclone copyto latest.json "$base/latest.json.tmp" - rclone moveto "$base/latest.json.tmp" "$base/latest.json" + # Promote the manifest with a directory `rclone copy`, exactly like the + # stable release flow writes releases/latest.json (upload-to-r2.yml). + # A single-file `rclone copyto`/`moveto` first issues a CreateBucket + # probe (PUT /) that the object-scoped R2 token can't satisfy + # (403 AccessDenied); a directory copy PUTs the object directly. R2 + # PutObject is atomic, so readers never observe a half-written manifest. + mkdir -p promote && cp latest.json promote/latest.json + rclone copy promote "$base/" - name: prune old nightly folders (keep newest 7) run: |