Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,10 @@ jobs:
# (`is_bun_runtime_crash`). The unsharded macOS control had no equivalent,
# so the same crash that Linux absorbs failed the whole promotion here.
#
# Keep the signature list in sync with `is_bun_runtime_crash` in
# scripts/ci/run-bun-test-batches.sh. An assertion failure still fails on
# the first attempt — only the crash signature is retried, exactly once.
# The classifier is `is_bun_runtime_crash` from scripts/ci/bun-crash-signatures.sh, which
# this leg, the Windows leg, the macOS control and the Linux batch runner all source. It used
# to be four inline copies kept in sync by a test; one definition cannot drift. An assertion
# failure still fails on the first attempt — only a crash is retried, exactly once.
- name: Test
env:
MACOS_TEST_SHARD: ${{ matrix.shard }}
Expand All @@ -546,6 +547,8 @@ jobs:
# errexit so a Bun crash reaches PIPESTATUS and the bounded retry.
set +e
set -uo pipefail
# One shared classifier for every lane; see scripts/ci/bun-crash-signatures.sh.
source scripts/ci/bun-crash-signatures.sh

run_macos_suite() {
local suite_log suite_status attempt
Expand All @@ -559,7 +562,7 @@ jobs:
rm -f "$suite_log"
return 0
fi
if ! grep -Eqi 'oh no: Bun has crashed|Internal assertion failure|Segmentation fault at address|Illegal instruction|Bus error|Aborted \(core dumped\)' "$suite_log"; then
if ! is_bun_runtime_crash "$suite_status" "$suite_log"; then
echo "::error::macOS suite failed on attempt ${attempt} (exit ${suite_status}); assertion failures are not retried."
rm -f "$suite_log"
return "$suite_status"
Expand Down Expand Up @@ -685,15 +688,17 @@ jobs:
# (`is_bun_runtime_crash`). The unsharded macOS control had no equivalent,
# so the same crash that Linux absorbs failed the whole promotion here.
#
# Keep the signature list in sync with `is_bun_runtime_crash` in
# scripts/ci/run-bun-test-batches.sh. An assertion failure still fails on
# the first attempt — only the crash signature is retried, exactly once.
# The classifier is `is_bun_runtime_crash` from scripts/ci/bun-crash-signatures.sh, shared
# with every other lane. An assertion failure still fails on the first attempt — only a
# crash is retried, exactly once.
- name: Test
run: |
# GitHub Actions starts bash `run:` blocks with `-e`. Disable
# errexit so a Bun crash reaches PIPESTATUS and the bounded retry.
set +e
set -uo pipefail
# One shared classifier for every lane; see scripts/ci/bun-crash-signatures.sh.
source scripts/ci/bun-crash-signatures.sh
suite_log="$(mktemp -t ocx-macos-suite.XXXXXX)"
for attempt in 1 2; do
# --timeout: Bun's default 5s per-test ceiling is the recurring flake
Expand All @@ -708,7 +713,7 @@ jobs:
if [ "$suite_status" -eq 0 ]; then
exit 0
fi
if ! grep -Eqi 'oh no: Bun has crashed|Internal assertion failure|Segmentation fault at address|Illegal instruction|Bus error|Aborted \(core dumped\)' "$suite_log"; then
if ! is_bun_runtime_crash "$suite_status" "$suite_log"; then
echo "::error::macOS suite failed on attempt ${attempt} (exit ${suite_status}); assertion failures are not retried."
exit "$suite_status"
fi
Expand Down Expand Up @@ -834,14 +839,16 @@ jobs:
run: |
set +e
set -uo pipefail
# One shared classifier for every lane; see scripts/ci/bun-crash-signatures.sh.
source scripts/ci/bun-crash-signatures.sh
suite_log="$(mktemp -t ocx-windows-suite.XXXXXX)"
for attempt in 1 2; do
bun test --isolate --timeout 60000 tests --shard=${{ matrix.shard }}/6 2>&1 | tee "$suite_log"
suite_status="${PIPESTATUS[0]}"
if [ "$suite_status" -eq 0 ]; then
exit 0
fi
if ! grep -Eqi 'oh no: Bun has crashed|Internal assertion failure|Segmentation fault at address|Illegal instruction|Bus error|Aborted \(core dumped\)' "$suite_log"; then
if ! is_bun_runtime_crash "$suite_status" "$suite_log"; then
echo "::error::Windows shard ${{ matrix.shard }}/6 failed on attempt ${attempt} (exit ${suite_status}); assertion failures are not retried."
exit "$suite_status"
fi
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1

# Keep the runtime aligned with package.json and pin the multi-platform image index.
ARG BUN_IMAGE=oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895
ARG BUN_IMAGE=oven/bun:1.4.0@sha256:5ff609364c049b54eb0ff560ec96319729a972078ef2c755d758f0c6ef89c2d6

FROM ${BUN_IMAGE} AS build
WORKDIR /home/bun/app
Expand Down
34 changes: 17 additions & 17 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@
"@bufbuild/protobuf": "^2.14.0",
"@modelcontextprotocol/sdk": "^1.30.0",
"@napi-rs/keyring": "1.3.0",
"bun": "1.4.2",
"bun": "1.4.0",
"zod": "4.4.3"
},
"devDependencies": {
"@types/bun": "1.4.2",
"@types/bun": "1.4.0",
"typescript": "7.0.2"
},
"overrides": {
Expand Down
68 changes: 68 additions & 0 deletions scripts/ci/bun-crash-signatures.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env bash
# The single definition of "this was a Bun runtime crash, not a test result".
#
# There were four copies of this list: one in the Linux batch runner and three inline in ci.yml
# (platform-windows, platform-macos, macos-control). ci-workflows.test.ts pinned them in sync
# rather than removing the duplication, because #2152 had already broken one copy by anchoring on
# `panic(thread 2852)` when Bun also emits `panic(main thread)` for the same class, and half the
# crashes stopped matching. Pinning four copies in sync only detects the drift it was written to
# expect; one definition cannot drift at all.
#
# Source it from the repository root: source scripts/ci/bun-crash-signatures.sh

# shellcheck shell=bash

# Sourced by nested shells in the same job, so a second source must be a no-op rather than a
# readonly-reassignment error.
if [[ -n "${OCX_BUN_CRASH_SIGNATURES_LOADED:-}" ]]; then
return 0
fi
OCX_BUN_CRASH_SIGNATURES_LOADED=1

# Never anchor on the thread-numbered form. `Internal assertion failure` is the stable fingerprint
# recorded in devlog/_fin/260731_pr_issue_triage_round/050_windows_ci_flake_rca.md.
OCX_BUN_CRASH_SIGNATURE_PATTERN='oh no: Bun has crashed|Internal assertion failure|Segmentation fault at address|Illegal instruction|Bus error|Aborted \(core dumped\)'

# True when the process output carries a Bun panic banner.
bun_log_has_crash_signature() {
grep -Eqi "$OCX_BUN_CRASH_SIGNATURE_PATTERN" "$1"
}

# True for a status that can only be a fatal signal.
#
# 128+N for SIGILL/SIGABRT/SIGBUS/SIGKILL/SIGSEGV and neighbours. Windows exit 3 is deliberately
# NOT in this list: it is the status a Windows Bun returns alongside a SIGSEGV panic, but unlike
# 132-139 it is an ordinary small exit code any process may return for its own reasons. Trusting
# it bare would reclassify a real test failure as a crash and hide it, which is the exact mistake
# this file exists to stop. Exit 3 is still covered, through the signature arm below, which is
# corroborated by the panic banner Bun actually printed -- that is how the Windows shard 5/6
# crashes of runs 35087572377, 35093667426 and 35098735960 are recognised.
bun_status_is_crash_code() {
case "$1" in
132|133|134|135|136|137|139) return 0 ;;
esac
return 1
}

# The shared predicate: is_bun_runtime_crash <exit-status> <log-file>
is_bun_runtime_crash() {
local status="$1"
local log_file="$2"

if bun_status_is_crash_code "$status"; then
return 0
fi

# Bun 1.3.14 can surface a Linux epoll registration failure as exit 1, even though the failure
# comes from Bun's internal WriteStream setup rather than a test assertion. Treat only that
# narrow runtime signature as a crash.
if [[ "$status" == "1" ]] \
&& grep -Fq '# Unhandled error between tests' "$log_file" \
&& grep -Fq 'error: EEXIST: file already exists, epoll_ctl' "$log_file" \
&& grep -Fq 'at new WriteStream (internal:fs/streams:' "$log_file"; then
return 0
fi

bun_log_has_crash_signature "$log_file"
}

Loading
Loading