Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions src/codegen/git/repo_operator/local_git_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
return f"{url_segments[-2]}/{url_segments[-1].replace('.git', '')}"

@cached_property
def origin_remote(self) -> Remote | None:

Check failure on line 36 in src/codegen/git/repo_operator/local_git_repo.py

View workflow job for this annotation

GitHub Actions / mypy

error: Missing return statement [return]
"""Returns the url of the first remote found on the repo, or None if no remotes are set"""
if self.has_remote():
return self.git_cli.remote("origin")
Expand All @@ -60,13 +60,14 @@

def get_language(self, access_token: str | None = None) -> str:
"""Returns the majority language of the repository"""
if access_token is None:
return str(determine_project_language(self.repo_path))

repo_config = RepoConfig.from_repo_path(repo_path=self.repo_path)
repo_config.full_name = self.full_name
remote_git = GitRepoClient(repo_config=repo_config, access_token=access_token)
return remote_git.repo.language.upper()
if access_token is not None:
repo_config = RepoConfig.from_repo_path(repo_path=self.repo_path)
repo_config.full_name = self.full_name
remote_git = GitRepoClient(repo_config=repo_config, access_token=access_token)
if (language := remote_git.repo.language) is not None:
return language.upper()

return str(determine_project_language(self.repo_path))

def has_remote(self) -> bool:
return bool(self.git_cli.remotes)
26 changes: 10 additions & 16 deletions src/codegen/git/schemas/repo_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import base64
import logging
import os.path

Expand All @@ -15,32 +14,27 @@ class RepoConfig(BaseModel):

name: str
full_name: str | None = None
organization_name: str | None = None
visibility: RepoVisibility | None = None

# Codebase fields
base_dir: str = "/tmp" # parent directory of the git repo
language: ProgrammingLanguage = ProgrammingLanguage.PYTHON
respect_gitignore: bool = True
base_path: str | None = None # root directory of the codebase within the repo
language: ProgrammingLanguage | None = ProgrammingLanguage.PYTHON
subdirectories: list[str] | None = None
respect_gitignore: bool = True

@property
def repo_path(self) -> str:
return f"{self.base_dir}/{self.name}"

@classmethod
def from_repo_path(cls, repo_path: str) -> "RepoConfig":
name = os.path.basename(repo_path)
base_dir = os.path.dirname(repo_path)
return cls(name=name, base_dir=base_dir)

# TODO: remove
def encoded_json(self):
return base64.b64encode(self.model_dump_json().encode("utf-8")).decode("utf-8")
@property
def repo_path(self) -> str:
return f"{self.base_dir}/{self.name}"

# TODO: remove, read from shared config instead
@staticmethod
def from_encoded_json(encoded_json: str) -> "RepoConfig":
decoded = base64.b64decode(encoded_json).decode("utf-8")
return RepoConfig.model_validate_json(decoded)
@property
def organization_name(self) -> str | None:
if self.full_name is not None:
return self.full_name.split("/")[0]
return None
13 changes: 5 additions & 8 deletions src/codegen/runner/clients/sandbox_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
from fastapi import params

from codegen.git.schemas.repo_config import RepoConfig
from codegen.runner.constants.envvars import FEATURE_FLAGS_BASE64, GITHUB_TOKEN, REPO_CONFIG_BASE64
from codegen.runner.models.apis import SANDBOX_SERVER_PORT
from codegen.runner.models.configs import RunnerFeatureFlags

logger = logging.getLogger(__name__)

Expand All @@ -33,15 +31,14 @@

