Skip to content

Commit 99f93eb

Browse files
committed
CG-10667: Add local codegen server daemon
1 parent 6d402f9 commit 99f93eb

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

Dockerfile-runner

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
2+
3+
# Set environment variables to prevent interactive prompts during installation
4+
ENV NVM_DIR=/root/.nvm \
5+
NODE_VERSION=18.17.0 \
6+
DEBIAN_FRONTEND=noninteractive \
7+
NODE_OPTIONS="--max-old-space-size=8192" \
8+
PYTHONUNBUFFERED=1 \
9+
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
10+
PYTHONPATH="/usr/local/lib/python3.13/site-packages" \
11+
IS_SANDBOX=True \
12+
HATCH_BUILD_HOOKS_ENABLE=1
13+
# Update packages lists and install git and curl
14+
RUN apt-get update && apt-get install -y \
15+
git \
16+
curl \
17+
gcc \
18+
build-essential \
19+
python3-dev \
20+
# Cleanup apt cache to reduce image size
21+
&& rm -rf /var/lib/apt/lists/*
22+
23+
# Install nvm and Node.js
24+
SHELL ["/bin/bash", "-c"]
25+
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash \
26+
&& source $NVM_DIR/nvm.sh \
27+
&& nvm install $NODE_VERSION \
28+
&& nvm use default \
29+
&& npm install -g yarn pnpm \
30+
&& corepack enable \
31+
&& corepack prepare yarn@stable --activate \
32+
&& corepack prepare pnpm@latest --activate \
33+
&& uv pip install --system uvicorn[standard]
34+
35+
# Add node and npm to PATH
36+
ENV PATH=$NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
37+
38+
# Install codegen from source instead of PyPI
39+
WORKDIR /codegen-sdk
40+
COPY . .
41+
42+
# Install dependencies and build codegen with entry points
43+
RUN --mount=type=cache,target=/root/.cache/uv \
44+
uv venv && source .venv/bin/activate \
45+
&& uv sync --frozen --no-dev --all-extras \
46+
&& uv pip install --system -e . --no-deps \
47+
&& uv pip install --system .
48+
49+
# Change back to app directory for running
50+
WORKDIR /app
51+
52+
# Verify all installations
53+
RUN codegen --version \
54+
&& node --version \
55+
&& corepack --version \
56+
&& npm --version \
57+
&& yarn --version \
58+
&& pnpm --version \
59+
&& python --version
60+
61+
# Create a non-root user for local development + debugging
62+
RUN useradd -m -s /bin/bash user
63+
USER root
64+
RUN chown -R user:user /home/user
65+
USER user
66+
67+
WORKDIR /app
68+
ENTRYPOINT ["/bin/bash", "-c"]

src/codegen/cli/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from codegen.cli.commands.reset.main import reset_command
1414
from codegen.cli.commands.run.main import run_command
1515
from codegen.cli.commands.run_on_pr.main import run_on_pr_command
16+
from codegen.cli.commands.start.main import start_command
1617
from codegen.cli.commands.style_debug.main import style_debug_command
1718

1819
click.rich_click.USE_RICH_MARKUP = True
@@ -39,6 +40,7 @@ def main():
3940
main.add_command(run_on_pr_command)
4041
main.add_command(notebook_command)
4142
main.add_command(reset_command)
43+
main.add_command(start_command)
4244

4345

4446
if __name__ == "__main__":
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from pathlib import Path
2+
3+
import click
4+
import rich
5+
from rich.box import ROUNDED
6+
from rich.panel import Panel
7+
8+
9+
@click.command(name="start")
10+
@click.option("--platform", "-t", type=click.Choice(["linux/amd64", "linux/arm64", "linux/amd64,linux/arm64"]), default="linux/amd64,linux/arm64", help="Target platform(s) for the Docker image")
11+
@click.option("--port", "-p", type=int, default=8000)
12+
@click.option("--detached", "-d", is_flag=True, default=False, help="Starts up the server as detached background process")
13+
def start_command(port: int, platform: str, detached: bool):
14+
"""Starts a local codegen server"""
15+
import subprocess
16+
from importlib.metadata import version
17+
18+
codegen_version = version("codegen")
19+
rich.print(codegen_version)
20+
repo_root = Path(__file__).parent.parent.parent.parent.parent.parent
21+
dockerfile_path = repo_root / "Dockerfile-runner"
22+
23+
# Build the Docker image
24+
rich.print("[bold blue]Building Docker image...[/bold blue]")
25+
build_cmd = [
26+
"docker",
27+
"buildx",
28+
"build",
29+
"--platform",
30+
platform,
31+
"-f",
32+
str(dockerfile_path),
33+
"-t",
34+
"codegen-runner",
35+
"--load",
36+
str(repo_root),
37+
]
38+
rich.print(f"build_cmd: {str.join(' ', build_cmd)}")
39+
40+
try:
41+
subprocess.run(build_cmd, check=True)
42+
43+
# Run the Docker container
44+
rich.print("[bold blue]Starting Docker container...[/bold blue]")
45+
run_mode = "-d" if detached else "-it"
46+
entry_point = f'"uv run --frozen uvicorn codegen.runner.sandbox.server:app --host 0.0.0.0 --port {port}"'
47+
run_cmd = ["docker", "run", run_mode, "-p", f"8000:{port}", "codegen-runner", entry_point]
48+
49+
rich.print(f"run_cmd: {str.join(' ', run_cmd)}")
50+
subprocess.run(run_cmd, check=True)
51+
52+
rich.print(Panel(f"[green]Server started successfully![/green]\nAccess the server at: [bold]http://0.0.0.0:{port}[/bold]", box=ROUNDED, title="Codegen Server"))
53+
54+
except subprocess.CalledProcessError as e:
55+
rich.print(f"[bold red]Error:[/bold red] Failed to {e.cmd[0]} Docker container")
56+
raise click.Abort()
57+
except Exception as e:
58+
rich.print(f"[bold red]Error:[/bold red] {e!s}")
59+
raise click.Abort()

0 commit comments

Comments
 (0)