The dynamic Worker bundler change made plugin-apps resolve @cloudflare/worker-bundler at runtime via import.meta.resolve, but package-runtime.ts never copied the package into the self-host image, so serve.js crashed on startup with a module-not-found error. Copy the package alongside the other runtime externals and pre-bundle dist/index.bundled.js at build time (the npm package does not ship it and the distroless runtime has no esbuild for the fallback), mirroring what apps/cli/src/build.ts does for the packed CLI. The CI smoke job only built the image, which is exactly why this slipped through: boot the container and require a healthy /api/health as well.
Showing the changes to .github (1 of 3 files). Show all
Unified · Split
| @@ -414,4 +414,35 @@ jobs: · 413 unmodified lines | ||
| 414 | 414 | context: . |
| 415 | 415 | file: apps/host-selfhost/Dockerfile |
| 416 | 416 | push: false |
| 417 | + load: true | |
| 417 | 418 | tags: executor-selfhost:ci |
| 419 | + | |
| 420 | + # Building alone doesn't catch startup crashes (e.g. a runtime-resolved | |
| 421 | + # package missing from the packaged runtime), so boot the container and | |
| 422 | + # require a healthy /api/health before calling the image good. | |
| 423 | + - name: Boot image and check health | |
| 424 | + shell: bash | |
| 425 | + run: | | |
| 426 | + set -euo pipefail | |
| 427 | + docker run -d --name selfhost-smoke -p 4788:4788 \ | |
| 428 | + -e BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ | |
| 429 | + -e EXECUTOR_BOOTSTRAP_ADMIN_EMAIL=smoke@example.com \ | |
| 430 | + -e EXECUTOR_BOOTSTRAP_ADMIN_PASSWORD="$(openssl rand -hex 16)" \ | |
| 431 | + -e EXECUTOR_WEB_BASE_URL=http://localhost:4788 \ | |
| 432 | + executor-selfhost:ci | |
| 433 | + for i in $(seq 1 30); do | |
| 434 | + if [ "$(docker inspect -f '{{.State.Running}}' selfhost-smoke)" != "true" ]; then | |
| 435 | + echo "container exited during startup" | |
| 436 | + docker logs selfhost-smoke | |
| 437 | + exit 1 | |
| 438 | + fi | |
| 439 | + if curl -fsS http://localhost:4788/api/health >/dev/null 2>&1; then | |
| 440 | + echo "healthy after ${i}s" | |
| 441 | + docker logs selfhost-smoke | |
| 442 | + exit 0 | |
| 443 | + fi | |
| 444 | + sleep 1 | |
| 445 | + done | |
| 446 | + echo "health check never passed" | |
| 447 | + docker logs selfhost-smoke | |
| 448 | + exit 1 | |