Skip to content

fix: copy every workspace manifest into the image deps layers - #370

Open
Deodat-Lawson wants to merge 1 commit into
mainfrom
fix/dockerfile-workspace-manifests
Open

fix: copy every workspace manifest into the image deps layers#370
Deodat-Lawson wants to merge 1 commit into
mainfrom
fix/dockerfile-workspace-manifests

Conversation

@Deodat-Lawson

@Deodat-Lawson Deodat-Lawson commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Problem

main has not produced a deployable image since 2026-08-29 — four consecutive failed runs of the Docker workflow. Because docker.yml only pushes :latest on a successful build, GHCR's :latest is still commit 5452aedd, and any production docker compose pull today is a no-op. Three merges have landed on a branch that cannot build.

The most recent failure:

../../packages/google-drive/src/wire.ts:7
Type error: Cannot find module 'zod'

packages/google-drive/package.json declares "zod": "^3.23.8", so the error points at the wrong thing.

Root cause

The deps stage copies workspace manifests one explicit COPY line at a time, so that source edits don't bust the install cache:

COPY packages/runtime/package.json ./packages/runtime/
COPY packages/evidence/package.json ./packages/evidence/
...

That list is maintained by hand and nothing has ever compared it to the actual workspace. The two packages added recently — packages/google-drive and packages/document-conversion-engine — were never added, in either Dockerfile.

So pnpm install --frozen-lockfile resolves a workspace that is missing those members. The install succeeds (the lockfile is consistent; the packages simply aren't part of the graph it sees), their dependencies are never installed, and the failure surfaces two minutes later in the builder stage as an unresolvable import — naming a dependency the package does declare, in a file that is not at fault.

apps/worker/Dockerfile had the identical omission, so the worker image would have failed the same way as soon as the web build was fixed.

Changes

  • apps/web/Dockerfile, apps/worker/Dockerfile — add the two missing manifests to the deps layer.
  • scripts/ci/check-dockerfile-manifests.mjs — compares every workspace manifest against each Dockerfile's deps layer and fails with the exact COPY line to add.
  • .github/workflows/CI.yml — runs that check early in the check job, before pnpm install. It needs no dependencies, so it fails in seconds rather than after a multi-minute image build.

Why the guard

This failure mode is silent at the point of the mistake and misleading at the point of discovery: adding a package is normal work, nothing warns you, and the error that eventually appears blames a dependency that is correctly declared. Without a check, the next package added repeats it.

Verified both directions:

$ node scripts/ci/check-dockerfile-manifests.mjs
[check-dockerfile-manifests] ok — 20 manifests present across 2 Dockerfiles

$ # with packages/google-drive removed from the web Dockerfile
[check-dockerfile-manifests] 1 workspace manifest(s) missing from a Dockerfile deps layer:
  ✗ apps/web/Dockerfile — add: COPY packages/google-drive/package.json ./packages/google-drive/

Validation

The pull_request trigger runs a smoke build of both images, which is the real test of this change — a green build here is proof the deps layer now resolves zod for packages/google-drive.

Note for whoever deploys after this merges

This unblocks the image, but production is still on 5452aedd and the intervening commits replace Clerk with better-auth. Deploying will need BETTER_AUTH_SECRET set (openssl rand -base64 32) before the app can boot — it is requiredString() — plus BETTER_AUTH_URL behind the proxy, and three new migrations will apply. That is a planned cutover, not a routine redeploy.

🤖 Generated with Claude Code


Note

Low Risk
Build/CI guardrails and Dockerfile manifest COPY lines only; no runtime auth, data, or application logic changes.

Overview
Fixes broken Docker image builds caused by hand-maintained deps-stage COPY lists omitting newer workspace packages (document-conversion-engine, google-drive). Without those manifests, pnpm install --frozen-lockfile sees an incomplete workspace, skips those packages’ dependencies, and the builder later fails with misleading errors (e.g. missing zod).

apps/web/Dockerfile and apps/worker/Dockerfile now copy both missing package.json files in the deps layer.

Adds scripts/ci/check-dockerfile-manifests.mjs, which enumerates workspace manifests under packages/, pipelines/, and apps/ and asserts each required path appears in the web and worker Dockerfiles (with app-specific rules so the worker image isn’t forced to list unrelated apps/* manifests).

.github/workflows/CI.yml runs that script early in the check job—before pnpm install—so omissions fail in seconds instead of deep in a multi-minute image build.

Reviewed by Cursor Bugbot for commit e792785. Bugbot is set up for automated code reviews on this repo. Configure here.

The deps stage lists workspace manifests one COPY at a time so source
edits don't bust the install cache. That list is hand-maintained and
nothing checked it against the workspace, so the two packages added
recently — google-drive and document-conversion-engine — were never
added to it.

pnpm install --frozen-lockfile then resolves a workspace missing those
members, their dependencies are never installed, and the failure only
surfaces in the builder stage as a type error naming a dependency the
package does declare:

    packages/google-drive/src/wire.ts:7
    Type error: Cannot find module 'zod'

Both image builds were affected, so the worker would have failed the
same way once the web build was fixed.

Adds scripts/ci/check-dockerfile-manifests.mjs, run early in CI: it
compares the workspace against each Dockerfile's deps layer and prints
the exact COPY line to add. Without it the next package repeats this,
and the symptom points at the wrong file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
launch-stack Error Error Aug 30, 2026 7:56pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
pdr-ai-v2 Ignored Ignored Aug 30, 2026 7:56pm

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e79278591c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +58 to +61
// apps/* manifests are only required in the Dockerfile that builds
// that app; a worker image has no reason to carry apps/web's.
if (manifest.startsWith("apps/") && !dockerfile.startsWith(manifest.slice(0, manifest.lastIndexOf("/")))) {
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the web manifest covered by the worker check

When apps/web/package.json is omitted from the worker dependency layer, this exception skips it and CI still reports success. The worker Dockerfile explicitly copies and runs source from apps/web, whose third-party dependencies are installed from that manifest, so removing its existing COPY recreates the unresolved-dependency failure this guard is intended to catch.

Useful? React with 👍 / 👎.

Comment on lines +63 to +65
if (!contents.includes(manifest)) {
failures.push({ dockerfile, manifest });
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify the manifest is copied before dependency installation

When a manifest path appears only in a comment or in a COPY after RUN pnpm install, this substring test passes even though the dependency layer does not contain the manifest at installation time. That leaves this new CI guard green while the subsequent image build fails with the same missing-dependency symptom; restrict the check to active COPY instructions before the install command.

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e792785. Configure here.

import { join, resolve as resolvePath } from "node:path";

const ROOT = resolvePath(import.meta.dirname, "../..");
const DOCKERFILES = ["apps/web/Dockerfile", "apps/worker/Dockerfile"];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manifest check skips prebuilt Dockerfile

Medium Severity

The new guard only inspects apps/web/Dockerfile and apps/worker/Dockerfile, so it never sees apps/web/Dockerfile.prebuilt. That file uses the same hand-maintained deps-layer COPY list and still omits packages/google-drive and packages/document-conversion-engine. docker.yml smoke-builds its migrate target from that incomplete workspace, and the check will report success the next time a package is added there too.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e792785. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant