Skip to content

Commit 733db6b

Browse files
ci: avoid SIGPIPE in e2e-failure-analyzer awk pipeline (#13702)
## Summary Follow-up to #13693. That PR replaced `grep | grep | head -1` with a single awk pipeline to avoid `head` closing its stdin and SIGPIPE-ing upstream `grep`. But the new awk script kept the same shape of bug: it calls `exit` after the first match, which closes awk's stdin and SIGPIPEs the upstream `printf`. Under `set -e -o pipefail` the step still dies. posit-dev/positron-builds CI confirms this with `printf: write error: Broken pipe` on real job logs. Small local logs don't reproduce because `printf` finishes writing before awk's `exit` closes the pipe. Fix: rewrite the awk script as an END-block accumulator. awk reads all input, captures the first concrete match into a variable, prints it at END. No early termination, no pipe-close race. The trade-off is reading the whole log instead of bailing on the first match. `gh api .../jobs/$ID/logs` payloads are bounded (~10MB max), so the cost is negligible compared to eliminating the race for good. ## Test plan - [ ] Trigger `analyze-e2e-failures.yml` on positron — should still work end-to-end (the awk script's external behavior is unchanged: prints the first concrete match or nothing). - [ ] positron-builds end-to-end will validate the SIGPIPE doesn't recur on real CI log sizes once positron-builds bumps to this SHA.
1 parent 8eaf5d9 commit 733db6b

1 file changed

Lines changed: 11 additions & 7 deletions

File tree

.github/actions/e2e-failure-analyzer/action.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,18 @@ runs:
155155
156156
# Resolve REPORT_DIR from the job's logs. The workflow logs both an
157157
# unresolved template line (REPORT_DIR="...-${IDENTIFIER}-${OS_SUFFIX}")
158-
# and the expanded value (REPORT_DIR: playwright-report-<run>-<attempt>-<id>-<os>).
159-
# Skip the template line, take the first concrete match. Single awk pass
160-
# rather than grep | grep | head -1 to avoid head closing its stdin while
161-
# upstream grep is still writing -- under `set -e -o pipefail` that
162-
# manifests as "grep: write error: Broken pipe" + exit 2 on large logs.
158+
# and the expanded value. Skip the template, capture the first concrete
159+
# match, emit it at END. Avoiding `exit` here is deliberate -- it would
160+
# close awk's stdin mid-pipeline, SIGPIPE upstream printf, and under
161+
# `set -e -o pipefail` kill the step (manifests as "printf: write error:
162+
# Broken pipe" on large log payloads).
163163
LOGS=$(gh api "repos/$REPO/actions/jobs/$JOB_ID/logs" 2>/dev/null || true)
164-
REPORT_DIR=$(printf '%s' "$LOGS" \
165-
| awk '!/\${/ && match($0, /playwright-report-[A-Za-z0-9_-]+/) { print substr($0, RSTART, RLENGTH); exit }')
164+
REPORT_DIR=$(printf '%s' "$LOGS" | awk '
165+
!/\${/ && !found && match($0, /playwright-report-[A-Za-z0-9_-]+/) {
166+
found = substr($0, RSTART, RLENGTH)
167+
}
168+
END { if (found) print found }
169+
')
166170
167171
if [ -z "$REPORT_DIR" ]; then
168172
echo "Could not resolve REPORT_DIR from logs of job $JOB_ID. Skipping."

0 commit comments

Comments
 (0)