Skip to content

Commit 48b3768

Browse files
start refactor of sudo modal
1 parent caeafa0 commit 48b3768

File tree

2 files changed

+109
-54
lines changed

2 files changed

+109
-54
lines changed

commit0/harness/modal_utils.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
""" Modal utility functions
2+
3+
A mirror of the docker utility functions.
4+
"""
5+
6+
import modal
7+
import os
8+
9+
from commit0.harness.docker_utils import HEREDOC_DELIMITER
10+
11+
12+
def create_sandbox(image: modal.Image, nfs: model.NetworkFileSystem) -> modal.Sandbox:
13+
return modal.Sandbox.create(
14+
"sleep",
15+
"infinity",
16+
image=image,
17+
network_file_systems={
18+
"/vol": nfs,
19+
},
20+
)
21+
22+
23+
def execute_command(sandbox: modal.Sandbox, command: str, timeout=) -> tuple[str,str]:
24+
process = sandbox.exec("bash", "-c", command)
25+
stdout = []
26+
for line in process.stdout:
27+
stdout.append(line)
28+
stderr = []
29+
for line in process.stderr:
30+
stderr.append(line)
31+
return "\n".join(stdout), "\n".join(stderr)
32+
33+
34+
def copy_file_to_sandbox(sandbox: modal.Sandbox, nfs: modal.NetworkFileSystem, src: Path, dst: Path) -> None:
35+
with src.open("rb") as f:
36+
nfs.write_file(str(src), f)
37+
sandbox.exec("bash", "-c", f"cp /vol/{str(src)} {str(dst)}")
38+
39+
40+
def copy_from_sandbox(sandbox: modal.Sandbox, src: Path, dst: Path) -> None:
41+
pass
42+
43+
44+
def delete_file_from_sandbox(sandbox: modal.Sandbox, file_path: str) -> None:
45+
pass
46+
47+
48+
def copy_ssh_pubkey_from_sandbox(sandbox: modal.Sandbox) -> None:
49+
process = sandbox.exec("bash", "-c", "cat /root/.ssh/id_rsa.pub")
50+
public_key = "".join([line for line in process.stdout]).strip()
51+
52+
# add to authorized keys locally. copy-pasted from utils
53+
local_authorized_keys_path = os.path.expanduser("~/.ssh/authorized_keys")
54+
os.makedirs(os.path.dirname(local_authorized_keys_path), exist_ok=True)
55+
if not os.path.exists(local_authorized_keys_path):
56+
# Since the file does not exist, create it
57+
open(local_authorized_keys_path, "a").close()
58+
write = True
59+
else:
60+
with open(local_authorized_keys_path, "r") as authorized_keys_file:
61+
content = authorized_keys_file.read()
62+
if public_key not in content:
63+
write = True
64+
else:
65+
write = False
66+
if write:
67+
with open(local_authorized_keys_path, "a") as authorized_keys_file:
68+
authorized_keys_file.write(public_key + "\n")
69+
70+
71+
def write_to_sandbox(sandbox: modal.Sandbox, data: str, dst: Path) -> None:
72+
pass

