Skip to content

Commit 7b687bd

Browse files
authored
Fixes CMD parser in Python from_dockerfile method (#1040)
What was happening is that the following snippet: ```dockerfile CMD ["sleep", "20"] ``` Was incorrectly converted to: ``` sleep, 20 ``` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Fixes parsing of Dockerfile CMD/ENTRYPOINT array syntax to a proper start command and updates tests accordingly. > > - **Python SDK**: > - `e2b/template/dockerfile_parser.py`: Parse CMD/ENTRYPOINT JSON array (e.g., `["sleep", "20"]`) into a space-joined command (`sleep 20`) and set as `start_cmd`. > - **Tests**: > - JS SDK and Python (sync/async): Add ENTRYPOINT case and assert `startCmd`/`_start_cmd` equals `sleep 20`. > - **Release**: > - Changeset: patch bump for `@e2b/python-sdk`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ed257ab. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 8810646 commit 7b687bd

File tree

5 files changed

+31
-3
lines changed

5 files changed

+31
-3
lines changed

.changeset/fluffy-shrimps-play.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@e2b/python-sdk': patch
3+
---
4+
5+
fixed cmd parser in from_dockerfile

packages/js-sdk/tests/template/methods/fromDockerfile.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ buildTemplateTest('fromDockerfile', async () => {
77
const dockerfile = `FROM node:24
88
WORKDIR /app
99
COPY package.json .
10-
RUN npm install`
10+
RUN npm install
11+
ENTRYPOINT ["sleep", "20"]`
1112

1213
const template = Template().fromDockerfile(dockerfile)
1314

@@ -71,6 +72,11 @@ RUN npm install`
7172
template.instructions[5].args[0],
7273
'user'
7374
)
75+
assert.equal(
76+
// @ts-expect-error - startCmd is not a property of TemplateBuilder
77+
template.startCmd,
78+
'sleep 20'
79+
)
7480
})
7581

7682
buildTemplateTest('fromDockerfile with default user and workdir', () => {

packages/python-sdk/e2b/template/dockerfile_parser.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import os
23
import re
34
import tempfile
@@ -257,6 +258,14 @@ def _handle_cmd_entrypoint_instruction(
257258
return
258259
command = value.strip()
259260

261+
# Try to parse as JSON (for array format like CMD ["sleep", "infinity"])
262+
try:
263+
parsed_command = json.loads(command)
264+
if isinstance(parsed_command, list):
265+
command = " ".join(str(item) for item in parsed_command)
266+
except Exception:
267+
pass
268+
260269
# Import wait_for_timeout locally to avoid circular dependency
261270
def wait_for_timeout(timeout: int) -> str:
262271
# convert to seconds, but ensure minimum of 1 second

packages/python-sdk/tests/async/template_async/methods/test_from_dockerfile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ async def test_from_dockerfile():
99
dockerfile = """FROM node:24
1010
WORKDIR /app
1111
COPY package.json .
12-
RUN npm install"""
12+
RUN npm install
13+
ENTRYPOINT ["sleep", "20"]"""
1314

1415
template = AsyncTemplate().from_dockerfile(dockerfile)
1516

@@ -37,6 +38,9 @@ async def test_from_dockerfile():
3738
assert instructions[5]["type"] == InstructionType.USER
3839
assert instructions[5]["args"][0] == "user"
3940

41+
# Start command
42+
assert template._template._start_cmd == "sleep 20"
43+
4044

4145
@pytest.mark.skip_debug()
4246
async def test_from_dockerfile_with_default_user_and_workdir():

packages/python-sdk/tests/sync/template_sync/methods/test_from_dockerfile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ def test_from_dockerfile():
99
dockerfile = """FROM node:24
1010
WORKDIR /app
1111
COPY package.json .
12-
RUN npm install"""
12+
RUN npm install
13+
ENTRYPOINT ["sleep", "20"]"""
1314

1415
template = Template().from_dockerfile(dockerfile)
1516

@@ -37,6 +38,9 @@ def test_from_dockerfile():
3738
assert instructions[5]["type"] == InstructionType.USER
3839
assert instructions[5]["args"][0] == "user"
3940

41+
# Start command
42+
assert template._template._start_cmd == "sleep 20"
43+
4044

4145
@pytest.mark.skip_debug()
4246
def test_from_dockerfile_with_default_user_and_workdir():

0 commit comments

Comments
 (0)