-
-
Notifications
You must be signed in to change notification settings - Fork 59
647 lines (598 loc) · 30.2 KB
/
Copy pathci.yml
File metadata and controls
647 lines (598 loc) · 30.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
on:
pull_request:
branches: ["*"]
# Release-please PRs only bump versions in CHANGELOG/manifest files.
# The underlying code was already validated when the feature PRs merged
# to main, so running the full CI matrix again is pure waste.
paths-ignore:
- "CHANGELOG.md"
- ".release-please-manifest.json"
- "release-please-config.json"
# Re-verify main after every merge: two individually green PRs can merge
# into a semantically broken combination, and nightly.yml publishes
# artifacts from main without running any tests of its own.
push:
branches: ["main"]
paths-ignore:
- "CHANGELOG.md"
- ".release-please-manifest.json"
- "release-please-config.json"
name: CI
permissions:
contents: read
pull-requests: read
# A force-push to a PR branch obsoletes the in-flight run; without a
# concurrency group each push stacks another full 17-job matrix behind it.
# Runs on main are never canceled — every merge commit gets a full verdict.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
checks:
name: ${{ matrix.check }} (${{ matrix.os }})
strategy:
# One failing check must not cancel the other twelve. With fail-fast
# a single Linux lint error cancelled every macOS job mid-install,
# and the run reported thirteen failures for one real problem —
# which is worse than no signal, because it hides which platforms
# were actually fine.
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
# vuln runs on every OS: govulncheck is build-tag aware, so a
# vulnerable Windows-only dependency is invisible from a macOS run.
check: [lint, vet, test, build, vuln]
include:
# Formatting check only on macOS (Objective-C clang-format)
- os: macos-latest
check: formatting
# Coverage only on macOS, the reference platform. Running it
# on all three would triple the test time to produce three
# numbers that differ only by which build tags were active.
- os: macos-latest
check: coverage
# The desktop-driving test tier, once per Linux display
# stack. `desktop` is the blessed stack of ADR 0013 — sway
# on the wlroots headless backend, where parity is a
# behavioral claim. `desktop-x11` is the same tier under
# Xvfb, where ADR 0013 asks for capability parity instead:
# a lower bar than behavior, but not the zero bar it had
# while nothing observed X11 at all.
#
# Every step below is shared between the two legs except
# the one that starts the display server and the one that
# asserts it; `session_packages` is that difference in apt
# form, and `session` is the name the job summary prints.
# What each leg covers and what it does not is stated in
# docs/DEVELOPMENT.md, with the rest of the test tiers.
- os: ubuntu-latest
check: desktop
session: headless sway (wlroots Wayland)
session_packages: sway wayland-utils
- os: ubuntu-latest
check: desktop-x11
session: Xvfb with openbox (X11)
session_packages: xvfb x11-utils openbox
runs-on: ${{ matrix.os }}
# Both desktop legs block. They are the only jobs that observe Linux
# behavior at all — Neru is developed on macOS, where none of it can
# run — so ADR 0013's promises are worth exactly as much as the jobs
# that check them, and an advisory job nobody has to read is not a
# check. The two legs owe different bars (behavioral parity on the
# blessed stack, capability parity on X11), which is a statement about
# what the tests assert, not about whether a suite that passes today may
# start failing unnoticed.
#
# They earned it on a measurement rather than a feeling: 40 runs each
# across pull requests and main with no failing step. Job-level
# `continue-on-error` reports a failed job as successful, so that was
# counted from step conclusions. docs/DEVELOPMENT.md carries the detail.
steps:
# Default checkout: on pull_request events this tests the merge
# commit (PR + main combined), which is what will actually land —
# overriding repository/ref to the branch head skips that and is
# wrong for fork PRs. On push events it checks out the pushed ref.
- uses: actions/checkout@v7
# Install Linux system dependencies (Wayland, X11, Cairo, etc.)
# Devbox doesn't pull *-dev outputs (https://github.com/jetify-com/devbox/issues/2761)
- name: Install Linux system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libcairo2-dev \
libwayland-dev \
libx11-dev \
libxtst-dev \
libxrandr-dev \
libxinerama-dev \
libxfixes-dev \
libxkbcommon-dev \
wayland-protocols \
libei-dev \
liboeffis-dev \
libtesseract-dev \
tesseract-ocr-eng \
libpipewire-0.3-dev
# Install Devbox on macOS only
# Pinned by commit: a tag is a movable pointer, so `@v0.15.0` is a
# request rather than a statement about which code runs. Dependabot
# updates SHA pins that carry a version comment.
- name: Install Devbox
if: runner.os == 'macOS'
uses: jetify-com/devbox-install-action@8c6a66ed6273138b1915457069de78cb52fe3bd7 # v0.15.0
with:
enable-cache: true
# Install Go directly on Windows & Linux
- name: Setup Go
if: runner.os == 'Windows' || runner.os == 'Linux'
uses: actions/setup-go@v7
with:
go-version-file: "go.mod"
cache: true
# Install Golangci directly on Windows & Linux (install only, lint step runs it)
- name: Setup Golangci
if: matrix.check == 'lint' && (runner.os == 'Windows' || runner.os == 'Linux')
uses: golangci/golangci-lint-action@v9
with:
version: v2.12.2
install-only: true
# Install just directly on Windows & Linux
- name: Install just
if: runner.os == 'Windows' || runner.os == 'Linux'
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4.0.0
with:
just-version: "1.58.0"
# Run checks with Devbox on macOS
- name: Run just lint
if: matrix.check == 'lint' && runner.os == 'macOS'
run: devbox run -- just lint
- name: Run just fmt-check
if: matrix.check == 'formatting' && runner.os == 'macOS'
run: devbox run -- just fmt-check
- name: Run just vet
if: matrix.check == 'vet' && runner.os == 'macOS'
run: devbox run -- just vet
- name: Run just build
if: matrix.check == 'build' && runner.os == 'macOS'
run: devbox run -- just build
- name: Run just test-ci
if: matrix.check == 'test' && runner.os == 'macOS'
run: devbox run -- just test-ci
- name: Run just vuln
if: matrix.check == 'vuln' && runner.os == 'macOS'
run: devbox run -- just vuln
- name: Run just coverage
if: matrix.check == 'coverage'
run: |
devbox run -- just coverage
{
echo "### Coverage"
echo ""
echo '```'
devbox run -- go tool cover -func=coverage.txt | tail -1
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload coverage profile
if: matrix.check == 'coverage'
uses: actions/upload-artifact@v7
with:
name: coverage
path: coverage.txt
retention-days: 14
# Run checks directly on Windows & Linux
- name: Run just lint (native)
if: matrix.check == 'lint' && (runner.os == 'Windows' || runner.os == 'Linux')
run: just lint
- name: Run just vet (native)
if: matrix.check == 'vet' && (runner.os == 'Windows' || runner.os == 'Linux')
run: just vet
- name: Run just build (native)
if: matrix.check == 'build' && (runner.os == 'Windows' || runner.os == 'Linux')
run: just build
shell: bash
- name: Run just test-ci (native)
if: matrix.check == 'test' && (runner.os == 'Windows' || runner.os == 'Linux')
run: just test-ci
shell: bash
- name: Run just vuln (native)
if: matrix.check == 'vuln' && (runner.os == 'Windows' || runner.os == 'Linux')
run: just vuln
shell: bash
# ---------------------------------------------------------------
# The desktop legs: everything below runs only for a matrix.check
# starting with 'desktop'. It stands up the session the desktop
# tier needs — a display server, a session bus, and AT-SPI on it —
# and runs the tier against it. Only the two display-server steps
# differ between the wlroots and X11 legs; the bus, AT-SPI, the
# CGO and a11y assertions, the tier itself, the reporting and the
# log artifact are one copy each. What the legs cover and what they
# do not is in docs/DEVELOPMENT.md.
# ---------------------------------------------------------------
- name: Install the desktop session
if: startsWith(matrix.check, 'desktop')
env:
SESSION_PACKAGES: ${{ matrix.session_packages }}
run: |
# Word-splitting SESSION_PACKAGES is the point: it is the one
# per-leg difference in an otherwise shared install.
# shellcheck disable=SC2086
sudo apt-get install -y \
dbus-x11 \
at-spi2-core \
$SESSION_PACKAGES
- name: Start the session bus
if: startsWith(matrix.check, 'desktop')
shell: bash
run: |
set -euo pipefail
# A Wayland compositor puts its socket in XDG_RUNTIME_DIR and
# refuses a world-readable one. The runner has neither. X11
# does not need it, but a session without one is not a session
# either stack should be tested in.
runtime_dir="${RUNNER_TEMP}/xdg-runtime"
mkdir -p "$runtime_dir"
chmod 700 "$runtime_dir"
# A session bus first: AT-SPI's bus launcher is activated on
# it, and every later step inherits the address through
# GITHUB_ENV.
eval "$(dbus-launch --sh-syntax)"
{
echo "XDG_RUNTIME_DIR=$runtime_dir"
echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS"
} >> "$GITHUB_ENV"
- name: Start sway
if: matrix.check == 'desktop'
shell: bash
run: |
set -euo pipefail
cat > "${RUNNER_TEMP}/sway.conf" <<'SWAYCONF'
# Xwayland is off deliberately. It would set DISPLAY, and
# neru's Linux backend detection would then have an X11 answer
# available on the one job whose purpose is the wlroots
# Wayland stack. X11 gets its own leg instead.
xwayland disable
output HEADLESS-1 resolution 1920x1080 position 0 0
SWAYCONF
# WLR_RENDERER=pixman because the runner has no /dev/dri for
# the GLES2 renderer to open.
WLR_BACKENDS=headless \
WLR_RENDERER=pixman \
WLR_LIBINPUT_NO_DEVICES=1 \
XDG_SESSION_TYPE=wayland \
XDG_CURRENT_DESKTOP=sway \
setsid sway -c "${RUNNER_TEMP}/sway.conf" -d \
> "${RUNNER_TEMP}/sway.log" 2>&1 &
socket=""
for _ in $(seq 1 100); do
socket=$(find "$XDG_RUNTIME_DIR" -maxdepth 1 -name 'wayland-*' \
! -name '*.lock' -print -quit)
[ -n "$socket" ] && break
sleep 0.2
done
if [ -z "$socket" ]; then
echo "sway never created a Wayland socket. Its log:" >&2
cat "${RUNNER_TEMP}/sway.log" >&2
exit 1
fi
# The IPC socket lands alongside the Wayland one, but "lands
# alongside" is an assumption rather than an ordering sway
# promises, so it gets the same wait and the same diagnostic.
swaysock=""
for _ in $(seq 1 50); do
swaysock=$(find "$XDG_RUNTIME_DIR" -maxdepth 1 \
-name 'sway-ipc.*.sock' -print -quit)
[ -n "$swaysock" ] && break
sleep 0.2
done
if [ -z "$swaysock" ]; then
echo "sway never created an IPC socket. Its log:" >&2
cat "${RUNNER_TEMP}/sway.log" >&2
exit 1
fi
{
echo "WAYLAND_DISPLAY=$(basename "$socket")"
echo "SWAYSOCK=$swaysock"
echo "XDG_SESSION_TYPE=wayland"
echo "XDG_CURRENT_DESKTOP=sway"
} >> "$GITHUB_ENV"
# Xvfb is a bare X server: it serves the extensions neru's X11
# paths call (XTEST for injection, XFIXES for the click-through
# overlay shape, RANDR for screen enumeration) but it is not a
# window manager, and EWMH properties are a window manager's job.
# Without one the root window has no _NET_SUPPORTED at all, so
# x11_system.c and x11_accessibility.c — which both read
# _NET_ACTIVE_WINDOW to answer "what is focused" — would find
# nothing and the leg would report a session no user runs. openbox
# is the smallest EWMH-aware answer in the archive; the verify step
# below turns that reasoning into an assertion rather than a claim.
- name: Start Xvfb and a window manager
if: matrix.check == 'desktop-x11'
shell: bash
run: |
set -euo pipefail
display=":99"
# 1920x1080x24 mirrors the sway leg's output so both legs
# answer the same screen geometry to XRandR and to
# wlr-output-management.
setsid Xvfb "$display" -screen 0 1920x1080x24 -nolisten tcp \
+extension RANDR +extension XTEST +extension XFIXES \
> "${RUNNER_TEMP}/xvfb.log" 2>&1 &
for attempt in $(seq 1 100); do
if DISPLAY="$display" xdpyinfo > /dev/null 2>&1; then
break
fi
if [ "$attempt" = "100" ]; then
echo "Xvfb never accepted a connection on $display. Its log:" >&2
cat "${RUNNER_TEMP}/xvfb.log" >&2
exit 1
fi
sleep 0.2
done
DISPLAY="$display" setsid openbox \
> "${RUNNER_TEMP}/openbox.log" 2>&1 &
# The window manager owns _NET_SUPPORTED, so its appearance on
# the root window is the readiness signal — openbox having
# been exec'd is not the same thing.
for attempt in $(seq 1 100); do
if DISPLAY="$display" xprop -root _NET_SUPPORTED 2>/dev/null \
| grep -q _NET_ACTIVE_WINDOW; then
break
fi
if [ "$attempt" = "100" ]; then
echo "openbox never claimed EWMH on $display. Its log:" >&2
cat "${RUNNER_TEMP}/openbox.log" >&2
exit 1
fi
sleep 0.2
done
{
echo "DISPLAY=$display"
echo "XDG_SESSION_TYPE=x11"
echo "XDG_CURRENT_DESKTOP=openbox"
} >> "$GITHUB_ENV"
- name: Start AT-SPI
if: startsWith(matrix.check, 'desktop')
shell: bash
run: |
set -euo pipefail
# at-spi2-core ships its launcher in libexec, and the
# directory moved between releases, so ask rather than assume.
launcher=""
for candidate in \
/usr/libexec/at-spi-bus-launcher \
/usr/lib/at-spi2-core/at-spi-bus-launcher \
/usr/lib/at-spi2/at-spi-bus-launcher; do
if [ -x "$candidate" ]; then
launcher="$candidate"
break
fi
done
if [ -z "$launcher" ]; then
echo "at-spi-bus-launcher not found; AT-SPI would be absent" >&2
exit 1
fi
setsid "$launcher" --launch-immediately \
> "${RUNNER_TEMP}/at-spi.log" 2>&1 &
# The tier is only worth its runtime if the session really is the
# blessed stack, so this asserts the two globals neru's wlroots
# paths bind (overlay_wayland.c, wlroots_client.h). A missing one
# fails here, where it reads as a broken environment rather than as
# test failures.
- name: Verify the session is the blessed stack
if: matrix.check == 'desktop'
shell: bash
run: |
set -euo pipefail
swaymsg -t get_outputs
wayland-info > "${RUNNER_TEMP}/wayland-info.log"
for global in zwlr_layer_shell_v1 zwlr_virtual_pointer_manager_v1; do
if ! grep -q "$global" "${RUNNER_TEMP}/wayland-info.log"; then
echo "compositor does not advertise $global" >&2
exit 1
fi
echo "advertised: $global"
done
# The X11 counterpart of the step above: the extensions neru's X11
# code calls, and the EWMH property that decides whether a window
# manager was needed here. It was: a bare Xvfb has no
# _NET_SUPPORTED, so this assertion fails without openbox running,
# which is what makes the previous step's window manager evidence
# rather than superstition.
- name: Verify the session is a usable X11 stack
if: matrix.check == 'desktop-x11'
shell: bash
run: |
set -euo pipefail
xdpyinfo > "${RUNNER_TEMP}/xdpyinfo.log"
# The extension list is the block between those two headings;
# matching the whole file would let "RANDR" in a screen's
# description stand in for the extension itself.
offered=$(sed -n '/number of extensions:/,/^default screen number/p' \
"${RUNNER_TEMP}/xdpyinfo.log")
for extension in XTEST XFIXES RANDR; do
if ! printf '%s\n' "$offered" \
| grep -q "^[[:space:]]*${extension}\$"; then
echo "X server does not offer the $extension extension" >&2
exit 1
fi
echo "offered: $extension"
done
supported="${RUNNER_TEMP}/net-supported.log"
xprop -root _NET_SUPPORTED > "$supported"
if ! grep -q _NET_ACTIVE_WINDOW "$supported"; then
echo "no EWMH window manager owns this display" >&2
cat "$supported" >&2
exit 1
fi
echo "EWMH: _NET_ACTIVE_WINDOW is supported"
- name: Verify CGO and the accessibility bus
if: startsWith(matrix.check, 'desktop')
shell: bash
run: |
set -euo pipefail
# ADR 0013 blesses the CGO build; the CGO-off Linux build is a
# near-total stub, and a green run of it would prove nothing.
cgo=$(go env CGO_ENABLED)
if [ "$cgo" != "1" ]; then
echo "CGO_ENABLED=$cgo; the blessed stack is the CGO build" >&2
exit 1
fi
# at-spi-bus-launcher was backgrounded a step ago and the bus
# is D-Bus-activated, so the first ask can arrive early.
for attempt in $(seq 1 25); do
if dbus-send --session --print-reply --dest=org.a11y.Bus \
/org/a11y/bus org.a11y.Bus.GetAddress; then
break
fi
if [ "$attempt" = "25" ]; then
echo "the accessibility bus never answered. Its log:" >&2
cat "${RUNNER_TEMP}/at-spi.log" >&2
exit 1
fi
sleep 0.4
done
# Both legs run this tier on a desktop with nothing focused, which
# is a state no other job here reaches: the X11 leg found a real
# defect in it on its first run (#1495, the X11 sibling of #1493),
# fixed before this leg landed. Capability status is
# docs/CROSS_PLATFORM.md's to state; docs/DEVELOPMENT.md says what
# these legs cover and what they do not.
- name: Run just test-desktop
if: startsWith(matrix.check, 'desktop')
shell: bash
timeout-minutes: 40
run: |
set -euo pipefail
just test-desktop 2>&1 | tee "${RUNNER_TEMP}/test-desktop.log"
# A skip in this tier is a claim that Linux behavior went unchecked,
# which is the thing the job exists to make visible — so executions,
# skips and failures are counted into the job summary rather than
# left in 20,000 lines of -v output nobody opens.
#
# The counts are also a floor, not decoration: a leg that skips its
# way to green is worth less than no leg at all, so this step fails
# when nothing executed, and when a test skipped because it could
# not see the display server this job exists to provide.
- name: Report what ran, skipped and failed
if: always() && startsWith(matrix.check, 'desktop')
shell: bash
env:
SESSION: ${{ matrix.session }}
run: |
set -euo pipefail
log="${RUNNER_TEMP}/test-desktop.log"
if [ ! -f "$log" ]; then
echo "The ${SESSION} desktop tier never ran; see the session steps above." \
>> "$GITHUB_STEP_SUMMARY"
echo "::error::the desktop tier never ran under ${SESSION}"
exit 1
fi
passes=$(grep -c -- '--- PASS: ' "$log" || true)
skips=$(grep -c -- '--- SKIP: ' "$log" || true)
fails=$(grep -c -- '--- FAIL: ' "$log" || true)
# Executed means started, so a failure counts. Passes alone
# would report "this leg ran nothing" for a run where
# everything ran and everything broke, which is the opposite
# of the truth and the opposite of what the floor is for.
executed=$((passes + fails))
# A package that fails to build reports FAIL with no failing
# test in it, so the per-test count alone would read as green.
badpkgs=$(grep -c '^FAIL[[:space:]]' "$log" || true)
# The skip reason a test gives when neither DISPLAY nor
# WAYLAND_DISPLAY reached it — owned by
# screencapture_integration_linux_test.go. On this job that is
# never a property of the test; it means the session steps
# above built a display server the test process never saw.
# Anchored to the file:line a t.Skip reason carries, so the
# phrase appearing anywhere else in 20,000 lines of -v output
# is not mistaken for one.
blind=$(grep -c -E '_test\.go:[0-9]+: no display server' "$log" || true)
{
echo "### Linux desktop tier — ${SESSION}"
echo ""
echo "Blocking: a failure here reds the pull request."
echo "See docs/DEVELOPMENT.md for what it covers."
echo ""
echo "| | Count |"
echo "| --- | --- |"
echo "| Executed (PASS + FAIL lines, subtests included) | ${executed} |"
echo "| Passed | ${passes} |"
echo "| \`--- FAIL:\` lines | ${fails} |"
echo "| Packages reporting FAIL | ${badpkgs} |"
echo "| Skipped tests | ${skips} |"
echo ""
if [ "$badpkgs" != "0" ]; then
echo "#### Packages"
echo ""
echo '```'
grep '^FAIL[[:space:]]' "$log"
echo '```'
echo ""
fi
if [ "$fails" != "0" ]; then
echo "#### Failures"
echo ""
echo '```'
grep -- '--- FAIL: ' "$log" | sed 's/^[[:space:]]*//'
echo '```'
echo ""
fi
if [ "$skips" != "0" ]; then
echo "#### Skips, with the reason each gave"
echo ""
echo '```'
# go test -v prints what t.Skip logged *before* the
# result line, so the reason is the line already gone
# past — hence the one-line lookback rather than getline.
awk '
/--- SKIP: /{
name = $0
sub(/^[[:space:]]*/, "", name)
print name
if (prev ~ /^[[:space:]]+[^[:space:]]+\.go:[0-9]+:/) {
reason = prev
sub(/^[[:space:]]*/, "", reason)
print " " reason
}
}
{ prev = $0 }
' "$log"
echo '```'
echo ""
fi
if [ "$executed" = "0" ] || [ "$blind" != "0" ]; then
echo "#### This leg proved nothing"
echo ""
echo "It is failing on its own floor, not on a test:"
echo "an executed count of zero, or a test that could not"
echo "see the display server this job exists to provide."
fi
} >> "$GITHUB_STEP_SUMMARY"
if [ "$executed" = "0" ]; then
echo "::error::the desktop tier executed no tests under ${SESSION}"
exit 1
fi
if [ "$blind" != "0" ]; then
echo "::error::${blind} test(s) skipped for want of a display server under ${SESSION}; the session never reached the test process"
exit 1
fi
- name: Upload desktop tier logs
if: always() && startsWith(matrix.check, 'desktop')
uses: actions/upload-artifact@v7
with:
# linux-desktop-logs for the sway leg, linux-desktop-x11-logs
# for the X11 one: artifact names are unique per run, so the
# two legs cannot share one.
name: linux-${{ matrix.check }}-logs
path: |
${{ runner.temp }}/test-desktop.log
${{ runner.temp }}/sway.log
${{ runner.temp }}/at-spi.log
${{ runner.temp }}/wayland-info.log
${{ runner.temp }}/xvfb.log
${{ runner.temp }}/openbox.log
${{ runner.temp }}/xdpyinfo.log
${{ runner.temp }}/net-supported.log
if-no-files-found: warn
retention-days: 14