commit0/harness/run_pytest_ids.py

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ class ExecutionBackend(StrEnum):
4040
def run_docker(
4141
spec: Spec, logger: logging.Logger, eval_file: Path, timeout: int, log_dir: Path
4242
) -> None:
43+
""" Runs the tests in a local docker container.
44+
45+
1. Creates docker container.
46+
2. Copies ssh public key from container to local machine.
47+
3. Copies eval.sh from local to container.
48+
4. Runs evaluation and saves to {log_dir}/test_output.txt.
49+
5. Copies over report.json if it exists.
50+
"""
4351
client = docker.from_env()
4452
container = None
4553
try:
@@ -107,78 +115,48 @@ def run_docker(
107115
def run_modal(
108116
spec: Spec, logger: logging.Logger, eval_file: Path, timeout: int, log_dir: Path
109117
) -> None:
110-
# get image name to pull from dockerhub
111-
# spec.repo_image_key
118+
""" Runs the tests in a remote Modal container.
119+
120+
1. Creates modal container.
121+
2. Copies ssh public key from container to local machine.
122+
3. Copies eval.sh from local to container.
123+
4. Runs evaluation and saves to {log_dir}/test_output.txt.
124+
5. Copies over report.json if it exists.
125+
"""
112126
import modal
127+
from commit0.harness.modal_utils import (
128+
create_sandbox,
129+
copy_to_sandbox,
130+
copy_from_sandbox,
131+
delete_file_from_sandbox,
132+
copy_ssh_pubkey_from_sandbox,
133+
write_to_sandbox,
134+
)
113135

136+
# the image must exist on dockerhub
114137
reponame = spec.repo.split("/")[-1]
115138
image_name = f"wentingzhao/{reponame}"
116139
image = modal.Image.from_registry(image_name)
117140

118141
with modal.NetworkFileSystem.ephemeral() as nfs:
119-
# create sleepy sandbox
120-
sandbox = modal.Sandbox.create(
121-
"sleep",
122-
"infinity",
123-
image=image,
124-
network_file_systems={
125-
"/vol": nfs,
126-
},
127-
)
142+
sandbox = create_sandbox(image, nfs)
128143

129-
# get ssh pubkey
130-
process = sandbox.exec("bash", "-c", "cat /root/.ssh/id_rsa.pub")
131-
public_key = "".join([line for line in process.stdout]).strip()
132-
133-
# add to authorized keys locally. copy-pasted from utils
134-
local_authorized_keys_path = os.path.expanduser("~/.ssh/authorized_keys")
135-
os.makedirs(os.path.dirname(local_authorized_keys_path), exist_ok=True)
136-
if not os.path.exists(local_authorized_keys_path):
137-
# Since the file does not exist, create it
138-
open(local_authorized_keys_path, "a").close()
139-
write = True
140-
else:
141-
with open(local_authorized_keys_path, "r") as authorized_keys_file:
142-
content = authorized_keys_file.read()
143-
if public_key not in content:
144-
write = True
145-
else:
146-
write = False
147-
if write:
148-
with open(local_authorized_keys_path, "a") as authorized_keys_file:
149-
authorized_keys_file.write(public_key + "\n")
144+
copy_ssh_pubkey_from_sandbox(sandbox)
150145

151146
# copy eval file
152-
with open(eval_file, "rb") as f:
153-
nfs.write_file("eval.sh", f)
154-
sandbox.exec("bash", "-c", "cp /vol/eval.sh /eval.sh")
147+
copy_file_to_sandbox(sandbox, nfs, eval_file, Path("/eval.sh"))
155148

156149
# DBG: check if eval file properly copied
157-
process = sandbox.exec("bash", "-c", "ls /")
158-
for line in process.stdout:
159-
print(line)
160-
# /DBG
150+
print(execute_command("ls /")[0])
161151

162152
# execute tests
163-
process = sandbox.exec("bash", "-c", "/bin/bash /eval.sh")
164-
output = []
165-
line = ""
166-
for line in process.stdout:
167-
output.append(line)
168-
output = "".join(line)
169-
logger.info(output)
153+
output, error = execute_command("/bin/bash /eval.sh")
170154
print(output)
171-
172-
output = []
173-
for line in process.stderr:
174-
output.append(line)
175-
output_s = "".join(line)
176-
logger.info(output_s)
177-
print(output_s)
155+
print(error)
178156

179157
timed_out = False
180158
test_output = extract_test_output(
181-
output_s, "--json-report --json-report-file=report.json"
159+
output, "--json-report --json-report-file=report.json"
182160
)
183161

184162
# stdout might be more straightforward
@@ -205,6 +183,11 @@ def main(
205183
backend: str,
206184
timeout: int,
207185
) -> None:
186+
""" Runs the pytests for repos in a dataset.
187+
188+
Tests are run either locally through docker
189+
or remotely through Modal.
190+
"""
208191
dataset: Iterator[RepoInstance] = load_dataset(dataset_name, split=dataset_split) # type: ignore
209192
spec = None
210193
example = None

0 commit comments

Comments
 (0)