Workflow
https://github.com/OpenStaticFish/ZigCraft/actions/runs/29634181508
Observed output
The checked-out workspace contains no build-output.log; the game command was never started. The failed job step status was:
Ensure visual-test label exists completed failure
Setup Lavapipe Vulkan completed skipped
Run menu screenshot capture completed skipped
Check screenshot exists completed success
Check build log exists completed success
The only available log retrieval response while the run was still active was:
run 29634181508 is still in progress; logs will be available when it is complete
weston.log contains only normal compositor shutdown:
[06:36:17.128] caught signal 15
There are no Vulkan instance/device, swapchain, shader, staging-buffer, fence, PPM/PNG, panic, or segfault errors from this run because the label bootstrap stopped execution before Lavapipe setup.
Diagnosis
The failure originates in .github/workflows/visual-test.yml:55-68, in the Ensure visual-test label exists step, not in the renderer. Both labels already exist in the repository. However, gh label list uses its default limit of 30 labels. The current label ordering places visual-test at position 21 and run-visual-test at position 41. The first probe can see visual-test, while the second probe cannot see run-visual-test, so the workflow attempts to create an already-existing label and the step fails.
The job declares issues: write at .github/workflows/visual-test.yml:20-24 and supplies GH_TOKEN at .github/workflows/visual-test.yml:67-68, so this is a label-discovery/idempotency bug rather than a Vulkan or Lavapipe environment failure.
The requested runtime paths were not exercised, but the source confirms the expected flow:
src/game/app.zig:260-276 selects screenshot mode and loads createHomeScreen; src/game/app.zig:495-587 applies ZIGCRAFT_SMOKE_FRAMES and requests the capture before ending the frame.
- The actual HomeScreen implementation is
modules/game-ui/src/screens/home.zig:33-41 and draws the preview/menu at modules/game-ui/src/screens/home.zig:62-98.
- RHI initialization enters
modules/engine-graphics/src/rhi_vulkan.zig:36-38, then modules/engine-graphics/src/vulkan/rhi_init_deinit.zig:26-41; screenshot requests are wired by modules/engine-graphics/src/rhi_vulkan.zig:415-419.
- The headless image path is
modules/engine-graphics/src/vulkan_swapchain.zig:127-174, where the offscreen image uses COLOR_ATTACHMENT | TRANSFER_SRC. Capture recording/completion is in modules/engine-graphics/src/vulkan/screenshot.zig:24-86 and :91-222.
One additional configuration mismatch is visible but was not reached: the checked-in workflow invokes -Dscreenshot-path=screenshot.png at .github/workflows/visual-test.yml:73-87, while a .ppm path would be rejected by modules/engine-graphics/src/vulkan/screenshot.zig:39-40 and :262-267, which currently supports PNG/JPEG/GIF/WebP only.
Suggested fix
Make label setup independent of pagination and safe when labels already exist. The simplest fix is to use --force and remove the list/grep probes:
- name: Ensure visual-test label exists
run: |
gh label create "visual-test" \
--description "Issues from automated visual regression tests" \
--color "E06C75" \
--force
gh label create "run-visual-test" \
--description "Run deterministic visual regression workflow on a PR" \
--color "E06C75" \
--force
env:
GH_TOKEN: ${{ secrets.OPENCODE_PAT }}
Alternatively, use gh label view <name> for existence checks or pass an explicit --limit greater than the repository label count, but --force makes the setup reliably idempotent as labels grow.
Workflow
https://github.com/OpenStaticFish/ZigCraft/actions/runs/29634181508
Observed output
The checked-out workspace contains no
build-output.log; the game command was never started. The failed job step status was:The only available log retrieval response while the run was still active was:
weston.logcontains only normal compositor shutdown:There are no Vulkan instance/device, swapchain, shader, staging-buffer, fence, PPM/PNG, panic, or segfault errors from this run because the label bootstrap stopped execution before Lavapipe setup.
Diagnosis
The failure originates in
.github/workflows/visual-test.yml:55-68, in theEnsure visual-test label existsstep, not in the renderer. Both labels already exist in the repository. However,gh label listuses its default limit of 30 labels. The current label ordering placesvisual-testat position 21 andrun-visual-testat position 41. The first probe can seevisual-test, while the second probe cannot seerun-visual-test, so the workflow attempts to create an already-existing label and the step fails.The job declares
issues: writeat.github/workflows/visual-test.yml:20-24and suppliesGH_TOKENat.github/workflows/visual-test.yml:67-68, so this is a label-discovery/idempotency bug rather than a Vulkan or Lavapipe environment failure.The requested runtime paths were not exercised, but the source confirms the expected flow:
src/game/app.zig:260-276selects screenshot mode and loadscreateHomeScreen;src/game/app.zig:495-587appliesZIGCRAFT_SMOKE_FRAMESand requests the capture before ending the frame.modules/game-ui/src/screens/home.zig:33-41and draws the preview/menu atmodules/game-ui/src/screens/home.zig:62-98.modules/engine-graphics/src/rhi_vulkan.zig:36-38, thenmodules/engine-graphics/src/vulkan/rhi_init_deinit.zig:26-41; screenshot requests are wired bymodules/engine-graphics/src/rhi_vulkan.zig:415-419.modules/engine-graphics/src/vulkan_swapchain.zig:127-174, where the offscreen image usesCOLOR_ATTACHMENT | TRANSFER_SRC. Capture recording/completion is inmodules/engine-graphics/src/vulkan/screenshot.zig:24-86and:91-222.One additional configuration mismatch is visible but was not reached: the checked-in workflow invokes
-Dscreenshot-path=screenshot.pngat.github/workflows/visual-test.yml:73-87, while a.ppmpath would be rejected bymodules/engine-graphics/src/vulkan/screenshot.zig:39-40and:262-267, which currently supports PNG/JPEG/GIF/WebP only.Suggested fix
Make label setup independent of pagination and safe when labels already exist. The simplest fix is to use
--forceand remove the list/grep probes:Alternatively, use
gh label view <name>for existence checks or pass an explicit--limitgreater than the repository label count, but--forcemakes the setup reliably idempotent as labels grow.