From d36a6bf27d0170bb4156765df648d53492350c3c Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Fri, 29 May 2026 19:20:50 +0000 Subject: [PATCH 1/3] Add JSC stress test workflow for PR validation --- .github/workflows/jsc-tests.yml | 156 ++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 .github/workflows/jsc-tests.yml diff --git a/.github/workflows/jsc-tests.yml b/.github/workflows/jsc-tests.yml new file mode 100644 index 000000000000..89add33cb068 --- /dev/null +++ b/.github/workflows/jsc-tests.yml @@ -0,0 +1,156 @@ +name: JSC Tests + +# Runs the upstream JavaScriptCore test suite (run-javascriptcore-tests) +# against a release jsc shell. The existing Preview Build workflow only +# verifies that the tree compiles; this is the first correctness gate. +# +# Scope: Linux x64 release, --quick mode (default + no-cjit-validate test +# variants only), stress/mozilla/chakra/layout corpora, no native test +# binaries (testmasm/testair/testb3/testdfg/testapi). Upstream EWS budgets +# ~1h for the full suite; --quick is the documented fast subset. + +on: + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: jsc-tests-pr-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + LLVM_VERSION: "21" + +jobs: + permission-check: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/github-script@v7 + with: + script: | + const { data: p } = await github.rest.repos.getCollaboratorPermissionLevel({ + owner: context.repo.owner, + repo: context.repo.repo, + username: context.actor, + }); + if (!['admin', 'write'].includes(p.permission)) { + core.setFailed(`${context.actor} lacks write access; trigger via workflow_dispatch.`); + } + + test: + name: Linux x64 (quick) + needs: [permission-check] + if: always() && (needs.permission-check.result == 'success' || github.event_name == 'workflow_dispatch') + runs-on: linux-x64-gh + timeout-minutes: 120 + steps: + - uses: actions/checkout@v4 + with: + # JSTests/ + LayoutTests/js/ are ~550 MB; we need them. Everything + # under LayoutTests/ that the jsc-layout-tests.yaml driver doesn't + # touch is excluded. + sparse-checkout-cone-mode: false + sparse-checkout: | + /* + !/Websites/ + !/LayoutTests/ + /LayoutTests/jsc-layout-tests.yaml + /LayoutTests/resources/standalone-pre.js + /LayoutTests/resources/standalone-post.js + /LayoutTests/resources/js-test-pre.js + /LayoutTests/resources/js-test-post.js + /LayoutTests/js/ + /LayoutTests/fast/regex/ + + - name: Install toolchain + run: | + set -euxo pipefail + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + ninja-build cmake ruby perl libicu-dev \ + python3 ca-certificates curl gnupg lsb-release + # Match the LLVM major used by the Docker artifact build. + curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s ${LLVM_VERSION} + for t in clang clang++ lld llvm-ar llvm-ranlib ld.lld; do + sudo ln -sf /usr/bin/${t}-${LLVM_VERSION} /usr/bin/${t} + done + clang --version + cmake --version + ruby --version + + - name: Build jsc (release) + run: | + set -euxo pipefail + export CC=clang CXX=clang++ + cmake -S . -B WebKitBuild/Release -G Ninja \ + -DPORT=JSCOnly \ + -DCMAKE_BUILD_TYPE=Release \ + -DENABLE_STATIC_JSC=ON \ + -DUSE_THIN_ARCHIVES=OFF \ + -DUSE_BUN_JSC_ADDITIONS=ON \ + -DUSE_BUN_EVENT_LOOP=ON \ + -DENABLE_FTL_JIT=ON \ + -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \ + -DENABLE_REMOTE_INSPECTOR=ON \ + -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \ + -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \ + -DCMAKE_AR=$(which llvm-ar) \ + -DCMAKE_RANLIB=$(which llvm-ranlib) \ + -DCMAKE_C_FLAGS="-march=haswell" \ + -DCMAKE_CXX_FLAGS="-march=haswell -fno-c++-static-destructors" + cmake --build WebKitBuild/Release --target jsc -- -k0 + WebKitBuild/Release/bin/jsc -e 'print("jsc OK", version())' + + - name: Run JavaScriptCore tests + run: | + set -euxo pipefail + # --root sets productDir; on non-Apple, executableProductDir() then + # appends /bin, so point at the cmake build dir, not bin/. + Tools/Scripts/run-javascriptcore-tests \ + --jsc-only --release --no-build --no-fail-fast \ + --root="$PWD/WebKitBuild/Release" \ + --quick --memory-limited \ + --no-testmasm --no-testair --no-testb3 --no-testdfg --no-testapi \ + --no-testwasmdebugger \ + --json-output="$PWD/jsc_results.json" \ + 2>&1 | tee jsc_test_output.log + + - name: Upload results + if: always() + uses: actions/upload-artifact@v4 + with: + name: jsc-test-results + path: | + jsc_results.json + jsc_test_output.log + retention-days: 14 + + - name: Summarize + if: always() + run: | + if [ -f jsc_results.json ]; then + python3 - <<'EOF' + import json, sys + with open("jsc_results.json") as f: + r = json.load(f) + stress = r.get("stressTestFailures", []) + print(f"## JSC test summary", file=sys.stderr) + print(f"stress failures: {len(stress)}") + for t in stress[:50]: + print(f" FAIL {t}") + if len(stress) > 50: + print(f" ... and {len(stress)-50} more") + with open("${{ runner.temp }}/summary.md", "w") as out: + out.write(f"### JSC tests (quick)\n\n") + out.write(f"- stress failures: **{len(stress)}**\n") + if stress: + out.write("\n
failures\n\n```\n") + out.write("\n".join(stress[:200])) + out.write("\n```\n
\n") + EOF + cat "${{ runner.temp }}/summary.md" >> "$GITHUB_STEP_SUMMARY" + fi From b37cdb19627476fa3ed6fd59691a583faa65e315 Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Fri, 29 May 2026 19:28:10 +0000 Subject: [PATCH 2/3] Drop --quick/--memory-limited: run full mode set like upstream EWS --- .github/workflows/jsc-tests.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/jsc-tests.yml b/.github/workflows/jsc-tests.yml index 89add33cb068..bceb79aa3f84 100644 --- a/.github/workflows/jsc-tests.yml +++ b/.github/workflows/jsc-tests.yml @@ -4,10 +4,9 @@ name: JSC Tests # against a release jsc shell. The existing Preview Build workflow only # verifies that the tree compiles; this is the first correctness gate. # -# Scope: Linux x64 release, --quick mode (default + no-cjit-validate test -# variants only), stress/mozilla/chakra/layout corpora, no native test -# binaries (testmasm/testair/testb3/testdfg/testapi). Upstream EWS budgets -# ~1h for the full suite; --quick is the documented fast subset. +# Scope: Linux x64 release, full mode set (matches upstream EWS), +# stress/mozilla/chakra/layout/wasm corpora, no native test binaries +# (testmasm/testair/testb3/testdfg/testapi/testwasmdebugger). on: pull_request: @@ -42,7 +41,7 @@ jobs: } test: - name: Linux x64 (quick) + name: Linux x64 needs: [permission-check] if: always() && (needs.permission-check.result == 'success' || github.event_name == 'workflow_dispatch') runs-on: linux-x64-gh @@ -113,7 +112,6 @@ jobs: Tools/Scripts/run-javascriptcore-tests \ --jsc-only --release --no-build --no-fail-fast \ --root="$PWD/WebKitBuild/Release" \ - --quick --memory-limited \ --no-testmasm --no-testair --no-testb3 --no-testdfg --no-testapi \ --no-testwasmdebugger \ --json-output="$PWD/jsc_results.json" \ From 25471103f9a163ab518890714984aeab1146696f Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Fri, 29 May 2026 19:44:31 +0000 Subject: [PATCH 3/3] Move JSC tests into build-reusable.yml; consume linux artifact instead of rebuilding --- .github/workflows/build-reusable.yml | 97 +++++++++++++++++ .github/workflows/jsc-tests.yml | 154 --------------------------- 2 files changed, 97 insertions(+), 154 deletions(-) delete mode 100644 .github/workflows/jsc-tests.yml diff --git a/.github/workflows/build-reusable.yml b/.github/workflows/build-reusable.yml index 1bafddd4acf0..1aae53917842 100644 --- a/.github/workflows/build-reusable.yml +++ b/.github/workflows/build-reusable.yml @@ -588,6 +588,103 @@ jobs: name: ${{matrix.label}} path: ${{runner.temp}}/bun-webkit.tar.gz + jsc-tests: + name: JSC Tests (${{ matrix.artifact }}) + needs: [linux] + runs-on: ${{ matrix.runs-on }} + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + include: + - artifact: bun-webkit-linux-amd64 + runs-on: linux-x64-gh + # macOS / Windows entries to follow once linux is green. + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.build_ref }} + # The build jobs sparse-exclude JSTests/LayoutTests; the test runner + # needs them. Exclude only the parts of LayoutTests/ the jsc driver + # doesn't touch. + sparse-checkout-cone-mode: false + sparse-checkout: | + /* + !/Websites/ + !/LayoutTests/ + /LayoutTests/jsc-layout-tests.yaml + /LayoutTests/resources/ + /LayoutTests/js/ + /LayoutTests/fast/regex/ + + - uses: actions/download-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: ${{ runner.temp }}/artifact + + - name: Extract jsc + run: | + set -euxo pipefail + mkdir -p WebKitBuild/Release + tar -xzf "${{ runner.temp }}/artifact/bun-webkit.tar.gz" -C "${{ runner.temp }}" + # webkitdirs.pm's executableProductDir() appends /bin to --root on + # non-Apple platforms, so the layout it expects is /bin/jsc. + cp -r "${{ runner.temp }}/bun-webkit/bin" WebKitBuild/Release/bin + file WebKitBuild/Release/bin/jsc + WebKitBuild/Release/bin/jsc -e 'print("jsc OK", version())' + + - name: Install runner deps + run: | + set -euxo pipefail + sudo apt-get update + sudo apt-get install -y --no-install-recommends ruby perl make + + - name: Run JavaScriptCore tests + run: | + set -euxo pipefail + Tools/Scripts/run-javascriptcore-tests \ + --jsc-only --release --no-build --no-fail-fast \ + --root="$PWD/WebKitBuild/Release" \ + --no-testmasm --no-testair --no-testb3 --no-testdfg --no-testapi \ + --no-testwasmdebugger \ + --json-output="$PWD/jsc_results.json" \ + 2>&1 | tee jsc_test_output.log + + - name: Upload results + if: always() + uses: actions/upload-artifact@v4 + with: + name: jsc-test-results-${{ matrix.artifact }} + path: | + jsc_results.json + jsc_test_output.log + retention-days: 14 + + - name: Summarize + if: always() + run: | + if [ -f jsc_results.json ]; then + python3 - <<'EOF' + import json + with open("jsc_results.json") as f: + r = json.load(f) + stress = r.get("stressTestFailures", []) + print(f"stress failures: {len(stress)}") + for t in stress[:50]: + print(f" FAIL {t}") + if len(stress) > 50: + print(f" ... and {len(stress)-50} more") + with open("summary.md", "w") as out: + out.write(f"### JSC tests — ${{ matrix.artifact }}\n\n") + out.write(f"- stress failures: **{len(stress)}**\n") + if stress: + out.write("\n
failures\n\n```\n") + out.write("\n".join(stress[:200])) + out.write("\n```\n
\n") + EOF + cat summary.md >> "$GITHUB_STEP_SUMMARY" + fi + release: name: release permissions: diff --git a/.github/workflows/jsc-tests.yml b/.github/workflows/jsc-tests.yml deleted file mode 100644 index bceb79aa3f84..000000000000 --- a/.github/workflows/jsc-tests.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: JSC Tests - -# Runs the upstream JavaScriptCore test suite (run-javascriptcore-tests) -# against a release jsc shell. The existing Preview Build workflow only -# verifies that the tree compiles; this is the first correctness gate. -# -# Scope: Linux x64 release, full mode set (matches upstream EWS), -# stress/mozilla/chakra/layout/wasm corpora, no native test binaries -# (testmasm/testair/testb3/testdfg/testapi/testwasmdebugger). - -on: - pull_request: - types: [opened, synchronize, reopened] - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: jsc-tests-pr-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -env: - LLVM_VERSION: "21" - -jobs: - permission-check: - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' - steps: - - uses: actions/github-script@v7 - with: - script: | - const { data: p } = await github.rest.repos.getCollaboratorPermissionLevel({ - owner: context.repo.owner, - repo: context.repo.repo, - username: context.actor, - }); - if (!['admin', 'write'].includes(p.permission)) { - core.setFailed(`${context.actor} lacks write access; trigger via workflow_dispatch.`); - } - - test: - name: Linux x64 - needs: [permission-check] - if: always() && (needs.permission-check.result == 'success' || github.event_name == 'workflow_dispatch') - runs-on: linux-x64-gh - timeout-minutes: 120 - steps: - - uses: actions/checkout@v4 - with: - # JSTests/ + LayoutTests/js/ are ~550 MB; we need them. Everything - # under LayoutTests/ that the jsc-layout-tests.yaml driver doesn't - # touch is excluded. - sparse-checkout-cone-mode: false - sparse-checkout: | - /* - !/Websites/ - !/LayoutTests/ - /LayoutTests/jsc-layout-tests.yaml - /LayoutTests/resources/standalone-pre.js - /LayoutTests/resources/standalone-post.js - /LayoutTests/resources/js-test-pre.js - /LayoutTests/resources/js-test-post.js - /LayoutTests/js/ - /LayoutTests/fast/regex/ - - - name: Install toolchain - run: | - set -euxo pipefail - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - ninja-build cmake ruby perl libicu-dev \ - python3 ca-certificates curl gnupg lsb-release - # Match the LLVM major used by the Docker artifact build. - curl -fsSL https://apt.llvm.org/llvm.sh | sudo bash -s ${LLVM_VERSION} - for t in clang clang++ lld llvm-ar llvm-ranlib ld.lld; do - sudo ln -sf /usr/bin/${t}-${LLVM_VERSION} /usr/bin/${t} - done - clang --version - cmake --version - ruby --version - - - name: Build jsc (release) - run: | - set -euxo pipefail - export CC=clang CXX=clang++ - cmake -S . -B WebKitBuild/Release -G Ninja \ - -DPORT=JSCOnly \ - -DCMAKE_BUILD_TYPE=Release \ - -DENABLE_STATIC_JSC=ON \ - -DUSE_THIN_ARCHIVES=OFF \ - -DUSE_BUN_JSC_ADDITIONS=ON \ - -DUSE_BUN_EVENT_LOOP=ON \ - -DENABLE_FTL_JIT=ON \ - -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \ - -DENABLE_REMOTE_INSPECTOR=ON \ - -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \ - -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" \ - -DCMAKE_AR=$(which llvm-ar) \ - -DCMAKE_RANLIB=$(which llvm-ranlib) \ - -DCMAKE_C_FLAGS="-march=haswell" \ - -DCMAKE_CXX_FLAGS="-march=haswell -fno-c++-static-destructors" - cmake --build WebKitBuild/Release --target jsc -- -k0 - WebKitBuild/Release/bin/jsc -e 'print("jsc OK", version())' - - - name: Run JavaScriptCore tests - run: | - set -euxo pipefail - # --root sets productDir; on non-Apple, executableProductDir() then - # appends /bin, so point at the cmake build dir, not bin/. - Tools/Scripts/run-javascriptcore-tests \ - --jsc-only --release --no-build --no-fail-fast \ - --root="$PWD/WebKitBuild/Release" \ - --no-testmasm --no-testair --no-testb3 --no-testdfg --no-testapi \ - --no-testwasmdebugger \ - --json-output="$PWD/jsc_results.json" \ - 2>&1 | tee jsc_test_output.log - - - name: Upload results - if: always() - uses: actions/upload-artifact@v4 - with: - name: jsc-test-results - path: | - jsc_results.json - jsc_test_output.log - retention-days: 14 - - - name: Summarize - if: always() - run: | - if [ -f jsc_results.json ]; then - python3 - <<'EOF' - import json, sys - with open("jsc_results.json") as f: - r = json.load(f) - stress = r.get("stressTestFailures", []) - print(f"## JSC test summary", file=sys.stderr) - print(f"stress failures: {len(stress)}") - for t in stress[:50]: - print(f" FAIL {t}") - if len(stress) > 50: - print(f" ... and {len(stress)-50} more") - with open("${{ runner.temp }}/summary.md", "w") as out: - out.write(f"### JSC tests (quick)\n\n") - out.write(f"- stress failures: **{len(stress)}**\n") - if stress: - out.write("\n
failures\n\n```\n") - out.write("\n".join(stress[:200])) - out.write("\n```\n
\n") - EOF - cat "${{ runner.temp }}/summary.md" >> "$GITHUB_STEP_SUMMARY" - fi