Skip to content

fix: prevent JS tests from hanging after completion#26143

Merged
dsyme merged 2 commits intomainfrom
copilot/fix-js-tests-hanging-issue
Apr 14, 2026
Merged

fix: prevent JS tests from hanging after completion#26143
dsyme merged 2 commits intomainfrom
copilot/fix-js-tests-hanging-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 14, 2026

After all tests passed, the vitest process hung for up to 18 minutes until the CI job timeout cancelled it. The culprit was mcp_http_server_runner.test.cjs: each test created a real HTTP server, made requests over keep-alive TCP connections, then called server.close() — which stops new connections but does not close existing ones. Those lingering sockets held the Node.js event loop open indefinitely.

Changes

  • mcp_http_server_runner.test.cjs: Replaced per-test server.close() calls with a shared afterEach hook that calls server.closeAllConnections() first, then awaits server.close() — fully draining all TCP connections before the next test.
afterEach(async () => {
  if (currentServer) {
    currentServer.closeAllConnections(); // force-close keep-alive sockets
    await new Promise(r => currentServer.close(r));
    currentServer = null;
  }
});
  • vitest.config.mjs: Added forceExit: true as a safety net so the process always exits after the test run, even if other tests leave behind open handles.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw 8680664/b083/vetrev-parse ache/go/1.25.8/x--show-toplevel gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq /usr/bin/git /tmp/go-build589git -trimpath /opt/hostedtoolc--show-toplevel git (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --show-toplevel 64/pkg/tool/linuorigin /usr/bin/git -json .cfg 64/pkg/tool/linu--show-toplevel /usr/bin/git conf�� --get-regexp ^remote\..*\.gh-resolved$ /usr/bin/git rtcfg .cfg 64/pkg/tool/linu--show-toplevel git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha --git-dir x_amd64/compile /usr/bin/git -json GO111MODULE x_amd64/compile git -C /tmp/gh-aw-test-runs/20260414-021024-33407/test-1777859453/custom/workflows l /usr/bin/git -json GO111MODULE x_amd64/vet git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha g_.a 8680664/b036/vet.cfg .cfg GOINSECURE til GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet estl�� QWDNxN3gv 8680664/b088/vet.cfg ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -p crypto/subtle -lang=go1.25 ortcfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git edOutput25744425git .cfg 64/pkg/tool/linu--show-toplevel git rev-�� pload-artifact/git/ref/tags/v7 64/pkg/tool/linuTest User /usr/bin/git sole.test 8680664/b012/vetrev-parse x_amd64/compile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linumyorg /usr/bin/git g/cli /tmp/go-build231rev-parse (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha --show-toplevel eutil.test /usr/bin/git se 8680664/b260/vet-f1 .cfg git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linustatus /usr/bin/git 7072/001/stabiligit 8680664/b189/vetrev-parse ache/go/1.25.8/x--show-toplevel git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json 1.5.0/internal/mcpgodebug/mcpgodebug.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/vet GOINSECURE jsonrpc2 GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha GOMODCACHE UpQRbjo/-LfbKy3Tlp9CVGJ11VEe /usr/bin/git _.a om/owner/repo.girev-parse lone-4282287512 git rev-�� --git-dir x_amd64/vet /opt/hostedtoolcache/node/24.14.1/x64/bin/node _.a deRMpwyMD 64/pkg/tool/linu--show-toplevel node (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha om/owner/repo.git /tmp/go-build2318680664/b440/_testmain.go /usr/bin/git lic_180857349/00git GO111MODULE x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git -json QuPWq4ACQ 64/pkg/tool/linu--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha -bool -buildtags 8680664/b444/timeutil.test -errorsas -ifaceassert -nilfunc 8680664/b444/timeutil.test e=/t�� t0 initial commit (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha 01/main.md pkg/mod/github.com/modelcontextprotocol/go-sdk@v1.5.0/internal/mcpgodebug/mcpgodebug.go ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -p crypto/internal/rev-parse -lang=go1.25 ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -o /tmp/go-build589493260/b229/_pkg_.a -trimpath 8680664/b197/vet.cfg -p github.com/modelrev-parse -lang=go1.25 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linurev-parse (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha 2291934837 ntifiers.go ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -p github.com/googlrev-parse -lang=go1.23 ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -uns�� -unreachable=false /tmp/go-build2318680664/b006/vet.cfg 1/x64/bin/node go1.25.8 -c=4 -nolocalimports /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linurev-parse (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha /tmp/go-build589493260/b212/_pkg_.a -trimpath /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -p crypto/tls/interrev-parse -lang=go1.25 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -uns�� -unreachable=false /tmp/go-build2318680664/b099/vet.cfg 8680664/b315/vet.cfg -goversion go1.25.8 -c=4 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linurev-parse (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq .object.sha --get remote.origin.url /usr/bin/git _.a 0/internal/numberev-parse x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git m/workflows bt7zDc9ZF 64/pkg/tool/linu--show-toplevel git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha -test.paniconexit0 -test.v=true /usr/bin/infocmp -test.timeout=10git -test.run=^Test -test.short=true--show-toplevel infocmp -1 xterm-color x_amd64/asm /usr/bin/git -json GO111MODULE x_amd64/compile git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha -aw/git/ref/tags/v3.0.0 -test.v=true 1/x64/bin/node -test.timeout=10git -test.run=^Test -test.short=true--show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -has�� ithub/workflows/archie.md go /usr/bin/git -json GO111MODULE x_amd64/compile git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE 493260/b078/ GOMODCACHE 64/pkg/tool/linux_amd64/vet env 493260/b208/_pkg_.a GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE g/x/crypto/chachrev-parse ache/go/1.25.8/x--show-toplevel 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 om/yosida95/uritemplate/v3@v3.0.2/compile.go 64/pkg/tool/linux_amd64/vet GOINSECURE fips140/check GOMODCACHE 64/pkg/tool/linux_amd64/vet env 890820051/.github/workflows wDwi/8TvZlM4P0nfuVfRvwDwi 64/pkg/tool/linux_amd64/compile GOINSECURE g/x/net/idna GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name LsRemoteWithRealGitcustom_branch1266743563/001' 1/x64/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/sh GOINSECURE GOMOD GOMODCACHE go env 970/001/stability-test.md GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE fips140/subtle GOMODCACHE 64/pkg/tool/linux_amd64/vet env 493260/b190/_pkg_.a .cfg util.test GOINSECURE GOMOD GOMODCACHE util.test (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 493260/b201/_pkg_.a -QbQ/h0mDcb4RKnBUHEwN-QbQ ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE fips140/hkdf GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name GO111MODULE n-dir/node GOINSECURE GOMOD GOMODCACHE go 1/x6�� y_with_explicit_repo2790362962/001 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE lite GOMODCACHE 64/pkg/tool/linuTest User env 493260/b192/_pkg_.a GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD 493260/b006/syma--get 64/pkg/tool/linuremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 493260/b197/_pkg_.a rn9z/FXv0oohNOW0KmEF_rn9z .cfg GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name itcustom_branch1266743563/002/work 86_64/node GOINSECURE GOMOD GOMODCACHE go 1/x6�� y_with_explicit_repo2790362962/001 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linu-nolocalimports GOINSECURE (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 om/modelcontextprotocol/go-sdk@v1.5.0/jsonrpc/js-ifaceassert 64/pkg/tool/linux_amd64/vet GOINSECURE randutil GOMODCACHE 64/pkg/tool/linux_amd64/vet env til.go til_test.go 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GO111MODULE tions/setup/js/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env */*.ts' '**/*.json' --ignore-path ../../../.prettierignore GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 1979903628 eFae/0ahu769BnKYz-hV-eFae 64/pkg/tool/linux_amd64/vet GOINSECURE g/x/crypto/interrev-parse GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 om/modelcontextprotocol/go-sdk@v1.5.0/internal/xcontext/xcontext.go 64/pkg/tool/linux_amd64/vet GOINSECURE 493260/b092/ GOMODCACHE 64/pkg/tool/linux_amd64/vet env 890820051/.github/workflows GO111MODULE .cfg GOINSECURE a95/uritemplate/rev-parse 493260/b092/syma--show-toplevel ache/go/1.25.8/x64/pkg/tool/linuremote (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name LsRemoteWithRealGitbranch_with_hyphen727662941/001' de_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env ut4044723850/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet ortc�� 1979903628 stmain.go 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 890820051 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE contextprotocol/init 493260/b092/symabis 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name GO111MODULE tions/setup/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env ut4044723850/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 rg/x/text@v0.36.0/internal/tag/tag.go 64/pkg/tool/linux_amd64/vet GOINSECURE fips140/aes GOMODCACHE 64/pkg/tool/linux_amd64/vet env edcfg qrnP/bIu9B-2Kyy25-yTJqrnP .cfg GOINSECURE t/internal/langu/tmp/js-hash-test-481457770/test-hash.js GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu-buildtags (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name itbranch_with_hyphen727662941/002/work tions/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env ut4044723850/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path -c=4 -nolocalimports -importcfg /tmp/go-build2318680664/b411/importcfg -pack /home/REDACTED/work/gh-aw/gh-aw/pkg/fileutil/fileutil.go /home/REDACTED/work/gh-aw/gh-aw/pkg/fileutil/tar.go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE x_amd64/vet env -json .go x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 b/gh-aw/pkg/tty GOMODCACHE 64/pkg/tool/linuremote1 env rity1415985556/001 .cfg x_amd64/compile GOINSECURE /go-yaml/parser GOMODCACHE x_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git 493260/b250/_pkggit _cnJ/4Be12s2Y-Oerev-parse ache/go/1.25.8/x--show-toplevel git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git se 8680664/b068/vet-c .cfg git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha 493260/b129/_pkg_.a .cfg x_amd64/compile GOINSECURE /go-yaml/lexer ache/go/1.25.8/xuser.email x_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE iE8t3kR/vbNrLVZ2R0Je6UaXk7lz (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha re GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env lGitmain_branch2--repo lGitmain_branch2owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE jsonrpc2 GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env _.a GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha re GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go ced successfullyinfocmp GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha rity1415985556/001 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE e/jsonschema-go/rev-parse GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE sysrand ache/go/1.25.8/x--show-toplevel 64/pkg/tool/linux_amd64/vet env 493260/b237/_pkg_.a REzZ/UVSmm-gThuyfG0BeREzZ 64/pkg/tool/linux_amd64/compile GOINSECURE t/message GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go tion�� -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo -nolocalimports -importcfg /tmp/go-build2318680664/b415/importcfg -pack p6OGyvU4qtQm env -json age/compact/comp-ifaceassert x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env ath ../../../.pr**/*.json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: /tmp/go-build2318680664/b397/cli.test /tmp/go-build2318680664/b397/cli.test -test.testlogfile=/tmp/go-build2318680664/b397/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /tmp/go-build679870948/b397/cli.test /tmp/go-build679870948/b397/cli.test -test.testlogfile=/tmp/go-build679870948/b397/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true !../../../pkg/wogo --ignore-path ../../../.pretti-json go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json ag.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • invalid.example.invalid
    • Triggering command: /usr/lib/git-core/git-remote-https /usr/lib/git-core/git-remote-https origin https://invalid.example.invalid/nonexistent-repo.git git comm�� -m lure test commit k/node_modules/.bin/git -b main ode-gyp-bin/git git conf�� user.email test@test.com /git -b feature-branch it git (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

…eExit

- Add `forceExit: true` to vitest.config.mjs to ensure test process exits
  after all tests complete, even if there are lingering event loop references
- Fix mcp_http_server_runner.test.cjs to properly clean up HTTP server
  connections using afterEach with closeAllConnections() + close()

Root cause: each test created an HTTP server with runHttpServer(), made
requests that established keep-alive TCP connections, and only called
server.close() which does NOT close existing connections. These lingering
sockets kept Node.js's event loop alive after all tests passed, causing
the vitest process to hang for the full 18+ minute CI job timeout.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/87c4e8e3-0d1e-42a9-aba9-d2a6625bee18

Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix JS tests hanging causing CI failures fix: prevent JS tests from hanging after completion Apr 14, 2026
Copilot AI requested a review from dsyme April 14, 2026 02:17
@dsyme dsyme marked this pull request as ready for review April 14, 2026 02:18
Copilot AI review requested due to automatic review settings April 14, 2026 02:18
@dsyme dsyme merged commit d8a62e4 into main Apr 14, 2026
121 of 161 checks passed
@dsyme dsyme deleted the copilot/fix-js-tests-hanging-issue branch April 14, 2026 02:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a Vitest hang where the Node.js event loop stayed alive after tests completed due to lingering keep-alive HTTP sockets.

Changes:

  • Centralized HTTP server teardown in mcp_http_server_runner.test.cjs using an afterEach hook that force-closes existing connections before awaiting server.close().
  • Added forceExit: true to Vitest config as a fallback to ensure the process exits after the run.
Show a summary per file
File Description
actions/setup/js/mcp_http_server_runner.test.cjs Ensures each test fully drains/terminates HTTP connections so the event loop can exit cleanly.
actions/setup/js/vitest.config.mjs Adds a safety-net configuration to force the Vitest process to exit after finishing.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0

@github-actions github-actions Bot mentioned this pull request Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 85/100

Excellent test quality

Metric Value
New/modified tests analyzed 8
✅ Design tests (behavioral contracts) 8 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 4 (50%)
Duplicate test clusters 0
Test inflation detected N/A — no production code changed (test infrastructure fix only)
🚨 Coding-guideline violations None

What Changed

This PR fixes a resource leak in mcp_http_server_runner.test.cjs. The previous code called server.close() ad-hoc at the end of each test body, which left keep-alive connections open, causing the Node.js event loop to hang after the test suite completed. The fix:

  1. Adds a shared afterEach hook that calls currentServer.closeAllConnections() followed by await new Promise(r => currentServer.close(r)), ensuring all sockets are torn down before vitest moves on.
  2. Renames the local server variable to currentServer (shared scope) so the hook can reference it.
  3. Removes the individual server.close() calls from each test body (now redundant).
  4. Adds forceExit: true to vitest.config.mjs as a belt-and-suspenders fallback.

No assertions changed. This is a pure test infrastructure fix.


Test Classification Details

All 8 test functions (click to expand)
Test File Classification Notes
sets CORS headers on every response mcp_http_server_runner.test.cjs ✅ Design Happy path; verifies CORS contract
responds 200 to OPTIONS preflight without calling transport mcp_http_server_runner.test.cjs ✅ Design Edge case: verifies transport isolation for preflight
responds to GET /health with payload from getHealthPayload mcp_http_server_runner.test.cjs ✅ Design Happy path; strong assertion coverage on response shape
responds 405 for non-POST methods other than GET /health and OPTIONS mcp_http_server_runner.test.cjs ✅ Design Error case: wrong HTTP method
responds 400 with JSON-RPC error for invalid JSON body mcp_http_server_runner.test.cjs ✅ Design Error case: malformed request
delegates valid POST requests to transport.handleRequest with parsed body mcp_http_server_runner.test.cjs ✅ Design Verifies delegation contract
calls configureServer callback with the http.Server instance before binding mcp_http_server_runner.test.cjs ✅ Design Verifies callback side-effect contract
returns 500 when transport.handleRequest throws mcp_http_server_runner.test.cjs ✅ Design Error case: transport error propagation

Minor Observation: forceExit: true

The forceExit: true flag in vitest.config.mjs forces vitest to terminate after all tests run, even if there are lingering open handles. This is fine as a safety net, but it can silently mask future resource leaks in tests. The afterEach cleanup (closeAllConnections + close) is the correct fix; forceExit: true should not be needed if every test properly tears down. Worth monitoring — if a future test starts hanging only without forceExit, that's a signal to fix the test teardown rather than rely on this flag.


Language Support

Tests analyzed:

  • 🐹 Go (*_test.go): 0 tests — no Go test files changed
  • 🟨 JavaScript (*.test.cjs, *.test.js): 8 tests (vitest)

Verdict

Check passed. 0% of modified tests are implementation tests (threshold: 30%). All 8 tests verify real behavioral contracts against a live HTTP server instance. The afterEach resource management fix is correct and well-implemented.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · ● 774.7K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 85/100. Test quality is excellent — 0% of modified tests are implementation tests (threshold: 30%). All 8 tests verify real behavioral contracts against a live HTTP server. The afterEach resource-management fix is well-implemented.

dsyme added a commit that referenced this pull request Apr 14, 2026
The JS test suite hung indefinitely because safe_output_manifest.test.cjs
called writeTemporaryIdMapFile({}, "/proc/fake/map.json") which internally
runs fs.mkdirSync('/proc/fake', { recursive: true }). This hangs on Linux
because the procfs filesystem blocks the recursive mkdir call.

Changes:
- Replace /proc/fake/map.json with /dev/null/fake/map.json which fails
  immediately (ENOTDIR) since /dev/null is a file, not a directory
- Remove forceExit: true from vitest.config.mjs (added by #26143 as a
  workaround, but it masked the real issue rather than fixing it)
dsyme added a commit that referenced this pull request Apr 14, 2026
* fix: resolve vitest hang caused by mkdirSync on /proc

The JS test suite hung indefinitely because safe_output_manifest.test.cjs
called writeTemporaryIdMapFile({}, "/proc/fake/map.json") which internally
runs fs.mkdirSync('/proc/fake', { recursive: true }). This hangs on Linux
because the procfs filesystem blocks the recursive mkdir call.

Changes:
- Replace /proc/fake/map.json with /dev/null/fake/map.json which fails
  immediately (ENOTDIR) since /dev/null is a file, not a directory
- Remove forceExit: true from vitest.config.mjs (added by #26143 as a
  workaround, but it masked the real issue rather than fixing it)

* fix tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JS tests hanging at end of tests, sometimes causing CI test failures for "js" job

3 participants