You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Trigger: scheduled nightly, commit 16527e3 (feat: add generated preloaded menu preview #915), dev branch.
Symptom
The visual-test workflow fails at step 8 ("Ensure visual-test label exists") and never reaches step 10 ("Run menu screenshot capture"). No screenshot.png is produced and no build-output.log is written. Every downstream step (Setup Lavapipe Vulkan, Run menu screenshot capture, Compare against golden image, Upload screenshot artifact, Upload build log artifact) is skipped. The visual-regression gate is effectively dead until this is fixed.
This is the third consecutive nightly run to fail at this same preflight. #916 (runs #17 / #18) reported it first; #931 (run #19) reported the regression one scheduled run later; this issue reports run #20. The fix proposed in both prior issues has not landed, so the workflow has been stuck at step 8 every night since 2026-07-12.
Why build-output.log is missing
The diagnosis workspace does not contain build-output.log. That is consistent with the failure: build-output.log is only created by the run-with-log composite action used in the "Run menu screenshot capture" step (.github/workflows/visual-test.yml:76-81). Because step 10 was skipped, the tee never ran and no log file was written.
The only artifact from the runner is weston.log, which shows the compositor started normally and was killed 1.4 seconds later by the post-failure cleanup step:
Signal 15 (SIGTERM) at 06:58:55 lines up with step 8 completing in a failed state shortly after 06:58:55, and the always-run "Stop headless Wayland compositor" cleanup step firing immediately afterward. The game binary was never executed, so there is nothing to diagnose in the engine, screenshot path, Lavapipe, or shader pipelines.
Step 8 fails before any of the engine-level code (screenshot.zig, vulkan_swapchain.zig, HomeScreen, Lavapipe, shaders) is exercised, so this is purely a workflow-config bug.
Root cause
The pre-flight existence check in .github/workflows/visual-test.yml:55-68 is buggy. gh label list (without --paginate or a higher --limit) returns only the first 30 labels, sorted alphabetically. The ZigCraft repo currently has 41 labels, so labels that sort past position 30 are invisible to the check. Alphabetical sort rank of the two labels in question, in the current label set:
Rank
Label
1
audit-b1
2
audit-b2
...
...
30
perf/bandwidth
31
perf/gpu-compute
32
perf/rendering
33
production-readiness
34
question
35
run-visual-test
...
...
38
visual-test
...
...
Both run-visual-test (rank 35) and visual-test (rank 38) are past the 30-label page cutoff. Both gh label list --json name --jq '.[].name' calls at .github/workflows/visual-test.yml:57 and :62 therefore return an empty match, both gh label create calls fire, and both fail because the labels already exist:
$ gh label list --repo OpenStaticFish/ZigCraft --json name --jq '.[].name' | wc -l
30
$ gh label list --repo OpenStaticFish/ZigCraft --limit 100 --json name --jq '.[].name' | wc -l
41
gh label create exits non-zero on duplicate. The step aborts on the first gh label create failure (the script uses set -e/pipefail semantics implicitly via run:), and the workflow proceeds to its failure() path.
Note: #916 and #931 were written when the label set had different sort positions; on run #17 the cutoff hid only run-visual-test and visual-test happened to land inside the first 30. Since then the label inventory has grown and now hides both. The bug is the same regardless — the unpaginated gh label list is the culprit.
Specifically .github/workflows/visual-test.yml:57 and .github/workflows/visual-test.yml:62 — the unpaginated gh label list --json name --jq '.[].name' calls.
The downstream game code paths were not exercised at all on this run, so the screenshot pipeline (modules/engine-graphics/src/vulkan/screenshot.zig), the headless swapchain (modules/engine-graphics/src/vulkan_swapchain.zig:119-166), and HomeScreen rendering (modules/game-ui/src/screens/home.zig) cannot be blamed for this failure. If the preflight is fixed the next run should either succeed or surface a different engine-level failure worth investigating.
Suggested fix
Pick one of the following (in increasing order of robustness). These match what #916 already recommends; option 1 is the smallest delta that preserves the existing "skip if present" intent:
1. Page the label list (minimal change)
Add --paginate (or --limit 100) to both gh label list invocations:
- name: Ensure visual-test label existsrun: | if ! gh label list --paginate --json name --jq '.[].name' | grep -q '^visual-test$'; then gh label create "visual-test" \ --description "Issues from automated visual regression tests" \ --color "E06C75" fi if ! gh label list --paginate --json name --jq '.[].name' | grep -q '^run-visual-test$'; then gh label create "run-visual-test" \ --description "Run deterministic visual regression workflow on a PR" \ --color "E06C75" fi
- name: Ensure visual-test label existsrun: | for spec in 'visual-test|E06C75|Issues from automated visual regression tests' \ 'run-visual-test|E06C75|Run deterministic visual regression workflow on a PR'; do name="${spec%%|*}" rest="${spec#*|}" color="${rest%%|*}" desc="${rest#*|}" if gh label list --search "^${name}$" --json name --jq '.[].name' | grep -qx "${name}"; then echo "label ${name} already exists" else gh label create "${name}" --description "${desc}" --color "${color}" fi done
Any of these is sufficient. Option 1 is preferred because it preserves the "skip if present" intent of the original script with the smallest patch surface.
Recommended next steps
Open a hotfix/* PR against dev with Option 1 (or any of the alternatives) on both calls at visual-test.yml:57 and :62. Two-line YAML change; doesn't need a feature branch.
Once the preflight lands and the next scheduled run reaches step 10, watch for an actual engine-level screenshot/diff result before declaring victory — that is the first time the gate will have executed end-to-end.
PR search for paginate / label list / visual-test against dev: no in-flight fix branch. Nothing is currently racing this. The regression has now persisted across three scheduled runs without a fix.
Workflow run
https://github.com/OpenStaticFish/ZigCraft/actions/runs/29312935256
Trigger: scheduled nightly, commit
16527e3(feat: add generated preloaded menu preview #915),devbranch.Symptom
The
visual-testworkflow fails at step 8 ("Ensure visual-test label exists") and never reaches step 10 ("Run menu screenshot capture"). Noscreenshot.pngis produced and nobuild-output.logis written. Every downstream step (Setup Lavapipe Vulkan, Run menu screenshot capture, Compare against golden image, Upload screenshot artifact, Upload build log artifact) is skipped. The visual-regression gate is effectively dead until this is fixed.This is the third consecutive nightly run to fail at this same preflight. #916 (runs #17 / #18) reported it first; #931 (run #19) reported the regression one scheduled run later; this issue reports run #20. The fix proposed in both prior issues has not landed, so the workflow has been stuck at step 8 every night since 2026-07-12.
Why
build-output.logis missingThe diagnosis workspace does not contain
build-output.log. That is consistent with the failure:build-output.logis only created by therun-with-logcomposite action used in the "Run menu screenshot capture" step (.github/workflows/visual-test.yml:76-81). Because step 10 was skipped, theteenever ran and no log file was written.The only artifact from the runner is
weston.log, which shows the compositor started normally and was killed 1.4 seconds later by the post-failure cleanup step:Signal 15 (SIGTERM) at 06:58:55 lines up with step 8 completing in a failed state shortly after 06:58:55, and the always-run "Stop headless Wayland compositor" cleanup step firing immediately afterward. The game binary was never executed, so there is nothing to diagnose in the engine, screenshot path, Lavapipe, or shader pipelines.
Job step status (run #20, attempt 1)
Step 8 fails before any of the engine-level code (screenshot.zig, vulkan_swapchain.zig, HomeScreen, Lavapipe, shaders) is exercised, so this is purely a workflow-config bug.
Root cause
The pre-flight existence check in
.github/workflows/visual-test.yml:55-68is buggy.gh label list(without--paginateor a higher--limit) returns only the first 30 labels, sorted alphabetically. The ZigCraft repo currently has 41 labels, so labels that sort past position 30 are invisible to the check. Alphabetical sort rank of the two labels in question, in the current label set:Both
run-visual-test(rank 35) andvisual-test(rank 38) are past the 30-label page cutoff. Bothgh label list --json name --jq '.[].name'calls at.github/workflows/visual-test.yml:57and:62therefore return an empty match, bothgh label createcalls fire, and both fail because the labels already exist:gh label createexits non-zero on duplicate. The step aborts on the firstgh label createfailure (the script usesset -e/pipefailsemantics implicitly viarun:), and the workflow proceeds to itsfailure()path.Note: #916 and #931 were written when the label set had different sort positions; on run #17 the cutoff hid only
run-visual-testandvisual-testhappened to land inside the first 30. Since then the label inventory has grown and now hides both. The bug is the same regardless — the unpaginatedgh label listis the culprit.Origin
.github/workflows/visual-test.yml:55-68—Ensure visual-test label existsstep..github/workflows/visual-test.yml:57and.github/workflows/visual-test.yml:62— the unpaginatedgh label list --json name --jq '.[].name'calls.The downstream game code paths were not exercised at all on this run, so the screenshot pipeline (
modules/engine-graphics/src/vulkan/screenshot.zig), the headless swapchain (modules/engine-graphics/src/vulkan_swapchain.zig:119-166), and HomeScreen rendering (modules/game-ui/src/screens/home.zig) cannot be blamed for this failure. If the preflight is fixed the next run should either succeed or surface a different engine-level failure worth investigating.Suggested fix
Pick one of the following (in increasing order of robustness). These match what #916 already recommends; option 1 is the smallest delta that preserves the existing "skip if present" intent:
1. Page the label list (minimal change)
Add
--paginate(or--limit 100) to bothgh label listinvocations:2. Make the create idempotent
3. Check a single label at a time
Any of these is sufficient. Option 1 is preferred because it preserves the "skip if present" intent of the original script with the smallest patch surface.
Recommended next steps
hotfix/*PR againstdevwith Option 1 (or any of the alternatives) on both calls atvisual-test.yml:57and:62. Two-line YAML change; doesn't need a feature branch.Related
PR search for
paginate/label list/visual-testagainstdev: no in-flight fix branch. Nothing is currently racing this. The regression has now persisted across three scheduled runs without a fix.