From a3f4618dec70f1e0932e1f78d953e880d5b237e4 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:33:36 -0400 Subject: [PATCH 1/2] feat(evm-wallet-experiment): capture kernel service logs via bind-mount Tee entrypoint stdout/stderr to /logs/.log so per-service logs persist beyond container lifetime and are accessible on the host. Replace the named ocap-logs volume with a bind-mount to ../logs so the host can read log files directly after a test run without docker cp. Add docker:ensure-logs script (mkdir -p logs) and call it from docker:up and docker:interactive:up so the bind-mount target always exists before the stack starts. --- .../docker/docker-compose.yml | 5 ++--- .../docker/entrypoint-kernel.mjs | 20 ++++++++++++++++++- packages/evm-wallet-experiment/package.json | 5 +++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/evm-wallet-experiment/docker/docker-compose.yml b/packages/evm-wallet-experiment/docker/docker-compose.yml index 842866e526..c07d1ec2d1 100644 --- a/packages/evm-wallet-experiment/docker/docker-compose.yml +++ b/packages/evm-wallet-experiment/docker/docker-compose.yml @@ -13,7 +13,7 @@ x-kernel-standard: &kernel-standard networks: [ocap-e2e] volumes: - ocap-run:/run/ocap - - ocap-logs:/logs + - ../logs:/logs entrypoint: - node - '--conditions' @@ -46,7 +46,7 @@ services: ports: ['8545:8545'] volumes: - ocap-run:/run/ocap - - ocap-logs:/logs + - ../logs:/logs healthcheck: test: ['CMD', 'test', '-f', '/run/ocap/contracts.json'] interval: 3s @@ -211,4 +211,3 @@ networks: volumes: ocap-run: - ocap-logs: diff --git a/packages/evm-wallet-experiment/docker/entrypoint-kernel.mjs b/packages/evm-wallet-experiment/docker/entrypoint-kernel.mjs index aca16dacb7..1bff567268 100644 --- a/packages/evm-wallet-experiment/docker/entrypoint-kernel.mjs +++ b/packages/evm-wallet-experiment/docker/entrypoint-kernel.mjs @@ -19,7 +19,12 @@ import { NodejsPlatformServices } from '@metamask/kernel-node-runtime'; import { startRpcSocketServer } from '@metamask/kernel-node-runtime/daemon'; import { makeSQLKernelDatabase } from '@metamask/kernel-store/sqlite/nodejs'; import { Kernel } from '@metamask/ocap-kernel'; -import { mkdirSync, unlinkSync, writeFileSync } from 'node:fs'; +import { + createWriteStream, + mkdirSync, + unlinkSync, + writeFileSync, +} from 'node:fs'; import { dirname } from 'node:path'; const NAME = process.env.SERVICE_NAME ?? 'kernel'; @@ -27,6 +32,19 @@ const { SOCKET_PATH } = process.env; const QUIC_ADDR = process.env.QUIC_LISTEN_ADDRESS; const { READY_FILE } = process.env; +// Tee stdout/stderr to a file so logs are accessible on the host via the +// bind-mounted logs directory even after the container exits. +mkdirSync('/logs', { recursive: true }); +const logStream = createWriteStream(`/logs/${NAME}.log`, { flags: 'w' }); +for (const stream of [process.stdout, process.stderr]) { + const original = stream.write.bind(stream); + // eslint-disable-next-line jsdoc/require-jsdoc + stream.write = (chunk, ...args) => { + logStream.write(chunk); + return original(chunk, ...args); + }; +} + if (!SOCKET_PATH) { console.error(`[${NAME}] FATAL: SOCKET_PATH is required`); process.exit(1); diff --git a/packages/evm-wallet-experiment/package.json b/packages/evm-wallet-experiment/package.json index 6f7550cc86..7036dd9234 100644 --- a/packages/evm-wallet-experiment/package.json +++ b/packages/evm-wallet-experiment/package.json @@ -60,9 +60,10 @@ "docker:compose:interactive": "node docker/run-interactive-compose.mjs", "docker:build": "yarn docker:compose build", "docker:build:force": "yarn docker:compose build --no-cache", - "docker:up": "yarn docker:compose up", + "docker:ensure-logs": "mkdir -p logs", + "docker:up": "yarn docker:ensure-logs && yarn docker:compose up", "docker:down": "yarn docker:compose down", - "docker:interactive:up": "node docker/run-interactive-compose.mjs up --build", + "docker:interactive:up": "yarn docker:ensure-logs && node docker/run-interactive-compose.mjs up --build", "docker:interactive:down": "node docker/run-interactive-compose.mjs down", "docker:setup:wallets": "yarn tsx test/e2e/docker/setup-wallets.ts", "docker:interactive:setup": "node docker/interactive-setup.mjs", From 31fa169994599bb9a3c27941f41a6bd33a2411f6 Mon Sep 17 00:00:00 2001 From: grypez <143971198+grypez@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:33:38 -0400 Subject: [PATCH 2/2] feat(evm-wallet-experiment): add vitest JSON reporter for docker e2e tests Write structured pass/fail results to logs/test-results.json so failures can be inspected without parsing terminal output. --- packages/evm-wallet-experiment/vitest.config.docker.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/evm-wallet-experiment/vitest.config.docker.ts b/packages/evm-wallet-experiment/vitest.config.docker.ts index a3b09d5818..ce3808e60d 100644 --- a/packages/evm-wallet-experiment/vitest.config.docker.ts +++ b/packages/evm-wallet-experiment/vitest.config.docker.ts @@ -14,5 +14,10 @@ export default defineConfig({ testTimeout: 180_000, // No setupFiles — we need real fetch (not mocked) and no lockdown shims. setupFiles: [], + // Write structured results to logs/ so agents and CI can inspect failures + // without parsing terminal output. Kernel service logs land alongside in + // logs/.log via the entrypoint tee. + reporters: ['default', 'json'], + outputFile: 'logs/test-results.json', }, });