Skip to content

Commit 3110529

Browse files
andyclaude
andcommitted
CI: fix both failures from the Test workflow's first run
Wiring the suites into CI immediately found two environment assumptions that a single dev box had been hiding. glxinfo is in mesa-utils, not x11-utils, so it was simply absent on the runner -- and hasGL() raised FileNotFoundError and took the whole apps suite down before a single app started. It is a diagnostic, not a requirement, so a missing tool now reports "unknown" instead of crashing, and mesa-utils is installed. Also dropped the "|| true" that was hiding apt failures in that step, which is how a missing package got this far unnoticed. broadwayd binds its port before it can serve clients, and the suite treated "port bound" as ready. On a slower machine that gap matters: the first two codes alphabetically (Amica, DirDyVTST) failed with "Unable to access the X Display" and every later one passed, which is exactly the shape of a startup race. It now probes with a real wx client and retries for up to 30s. Neither was reproducible locally, which is the point of running these somewhere other than the machine they were written on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFMUNbw2UpRPmgsqviAowb
1 parent 4f9cbb0 commit 3110529

4 files changed

Lines changed: 53 additions & 8 deletions

File tree

‎.github/workflows/test.yml‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,14 @@ jobs:
8282
# libgl1-mesa-dri: llvmpipe, the software renderer that actually
8383
# answers those GLX calls. Without it the apps get no GL and
8484
# the suite says so on startup.
85-
# x11-utils: xdpyinfo/xwininfo/glxinfo, used to see whether a
86-
# window actually appeared.
85+
# x11-utils: xdpyinfo/xwininfo, used to see whether a window
86+
# actually appeared. glxinfo is in mesa-utils, separately.
87+
# mesa-utils: glxinfo, only to report whether GL is working.
8788
# python3-wxgtk4.0: pulled in because the installed package's
8889
# codereg dialogs need it at runtime.
8990
sudo apt-get install -y \
9091
apache2 apache2-utils xvfb libgl1-mesa-dri x11-utils \
91-
activemq python3-wxgtk4.0 || true
92+
mesa-utils activemq python3-wxgtk4.0
9293
9394
- name: Build
9495
run: |

‎tests/apps/run_tests.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,13 @@ def main():
251251
before = apps.serviceState()
252252
results = Results()
253253
try:
254+
gl = display.hasGL()
254255
print("display: %s (GL: %s)"
255-
% (display.name, "yes" if display.hasGL() else "NO -- the "
256-
"viewer apps will not render"))
256+
% (display.name,
257+
"yes" if gl else
258+
("unknown -- glxinfo not installed (mesa-utils)"
259+
if gl is None else
260+
"NO -- the viewer apps will not render")))
257261
serviceLog = []
258262
apps.startServices(display, serviceLog)
259263
for line in serviceLog:

‎tests/apps/xdisplay.py‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,20 @@ def windows(self):
124124
return found
125125

126126
def hasGL(self):
127-
result = subprocess.run(["glxinfo", "-display", self.name, "-B"],
128-
stdout=subprocess.PIPE,
129-
stderr=subprocess.DEVNULL)
127+
"""True when GLX is answering. Unknown counts as "probably fine".
128+
129+
glxinfo lives in mesa-utils, which is not installed everywhere, and
130+
this is a diagnostic rather than a requirement -- the apps
131+
themselves will fail loudly if they really cannot get a context. A
132+
missing tool must not take the whole suite down, which is exactly
133+
what it did on its first CI run.
134+
"""
135+
try:
136+
result = subprocess.run(["glxinfo", "-display", self.name, "-B"],
137+
stdout=subprocess.PIPE,
138+
stderr=subprocess.DEVNULL)
139+
except (FileNotFoundError, OSError):
140+
return None
130141
return b"direct rendering: Yes" in result.stdout
131142

132143

‎tests/dialogs/harness.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,35 @@ def _startBroadway(self):
137137
"BROADWAY_DISPLAY": ":%d" % number,
138138
"DISPLAY": "",
139139
}
140+
self._waitUntilUsable()
141+
142+
def _waitUntilUsable(self):
143+
"""Wait until a GTK client can actually connect, not just until the
144+
port is bound.
145+
146+
broadwayd binds its port before it is ready to serve, and on a slow
147+
machine the gap is big enough to matter: the first CI run of this
148+
suite failed the first two codes alphabetically with "Unable to
149+
access the X Display" and then succeeded for all the rest. Probing
150+
with a real wx client is the only check that means anything here.
151+
"""
152+
environment = dict(os.environ)
153+
environment.update(self.env)
154+
probe = "import wx; wx.App(); raise SystemExit(0)"
155+
deadline = time.time() + 30
156+
lastError = ""
157+
while time.time() < deadline:
158+
result = subprocess.run([sys.executable, "-c", probe],
159+
env=environment,
160+
stdout=subprocess.DEVNULL,
161+
stderr=subprocess.PIPE)
162+
if result.returncode == 0:
163+
return
164+
lastError = result.stderr.decode("utf-8", "replace").strip()
165+
time.sleep(0.5)
166+
raise HarnessUnavailable(
167+
"broadwayd is listening but no wx client can connect: %s"
168+
% lastError[-300:])
140169

141170
def __exit__(self, *exc):
142171
if self._proc is not None:

0 commit comments

Comments
 (0)