lots of change - all to start my 3rd redo
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# GENERATED — do not edit. Source: scripts/gen-harbor-dockerfiles.ts (fragments + member metadata).
|
||||
# Per-repo harbor task Dockerfile for potion-web. Nuxt 3 marketing/app front end; no test suite.
|
||||
|
||||
FROM node:18-bookworm
|
||||
|
||||
# System deps for this member's runtime + services.
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
sudo \
|
||||
jq \
|
||||
ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# --- Python >=3.10 for the reduced-toolset agent's str_replace_editor ---
|
||||
# str_replace_editor (shebang `python3`) uses dataclass(kw_only=True) → it requires Python
|
||||
# >=3.10. The era-matched base ships Debian's older system python (ruby:3.2.1/3.1.2 → 3.9,
|
||||
# ruby:2.6.6 → 3.7), so install a modern CPython via uv (a single static binary that downloads
|
||||
# a managed interpreter — no compile, no apt, works even on archived buster) and make it the
|
||||
# default `python3`. Without this the agent's file editor can't load and every trial dies at
|
||||
# agent setup (NonZeroAgentExitCodeError). Independent of the repo's own runtime.
|
||||
RUN curl -fsSL https://astral.sh/uv/0.12.10/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh \
|
||||
&& uv python install 3.10 \
|
||||
&& ln -sf "$(uv python find 3.10)" /usr/local/bin/python3 \
|
||||
&& python3 --version
|
||||
|
||||
# --- Playwright + Chromium, when the task opts in ----------------------------
|
||||
# Installed only when task.toml sets `[metadata] browser = true`. A Dockerfile cannot read
|
||||
# task.toml, so build-workspace.sh writes that answer to environment/browser-optin.
|
||||
# Self-contained under /opt — the member's own runtime is untouched.
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright
|
||||
COPY browser-optin /tmp/browser-optin
|
||||
RUN set -eu; \
|
||||
if [ "$(cat /tmp/browser-optin)" != "1" ]; then echo "browser: task did not opt in; skipping Playwright"; exit 0; fi; \
|
||||
set -x; \
|
||||
apt-get update -qq; \
|
||||
apt-get install -y -qq --no-install-recommends \
|
||||
xz-utils \
|
||||
libxcomposite1 \
|
||||
libxdamage1 \
|
||||
libxfixes3 \
|
||||
libxrandr2 \
|
||||
libasound2 \
|
||||
libatk1.0-0 \
|
||||
libatk-bridge2.0-0 \
|
||||
libatspi2.0-0 \
|
||||
libcups2 \
|
||||
libdbus-1-3 \
|
||||
libgbm1 \
|
||||
libnspr4 \
|
||||
libnss3 \
|
||||
libxkbcommon0 \
|
||||
libpango-1.0-0 \
|
||||
libcairo2 \
|
||||
libxshmfence1 \
|
||||
libx11-xcb1 \
|
||||
libxcb-dri3-0 \
|
||||
libdrm2; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
arch="$(dpkg --print-architecture)"; \
|
||||
case "$arch" in amd64) nodearch=x64;; arm64) nodearch=arm64;; *) echo "unsupported arch: $arch" >&2; exit 1;; esac; \
|
||||
curl -fsSL "https://nodejs.org/dist/v20.19.5/node-v20.19.5-linux-${nodearch}.tar.xz" -o /tmp/pw-node.tar.xz; \
|
||||
mkdir -p /opt/pw-node; \
|
||||
tar -xJf /tmp/pw-node.tar.xz -C /opt/pw-node --strip-components=1; \
|
||||
rm /tmp/pw-node.tar.xz; \
|
||||
export npm_config_prefix=/opt/pw-node PATH="/opt/pw-node/bin:$PATH"; \
|
||||
/opt/pw-node/bin/npm install -g playwright@1.56.0; \
|
||||
test -d /opt/pw-node/lib/node_modules/playwright; \
|
||||
/opt/pw-node/bin/node /opt/pw-node/lib/node_modules/playwright/cli.js install chromium; \
|
||||
printf '#!/bin/sh\nNODE_PATH=/opt/pw-node/lib/node_modules exec /opt/pw-node/bin/node "$@"\n' > /usr/local/bin/pw; \
|
||||
chmod +x /usr/local/bin/pw; \
|
||||
printf 'const{chromium}=require("playwright");(async()=>{const b=await chromium.launch();const p=await b.newPage();await p.setContent("<h1 id=t>ok</h1>");if(await p.textContent("#t")!=="ok")throw new Error("bad render");await b.close();console.log("chromium OK");})()\n' > /tmp/pw-check.js; \
|
||||
pw /tmp/pw-check.js; \
|
||||
rm -f /tmp/pw-check.js
|
||||
|
||||
# Install Claude Code globally (the grader in test.sh runs `claude`). Retry the
|
||||
# network install, then FAIL THE BUILD if `claude` isn't on PATH — a missing grader
|
||||
# CLI silently zeros every reward, so a broken image must NEVER be cached.
|
||||
# NOTE: download-to-file, NOT `curl … | bash` — a pipe returns bash's exit (0 on
|
||||
# empty stdin), masking a failed curl so the retry would break after one attempt.
|
||||
# CLAUDE_CODE_MIN is the oldest CLI the grader model accepts. Referencing it in the RUN
|
||||
# puts it in the layer's cache key, so bumping it rebuilds the install everywhere, and the
|
||||
# assert refuses to cache an image whose installer returned something older.
|
||||
ARG CLAUDE_CODE_MIN=2.1.251
|
||||
RUN for i in 1 2 3; do \
|
||||
if curl -fsSL https://claude.ai/install.sh -o /tmp/claude-install.sh && bash /tmp/claude-install.sh; then break; fi; \
|
||||
echo "WARNING: claude install attempt $i failed; retrying in 5s" >&2; sleep 5; \
|
||||
done; \
|
||||
rm -f /tmp/claude-install.sh; \
|
||||
for p in /root/.claude-code/claude /root/.local/bin/claude "$(find /root -name claude -type f 2>/dev/null | head -1)"; do \
|
||||
[ -n "$p" ] && [ -x "$p" ] && ln -sf "$p" /usr/local/bin/claude && break; \
|
||||
done; \
|
||||
command -v claude >/dev/null 2>&1 || { echo "FATAL: claude CLI not installed (see the install output above) — the grader needs it" >&2; exit 1; }; \
|
||||
_v="$(claude --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"; \
|
||||
[ "$(printf '%s\n%s\n' "$CLAUDE_CODE_MIN" "$_v" | sort -V | head -1)" = "$CLAUDE_CODE_MIN" ] \
|
||||
|| { echo "FATAL: claude $_v is older than $CLAUDE_CODE_MIN, the minimum the grader needs" >&2; exit 1; }; \
|
||||
echo "claude $_v installed at $(command -v claude)"
|
||||
|
||||
# Install the Codex CLI at BUILD time, like claude: one fetch per image rather than one per
|
||||
# trial. Never fatal — agent-setup still has the network (the DNS jail lands after it), so a
|
||||
# codex-less image costs a slower first trial, not a broken build on a worker's machine.
|
||||
RUN for i in 1 2 3; do \
|
||||
if curl -fsSL https://chatgpt.com/codex/install.sh -o /tmp/codex-install.sh \
|
||||
&& CODEX_INSTALL_DIR=/usr/local/bin CODEX_NON_INTERACTIVE=true sh /tmp/codex-install.sh; then break; fi; \
|
||||
echo "WARNING: codex install attempt $i failed; retrying in 5s" >&2; sleep 5; \
|
||||
done; \
|
||||
rm -f /tmp/codex-install.sh; \
|
||||
if ! command -v codex >/dev/null 2>&1 && [ -x "$HOME/.local/bin/codex" ]; then \
|
||||
ln -sf "$HOME/.local/bin/codex" /usr/local/bin/codex; \
|
||||
fi; \
|
||||
if ! command -v codex >/dev/null 2>&1 && command -v npm >/dev/null 2>&1; then \
|
||||
npm install -g @openai/codex@latest || true; \
|
||||
fi; \
|
||||
command -v codex >/dev/null 2>&1 \
|
||||
&& echo "codex installed at $(command -v codex)" \
|
||||
|| echo "WARNING: codex CLI not installed (see the install output above)" >&2
|
||||
|
||||
# Restrict DNS to the model endpoint when DNSJAIL_ALLOW is set (the agent supplies it).
|
||||
# Source: scripts/lib/dns-jail-container.sh, staged here by build-workspace.sh.
|
||||
COPY dns-jail/ /opt/raccoon-dns-jail/
|
||||
RUN if [ -f /opt/raccoon-dns-jail/dns-jail-container.sh ]; then \
|
||||
install -m 0755 /opt/raccoon-dns-jail/dns-jail-container.sh /usr/local/bin/raccoon-dns-jail \
|
||||
&& sh -n /usr/local/bin/raccoon-dns-jail; \
|
||||
else echo "NOTE: no DNS jail script staged; trials on this image run unjailed" >&2; fi
|
||||
|
||||
# Resolver for the trial DNS allowlist (scripts/dnsjail.py); if this
|
||||
# does not land, trials just run unjailed.
|
||||
RUN (command -v apk >/dev/null 2>&1 && apk add --no-cache dnsmasq bind-tools) \
|
||||
|| (apt-get update && apt-get install -y --no-install-recommends dnsmasq-base dnsutils \
|
||||
&& rm -rf /var/lib/apt/lists/*) \
|
||||
|| true
|
||||
|
||||
USER root
|
||||
|
||||
WORKDIR /workspace
|
||||
COPY workspace/ .
|
||||
|
||||
# Block CC's network tools — agent should execute code locally, not fetch
|
||||
RUN mkdir -p .claude && \
|
||||
echo '{"permissions":{"deny":["WebFetch","WebSearch"]}}' > .claude/settings.json
|
||||
|
||||
RUN git init && \
|
||||
git config user.email "dev@agent" && \
|
||||
git config user.name "Dev" && \
|
||||
git add -A && \
|
||||
git commit -m "initial" --quiet
|
||||
|
||||
# Install JS deps from the committed yarn.lock; fall back to a plain install if it drifted.
|
||||
RUN yarn install --frozen-lockfile --network-timeout 600000 \
|
||||
|| yarn install --network-timeout 600000
|
||||
|
||||
# Fold the env-prep above into the baseline commit: tests/test.sh captures the agent's
|
||||
# work as the diff against it, so uncommitted setup edits ship as the agent's own.
|
||||
RUN git add -A && git commit --amend --no-edit --quiet
|
||||
|
||||
# Fail loudly if any load-bearing tool is missing.
|
||||
RUN for t in node yarn claude; do \
|
||||
command -v "$t" >/dev/null 2>&1 || { echo "FATAL: required tool '$t' missing from image" >&2; exit 1; }; \
|
||||
done; \
|
||||
echo "toolchain OK"
|
||||
|
||||
CMD ["sleep", "infinity"]
|
||||
Reference in New Issue
Block a user