Krishna1107's picture
inference fixed, port changed to 7860
eb895b1
"""Task: Full Stack Deployment Pipeline — EXPERT.
Agent debugs multi-error scenarios spanning the entire stack:
GHA workflow + Dockerfile + Kubernetes manifests.
Multiple bugs per scenario requiring cross-file reasoning.
"""
from server.models import TaskDifficulty
from server.tasks.base import BaseTask
class PipelineFullTask(BaseTask):
NAME = "Full Stack Deployment Pipeline"
DESCRIPTION = "Debug complex multi-error deployment pipelines across GHA workflows, Dockerfiles, and Kubernetes manifests"
DIFFICULTY = TaskDifficulty.HARD
AVAILABLE_SECRETS = ["GITHUB_TOKEN", "DOCKER_USERNAME", "DOCKER_PASSWORD"]
SCENARIOS = [
# Scenario 1: GHCR token missing env + K8s service selector mismatch
{
"id": "full_pipeline_ghcr_and_selector",
"files": [
{
"path": ".github/workflows/deploy.yml",
"type": "workflow",
"content": (
"name: Build and Deploy\n"
"on:\n"
" push:\n"
" branches: [main]\n"
"\n"
"jobs:\n"
" deploy:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - uses: actions/checkout@v4\n"
"\n"
" - name: Build Docker image\n"
" run: docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .\n"
"\n"
" - name: Login to GHCR\n"
" run: echo $GITHUB_TOKEN | docker login ghcr.io -u ${{ github.actor }} --password-stdin\n"
"\n"
" - name: Push image\n"
" run: docker push ghcr.io/${{ github.repository }}:${{ github.sha }}\n"
),
},
{
"path": "Dockerfile",
"type": "dockerfile",
"content": (
"FROM node:20-alpine\n"
"WORKDIR /app\n"
"COPY package*.json ./\n"
"RUN npm ci\n"
"COPY . .\n"
"EXPOSE 3000\n"
'CMD ["npm", "start"]\n'
),
},
{
"path": "package.json",
"type": "other",
"content": '{"name": "myapp", "scripts": {"start": "node server.js"}}',
},
{
"path": "k8s/deployment.yaml",
"type": "kubernetes",
"content": (
"apiVersion: apps/v1\n"
"kind: Deployment\n"
"metadata:\n"
" name: myapp\n"
"spec:\n"
" replicas: 3\n"
" selector:\n"
" matchLabels:\n"
" app: myapp\n"
" template:\n"
" metadata:\n"
" labels:\n"
" app: myapp\n"
" spec:\n"
" containers:\n"
" - name: app\n"
" image: ghcr.io/OWNER/REPO:TAG\n"
" ports:\n"
" - containerPort: 3000\n"
),
},
{
"path": "k8s/service.yaml",
"type": "kubernetes",
"content": (
"apiVersion: v1\n"
"kind: Service\n"
"metadata:\n"
" name: myapp-service\n"
"spec:\n"
" selector:\n"
" app: my-app\n"
" ports:\n"
" - port: 80\n"
" targetPort: 3000\n"
),
},
],
"error": {
"phase": "pipeline_deploy",
"message": (
"Run: Build and Deploy\n"
"\n"
"Step: Login to GHCR ✗\n"
"Error: Cannot perform an interactive login from a non TTY device\n"
"Error: GITHUB_TOKEN environment variable is not set\n"
"\n"
"---\n"
"(If login had succeeded, deployment would also fail with:)\n"
"Error: Service 'myapp-service' has no endpoints"
),
},
"expected_fixes": [
{
"file": ".github/workflows/deploy.yml",
"type": "contains",
"expected": "GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}",
"hint": "GITHUB_TOKEN is used as shell variable but not mapped from secrets via env block",
},
{
"file": "k8s/service.yaml",
"type": "contains",
"expected": "app: myapp",
"hint": "Service selector 'app: my-app' doesn't match Deployment label 'app: myapp'",
},
],
},
# Scenario 2: Dockerfile missing WORKDIR + workflow missing checkout + K8s wrong port
{
"id": "full_pipeline_three_bugs",
"files": [
{
"path": ".github/workflows/ci.yml",
"type": "workflow",
"content": (
"name: CI Pipeline\n"
"on:\n"
" push:\n"
" branches: [main]\n"
"\n"
"jobs:\n"
" build:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - name: Build image\n"
" run: docker build -t myapp:${{ github.sha }} .\n"
"\n"
" - name: Run tests\n"
" run: docker run myapp:${{ github.sha }} npm test\n"
),
},
{
"path": "Dockerfile",
"type": "dockerfile",
"content": (
"FROM node:18-alpine\n"
"COPY package*.json ./\n"
"RUN npm ci\n"
"COPY . .\n"
"EXPOSE 3000\n"
'CMD ["npm", "start"]\n'
),
},
{
"path": "package.json",
"type": "other",
"content": '{"name": "myapp", "scripts": {"start": "node server.js", "test": "jest"}}',
},
{
"path": "k8s/deployment.yaml",
"type": "kubernetes",
"content": (
"apiVersion: apps/v1\n"
"kind: Deployment\n"
"metadata:\n"
" name: myapp\n"
"spec:\n"
" replicas: 2\n"
" selector:\n"
" matchLabels:\n"
" app: myapp\n"
" template:\n"
" metadata:\n"
" labels:\n"
" app: myapp\n"
" spec:\n"
" containers:\n"
" - name: app\n"
" image: myapp:latest\n"
" ports:\n"
" - containerPort: 8080\n"
),
},
{
"path": "k8s/service.yaml",
"type": "kubernetes",
"content": (
"apiVersion: v1\n"
"kind: Service\n"
"metadata:\n"
" name: myapp-svc\n"
"spec:\n"
" selector:\n"
" app: myapp\n"
" ports:\n"
" - port: 80\n"
" targetPort: 8080\n"
),
},
],
"error": {
"phase": "pipeline_deploy",
"message": (
"Run: CI Pipeline\n"
"\n"
"Step: Build image ✗\n"
"Error: Checkout must happen before Docker build steps\n"
"(No actions/checkout@v4 step found before docker build)\n"
"\n"
"---\n"
"Additionally:\n"
"- Dockerfile: npm reports module resolution errors at runtime\n"
"- K8s: Service returns connection refused when accessed"
),
},
"expected_fixes": [
{
"file": ".github/workflows/ci.yml",
"type": "contains",
"expected": "actions/checkout@v4",
"hint": "Workflow needs a checkout step before docker build",
},
{
"file": "Dockerfile",
"type": "contains",
"expected": "WORKDIR /app",
"hint": "Dockerfile needs WORKDIR /app before COPY commands",
},
{
"file": "k8s/deployment.yaml",
"type": "contains",
"expected": "containerPort: 3000",
"hint": "Container port should be 3000 to match the app's EXPOSE/listen port",
},
{
"file": "k8s/service.yaml",
"type": "contains",
"expected": "targetPort: 3000",
"hint": "Service targetPort should be 3000 to match container port",
},
],
},
# Scenario 3: Wrong GHCR password secret + Dockerfile base image typo + K8s OOM
{
"id": "full_pipeline_ghcr_dockerfile_k8s",
"files": [
{
"path": ".github/workflows/release.yml",
"type": "workflow",
"content": (
"name: Release Pipeline\n"
"on:\n"
" release:\n"
" types: [published]\n"
"\n"
"jobs:\n"
" release:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - uses: actions/checkout@v4\n"
"\n"
" - name: Login to GHCR\n"
" run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin\n"
"\n"
" - name: Build\n"
" run: docker build -t ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }} .\n"
"\n"
" - name: Push\n"
" run: docker push ghcr.io/${{ github.repository }}:${{ github.event.release.tag_name }}\n"
),
},
{
"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 ["gunicorn", "app:app", "-b", "0.0.0.0:7860"]\n'
),
},
{
"path": "requirements.txt",
"type": "requirements",
"content": "flask==3.0.0\ngunicorn==21.2.0\n",
},
{
"path": "k8s/deployment.yaml",
"type": "kubernetes",
"content": (
"apiVersion: apps/v1\n"
"kind: Deployment\n"
"metadata:\n"
" name: api\n"
"spec:\n"
" replicas: 3\n"
" selector:\n"
" matchLabels:\n"
" app: api\n"
" template:\n"
" metadata:\n"
" labels:\n"
" app: api\n"
" spec:\n"
" containers:\n"
" - name: api\n"
" image: ghcr.io/myorg/myapp:latest\n"
" ports:\n"
" - containerPort: 7860\n"
" resources:\n"
" limits:\n"
' memory: "64Mi"\n'
' cpu: "100m"\n'
),
},
],
"error": {
"phase": "pipeline_deploy",
"message": (
"Run: Release Pipeline\n"
"\n"
"Step: Login to GHCR ✗\n"
"Error: GHCR requires GITHUB_TOKEN for authentication, not DOCKER_PASSWORD\n"
"\n"
"---\n"
"Additional issues found:\n"
"- Dockerfile: pull access denied for base image — repository does not exist\n"
"- K8s: Pod in CrashLoopBackOff with exit code 137"
),
},
"expected_fixes": [
{
"file": ".github/workflows/release.yml",
"type": "contains",
"expected": "secrets.GITHUB_TOKEN",
"hint": "GHCR uses GITHUB_TOKEN, not DOCKER_PASSWORD",
},
{
"file": "Dockerfile",
"type": "not_contains",
"expected": "python:3.9-slimm",
"hint": "Base image tag has a typo: 'slimm' should be 'slim'",
},
{
"file": "k8s/deployment.yaml",
"type": "contains",
"expected": 'memory: "256Mi"',
"hint": "Memory limit 64Mi is too low for gunicorn — increase to at least 256Mi",
},
],
},
# Scenario 4: Missing permissions block + hardcoded K8s image + missing ingress class
{
"id": "full_pipeline_permissions_image_ingress",
"files": [
{
"path": ".github/workflows/deploy.yml",
"type": "workflow",
"content": (
"name: Deploy to Production\n"
"on:\n"
" push:\n"
" branches: [main]\n"
"\n"
"jobs:\n"
" build-and-push:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - uses: actions/checkout@v4\n"
"\n"
" - name: Login to GHCR\n"
" run: echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin\n"
"\n"
" - name: Build and push\n"
" run: |\n"
" docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .\n"
" docker push ghcr.io/${{ github.repository }}:${{ github.sha }}\n"
),
},
{
"path": "Dockerfile",
"type": "dockerfile",
"content": (
"FROM node:20-alpine\n"
"WORKDIR /app\n"
"COPY package*.json ./\n"
"RUN npm ci\n"
"COPY . .\n"
"EXPOSE 3000\n"
'CMD ["npm", "start"]\n'
),
},
{
"path": "package.json",
"type": "other",
"content": '{"name": "app", "scripts": {"start": "node index.js"}}',
},
{
"path": "k8s/deployment.yaml",
"type": "kubernetes",
"content": (
"apiVersion: apps/v1\n"
"kind: Deployment\n"
"metadata:\n"
" name: webapp\n"
"spec:\n"
" replicas: 3\n"
" selector:\n"
" matchLabels:\n"
" app: webapp\n"
" template:\n"
" metadata:\n"
" labels:\n"
" app: webapp\n"
" spec:\n"
" containers:\n"
" - name: webapp\n"
" image: ghcr.io/OWNER/REPO:TAG\n"
" ports:\n"
" - containerPort: 3000\n"
),
},
{
"path": "k8s/service.yaml",
"type": "kubernetes",
"content": (
"apiVersion: v1\n"
"kind: Service\n"
"metadata:\n"
" name: webapp-svc\n"
"spec:\n"
" selector:\n"
" app: webapp\n"
" ports:\n"
" - port: 80\n"
" targetPort: 3000\n"
),
},
{
"path": "k8s/ingress.yaml",
"type": "kubernetes",
"content": (
"apiVersion: networking.k8s.io/v1\n"
"kind: Ingress\n"
"metadata:\n"
" name: webapp-ingress\n"
"spec:\n"
" rules:\n"
" - host: webapp.example.com\n"
" http:\n"
" paths:\n"
" - path: /\n"
" pathType: Prefix\n"
" backend:\n"
" service:\n"
" name: webapp-svc\n"
" port:\n"
" number: 80\n"
),
},
],
"error": {
"phase": "pipeline_deploy",
"message": (
"Run: Deploy to Production\n"
"\n"
"Step: Build and push ✗\n"
"Error: denied: permission_denied: write_package\n"
"GITHUB_TOKEN does not have packages:write permission\n"
"\n"
"---\n"
"Additional issues:\n"
"- K8s Deployment image is hardcoded as 'ghcr.io/OWNER/REPO:TAG' — "
"should reference the actual built image\n"
"- Ingress has no ingressClassName — won't be picked up by nginx controller"
),
},
"expected_fixes": [
{
"file": ".github/workflows/deploy.yml",
"type": "contains",
"expected": "packages: write",
"hint": "Add permissions block with 'packages: write' to allow GHCR push",
},
{
"file": "k8s/deployment.yaml",
"type": "not_contains",
"expected": "OWNER/REPO:TAG",
"hint": "Replace hardcoded 'OWNER/REPO:TAG' placeholder with actual image reference",
},
{
"file": "k8s/ingress.yaml",
"type": "contains",
"expected": "ingressClassName: nginx",
"hint": "Add ingressClassName: nginx to the Ingress spec",
},
],
},
# Scenario 5: Workflow secrets not wired + Dockerfile wrong output dir + K8s probe port wrong
{
"id": "full_pipeline_secrets_build_probe",
"files": [
{
"path": ".github/workflows/build.yml",
"type": "workflow",
"content": (
"name: Build and Push\n"
"on:\n"
" push:\n"
" branches: [main]\n"
"\n"
"jobs:\n"
" build:\n"
" runs-on: ubuntu-latest\n"
" steps:\n"
" - uses: actions/checkout@v4\n"
"\n"
" - name: Login to DockerHub\n"
" run: echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin\n"
"\n"
" - name: Build\n"
" run: docker build -t myuser/frontend:${{ github.sha }} .\n"
"\n"
" - name: Push\n"
" run: docker push myuser/frontend:${{ github.sha }}\n"
),
},
{
"path": "Dockerfile",
"type": "dockerfile",
"content": (
"FROM node:20-alpine AS builder\n"
"WORKDIR /app\n"
"COPY package*.json ./\n"
"RUN npm ci\n"
"COPY . .\n"
"RUN npm run build\n"
"\n"
"FROM nginx:alpine\n"
"COPY --from=builder /app/dist /usr/share/nginx/html\n"
"EXPOSE 80\n"
'CMD ["nginx", "-g", "daemon off;"]\n'
),
},
{
"path": "package.json",
"type": "other",
"content": '{"name": "frontend", "scripts": {"build": "react-scripts build", "start": "react-scripts start"}}',
},
{
"path": "k8s/deployment.yaml",
"type": "kubernetes",
"content": (
"apiVersion: apps/v1\n"
"kind: Deployment\n"
"metadata:\n"
" name: frontend\n"
"spec:\n"
" replicas: 2\n"
" selector:\n"
" matchLabels:\n"
" app: frontend\n"
" template:\n"
" metadata:\n"
" labels:\n"
" app: frontend\n"
" spec:\n"
" containers:\n"
" - name: frontend\n"
" image: myuser/frontend:latest\n"
" ports:\n"
" - containerPort: 80\n"
" livenessProbe:\n"
" httpGet:\n"
" path: /healthz\n"
" port: 3000\n"
" initialDelaySeconds: 10\n"
" periodSeconds: 5\n"
),
},
],
"error": {
"phase": "pipeline_deploy",
"message": (
"Run: Build and Push\n"
"\n"
"Step: Login to DockerHub ✗\n"
"Error: DOCKER_USERNAME and DOCKER_PASSWORD env vars are empty — "
"secrets not wired via env block\n"
"\n"
"---\n"
"Additional issues:\n"
"- Dockerfile: COPY failed: stat app/dist: file does not exist "
"(react-scripts outputs to 'build/' not 'dist/')\n"
"- K8s: Liveness probe port 3000 doesn't match container port 80 "
"(nginx listens on 80)"
),
},
"expected_fixes": [
{
"file": ".github/workflows/build.yml",
"type": "contains",
"expected": "DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}",
"hint": "Docker login secrets need to be mapped via env block",
},
{
"file": ".github/workflows/build.yml",
"type": "contains",
"expected": "DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}",
"hint": "Both DOCKER_USERNAME and DOCKER_PASSWORD must be in env block",
},
{
"file": "Dockerfile",
"type": "contains",
"expected": "COPY --from=builder /app/build",
"hint": "react-scripts outputs to 'build/' not 'dist/'",
},
{
"file": "k8s/deployment.yaml",
"type": "contains",
"expected": "port: 80",
"hint": "Liveness probe port should be 80 to match nginx container",
},
],
},
]