Skip to content

Phase 4b: add Go local runner - #46

Merged
SPerekrestova merged 4 commits into
mainfrom
devin/1781089328-phase-4b-go-runner
Jun 10, 2026
Merged

Phase 4b: add Go local runner#46
SPerekrestova merged 4 commits into
mainfrom
devin/1781089328-phase-4b-go-runner

Conversation

@SPerekrestova

@SPerekrestova SPerekrestova commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Adds go to IMPLEMENTED_LANGUAGES and executes Go submissions via the same isolated subprocess path as Python:

go: {
  extension: "go",
  probe: { cmd: "go", args: ["version"] },
  buildArgs: (sourcePath) => ({ cmd: "go", args: ["run", sourcePath] })
}

Go runs keep the per-invocation temp HOME isolation, but now receive stable process-scoped GOCACHE/GOMODCACHE directories that are also whitelisted in OS sandbox wrappers. This avoids cold-compiling the Go stdlib on every run_local_tests invocation without exposing the user's real home or shell env.

Keeps java as the only still-unimplemented supported runner language, updates run_local_tests messaging, and adds runtime-gated unit/e2e coverage for Go success, absent-runtime behavior, and stable Go cache reuse. Verified locally with npm run build, npm run test:types, npx prettier --check ., npm test, npm run test:e2e, and npm run test:all; this VM does not have Go installed, so real Go execution tests are present but skipped locally unless a Go runtime is available.

Link to Devin session: https://app.devin.ai/sessions/3e6f3e63f6e54852b9bf6da1c792774f
Requested by: @SPerekrestova

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fcc4356e-6433-4858-8548-99da2b9cde01

📥 Commits

Reviewing files that changed from the base of the PR and between a734c6f and c840786.

📒 Files selected for processing (1)
  • src/runner/subprocess-runner.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/runner/subprocess-runner.ts

📝 Walkthrough

Walkthrough

This PR adds Go as a supported runtime to the local test runner, extends sandboxing to accept writable cache paths, forwards Go-specific env into spawned processes, updates config/docs to list python3 and go as runnable (java remains unimplemented), and broadens unit, integration, and e2e tests to cover Go paths.

Changes

Go Runtime Implementation and Integration

Layer / File(s) Summary
Subprocess runner: Go runtime, env, and timeouts
src/runner/subprocess-runner.ts
Adds a Go LanguageSpec with defaultTimeoutMs and prepareRuntime() that creates per-run Go cache dirs and returns env + writablePaths; run() prefers language default timeout, calls prepareRuntime(), passes writablePaths to sandbox, and forwards env to the spawned subprocess.
Sandbox: writable paths support
src/runner/sandbox.ts, tests/runner/sandbox.test.ts
wrapWithSandbox gains a writablePaths parameter; bwrap/firejail/macOS logic now includes all allowed write paths. Adds test asserting extra cache path appears in --bind args.
Config, types, and tool description updates
src/runner/runner.ts, src/mcp/tools/runner-tools.ts, src/types/runner.ts
IMPLEMENTED_LANGUAGES now includes go; run_local_tests description and RunInput.timeoutMs docs updated to indicate language-specific default timeouts.
Tests: unit, integration, and e2e
tests/runner/subprocess-runner.test.ts, tests/e2e/runner.test.ts, tests/integration/runner-tools-integration.test.ts
Adds Go availability probe and conditional Go run/build-cache tests; updates e2e fixtures to include Go snippet and adds Go e2e test gated by host availability; shifts "not implemented" expectations to java and updates integration test to simulate Java runner.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch devin/1781089328-phase-4b-go-runner

Comment @coderabbitai help to get the list of available commands and usage tips.

@SPerekrestova SPerekrestova left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Reviewed the diff. Two concrete findings — one reliability issue worth addressing, one stale-comment fix.

1. Reliability — Go inherits a fresh empty HOME on every run, so GOCACHE is cold every time

src/runner/subprocess-runner.ts (lines 224, 266–270) sets cwd to a freshly-mkdtemp'd dir and forwards only PATH, HOME, LANG, with HOME pointed at that same temp dir (which is removed in the finally). go run resolves GOCACHE from $HOME/.cache/go-build when unset, so every invocation:

  • creates an empty build cache under the temp dir,
  • cold-compiles every stdlib package the snippet touches (e.g. fmt),
  • and throws the cache away at the end of the run.

