End-to-end: Docker on a hosted runner with the change's own docker wrapper, daemon config and agent
A job that stops the hosted runner's Docker daemon, installs this change's image/docker, image/daemon.json and agent (its registry relay), starts the daemon with three docker commands at once, and runs the runner's Docker tests. A daemon start lock leak like the one #225 fixed fails here, before merge, instead of in the Live test after a deploy. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXYSyuyJ1XDRKcW2aTR2Zj
- CI / Typecheck and bundlesuccess
- CI / Unit tests (1/2)success
- CI / Unit tests (2/2)success
- End-to-end / End-to-end (agent reviews, tasks, Today)success
- End-to-end / End-to-end (git, PRs, Actions)success
- End-to-end / End-to-end (large pushes)success
- End-to-end / End-to-end (passkeys, registry, email)success
- End-to-end / End-to-end (real histories)success
- End-to-end / End-to-end (runner Docker)success
- End-to-end / End-to-end (security)success
1 file changed+49−0
modified.github/workflows/e2e.yml+49−0View file
| @@ -82,3 +82,52 @@ | ||
| 82 | 82 | esac |
| 83 | 83 | echo "$files" |
| 84 | 84 | node --test --test-concurrency=1 "${opts[@]}" $files |
| 85 | + | |
| 86 | + # Docker as the hosted runner image runs it, with this change's docker wrapper, daemon config | |
| 87 | + # and agent (its registry relay): this job runs on a hosted runner, so the real dockerd is there. | |
| 88 | + # A daemon an earlier step started is stopped first, so the first uses below start it afresh. | |
| 89 | + runner-docker: | |
| 90 | + name: End-to-end (runner Docker) | |
| 91 | + runs-on: ubuntu-latest | |
| 92 | + timeout-minutes: 20 | |
| 93 | + steps: | |
| 94 | + - uses: actions/checkout@v4 | |
| 95 | + - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 | |
| 96 | + - uses: actions/setup-node@v4 | |
| 97 | + with: | |
| 98 | + node-version: 22 | |
| 99 | + cache: pnpm | |
| 100 | + - run: pnpm install --frozen-lockfile | |
| 101 | + - run: pnpm --filter @diffinery/runner build | |
| 102 | + - name: Use this change's Docker wrapper, daemon config and agent | |
| 103 | + run: | | |
| 104 | + set -euo pipefail | |
| 105 | + as_root() { if [ "$(id -u)" = 0 ]; then "$@"; else sudo "$@"; fi; } | |
| 106 | + if [ ! -f /opt/diffinery/agent.mjs ] || ! grep -q "registry relay" /usr/local/bin/docker 2>/dev/null; then | |
| 107 | + echo "::error::this job needs a Diffinery hosted runner (its docker wrapper and agent)" | |
| 108 | + exit 1 | |
| 109 | + fi | |
| 110 | + as_root pkill -x dockerd || true | |
| 111 | + as_root pkill -f -- "--registry-relay" || true | |
| 112 | + for _ in $(seq 1 60); do pgrep -x dockerd >/dev/null || break; sleep 0.5; done | |
| 113 | + as_root rm -f /run/diffinery-dockerd.ready | |
| 114 | + as_root cp --remove-destination containers/runner/image/docker /usr/local/bin/docker | |
| 115 | + as_root cp --remove-destination containers/runner/image/daemon.json /etc/docker/daemon.json | |
| 116 | + as_root cp --remove-destination containers/runner/dist/agent.mjs /opt/diffinery/agent.mjs | |
| 117 | + - name: Docker's first uses, several at once | |
| 118 | + timeout-minutes: 4 | |
| 119 | + run: | | |
| 120 | + set -uo pipefail | |
| 121 | + start=$(date +%s) | |
| 122 | + docker info >/dev/null & a=$! | |
| 123 | + docker ps >/dev/null & b=$! | |
| 124 | + docker version >/dev/null & c=$! | |
| 125 | + failed=0 | |
| 126 | + for p in $a $b $c; do wait "$p" || failed=1; done | |
| 127 | + echo "three docker commands at once, the daemon starting: $(( $(date +%s) - start )) s" | |
| 128 | + [ "$failed" = 0 ] || { echo "::error::a docker command failed while the daemon started"; exit 1; } | |
| 129 | + docker run --rm mirror.gcr.io/library/alpine:3.20 echo "container ok" | |
| 130 | + - name: Runner Docker tests (job containers, services, Docker actions) | |
| 131 | + timeout-minutes: 10 | |
| 132 | + working-directory: containers/runner | |
| 133 | + run: pnpm exec vitest run test/docker.test.ts test/docker-wrapper.test.ts |