def _start_server(self, repo_config: RepoConfig, git_access_token: str | None) -> None:
"""Start the FastAPI server in a subprocess"""
# encoded_flags = runner_flags_from_posthog(repo_config.name).encoded_json() # TODO: once migrated to dockerized image, uncomment this line
encoded_flags = RunnerFeatureFlags().encoded_json()
env = os.environ.copy()
env.update(
{
REPO_CONFIG_BASE64: repo_config.encoded_json(),
FEATURE_FLAGS_BASE64: encoded_flags,
"OPENAI_PASS": "open-ai-password",
GITHUB_TOKEN: git_access_token,
"CODEGEN_REPOSITORY__REPO_PATH": repo_config.repo_path,
"CODEGEN_REPOSITORY__REPO_NAME": repo_config.name,
"CODEGEN_REPOSITORY__FULL_NAME": repo_config.full_name,

Check failure on line 39 in src/codegen/runner/clients/sandbox_client.py

View workflow job for this annotation

GitHub Actions / mypy

error: Dict entry 2 has incompatible type "str": "str | None"; expected "str": "str" [dict-item]
"CODEGEN_REPOSITORY__LANGUAGE": repo_config.language.value,
"CODEGEN_SECRETS__GITHUB_TOKEN": git_access_token,

Check failure on line 41 in src/codegen/runner/clients/sandbox_client.py

View workflow job for this annotation

GitHub Actions / mypy

error: Dict entry 4 has incompatible type "str": "str | None"; expected "str": "str" [dict-item]
}
)

Expand Down
56 changes: 0 additions & 56 deletions src/codegen/runner/models/configs.py

This file was deleted.

19 changes: 9 additions & 10 deletions src/codegen/runner/sandbox/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from codegen.git.repo_operator.remote_repo_operator import RemoteRepoOperator
from codegen.git.schemas.repo_config import RepoConfig
from codegen.runner.models.apis import CreateBranchRequest, CreateBranchResponse, GetDiffRequest, GetDiffResponse
from codegen.runner.models.configs import get_codebase_config
from codegen.runner.sandbox.executor import SandboxExecutor
from codegen.sdk.codebase.config import ProjectConfig, SessionOptions
from codegen.sdk.codebase.config import CodebaseConfig, GSFeatureFlags, ProjectConfig, SessionOptions
from codegen.sdk.codebase.factory.codebase_factory import CodebaseType
from codegen.sdk.core.codebase import Codebase
from codegen.sdk.secrets import Secrets
from codegen.shared.compilation.string_to_code import create_execute_function_from_codeblock
from codegen.shared.configs.config import config
from codegen.shared.performance.stopwatch_utils import stopwatch
Expand All @@ -30,12 +30,9 @@
codebase: CodebaseType
executor: SandboxExecutor

def __init__(
self,
repo_config: RepoConfig,
) -> None:
def __init__(self, repo_config: RepoConfig, access_token: str) -> None:
self.repo = repo_config
self.op = RemoteRepoOperator(repo_config=repo_config, access_token=config.secrets.github_token)
self.op = RemoteRepoOperator(repo_config=self.repo, access_token=access_token)
self.commit = self.op.git_cli.head.commit

async def warmup(self) -> None:
Expand All @@ -48,9 +45,11 @@

async def _build_graph(self) -> Codebase:
logger.info("> Building graph...")
programming_language = self.op.repo_config.language
projects = [ProjectConfig(programming_language=programming_language, repo_operator=self.op, base_path=self.op.repo_config.base_path, subdirectories=self.op.repo_config.subdirectories)]
return Codebase(projects=projects, config=get_codebase_config())
projects = [ProjectConfig(programming_language=self.repo.language, repo_operator=self.op, base_path=self.repo.base_path, subdirectories=self.repo.subdirectories)]
gs_ffs = GSFeatureFlags(**config.feature_flags.model_dump())
secrets = Secrets(openai_key=config.secrets.openai_api_key)
codebase_config = CodebaseConfig(secrets=secrets, feature_flags=gs_ffs)
return Codebase(projects=projects, config=codebase_config)

@stopwatch
def reset_runner(self) -> None:
Expand Down Expand Up @@ -87,7 +86,7 @@

