Skip to content

Commit 18847b1

Browse files
committed
fix: use fresh upload_url after asset deletion to prevent 422 errors
**Problem:** After deleting an existing asset with different size, the upload fails with 422 Unprocessable Entity because we were using the upload_url from the initial release object instead of the refreshed one. **Root Cause:** - upload_url was captured at the beginning from the initial release object - After deleting an asset, GitHub may invalidate or update the upload_url - The old upload_url was being used, causing 422 errors **Solution:** 1. Remove early upload_url extraction 2. Always use fresh_release for upload_url 3. After asset deletion, refresh release data again 4. Extract upload_url from fresh_release just before upload **Flow:** 1. Refresh release → get current assets list 2. If asset exists with different size → delete it 3. Refresh again after deletion → get updated upload_url 4. Extract upload_url from fresh data → upload **Testing:** This should fix the nats_exporter DEB upload that was failing with: - Local size: 4106706 bytes - Remote size: 4106680 bytes (26 bytes difference) - After deletion → 422 error on re-upload
1 parent fbebdf5 commit 18847b1

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

core/scripts/upload_to_release.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,18 @@ def upload_asset(release: Dict, file_path: Path, token: str, repo: str) -> Dict:
142142
"Content-Type": "application/octet-stream",
143143
}
144144

145-
# Get upload URL
146-
if "upload_url" not in release:
147-
raise ValueError(f"Release missing upload_url: {release.get('id', 'unknown')}")
148-
149-
upload_url = release["upload_url"].replace("{?name,label}", "")
150145
file_name = file_path.name
151146

152147
# Refresh release data to get current assets list
153148
# This is critical for handling parallel uploads correctly
154149
print(f"Refreshing release data to check for existing assets...")
155150
fresh_release = get_release_by_id(repo, release["id"], token)
156-
print(f"Using upload URL: {upload_url}")
151+
152+
# Verify upload_url is available
153+
if "upload_url" not in fresh_release:
154+
raise ValueError(
155+
f"Release missing upload_url: {fresh_release.get('id', 'unknown')}"
156+
)
157157

158158
# Check if asset already exists (using fresh data)
159159
existing_asset = None
@@ -185,11 +185,18 @@ def upload_asset(release: Dict, file_path: Path, token: str, repo: str) -> Dict:
185185
)
186186
if delete_response.status_code == 204:
187187
print(f"✓ Deleted existing asset {file_name}")
188+
# After deletion, refresh again to get updated upload_url
189+
print(f"Refreshing release data after deletion...")
190+
fresh_release = get_release_by_id(repo, release["id"], token)
188191
else:
189192
print(
190193
f"⚠ Delete returned {delete_response.status_code}, continuing anyway..."
191194
)
192195

196+
# Use upload_url from fresh release data (critical after deletion)
197+
upload_url = fresh_release["upload_url"].replace("{?name,label}", "")
198+
print(f"Using upload URL: {upload_url}")
199+
193200
# Upload asset with retry and longer timeout
194201
print(f"📤 Uploading {file_name}...")
195202

0 commit comments

Comments
 (0)