Skip to content

Install real toolchains for every judge-offered language - #39

Merged
matbrgz merged 2 commits into
masterfrom
feat/expand-autojudge-language-support
Sep 10, 2026
Merged

matbrgz merged 2 commits into
masterfrom
feat/expand-autojudge-language-support

Conversation

@matbrgz

@matbrgz matbrgz commented Sep 10, 2026

Copy link
Copy Markdown
Member

Summary

Language::getDefaultLanguages() already lists Java, Node, TypeScript, Kotlin, C#, Rust, Go, PHP, Ruby and Pascal as is_active, and the Contest Wizard already lets an admin select any of them per contest -- but the Docker images that actually run the judge only ever installed gcc/g++/python3. Every other language was offered but silently failed to compile/run.

  • Add the missing toolchains to both Dockerfile.dev and Dockerfile (apk packages where available; Kotlin and Free Pascal have none, so they're installed from their official upstream releases, with retry+verification for the flaky SourceForge FPC download).
  • Fix Node/TypeScript: the catalog's run_command called nvm, but the container only installs one real Node runtime -- switched to plain node, deactivated the two Node versions that no longer correspond to an installed binary (kept for a future real multi-version setup). Also fixed TypeScript's compile_command: tsc --outFile was removed in TypeScript 7.
  • Fix C#: dotnet build/dotnet run need a project, not a bare .cs file -- added resources/judge-runtime/csharp/{compile,run}.sh to scaffold a throwaway console project around the submitted source before building.
  • Deactivate PyPy: no musl/Alpine build exists upstream; CPython 3.12 already covers the language.

Test plan

  • New tests/E2E/MultiLanguageJudgingTest.php: submits a real, correct "A + B" solution in every is_active language and asserts a real AC verdict -- nothing mocked, same style as FullBocaLifecycleTest. All 14 active languages pass.
  • Full suite: 493 passed, 0 failed.
  • Rebuilt the dev Docker images from scratch and manually verified each toolchain compiles+runs a trivial program inside the container before wiring it into the catalog.

🤖 Generated with Claude Code

https://claude.ai/code/session_011u3o4QCgpcqH51edYyRPMn

matbrgz and others added 2 commits September 10, 2026 15:15
Language::getDefaultLanguages() already listed Java, Node, TypeScript,
Kotlin, C#, Rust, Go, PHP, Ruby and Pascal as is_active, and the
Contest Wizard already lets admins select any of them -- but
Dockerfile.dev/Dockerfile only ever installed gcc/g++/python3. Every
other language silently failed to compile/run; participants and
admins were offered languages the judge couldn't actually execute.

- Add openjdk21-jdk, nodejs, npm, dotnet8-sdk, go, rust, cargo, ruby to
  both Dockerfiles (apk packages, verified in Alpine 3.24).
- Install TypeScript globally (npx tsc) and Kotlin from JetBrains'
  GitHub release zip (no Alpine package exists).
- Install Free Pascal (FPC) from the official per-arch SourceForge
  binary tarball, also with no Alpine package; the RUN step detects
  x86_64 vs aarch64 and retries the (occasionally truncated) download
  up to 6 times, verifying the tarball with `tar -tf` before trusting it.
- Fix Node/TypeScript run_command: they called nvm, but the container
  only installs one Node runtime -- switched to plain `node`, and
  deactivated the Node 20/22 catalog entries that no longer correspond
  to an installed binary (kept for a future real multi-version setup).
  Fixed TypeScript's compile_command too: `tsc --outFile` was removed
  in TypeScript 7.
- Fix C#: `dotnet build`/`dotnet run` need a project, not a bare .cs
  file. Added resources/judge-runtime/csharp/{compile,run}.sh, which
  scaffold a throwaway console project around the submitted source
  before building -- referenced via a new {judge_runtime} placeholder
  resolved by AutoJudgeService (not baked into the catalog directly,
  since Language::getDefaultLanguages() runs in contexts, like PHPUnit
  data providers, where the app isn't booted and base_path() fails).
- Deactivate PyPy: no musl/Alpine build exists upstream; CPython 3.12
  already covers the language, so it's left inactive with a comment
  rather than silently failing every submission.
- Add tests/E2E/MultiLanguageJudgingTest.php: submits a real, correct
  "A + B" solution in every is_active language and asserts a real AC,
  nothing mocked (same style as FullBocaLifecycleTest) -- the
  regression net for all of the above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011u3o4QCgpcqH51edYyRPMn
- Bring Dockerfile.judge (the standalone autojudge:start worker image,
  used by docker-compose.yml's separate autojudge service) up to the
  same toolchain set as Dockerfile/Dockerfile.dev. It only had
  gcc/g++/python3/go/rust/ruby and an nvm-based multi-Node setup
  defaulting to v20; C# and Pascal were completely missing, and Java
  was still 17, not 21 -- every one of those submissions would fail
  with "command not found" or a version mismatch in that worker while
  looking correct from the other two Dockerfiles alone.
- Fix a real permission bug: npm/npx (TypeScript), dotnet, and go all
  write caches under $HOME, but PHP-FPM runs the judge as the `www`
  user without setting HOME, so it inherits (or is left without) a
  HOME the worker can't write to. Reproduced directly (a `dotnet
  build` under HOME=/root as uid 1000 fails with EPERM creating
  ~/.dotnet) and fixed by explicitly setting HOME to the run's own
  writable working directory on both Process::run() calls in
  AutoJudgeService.
- Replace the `find ... -name 'ppc*'` FPC binary lookup (could match
  more than one file and break `install`) with the exact known
  filename per architecture (ppcx64/ppca64).
- Remove `cargo`: the only active Rust language compiles directly with
  `rustc`, never invokes cargo.
- Fix a stale comment referencing the old "TypeScript (Node 22)" name.
- tests/E2E/MultiLanguageJudgingTest.php: activeLanguages() silently
  drops any is_active language missing from its solutions map instead
  of failing, which would let a newly-activated untested language ship
  green. Added a companion test that fails loudly if the two ever
  diverge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011u3o4QCgpcqH51edYyRPMn
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