Skip to content

Commit 2714c2c

Browse files
committed
CG-10667: Add local codegen server daemon
1 parent 68b8a1a commit 2714c2c

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

Dockerfile-runner

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
# TODO: pare down to only the files needed
41+
COPY . .
42+
43+
# Install dependencies and build codegen with entry points
44+
RUN --mount=type=cache,target=/root/.cache/uv \
45+
uv venv && source .venv/bin/activate \
46+
&& uv sync --frozen --no-dev --all-extras \
47+
&& uv pip install --system -e . --no-deps \
48+
&& uv pip install --system .
49+
50+
# Change back to app directory for running
51+
WORKDIR /app
52+
53+
# Verify all installations
54+
RUN codegen --version \
55+
&& node --version \
56+
&& corepack --version \
57+
&& npm --version \
58+
&& yarn --version \
59+
&& pnpm --version \
60+
&& python --version
61+
62+
# Create a non-root user for local development + debugging
63+
RUN useradd -m -s /bin/bash user
64+
USER root
65+
RUN chown -R user:user /home/user
66+
USER user
67+
68+
WORKDIR /app
69+
ENTRYPOINT ["/bin/bash", "-c"]

src/codegen/cli/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from codegen.cli.commands.reset.main import reset_command
1717
from codegen.cli.commands.run.main import run_command
1818
from codegen.cli.commands.run_on_pr.main import run_on_pr_command
19+
from codegen.cli.commands.start.main import start_command
1920
from codegen.cli.commands.style_debug.main import style_debug_command
2021
from codegen.cli.commands.update.main import update_command
2122

@@ -47,6 +48,8 @@ def main():
4748
main.add_command(update_command)
4849
main.add_command(config_command)
4950
main.add_command(lsp_command)
51+
main.add_command(start_command)
52+
5053

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

0 commit comments

Comments
 (0)