Skip to content

fix(simulator): prevent AppleDouble metadata in cached .app tarballs#28

Open
janodetzel wants to merge 1 commit into
callstackincubator:mainfrom
janodetzel:fix/strip-applefile-metadata-from-tar
Open

fix(simulator): prevent AppleDouble metadata in cached .app tarballs#28
janodetzel wants to merge 1 commit into
callstackincubator:mainfrom
janodetzel:fix/strip-applefile-metadata-from-tar

Conversation

@janodetzel
Copy link
Copy Markdown

Problem

The simulator-build step packages the built .app with macOS BSD tar:
https://github.com/callstackincubator/ios/blob/main/action.yml#L377-L385

On a macOS runner, BSD tar encodes every extended attribute on the input files as a sibling AppleDouble (._*) entry inside the tarball, unless COPYFILE_DISABLE=1 is set. xcodebuild leaves xattrs (com.apple.*) on practically every artifact it produces, so the cached tarball ends up full of ._* files.

When a consumer downloads the cached artifact and extracts it with an implementation that does not have BSD tar's built-in AppleDouble self-healing — e.g. node-tar (used by rock run:ios), bsdtar on Linux, GNU tar, or anything else — those ._* files materialize as real files on disk. simctl install then walks MyApp.app/PlugIns/* and treats every entry as an app extension.

For any app that has app extensions or widgets, this fails:

An error was encountered processing the command (domain=IXErrorDomain, code=2):
Simulator device failed to install the application.
File not found.
Underlying error (domain=IXErrorDomain, code=2):
     Failed to create app extension placeholder for
     …/MyApp.app/PlugIns/._WidgetExtensionExtension.appex
     Failed to create promise.

The bug is invisible inside this action's own end-to-end CI because macOS BSD tar's extract step silently reattaches ._* entries as xattrs instead of materializing them as files. It only surfaces when a non-BSD-tar consumer enters the picture.
Reproducer: any RN project with a widget/share/notification extension that uses this action to cache simulator builds, then consumes the cache via rock run:ios --destination simulator.

Fix

  1. Pass COPYFILE_DISABLE=1 to the tar -czvf in Find Build Artifact (simulator branch) so new caches don't contain ._* entries.
  2. Pass COPYFILE_DISABLE=1 to the tar -czf in Repack APP into tar.gz (re-sign flow) for the same reason.
    Equivalent alternatives would be tar --no-xattrs (BSD tar) or tar --no-mac-metadata (libarchive ≥ 3.7), but COPYFILE_DISABLE=1 is the most widely portable and matches Apple's own guidance.
    No extract-side changes are needed: existing poisoned tarballs in cache are handled correctly by macOS BSD tar's self-healing on the runner during the re-sign flow, and will age out of cache naturally once this fix lands.

Scope

  • Only action.yml. No behavior change for caches that were already clean.
  • IPA path (device destination) is untouched — .ipa is produced via xcodebuild -exportArchive, not tar, so this bug doesn't apply there.

Test plan

  • Built and cached a simulator .app containing a PlugIns/WidgetExtensionExtension.appex with this fix applied locally; the resulting tarball contains zero ._* entries (verified with tar -tzf | grep '\._').
  • Consumer extracted the artifact with node-tar (via rock run:ios --destination simulator), the app installed and launched successfully.
  • Without the fix, the same flow reproduces the IXErrorDomain code=2 failure quoted above.

macOS BSD tar embeds extended attributes (set by xcodebuild on built
artifacts) as AppleDouble "._*" entries inside the tarball unless
COPYFILE_DISABLE=1 is set. When consumers extract the cached tarball
without macOS BSD tar's AppleDouble self-healing (e.g. node-tar via
`rock run:ios`, or any non-Apple tar implementation), `._*` files
materialize on disk. `simctl install` then walks PlugIns/ and treats
`._WidgetExtension.appex` as a real app extension, failing with:

  IXErrorDomain code=2: Failed to create app extension placeholder

This affects every app with an app extension or widget that uses this
action's simulator cache.

- Set COPYFILE_DISABLE=1 on the simulator-build `tar -czvf` so newly
  produced cache artifacts are clean.
- Set COPYFILE_DISABLE=1 on the re-sign repack as well.
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