File size: 7,842 Bytes
4b07aaf
 
 
 
 
 
85b7ac8
a7caaff
85b7ac8
 
 
 
 
 
 
 
 
 
4b07aaf
85b7ac8
4b07aaf
85b7ac8
 
 
 
 
 
4b07aaf
 
 
 
 
 
 
 
 
 
 
 
 
85b7ac8
 
 
 
 
4b07aaf
 
85b7ac8
 
 
 
 
 
 
4b07aaf
85b7ac8
 
4b07aaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eb895b1
4b07aaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85b7ac8
2794920
4b07aaf
2794920
4b07aaf
 
 
 
 
 
 
2794920
 
4b07aaf
 
 
 
2794920
4b07aaf
2794920
4b07aaf
 
 
 
2794920
4b07aaf
2794920
 
4b07aaf
 
 
 
 
2794920
 
4b07aaf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
"""Task 1: Dockerfile Syntax Errors — EASY.

Agent fixes common Dockerfile instruction/syntax mistakes:
typos in filenames, invalid base image tags, bad RUN syntax,
quoted EXPOSE values, missing FROM instruction.
"""



from server.models import TaskDifficulty
from server.tasks.base import BaseTask


class DockerfileSyntaxTask(BaseTask):
    NAME = "Dockerfile Syntax Errors"
    DESCRIPTION = "Fix syntax and instruction errors in Dockerfiles"
    DIFFICULTY = TaskDifficulty.EASY
    AVAILABLE_SECRETS = []

    SCENARIOS = [
        # Scenario 1: Typo in requirements filename
        {
            "id": "typo_filename",
            "files": [
                {
                    "path": "Dockerfile",
                    "type": "dockerfile",
                    "content": (
                        "FROM python:3.9-slim\n"
                        "WORKDIR /app\n"
                        "COPY requirments.txt .\n"
                        "RUN pip install --no-cache-dir -r requirements.txt\n"
                        "COPY . .\n"
                        'CMD ["python", "app.py"]'
                    ),
                },
                {
                    "path": "requirements.txt",
                    "type": "requirements",
                    "content": "flask==2.0.0\nrequests==2.28.0",
                },
            ],
            "error": {
                "phase": "docker_build",
                "message": "COPY failed: file not found in build context: requirments.txt",
                "exit_code": 1,
                "failed_step": "COPY requirments.txt .",
                "line_hint": 3,
            },
            "expected_fixes": [
                {
                    "file": "Dockerfile",
                    "type": "contains",
                    "expected": "COPY requirements.txt",
                    "hint": "Check spelling of the requirements filename — 'requirments' vs 'requirements'",
                }
            ],
        },

        # Scenario 2: Wrong base image tag (extra 'm')
        {
            "id": "invalid_base_image",
            "files": [
                {
                    "path": "Dockerfile",
                    "type": "dockerfile",
                    "content": (
                        "FROM python:3.9-slimm\n"
                        "WORKDIR /app\n"
                        "COPY requirements.txt .\n"
                        "RUN pip install -r requirements.txt\n"
                        "COPY . .\n"
                        "EXPOSE 7860\n"
                        'CMD ["python", "app.py"]'
                    ),
                },
                {
                    "path": "requirements.txt",
                    "type": "requirements",
                    "content": "flask==2.0.0",
                },
            ],
            "error": {
                "phase": "docker_build",
                "message": (
                    "pull access denied for python:3.9-slimm, "
                    "repository does not exist or may require 'docker login'"
                ),
                "exit_code": 1,
                "failed_step": "FROM python:3.9-slimm",
                "line_hint": 1,
            },
            "expected_fixes": [
                {
                    "file": "Dockerfile",
                    "type": "not_contains",
                    "expected": "FROM python:3.9-slimm",
                    "hint": "The base image tag is 'slim', not 'slimm' — remove the extra 'm'",
                }
            ],
        },

        # Scenario 3: && operator on its own line (invalid Dockerfile instruction)
        {
            "id": "invalid_run_syntax",
            "files": [
                {
                    "path": "Dockerfile",
                    "type": "dockerfile",
                    "content": (
                        "FROM python:3.9\n"
                        "WORKDIR /app\n"
                        "COPY . .\n"
                        "RUN pip install -r requirements.txt\n"
                        "    && python setup.py install\n"
                        'CMD ["python", "main.py"]'
                    ),
                },
                {
                    "path": "requirements.txt",
                    "type": "requirements",
                    "content": "numpy==1.21.0",
                },
            ],
            "error": {
                "phase": "docker_build",
                "message": "Dockerfile parse error: unknown instruction: &&",
                "exit_code": 1,
                "line_hint": 5,
            },
            "expected_fixes": [
                {
                    "file": "Dockerfile",
                    "type": "contains",
                    "expected": "RUN pip install -r requirements.txt && python setup.py install",
                    "hint": (
                        "Multi-line RUN commands must use backslash continuation "
                        "(RUN cmd1 \\\\\\n    && cmd2) or be written on one line"
                    ),
                }
            ],
        },

        # Scenario 4: COPY references a file that doesn't exist in context
        {
            "id": "copy_missing_source",
            "files": [
                {
                    "path": "Dockerfile",
                    "type": "dockerfile",
                    "content": (
                        "FROM nginx:alpine\n"
                        "COPY nginx.conf /etc/nginx/nginx.conf\n"
                        "COPY dist/ /usr/share/nginx/html\n"
                        "EXPOSE 80\n"
                        'CMD ["nginx", "-g", "daemon off;"]'
                    ),
                },
                {
                    "path": "build/index.html",
                    "type": "other",
                    "content": "<!DOCTYPE html><html><body>Hello</body></html>",
                },
            ],
            "error": {
                "phase": "docker_build",
                "message": "COPY failed: file not found in build context: dist/",
                "exit_code": 1,
                "failed_step": "COPY dist/ /usr/share/nginx/html",
                "line_hint": 3,
            },
            "expected_fixes": [
                {
                    "file": "Dockerfile",
                    "type": "contains",
                    "expected": "COPY build/",
                    "hint": "The build output is in 'build/' not 'dist/' — check the build context files",
                }
            ],
        },

        # Scenario 5: Missing FROM instruction — Dockerfile starts with WORKDIR
        {
            "id": "missing_from_instruction",
            "files": [
                {
                    "path": "Dockerfile",
                    "type": "dockerfile",
                    "content": (
                        "WORKDIR /app\n"
                        "COPY requirements.txt .\n"
                        "RUN pip install -r requirements.txt\n"
                        "COPY . .\n"
                        'CMD ["python", "app.py"]'
                    ),
                },
                {
                    "path": "requirements.txt",
                    "type": "requirements",
                    "content": "flask==2.0.0",
                },
            ],
            "error": {
                "phase": "docker_build",
                "message": "Dockerfile parse error: FROM is required as the first instruction",
                "exit_code": 1,
                "line_hint": 1,
            },
            "expected_fixes": [
                {
                    "file": "Dockerfile",
                    "type": "contains",
                    "expected": "FROM python:",
                    "hint": "Every Dockerfile must start with a FROM instruction",
                }
            ],
        },
    ]