A trivial fmt.Println snippet that takes ~50 ms warm can easily take 1–3 s cold, and on slow CI hosts that pushes uncomfortably close to the default DEFAULT_TIMEOUT_MS = 5_000. It also makes every Go run noticeably slower than Python, which is contrary to the "turns around in seconds" promise in the tool description.

Two fixes either of which would address it:

  • Forward a stable, process-scoped GOCACHE (and ideally GOMODCACHE) in spawnAndCapture's env so the build cache survives across runs — e.g., a directory under tmpdir() created once per process and reused.
  • Or, only for go, override HOME to a stable per-process dir (still distinct from the user's real $HOME) so Go's defaults land in a persistent location.

A unit/e2e assertion that two consecutive Go runs of the same trivial program complete well under the timeout would catch regressions here.

2. Stale comment — go registry entry is now described as an unimplemented stub

src/runner/subprocess-runner.ts lines 76–78:

    // Phase 4c stub — present in the registry so the type system
    // requires they stay in sync with `RunnerLanguage`. The runner
    // refuses to use it until we actually wire the harness.
    go: {
        extension: "go",
        probe: { cmd: "go", args: ["version"] },
        buildArgs: (sourcePath) => ({
            cmd: "go",
            args: ["run", sourcePath]
        })
    },
    java: {

The "Phase 4c stub … refuses to use it" comment now sits directly above the fully-implemented go entry, so a reader will conclude go is still a stub. Move the comment block so it lives immediately above java: (the only remaining stub).

Otherwise LGTM — the registry-driven extension, the runtime-gated skipIf test pattern, and the symmetry with the existing Python path all look clean.


Generated by Claude Code

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/runner/subprocess-runner.ts`:
- Around line 76-78: The "Phase 4c stub" comment is misplaced before the Go
entry; move that comment so it precedes the java: entry instead, keeping its
text about staying in sync with RunnerLanguage and the runner refusing to use it
until the harness is wired; locate the comment string "Phase 4c stub" and the
java: enum/registry entry and cut/paste the comment immediately above the java:
label (leaving the Go entry and its surrounding comments unchanged) so the
comment accurately documents the stub behavior for Java.

In `@tests/runner/subprocess-runner.test.ts`:
- Around line 115-134: The Go happy-path test omits timeoutMs causing flaky
timeouts; update the runner.run call in the test (the invocation of runner.run
in tests/runner/subprocess-runner.test.ts inside the "executes a happy-path Go
program" spec) to include timeoutMs: 20_000 in its options object so the
SubprocessRunner has a 20s timeout for this test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b889ff1-9c49-4679-8209-c654fa1f1227

📥 Commits

Reviewing files that changed from the base of the PR and between 8ef83d6 and ff24ea6.

📒 Files selected for processing (6)
  • src/mcp/tools/runner-tools.ts
  • src/runner/runner.ts
  • src/runner/subprocess-runner.ts
  • tests/e2e/runner.test.ts
  • tests/integration/runner-tools-integration.test.ts
  • tests/runner/subprocess-runner.test.ts

Comment thread src/runner/subprocess-runner.ts Outdated
Comment thread tests/runner/subprocess-runner.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/runner/subprocess-runner.ts`:
- Around line 81-95: The cached promise goRuntimePathsPromise can stay rejected
if mkdtemp or mkdir throws, causing all future calls to getGoRuntimePaths() to
fail; wrap the async initializer inside getGoRuntimePaths() in a try/catch, and
if the inner async IIFE rejects, reset goRuntimePathsPromise to undefined before
rethrowing the error so transient failures don't permanently pollute the cache
(update the logic inside getGoRuntimePaths and touch goRuntimePathsPromise and
the anonymous initializer accordingly).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 78677c9d-6118-4351-955d-ab464e8f3adc

📥 Commits

Reviewing files that changed from the base of the PR and between ff24ea6 and a734c6f.

📒 Files selected for processing (6)
  • src/mcp/tools/runner-tools.ts
  • src/runner/sandbox.ts
  • src/runner/subprocess-runner.ts
  • src/types/runner.ts
  • tests/runner/sandbox.test.ts
  • tests/runner/subprocess-runner.test.ts
✅ Files skipped from review due to trivial changes (2)
  • src/mcp/tools/runner-tools.ts
  • src/types/runner.ts

Comment thread src/runner/subprocess-runner.ts
@SPerekrestova
SPerekrestova merged commit 2f5aeaa into main Jun 10, 2026
2 checks passed
@SPerekrestova
SPerekrestova deleted the devin/1781089328-phase-4b-go-runner branch June 10, 2026 11:45
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.

1 participant