Skip to content

[Visual Test] Label pagination aborts workflow before screenshot capture on run #31080801035 #975

Description

@MichaelFisher1997

Failures (entire visual-test job)

Run: https://github.com/OpenStaticFish/ZigCraft/actions/runs/31080801035
Head SHA: 8d205ff0b27a951ac7136cb72796ecd8e2e91ed4 (the only commit on
dev: the nix flake → devenv migration, PR #951)

The visual-test workflow aborted before the game was ever built or run. No
build-output.log and no screenshot.png were produced. The workspace
contains only weston.log (weston startup at 07:28:36 followed by
[07:28:39.397] caught signal 15 from the Stop headless Wayland compositor step). The only failing step is the preflight that bootstraps
the issue labels.

Step table (run #31080801035, jobs API)

# Step Status Conclusion
1-7 Set up job → Load visual diagnosis prompt completed success
8 Ensure visual-test label exists completed failure
9 Setup Lavapipe Vulkan completed skipped
10 Run menu screenshot capture completed skipped
11 Check screenshot exists completed success (screenshot_exists=false)
12 Compare against golden image completed skipped
13 Upload screenshot artifact completed skipped
14 Check build log exists completed success (file absent)
15 Upload build log artifact completed skipped
16 Stop headless Wayland compositor completed success
17 Run opencode visual verification completed skipped
18 Run opencode failure diagnosis in_progress

Exact failure

The failing step is Ensure visual-test label exists at
.github/workflows/visual-test.yml:55-66. It runs:

if ! gh label list --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 --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

gh label list returns the GitHub default 30 labels per page. This
repository currently has 41 labels (verified locally with
gh label list --repo OpenStaticFish/ZigCraft --limit 100 --json name).
visual-test is at index 20 (visible on page 1), but run-visual-test
is at index 40 (only on page 2). The precheck at visual-test.yml:62
therefore reports run-visual-test as missing even though it exists. The
subsequent gh label create then fails with:

label with name "run-visual-test" already exists; use `--force` to update its color and description

Because the step uses set -euo pipefail (the gh CLI exits non-zero
on a duplicate create), the step exits 1. Subsequent steps
(Setup Lavapipe Vulkan, Run menu screenshot capture, the screenshot
existence check, the golden-image diff, and the artifact uploads) are
skipped. Only the Stop headless Wayland compositor step runs
(if: always()), and it kills the weston process with SIGTERM — which
is the signal recorded in weston.log:62.

Why there is no Vulkan, swapchain, or screenshot error

VulkanSwapchain.createSwapchain at
modules/engine-graphics/src/vulkan_swapchain.zig:127, the headless
color-attachment image setup at the same file lines 128-174,
screenshot-mode init at src/game/app.zig:268-276, HomeScreen.init at
modules/game-ui/src/screens/home.zig:33-40, and
screenshot.requestCapture at
modules/engine-graphics/src/vulkan/screenshot.zig:24-44 were never
executed. The Zig binary was never launched; only the YAML pipeline ran.

Root cause

  • File: .github/workflows/visual-test.yml
  • Function/step: Ensure visual-test label exists at lines 55-66
  • The precheck at line 62
    (gh label list --json name --jq '.[].name' | grep -q '^run-visual-test$')
    silently truncates to 30 labels and treats the existing run-visual-test
    label as absent.
  • The unconditional-on-miss create at lines 63-65 then fails with a
    non-zero exit, surviving set -euo pipefail.

Recurring regression

This is the same root cause that has been filed repeatedly against
unmodified visual-test.yml since the devenv migration commit
8d205ff (the only commit on dev). Open duplicates of this exact
bug include (newest first):

None of those proposed fixes have been merged into dev. The
Ensure visual-test label exists step has not been modified since the
devenv migration, so the regression re-fires on every nightly schedule
run.

Suggested fix

Make the bootstrap idempotent without relying on paginated list output.
Apply in .github/workflows/visual-test.yml at lines 55-68:

- name: Ensure visual-test labels exist
  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 }}

--force makes gh label create succeed on existing labels (updating
color/description in place) and eliminates the paginated precheck
entirely.

Alternatives if a precheck is preferred:

  • Query each exact label through gh api repos/$GITHUB_REPOSITORY/labels/<name>
    (single-resource GET, no pagination), or
  • Pass --limit 100 to the existing gh label list call.

--limit 100 masks the immediate bug but reintroduces a hidden
threshold as the label catalog grows, so --force is the more robust
fix.

Side observations (not blocking)

  • The diagnosis prompt is stale:
    .github/prompts/visual-test-diagnose.md:7 still says
    screenshot.ppm, while the actual command at
    .github/workflows/visual-test.yml:81 uses the supported
    screenshot.png. The current encoder would still reject .ppm at
    modules/engine-graphics/src/vulkan/screenshot.zig:39
    (detectScreenshotFormat only accepts .png, .jpg, .jpeg,
    .gif, .webp) if a future run ever reverted to .ppm. The prompt
    also references src/game/screens/home.zig, but the HomeScreen now
    lives at modules/game-ui/src/screens/home.zig.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghotfixvisual-testIssues from automated visual regression tests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions