@@ -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