Skip to content

Commit e114b2a

Browse files
committed
fix: use GitHub API with size verification for release uploads
gh CLI truncates large files during upload. Switch to direct GitHub API upload with curl, verify uploaded size matches local file size, and retry up to 3 times on mismatch.
1 parent 54d19ab commit e114b2a

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

.github/workflows/desktop-release.yml

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,22 +136,55 @@ jobs:
136136
if-no-files-found: error
137137
retention-days: 7
138138

139-
# Upload directly to release from build runner (avoids artifact download corruption)
139+
# Upload directly to release via GitHub API (gh CLI truncates large files)
140140
- name: Upload to release
141141
if: startsWith(github.ref, 'refs/tags/desktop-v')
142142
shell: bash
143143
env:
144-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
144+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
145145
run: |
146+
# Get release upload URL
147+
RELEASE_ID=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
148+
"https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }}" \
149+
| jq -r '.id')
150+
echo "Release ID: $RELEASE_ID"
151+
146152
for file in apps/desktop/release/*.dmg apps/desktop/release/*.zip apps/desktop/release/*.exe; do
147153
[ -f "$file" ] || continue
148-
echo "Uploading $file ..."
154+
filename=$(basename "$file")
155+
filesize=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
156+
echo "Uploading $filename ($filesize bytes)..."
157+
158+
# Delete existing asset if any
159+
existing=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
160+
"https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets" \
161+
| jq -r ".[] | select(.name == \"$filename\") | .id")
162+
if [ -n "$existing" ]; then
163+
curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
164+
"https://api.github.com/repos/${{ github.repository }}/releases/assets/$existing"
165+
echo " Deleted existing asset"
166+
fi
167+
149168
for attempt in 1 2 3; do
150-
if gh release upload "${{ github.ref_name }}" "$file" --clobber; then
151-
echo " OK"
169+
response=$(curl -s -w "\n%{http_code}" \
170+
-H "Authorization: token $GITHUB_TOKEN" \
171+
-H "Content-Type: application/octet-stream" \
172+
--data-binary "@$file" \
173+
"https://uploads.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$filename")
174+
http_code=$(echo "$response" | tail -1)
175+
upload_size=$(echo "$response" | head -1 | jq -r '.size // 0')
176+
177+
if [ "$http_code" = "201" ] && [ "$upload_size" = "$filesize" ]; then
178+
echo " OK (verified: $upload_size bytes)"
152179
break
153180
fi
154-
echo " Attempt $attempt failed, retrying in 10s..."
181+
echo " Attempt $attempt: HTTP $http_code, uploaded $upload_size / expected $filesize"
182+
# Clean up partial upload
183+
partial=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
184+
"https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets" \
185+
| jq -r ".[] | select(.name == \"$filename\") | .id")
186+
[ -n "$partial" ] && curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
187+
"https://api.github.com/repos/${{ github.repository }}/releases/assets/$partial"
155188
sleep 10
156189
done
157190
done

0 commit comments

Comments
 (0)