Local setup

How to build and run the pieces on your own machine.

Prerequisites

  • JDK 21. This is what CI uses and what the Gradle toolchain targets.
  • The Gradle wrapper. Use ./gradlew, which pins the Gradle version. Do not install Gradle separately.
  • Docker, if you want to run the judge for real. The judge shells out to docker run, so without Docker you can build and start the judge but code execution will fail.
  • Ruby 3.1+ and Bundler, only if you want to work on this documentation site (it is a separate Jekyll project under docs/). Build it with cd docs && bundle install && bundle exec jekyll serve. macOS system Ruby (2.6) is too old — install a newer one with Homebrew or a version manager.

You do not need to install PostgreSQL to run locally. The backend depends on an H2 in-memory database at runtime, so it can start without an external database.

Building

Build everything and run the tests:

./gradlew build
./gradlew test

Build the shipping jar (backend + frontend + CLI in one):

./gradlew :cli:bootJar
# produces cli/build/libs/cs30-1.0-SNAPSHOT.jar

Running the backend

The backend’s main class is com.cs30.server.app.ApplicationKt. Run it with:

./gradlew :backend:bootRun

The application.properties bundled into the jars (copied from the repo root at build time) is intentionally empty — production supplies real config through an external file (deploy/application.properties, copied to /opt/cs30 and loaded via --spring.config.additional-location). For local runs, :backend:bootRun activates the local Spring profile; put local-only database or OAuth settings in a gitignored application-local.properties overlay rather than committing them.

You can also run the built jar directly. The first argument selects the mode:

# start the server
java -jar cli/build/libs/cs30-1.0-SNAPSHOT.jar serve

# run an admin command instead
java -jar cli/build/libs/cs30-1.0-SNAPSHOT.jar validatecourse ...

Running the frontend

The web frontend is normally exercised just by running the backend, which serves the compiled wasm bundle at its root. For a standalone frontend dev server, the Kotlin wasm browser target provides a dev-run task (:frontend:wasmJsBrowserDevelopmentRun). The desktop app is a Compose desktop application with main class app.MainKt:

./gradlew :frontend:run

If a task name has changed, list what is available with ./gradlew :frontend:tasks.

Running the judge

The judge is a separate Spring Boot service. Its main class is com.cs30.judge.JudgeApplicationKt, and it listens on judge.port (default 8000), set by a small customizer so it does not collide with the backend’s port.

./gradlew :kt-judge:bootRun
# or build a jar
./gradlew :kt-judge:bootJar

For the judge to actually run code, Docker must be available and the sandbox image (judge-sandbox:latest) must be built. The image is built from kt-judge/sandbox/. CI builds and pushes it, but for local work you build it yourself from that directory.

Putting it together locally

To exercise the full run/submit path locally you need: the backend running, the judge running with judge.url pointing at it, the sandbox image built, and a course loaded from YAML via the CLI so there is a problem to open. This is more setup than most changes need, so lean on the tests and run only the piece you are changing when you can.