fix(release): a SHA256SUMS replaced between its listing and its read is read again (flaky nightly test) #2822
Closed
github-sync
wants to merge 1 commit from
github/pr/2822 into main
pull from: github/pr/2822
merge into: MagicBeanDev:main
MagicBeanDev:main
MagicBeanDev:github/pr/2893
MagicBeanDev:github/pr/2890
MagicBeanDev:github/pr/2887
MagicBeanDev:github/pr/2878
MagicBeanDev:github/pr/2875
MagicBeanDev:github/pr/2874
MagicBeanDev:github/pr/2873
MagicBeanDev:github/pr/2871
MagicBeanDev:github/pr/2756
MagicBeanDev:github/pr/2897
MagicBeanDev:github/pr/2896
MagicBeanDev:github/pr/2718
MagicBeanDev:github/pr/2842
MagicBeanDev:github/pr/2691
MagicBeanDev:github/pr/2895
MagicBeanDev:github/pr/2743
MagicBeanDev:github/pr/2765
MagicBeanDev:github/pr/2708
MagicBeanDev:github/pr/2732
MagicBeanDev:github/pr/2755
MagicBeanDev:github/pr/2817
MagicBeanDev:github/pr/2876
MagicBeanDev:release-please--branches--main
MagicBeanDev:release-please--branches--main--release-notes
MagicBeanDev:github/pr/2778
MagicBeanDev:github/pr/2888
MagicBeanDev:github/pr/2866
MagicBeanDev:github/pr/2877
MagicBeanDev:github/pr/2800
MagicBeanDev:github/pr/2829
MagicBeanDev:github/pr/2850
MagicBeanDev:github/pr/2889
MagicBeanDev:github/pr/2882
MagicBeanDev:github/pr/2860
MagicBeanDev:github/pr/2849
MagicBeanDev:github/pr/2886
MagicBeanDev:github/pr/2794
MagicBeanDev:github/pr/2840
MagicBeanDev:github/pr/2830
MagicBeanDev:github/pr/2834
MagicBeanDev:github/pr/2719
MagicBeanDev:github/pr/2742
MagicBeanDev:github/pr/2741
MagicBeanDev:github/pr/2820
MagicBeanDev:github/pr/2771
MagicBeanDev:github/pr/2859
MagicBeanDev:github/pr/2858
MagicBeanDev:github/pr/2823
MagicBeanDev:github/pr/2757
MagicBeanDev:github/pr/2769
MagicBeanDev:github/pr/2844
MagicBeanDev:github/pr/2843
MagicBeanDev:github/pr/2673
MagicBeanDev:github/pr/2855
MagicBeanDev:github/pr/2739
MagicBeanDev:github/pr/2807
MagicBeanDev:github/pr/2851
MagicBeanDev:github/pr/2789
MagicBeanDev:github/pr/2814
MagicBeanDev:github/pr/2818
MagicBeanDev:github/pr/2774
MagicBeanDev:github/pr/2772
MagicBeanDev:github/pr/2750
MagicBeanDev:github/pr/2786
MagicBeanDev:github/pr/2785
MagicBeanDev:github/pr/2782
MagicBeanDev:github/pr/2779
MagicBeanDev:github/pr/2775
MagicBeanDev:github/pr/2706
MagicBeanDev:github/pr/2766
MagicBeanDev:github/pr/2747
MagicBeanDev:github/pr/2759
MagicBeanDev:github/pr/2745
MagicBeanDev:github/pr/2740
MagicBeanDev:github/pr/2733
MagicBeanDev:github/pr/2725
MagicBeanDev:github/pr/2727
MagicBeanDev:github/pr/2728
MagicBeanDev:github/pr/2729
MagicBeanDev:github/pr/2721
MagicBeanDev:github/pr/2722
MagicBeanDev:github/pr/2715
MagicBeanDev:github/pr/2714
MagicBeanDev:github/pr/2707
MagicBeanDev:github/pr/2703
MagicBeanDev:github/pr/2705
MagicBeanDev:github/pr/2697
MagicBeanDev:github/pr/2679
MagicBeanDev:github/pr/2676
MagicBeanDev:github/pr/2669
MagicBeanDev:docs/what-hookshot-connects-to
MagicBeanDev:fix/hdr-encode-test
MagicBeanDev:fix/main-tests
MagicBeanDev:fix/play-cache-files
MagicBeanDev:perf/game-barrier-order
MagicBeanDev:feat/heap-lazy
MagicBeanDev:feat/texture-detail
MagicBeanDev:perf/astc-opaque-bc1
MagicBeanDev:fix/fs-dir-lock
MagicBeanDev:fix/framegen-native-kept
MagicBeanDev:fix/update-no-downgrade
MagicBeanDev:port/k10-gcn-f16-mirrors
MagicBeanDev:fix/framegen-mult-cap
MagicBeanDev:chore/release-as-2.1.1
MagicBeanDev:perf/pcache-load-switch
MagicBeanDev:fix/prepare-progress-log
MagicBeanDev:fix/update-closes-stale-game
MagicBeanDev:fix/hdr-scaled-sampled
MagicBeanDev:perf/first-start-preset
MagicBeanDev:perf/zero-upload
MagicBeanDev:fix/vcore-escape-2s
MagicBeanDev:test/fake-gh-atomic
MagicBeanDev:perf/batch-idle-flush
MagicBeanDev:test/finish-stub-a
MagicBeanDev:chore/record-2.1.0
MagicBeanDev:fix/main-red-tests
MagicBeanDev:fix/test-display-startup-driver-cache
MagicBeanDev:feat/mesh-shader-mode
MagicBeanDev:fix/menu-probes-at-startup
MagicBeanDev:fix/fps-counter-classic
MagicBeanDev:fix/test-log-batch-flake
MagicBeanDev:fix/narrow-screen-hud
MagicBeanDev:ci/prereleases
MagicBeanDev:release/v2.0.15
MagicBeanDev:hotfix/v2.0.15
MagicBeanDev:fix/present-ahead-replay
MagicBeanDev:release/v2.0.13
MagicBeanDev:fix/bracket-paths-2013
MagicBeanDev:fix/hdr-overlays-2013
MagicBeanDev:fix/fps-counter-scale-2013
MagicBeanDev:fix/stick-seen-at-rest
MagicBeanDev:hotfix/menu-fits-screen
MagicBeanDev:fix/f1-always-opens-menu
MagicBeanDev:fix/ini-keep-lines
MagicBeanDev:claude/cranky-pike-7cf247
MagicBeanDev:perf/texture-answer-flat
MagicBeanDev:fix/stamp-test-modules
MagicBeanDev:fix/appimage-fonts
MagicBeanDev:fix/display-awake
MagicBeanDev:release/v2.0.12
MagicBeanDev:fix/discord-windows
MagicBeanDev:rc/v2.0.12-tests
MagicBeanDev:fix/dlss-keep-feature
MagicBeanDev:rc/v2.0.12
MagicBeanDev:button-icons
No reviewers
Labels
Clear labels
accessibility
Barrier affecting people with disabilities
autorelease: pending
autorelease: tagged
bug
Something isn't working
dependencies
Pull requests that update a dependency file
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
github_actions
Pull requests that update GitHub Actions code
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
testing wanted
wontfix
This will not be worked on
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
Milestone
Clear milestone
No items
No milestone
Assignees
Clear assignees
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!2822
Loading…
Reference in a new issue
No description provided.
Delete branch "github/pr/2822"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
tests/test_release_scripts.py'stest_nightly_two_runs_at_once_end_at_the_newer_commitfails now and then on the ubuntu part 2 check (klimovich008 saw it on #2708 and #2732 today), and the same race can fail a real nightly when the Linux and Windows runs finish together:release_files.sh finishgives up with "SHA256SUMS still differs from the files after 5 uploads".Cause
From the failing runs' logs (e.g. run 43237869157): after
nightly: moved forward ...and its uploads, the run printedgh: Not Found (HTTP 404)three times, then the five-uploads error.uploaded()lists the release's files, then reads SHA256SUMS by its id; the other platform's run replaces SHA256SUMS (a new id) between those two calls, the read 404s, and|| trueturned that into "no SHA256SUMS". So the run uploads it again, which replaces it under the other run's read, and the two runs ping-pong until one has used its five uploads (in the testssleepis a no-op, so the runs retry in step).Change
uploaded()lists and reads again (up to three times) when the read fails, so a file replaced meanwhile is read under its new id instead of counting as missing. A read that keeps failing still answers nothing, as before.race: {"SHA256SUMS": n}: the next n reads of it find it replaced under a new id), andtest_sums_replaced_between_listing_and_read_are_read_againchecks thatcheckpasses andfinishuploads nothing through two such replacements. On main's scriptcheckfails (the empty read) andfinishuploads SHA256SUMS again.Overlap: #2779 (Nitnek, draft) adds one more check after the fifth upload in
finish(); this PR does not touchfinish()and the two merge in either order. Both together: this one stops the ping-pong, #2779 catches a last upload not yet visible. #2626 changes other lines offinish().Tested
python -I -B tests/run_all.pyon Windows 11 (419 passed; 5 failed, the same 5 as main on this PC: compiler headers and Python modules here).test_release_scripts.pyis skipped on Windows (it needsfcntlandjq), so its run is this PR's Linux CI.bash -n scripts/release_files.sh.🤖 Generated with Claude Code
The one red check here (test_linux_saves_move, ubuntu part 1/2) is not this PR: it is an order-dependent bug on main in host/hos_main.c's copy_link (an absolute link listed after the entry it names keeps the old place). Fix and a stronger test: #2832. A rerun of the failed job (needs a maintainer) should pass.
Thanks, this is a good catch and a clean fix for the flaky nightly test. Read from the diff only (I did not run anything); CI is the test evidence.
The race.
uploaded()now re-lists and re-reads when the read itself fails, so a SHA256SUMS replaced under a new id between the listing and the read is picked up instead of turning into "nothing there". The retry is bounded (3 tries) and only triggers on a failed read, never on a content mismatch: a real difference between the sums and the files still comes out ofcmpinfinish()/check()exactly as before, so it cannot be hidden. The retry is also the only thing that changed;finish()and its 5-upload limit with the clear error are untouched.Shell. Fine under
set -euo pipefail: the read goes to a temp file, so a half-written body is never printed before a failedgh, and the[[ -n $asset ]] || breakis safe. Nit, not blocking: a persistent read failure after 3 tries still answers nothing silently (as before, andfinish()then reports it); a one-line stderr note there would make the logs clearer. Another nit: ifassetsitself fails underset -ethe temp file is left behind (the other helpers use atrapor have the same shape, so I would not bother).Test. The fake gh's
racecounter makes the replacement deterministic: each read of SHA256SUMS bumps the id and 404s,race: 2needs exactly the third try, and the test checks bothcheckandfinishand that nothing uploaded SHA256SUMS. On main's script the first read 404s,|| truemakes it empty, socheckfails andfinishuploads again, as the description says. That matches the cause from the failing runs' logs (404 x3 then the five-uploads error), so it explains main's red runs too.One residual window (non-blocking, a separate follow-up if you want it).
upload()deletes the old SHA256SUMS and then POSTs the new one, so there is a short moment when no SHA256SUMS is listed at all. A run that lists in that moment still gets "none" and uploads again. This PR closes the replaced-under-a-new-id case that the CI logs show; the delete/POST gap is much narrower and is what #2779's extra check after the fifth upload would catch.CI. ubuntu part 2/2 (where
test_release_scriptsruns) passes. The one red check, ubuntu part 1/2, istest_linux_saves_move, unrelated to these files; the author points at #2832 for it. Nothing here for rule 3c beyond the test failing before and passing after, which holds.Thanks @hckrman101 for the review and the merge. Agreed on the delete/POST window: it is narrower than the replaced-under-a-new-id case the CI logs showed, and #2779's check after the fifth upload covers it. The two nits (a stderr note after the third failed read, the temp file left when
assetsfails) are fair; I'll keep them for a small follow-up if the nightly test flakes again rather than open one for logs alone.