Skip to content

Commit f16bbbb

Browse files
voidstackloopclaude
andcommitted
release.yml: verify by asset size, not just name presence
Run #19 (the v1.1.1 rebuild meant to fix the missing .exe) reported success but the exe still 404s. Root cause: the previous run left a ghost asset entry on the release under the right name but with no real content (a failed/partial upload that still registered metadata) — my earlier verify-and-retry step only checked whether a name existed in the asset list, so it saw "Modelforge-Setup-1.1.1.exe" already there and skipped the retry entirely. Now compares actual byte size (local file vs gh release view's reported asset size), deletes any mismatched/ghost asset before re-uploading, and re-checks the size again after the retry rather than trusting gh's exit code alone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent b8e20ad commit f16bbbb

1 file changed

Lines changed: 22 additions & 3 deletions

File tree

.github/workflows/release.yml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,39 @@ jobs:
152152
# confirms the files exist locally in dist/ *before* this upload;
153153
# this checks what the release *actually* ended up with afterward, and
154154
# retries anything gh's own upload silently dropped.
155+
#
156+
# Comparing by NAME alone isn't enough (learned the hard way on the
157+
# v1.1.1 rebuild): a failed/partial upload can still register a ghost
158+
# asset entry under the right name with the wrong size (or 0), which a
159+
# name-only check treats as "already there" and never retries. Byte
160+
# size is compared against the local file instead — cheap, and the one
161+
# signal that actually distinguishes a real upload from a placeholder.
155162
- name: Verify every local asset actually landed on the release, retry any that didn't
156163
env:
157164
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
158165
run: |
159166
set -euo pipefail
160-
published=$(gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" --json assets --jq '.assets[].name')
167+
published_json=$(gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" --json assets --jq '.assets')
161168
missing=0
162169
for f in dist/*; do
163170
name=$(basename "$f")
164-
if ! grep -qxF "$name" <<< "$published"; then
165-
echo "::warning::Asset '$name' didn't land on the release after the initial publish — retrying its upload."
171+
local_size=$(stat -c%s "$f")
172+
remote_size=$(jq -r --arg name "$name" '.[] | select(.name == $name) | .size' <<< "$published_json")
173+
if [ -z "$remote_size" ] || [ "$remote_size" != "$local_size" ]; then
174+
echo "::warning::Asset '$name' is missing or wrong size on the release (local: ${local_size} bytes, remote: ${remote_size:-none}) — deleting any partial copy and re-uploading."
175+
gh release delete-asset "${{ github.ref_name }}" "$name" --repo "${{ github.repository }}" --yes 2>/dev/null || true
166176
if ! gh release upload "${{ github.ref_name }}" "$f" --repo "${{ github.repository }}" --clobber; then
167177
echo "::error::Retry upload failed for '$name'."
168178
missing=1
179+
continue
180+
fi
181+
# Re-check size after the retry rather than trusting gh's exit
182+
# code alone — that's the exact assumption that let the
183+
# original silent failure through.
184+
new_size=$(gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" --json assets --jq --arg name "$name" '.assets[] | select(.name == $name) | .size')
185+
if [ "$new_size" != "$local_size" ]; then
186+
echo "::error::Asset '$name' still wrong size after retry (local: ${local_size}, remote: ${new_size:-none})."
187+
missing=1
169188
fi
170189
fi
171190
done

0 commit comments

Comments
 (0)