Skip to content

Runtime Registry

The runtime registry defines how each programming language is executed inside Kubernetes pods. It maps language/version pairs to Docker images, file extensions, and interpreter commands. Adding a new language or version is a matter of extending the specification dictionary.

Supported Languages

Language Versions Image Template File Extension
Python 3.7, 3.8, 3.9, 3.10, 3.11, 3.12 python:{version}-slim .py
Node.js 18, 20, 22 node:{version}-alpine .js
Ruby 3.1, 3.2, 3.3 ruby:{version}-alpine .rb
Go 1.20, 1.21, 1.22 golang:{version}-alpine .go
Bash 5.1, 5.2, 5.3 bash:{version} .sh

Language Specification

Each language is defined by a LanguageSpec dictionary containing the available versions, Docker image template, file extension, and interpreter command:

class LanguageSpec(TypedDict):
    versions: list[str]
    image_tpl: str
    file_ext: str
    interpreter: list[str]

The full specification for all languages:

LANGUAGE_SPECS: dict[str, LanguageSpec] = {
    "python": {
        "versions": ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"],
        "image_tpl": "python:{version}-slim",
        "file_ext": "py",
        "interpreter": ["python"],
    },
    "node": {
        "versions": ["18", "20", "22"],
        "image_tpl": "node:{version}-alpine",
        "file_ext": "js",
        "interpreter": ["node"],
    },
    "ruby": {
        "versions": ["3.1", "3.2", "3.3"],
        "image_tpl": "ruby:{version}-alpine",
        "file_ext": "rb",
        "interpreter": ["ruby"],
    },
    "bash": {
        "versions": ["5.1", "5.2", "5.3"],
        "image_tpl": "bash:{version}",
        "file_ext": "sh",
        "interpreter": ["bash"],
    },
    "go": {
        "versions": ["1.20", "1.21", "1.22"],
        "image_tpl": "golang:{version}-alpine",
        "file_ext": "go",
        "interpreter": ["go", "run"],
    },
}

Runtime Configuration

The registry generates a RuntimeConfig for each language/version combination. This contains everything needed to run a script in a pod:

class RuntimeConfig(NamedTuple):
    image: str  # Full Docker image reference
    file_name: str  # Name that will be mounted under /scripts/
    command: list[str]  # Entrypoint executed inside the container
  • image: The full Docker image reference (e.g., python:3.11-slim)
  • file_name: The script filename mounted at /scripts/ (e.g., main.py)
  • command: The command to execute (e.g., ["python", "/scripts/main.py"])

Adding a New Language

To add support for a new programming language:

  1. Add an entry to LANGUAGE_SPECS with versions, image template, file extension, and interpreter
  2. Add an example script to EXAMPLE_SCRIPTS demonstrating version-specific features
  3. The _make_runtime_configs() function automatically generates runtime configs

For example, to add Rust support:

"rust": {
    "versions": ["1.75", "1.76", "1.77"],
    "image_tpl": "rust:{version}-slim",
    "file_ext": "rs",
    "interpreter": ["rustc", "-o", "/tmp/main", "{file}", "&&", "/tmp/main"],
}

The image template uses {version} as a placeholder, which gets replaced with each version number when generating the registry.

Example Scripts

Each language includes an example script that demonstrates both universal features and version-specific syntax. These scripts are shown in the frontend editor as templates:

EXAMPLE_SCRIPTS: dict[str, str] = {
    "python": """
# This f-string formatting works on all supported Python versions (3.7+)
py_version = "3.x"
print(f"Hello from a Python {py_version} script!")

# The following block uses Structural Pattern Matching,
# which was introduced in Python 3.10.
# THIS WILL CAUSE A SYNTAX ERROR ON VERSIONS < 3.10.

lang_code = 1
match lang_code:
    case 1:
        print("Structural Pattern Matching is available on this version (Python 3.10+).")
    case _:
        print("Default case.")

# Union types using | operator (Python 3.10+)
def process_data(value: int | str | None) -> str:
    if value is None:
        return "No value"
    return f"Got: {value}"

print(process_data(42))
print(process_data("hello"))
print(process_data(None))
""",
    "node": """
// This works on all supported Node versions (18+)
console.log(`Hello from Node.js ${process.version}!`);

// The Promise.withResolvers() static method was introduced in Node.js 22.
// This will throw a TypeError on versions < 22.
if (typeof Promise.withResolvers === 'function') {
  const { promise, resolve } = Promise.withResolvers();
  console.log("Promise.withResolvers() is supported (Node.js 22+).");
  resolve('Success');
  promise.then(msg => console.log(`Resolved with: ${msg}`));
} else {
  console.log("Promise.withResolvers() is not supported on this version.");
}
""",
    "ruby": """
# This works on all supported Ruby versions (3.1+)
puts "Hello from Ruby #{RUBY_VERSION}!"

# The Data class for immutable value objects was introduced in Ruby 3.2.
# This will cause an error on Ruby 3.1.
begin
  # This line will fail on Ruby < 3.2
  Point = Data.define(:x, :y)
  p = Point.new(1, 2)
  puts "Data objects are supported (Ruby 3.2+). Created point: #{p.inspect}"
rescue NameError
  puts "Data objects are not supported on this version."
end
""",
    "bash": """
# This works on any modern Bash version
echo "Hello from Bash version $BASH_VERSION"

# BASH_VERSINFO is an array holding version details.
# We can check the major and minor version numbers.
echo "Bash major version: ${BASH_VERSINFO[0]}"
echo "Bash minor version: ${BASH_VERSINFO[1]}"

# The ${var@U} expansion for uppercasing was added in Bash 5.2
if [[ "${BASH_VERSINFO[0]}" -ge 5 && "${BASH_VERSINFO[1]}" -ge 2 ]]; then
    my_var="hello"
    echo "Testing variable expansion (Bash 5.2+ feature)..."
    echo "Original: $my_var, Uppercased: ${my_var@U}"
else
    echo "The '${var@U}' expansion is not available in this Bash version."
fi
""",
    "go": """
package main

import (
    "fmt"
    "runtime"
)

// This function uses generics, available since Go 1.18,
// so it will work on all supported versions (1.20+).
func Print[T any](s T) {
    fmt.Println(s)
}

func main() {
    Print(fmt.Sprintf("Hello from Go version %s!", runtime.Version()))

    // The built-in 'clear' function for maps and slices
    // was introduced in Go 1.21.
    // THIS WILL FAIL TO COMPILE on Go 1.20.
    myMap := make(map[string]int)
    myMap["a"] = 1
    Print(fmt.Sprintf("Map before clear: %v", myMap))
    clear(myMap) // This line will fail on Go < 1.21
    Print(fmt.Sprintf("Map after 'clear' (Go 1.21+ feature): length is %d", len(myMap)))
}
""",
}

The example scripts intentionally use features that may not work on older versions, helping users understand version compatibility. For instance, Python's match statement (3.10+), Node's Promise.withResolvers() (22+), and Go's clear() function (1.21+).

API Endpoints

The runtime information is exposed via two public GET endpoints:

  • GET /api/v1/k8s-limits — returns resource limits (cpu_limit, memory_limit, execution_timeout) and a map of supported runtimes with their available versions and file extensions. The frontend uses this to populate the language/version picker and show resource constraints.
  • GET /api/v1/example-scripts — returns a map of language → example script string. Shown in the editor as starter templates when a user picks a language.

Key Files