Fix: bound and await the Go module bootstrap in the cross-language test helpers - #724
Open
AmaadMartin wants to merge 3 commits into
Open
Fix: bound and await the Go module bootstrap in the cross-language test helpers#724AmaadMartin wants to merge 3 commits into
AmaadMartin wants to merge 3 commits into
Conversation
added 3 commits
August 6, 2026 07:10
…e suites The two Go test helpers bootstrap their modules with a synchronous, unbounded execSync that swallows every failure. Add ensureGoModules, which awaits the tidy under an explicit budget and rejects with the command, the module directory, the concrete cause and the manual remediation.
AdkGoServer and GoAgent now call ensureGoModules, so a missing Go toolchain fails in milliseconds with a Go-specific message instead of a hook or test timeout. Raise AdkGoServer's default readiness budget to 60000 to match the Node API server: `go run .` compiles the module before it boots, so the tighter default was backwards.
…mments No caller sets the timeout, so ensureGoModules now reads GO_MOD_TIDY_TIMEOUT_MS directly. Inline the single-use ExecFileFailure alias into its guard, and cut the DEFAULT_TIMEOUT and budget rationales to the reason each number holds.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
None.
Problem:
AdkGoServer.start()andGoAgent.run()bootstrap their Go modules with a synchronousexecSync('go mod tidy')that has no timeout and swallows every failure into aconsole.warn.go.sumis gitignored, so this branch runs on every fresh clone. A developer without the Go toolchain therefore waits for a Vitest timeout that names neither Go nor the real cause.AdkGoServer.DEFAULT_TIMEOUTwas also 30000 against the Node API server's 60000, althoughgo run .compiles the module before it boots.Solution: A new
tests/cross_language/go_modules.tsexportsensureGoModules(moduleDir). It skips the tidy whengo.sumexists, awaitsexecFileunder an explicit 45000ms budget, and rejects with the command, the module directory, the concrete cause and the manual remediation. Both helpers now call it.AdkGoServer.DEFAULT_TIMEOUTbecomes 60000 to matchAdkTsApiServer.Notes on choices:
cross_languageroot because Go module bootstrap has nothing to do with A2A, and the two callers live in differenta2a/subtrees.execFile, notexec: no shell is involved, and a missing binary arrives ascode === 'ENOENT'.any, no cast, no suppression: the catch narrowsunknownthrough anisExecFileFailureguard and rethrows with{cause: error}.Collision check (open PRs on this fork,
--limit 1000): no open PR adds this helper or edits thego mod tidyblock. #629 ownsts_a2a_go_test.ts,go_a2a_ts_test.tsandvitest.config.ts; #673 ownstests/integration/test_api_server.ts; #685 ownsgo_backend/go.mod; #648, #427, #393 and #306 own the cross-language workflow. This PR touches none of them. #218, #545 and #546 do editgo_server.ts, but only itssuccessLogMessageline, which this diff leaves alone.Testing Plan
Unit Tests:
tests/cross_language/go_modules_test.tscovers the eight paths of the new module with a mockednode:child_processand a realmkdtempdirectory, so it needs neither the Go toolchain nor the network.Coverage of
tests/cross_language/go_modules.tsis 100% of statements, branches, functions and lines (v8):Proof that the tests can fail. I mutated the source four times and re-ran the suite.
throwwith the oldconsole.warnplusreturn. 6 of 8 failed:existsSyncearly return. 1 of 8 failed:timeoutwith an unrelated constant. 1 of 8 failed:Manual End-to-End (E2E) Tests:
Run
npm install && npm run buildfirst. Then delete bothgo.sumfiles and run each suite with aPATHthat has nogoon it.Before this change,
go_tstimed out twice at 60000ms and named nothing:After:
The
ts_gosuite reportedFailed to start go server: spawn go ENOENTbefore this change, not a hook timeout: its readiness watcher catches thespawnerror of thego run .that follows the swallowed tidy. That message still named neithergo mod tidy, nor the module directory, nor a remedy. It now reports the sameensureGoModulesmessage, in 13ms of test time.I also drove the timeout branch against a real
go mod tidy(no mock), with the budget temporarily lowered to 5ms: it rejects withit exceeded its 5ms budget.Cold positive path, with
goback onPATHand bothgo.sumfiles deleted:Both
go.sumfiles were rebuilt and bothgo.modfiles stayed byte-identical.Other gates on the pushed commit:
npm run lint,npm run format:checkandbash scripts/check_license.shall pass.npm run ts:checkreports the same 2845 lines of pre-existing errors before and after this branch, byte for byte; they come from the builtcore/dist/typesand CI does not run it.CI on this branch is green on all four
run-testsjobs. The windows-latest job first failed on two pre-existing flakes that this diff cannot reach,core/test/code_executors/unsafe_local_code_executor_test.tsandtests/integration/a2a/stream/stream_test.ts; it passed on re-run.Checklist