fix(worker): copy packages/core into worker runtime image#1035
Conversation
The worker Dockerfile builds @lobu/core in the builder stage but never copies packages/core into the runtime stage. bun install's workspace symlink (connector-sdk/node_modules/@lobu/core -> ../../../core) then dangles at runtime, so every connector feed sync crashes with "ENOENT reading .../connector-sdk/node_modules/@lobu/core" when @lobu/connector-sdk loads its @lobu/core-backed logger/retry helpers. Add the missing COPY, mirroring docker/app/Dockerfile which already copies packages/core.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Docker worker runtime image is updated to explicitly copy ChangesDocker Worker Runtime Symlink Fix
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
connector-worker has no direct @lobu/core dependency — it's consumed transitively by @lobu/connector-sdk (logger/retry). The self-check resolved @lobu/core from connector-worker's own location, which resolves in the hoisted dev workspace but fails in the isolated-linker worker image: a false negative (caught by the gate's own docker leg on #1037). Resolve/import @lobu/core anchored at @lobu/connector-sdk (its real consumer), reproducing the exact prod edge that dangled in #1035: .../connector-sdk/node_modules/@lobu/core.
* ci: add connector runtime parity smoke gate Guards against the packaging/parity drift that broke prod in #1035: the worker Docker image shipped missing `COPY packages/core`, so @lobu/connector-sdk's transitive @lobu/core import dangled and every connector feed sync crashed at runtime — yet all CI was green because the workspace tests resolve @lobu/core and build-images.yml builds + pushes images but never RUNS them. Add a single SHARED runtime self-check (packages/connector-worker/src/self-check) executed from BOTH the built CLI runtime (`lobu connector runtime-self-check`, hidden) and the worker image (`bun src/bin.ts self-check`). Both entrypoints call the SAME runConnectorRuntimeSelfCheck() over the same compile + default SubprocessExecutor path (the parity invariant; only the connector-source discovery roots differ). It asserts artifact/packaging facts only — @lobu/connector-sdk + @lobu/core resolve+import, EXTERNAL_RUNTIME_DEPS (playwright/sharp/jimp) resolve, the bundled connector source dir is discoverable, all discovered connectors instantiate with unique key/name/version, and a synthetic no-op connector compiles + runs through the default SubprocessExecutor. No network/DB/gateway/OAuth; passes under docker run --network=none. CI wiring: - ci.yml PR gate (path-filtered like mac-build-smoke): build worker image amd64 (load, no push), run the image self-check with --network=none, and run the CLI self-check on the host. - build-images.yml main/deploy gate: same amd64 image self-check as a job that build-worker (and transitively build-app) depends on, so a failing smoke blocks BOTH worker and app pushes — Flux can't roll the shared tag to a broken worker. Shares the buildx cache scope with build-worker. * ci: anchor @lobu/core self-check resolution at connector-sdk connector-worker has no direct @lobu/core dependency — it's consumed transitively by @lobu/connector-sdk (logger/retry). The self-check resolved @lobu/core from connector-worker's own location, which resolves in the hoisted dev workspace but fails in the isolated-linker worker image: a false negative (caught by the gate's own docker leg on #1037). Resolve/import @lobu/core anchored at @lobu/connector-sdk (its real consumer), reproducing the exact prod edge that dangled in #1035: .../connector-sdk/node_modules/@lobu/core. * ci: drop duplicate pathToFileURL import in self-check The previous commit added a pathToFileURL import that already existed (line 50), tripping TS2300 in make build-packages. pathToFileURL is already imported; remove the duplicate. * refactor(self-check): consolidate checks via async helper, trim prose Collapse the four hand-written async try/catch IIFEs into one async check() helper (records returned detail or error); fold connector discovery and key-uniqueness into the same pattern; trim duplicated narration while keeping the non-obvious rationale (SDK-anchored core resolution, cwd temp file, dynamic-import probes). No behavior change: 534 -> 413 lines, all 11 checks still pass and the dangling-@lobu/core failure path still exits 1. * ci(self-check): cwd-anchor external dep resolution; fail on unreadable connector subdir Address CodeRabbit review: - Resolve EXTERNAL_RUNTIME_DEPS from a cwd-rooted require, matching how child-runner stages and resolves the compiled bundle, so the probe fails where a real connector would instead of off connector-worker's hoisted tree. - Propagate readdir errors on connector subdirs (an unreadable subdir is a packaging defect for a parity gate) instead of silently skipping. - Document the self-check + child-runner runtime-compiled-bundle imports in the AGENTS.md dynamic-import allow-list. - Add least-privilege contents:read to the connector-parity-smoke job.
Problem
Every connector feed sync on the worker deployment (
summaries-app-lobu-worker) crashes at runtime with:Nothing gets ingested. Discovered while wiring the Spotify connector (valid OAuth, all scopes) — the sync runs fail before emitting any events.
Root cause
docker/worker/Dockerfilebuilds@lobu/corein the builder stage (cd packages/core && bunx tsc, line 54) but the runtime stage COPY block (lines 82-88) copiesnode_modules,connector-sdk,connectors,embeddings,connector-worker— neverpackages/core.At feed-sync time the compiled connector emits a bare
import '@lobu/connector-sdk'(the SDK is externalized by the compile pipeline).@lobu/connector-sdk/dist/index.jsre-exportslogger.js+retry.js, whichimport { createLogger, retryWithBackoff } from '@lobu/core'.bun install's workspace symlinkconnector-sdk/node_modules/@lobu/core → ../../../corethen dangles because its target (packages/core) was never copied →ENOENT.docker/app/Dockerfilealready copies core (line 139), which is why the app deployment isn't affected.Not a regression — long-standing latent gap: the worker runtime stage has never copied
packages/core. It only surfaces now that the worker deployment is being exercised for connector sync.Fix
One line in the runtime COPY block (mirrors the app image):
COPY --from=builder --chown=worker:worker /app/packages/core ./packages/coreValidation (red → green)
No Docker on the dev host, so reproduced the exact failure mode at the module-resolution level with the real built artifacts (Node 22), replicating the runtime image's COPY layout:
packages/core, current behavior):fs.realpathSynconconnector-sdk/node_modules/@lobu/corethrowsENOENT— the exact prod error.packages/core+ rootnode_modules, as the image has after the fix): the symlink resolves, Node resolves@lobu/corefrom connector-sdk's dist, and the module loads exposingcreateLogger+retryWithBackoff(the functions connector-sdk imports).Full image build verification happens in CI (the worker image build). After this deploys, re-triggering the Spotify feeds in
burembashould ingest cleanly.🤖 Generated with Claude Code
Summary by CodeRabbit