Skip to content

fix(mcp-build): normalize dist modes before cp -a (macOS gRPC-FUSE)#28

Merged
hunzlahmalik merged 1 commit into
sync/upstream-2.15.3from
fix/mcp-build-macos-grpcfuse-xattr
May 20, 2026
Merged

fix(mcp-build): normalize dist modes before cp -a (macOS gRPC-FUSE)#28
hunzlahmalik merged 1 commit into
sync/upstream-2.15.3from
fix/mcp-build-macos-grpcfuse-xattr

Conversation

@hunzlahmalik

Copy link
Copy Markdown

Summary

On macOS Docker Desktop, make dev.build.penpot.mcp produced a bundle whose files were owned mode 200 on the host — making the bundle unreadable to the subsequent rsync into the Docker build context, and to any container that later tried to consume them.

Root cause

Even with VirtioFS selected in Docker Desktop's UI, both UseGrpcfuse: true and UseVirtualizationFrameworkVirtioFS: true end up in the persisted settings JSON. gRPC-FUSE's ownership-tracking layer remains active and writes a com.docker.grpcfuse.ownership xattr on any file created via a metadata-preserving op (Node's fs.cpSync, cp -p, …). For the cpSync inside packages/server/scripts/copy-resources.js, the xattr lands with "mode": 200 even though the host inode is 644.

A subsequent cp -a (or rsync -avr -a) then reads the source mode via the xattr lens, sees 200, and chmods the destination to 200 — which through the VirtioFS layer becomes the real host mode 200. The bundle is now unreadable even by its owner.

Fix

chmod -R u=rwX,go=rX packages/server/dist after pnpm run build and before the cp -a. While the host mode is still 644, the chmod rewrites the xattr mode to 644 (and dir mode to 755), so the subsequent cp -a propagates the correct mode all the way through to the bundle.

Impact

  • macOS: bundle files end up host-mode 644 (dirs 755). Downstream rsync into the Docker build context succeeds.
  • Linux / CI: gRPC-FUSE is macOS-only; the xattr is never written. The chmod -R is a no-op (modes already match) and adds <1 s to the build.

Test plan

  • make dev.build.penpot.mcp on macOS (Docker Desktop, Apple Virtualization framework + VirtioFS selected, with UseGrpcfuse: true still present in settings) — bundle builds, image foss-devstack/penpot-mcp:dev produced.
  • CI build on Linux — verify the chmod -R adds no observable diff (mode bits already correct).

On macOS Docker Desktop, Node's fs.cpSync writes files in the bind
mount with a com.docker.grpcfuse.ownership xattr declaring mode 200
even when the host inode is 644. The subsequent `cp -a` (and the
original `rsync -avr`) then chmod the destination to 200, which lands
on the real host inode and renders the bundle unreadable to anything
outside the build container (Linux containers via gRPC-FUSE included).

chmod-ing packages/server/dist before the copy rewrites the xattr to
644 while the host mode is still 644, so cp -a propagates the correct
mode and the bundle is readable downstream.

Behaviour on Linux hosts is unchanged: gRPC-FUSE only runs on macOS
Docker Desktop; chmod -R is a no-op when modes are already correct.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hunzlahmalik hunzlahmalik changed the base branch from foss-main to sync/upstream-2.15.3 May 20, 2026 07:08
@hunzlahmalik hunzlahmalik merged commit 7d5d8f3 into sync/upstream-2.15.3 May 20, 2026
0 of 12 checks passed
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