branch_config.custom_base_branch = branch_config.custom_base_branch or self.codebase.default_branch
self.executor.remote_repo.set_up_base_branch(branch_config.custom_base_branch)
self.executor.remote_repo.set_up_head_branch(branch_config.custom_head_branch, branch_config.force_push_head_branch)

Check failure on line 89 in src/codegen/runner/sandbox/runner.py

View workflow job for this annotation

GitHub Actions / mypy

error: Argument 1 to "set_up_head_branch" of "SandboxRepo" has incompatible type "str | None"; expected "str" [arg-type]

response = CreateBranchResponse()
if "codebase.flag_instance" in request.codemod.user_code:
Expand All @@ -97,9 +96,9 @@
response.group_segments = [group.segment for group in flag_groups]
if len(flag_groups) == 0:
logger.info("No flag groups found. Running without flagging.")
flag_groups = [None]

Check failure on line 99 in src/codegen/runner/sandbox/runner.py

View workflow job for this annotation

GitHub Actions / mypy

error: List item 0 has incompatible type "None"; expected "Group" [list-item]
else:
flag_groups = [None]

Check failure on line 101 in src/codegen/runner/sandbox/runner.py

View workflow job for this annotation

GitHub Actions / mypy

error: List item 0 has incompatible type "None"; expected "Group" [list-item]

# TODO: do this as part of find_flag_groups?
max_prs = request.grouping_config.max_prs
Expand Down
16 changes: 11 additions & 5 deletions src/codegen/runner/sandbox/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import psutil
from fastapi import FastAPI

from codegen.git.schemas.repo_config import RepoConfig
from codegen.runner.enums.warmup_state import WarmupState
from codegen.runner.models.apis import (
BRANCH_ENDPOINT,
Expand All @@ -20,9 +21,10 @@
SignalShutdownResponse,
UtilizationMetrics,
)
from codegen.runner.models.configs import get_repo_config
from codegen.runner.sandbox.middlewares import CodemodRunMiddleware
from codegen.runner.sandbox.runner import SandboxRunner
from codegen.shared.configs.config import config
from codegen.shared.enums.programming_language import ProgrammingLanguage
from codegen.shared.performance.memory_utils import get_memory_stats

logger = logging.getLogger(__name__)
Expand All @@ -37,11 +39,15 @@
global runner

try:
repo_config = get_repo_config()
server_info = ServerInfo(repo_name=repo_config.full_name)
server_info = ServerInfo(repo_name=config.repository.full_name)
logger.info(f"Starting up sandbox fastapi server for repo_name={server_info.repo_name}")

runner = SandboxRunner(repo_config=repo_config)
repo_config = RepoConfig(
name=config.repository.repo_name,
full_name=config.repository.full_name,
base_dir=os.path.dirname(config.repository.repo_path),

Check failure on line 47 in src/codegen/runner/sandbox/server.py

View workflow job for this annotation

GitHub Actions / mypy

error: Value of type variable "AnyOrLiteralStr" of "dirname" cannot be "str | None" [type-var]
language=ProgrammingLanguage(config.repository.language.upper()),
)
runner = SandboxRunner(repo_config=repo_config, access_token=config.secrets.github_token)
server_info.warmup_state = WarmupState.PENDING
await runner.warmup()
server_info.warmup_state = WarmupState.COMPLETED
Expand Down
28 changes: 19 additions & 9 deletions src/codegen/shared/configs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@
from codegen.shared.configs.constants import CONFIG_PATH, ENV_PATH


class TypescriptConfig(BaseModel):
def _get_setting_config(group_name: str) -> SettingsConfigDict:
return SettingsConfigDict(

Check failure on line 12 in src/codegen/shared/configs/models.py

View workflow job for this annotation

GitHub Actions / mypy

error: Extra key "exclude_defaults" for TypedDict "SettingsConfigDict" [typeddict-unknown-key]
env_prefix=f"CODEGEN_{group_name}__",
env_file=ENV_PATH,
case_sensitive=False,
extra="ignore",
exclude_defaults=False,
)


class TypescriptConfig(BaseSettings):
model_config = _get_setting_config("FEATURE_FLAGS_TYPESCRIPT")
ts_dependency_manager: bool | None = None
ts_language_engine: bool | None = None
v8_ts_engine: bool | None = None


class CodebaseFeatureFlags(BaseModel):
class CodebaseFeatureFlags(BaseSettings):
model_config = _get_setting_config("FEATURE_FLAGS")
debug: bool | None = None
verify_graph: bool | None = None
track_graph: bool | None = None
Expand All @@ -28,25 +40,23 @@
typescript: TypescriptConfig = Field(default_factory=TypescriptConfig)


class RepositoryConfig(BaseModel):
class RepositoryConfig(BaseSettings):
"""Configuration for the repository context to run codegen.
To populate this config, call `codegen init` from within a git repository.
"""

model_config = _get_setting_config("REPOSITORY")

repo_path: str | None = None
repo_name: str | None = None
full_name: str | None = None
language: str | None = None
user_name: str | None = None
user_email: str | None = None
language: str | None = None


class SecretsConfig(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="CODEGEN_SECRETS__",
env_file=ENV_PATH,
case_sensitive=False,
)
model_config = _get_setting_config("SECRETS")
github_token: str | None = None
openai_api_key: str | None = None

Expand All @@ -56,7 +66,7 @@


class Config(BaseSettings):
model_config = SettingsConfigDict(

Check failure on line 69 in src/codegen/shared/configs/models.py

View workflow job for this annotation

GitHub Actions / mypy

error: Extra key "exclude_defaults" for TypedDict "SettingsConfigDict" [typeddict-unknown-key]
extra="ignore",
exclude_defaults=False,
)
Expand Down
15 changes: 2 additions & 13 deletions tests/unit/codegen/runner/sandbox/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import pytest

from codegen.git.repo_operator.local_repo_operator import LocalRepoOperator
from codegen.runner.models.configs import RunnerFeatureFlags
from codegen.runner.sandbox.executor import SandboxExecutor
from codegen.runner.sandbox.runner import SandboxRunner
from codegen.sdk.codebase.config import CodebaseConfig, GSFeatureFlags, ProjectConfig
from codegen.sdk.codebase.config import ProjectConfig
from codegen.sdk.core.codebase import Codebase
from codegen.sdk.secrets import Secrets
from codegen.shared.enums.programming_language import ProgrammingLanguage


Expand All @@ -17,7 +15,7 @@
def codebase(tmpdir) -> Codebase:
op = LocalRepoOperator.create_from_files(repo_path=f"{tmpdir}/test-repo", files={"test.py": "a = 1"}, bot_commit=True)
projects = [ProjectConfig(repo_operator=op, programming_language=ProgrammingLanguage.PYTHON)]
codebase = Codebase(projects=projects)

Check failure on line 18 in tests/unit/codegen/runner/sandbox/conftest.py

View workflow job for this annotation

GitHub Actions / mypy

error: Need type annotation for "codebase" [var-annotated]
return codebase


Expand All @@ -33,13 +31,4 @@
mock_init_codebase.return_value = codebase
mock_op.return_value = codebase.op

yield SandboxRunner(repo_config=codebase.op.repo_config)


@pytest.fixture(autouse=True)
def mock_codebase_config():
with patch("codegen.runner.sandbox.runner.get_codebase_config") as mock_config:
gs_ffs = GSFeatureFlags(**RunnerFeatureFlags().model_dump())
secrets = Secrets(openai_key="test-key")
mock_config.return_value = CodebaseConfig(secrets=secrets, feature_flags=gs_ffs)
yield mock_config
yield SandboxRunner(repo_config=codebase.op.repo_config, access_token="test-token")