Sentry – iOS build Error script automation with ionic commands

Recently, I have been using Sentry framework to automatic reporting of errors, messages, and exceptions, and identifies performance issues for ionic apps( both iOS and Android).

It works great with debug builds and i see both native and javascript errors logging in the Sentry dashboard and it is ready for production release.

While submitting the builds to the store, I started receiving an error while submitting your build to App Store Connect.

xcode-build error sentry
Sentry xcode build error

Below shell script which helps to remove from unwanted architectures.
source: https://docs.sentry.io/platforms/javascript/guides/cordova/troubleshooting/


# SENTRY_FRAMEWORK_PATCH
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
    FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
    FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
    echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
    EXTRACTED_ARCHS=()

    for ARCH in $ARCHS
    do
        echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
        lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
        EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
    done

    echo "Merging extracted architectures: ${ARCHS}"
    lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
    rm "${EXTRACTED_ARCHS[@]}"
    echo "Replacing original executable with thinned version"
    rm "$FRAMEWORK_EXECUTABLE_PATH"
    mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done

To make this script work, it requires to add manually to the xcode build phases.

xcode – build phases

Incase, if you are using any CICD tools like CircleCI or bitrise for build automation like me,

Create a cordova hook to run the script whenever app tries to build the app and add script file (before_build.js) under scripts folder. It should remove unwanted architectures from the app build whenever you tries to submit builds to stores.

<hook src="scripts/build_before.js" type="before_build" />
const fs = require('fs');
const path = require('path');
const xcode = require('xcode');

const shellScript = `
APP_PATH="\${TARGET_BUILD_DIR}/\${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: \${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "\${EXTRACTED_ARCHS[@]}"
rm "\${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done
`;

module.exports = function (context) {
  console.log('triggered from build script files');
  const projectDir = path.resolve(context.opts.projectRoot, 'platforms/ios')
  const dirContent = fs.readdirSync(projectDir)
  const matchingProjectFiles = dirContent.filter(filePath => /.*\.xcodeproj/gi.test(filePath));
  const projectPath = path.join(projectDir, matchingProjectFiles[0], 'project.pbxproj');

  const project = xcode.project(projectPath)

  project.parse(error => {
    if (error) {
      console.error('Failed to parse project', error);
      process.exit(1);
    }
    const options = {
      shellPath: '/bin/sh',
      shellScript,
      inputPaths: ['"$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)"']
    };

    project.addBuildPhase( 
      [],
      'PBXShellScriptBuildPhase',
      'Remove Unused Architectures',
      project.getFirstTarget().uuid,
      options
    );
    fs.writeFileSync(projectPath, project.writeSync());
  })
};

Helpful links to create cordova hooks,

https://cordova.apache.org/docs/en/10.x/guide/appdev/hooks/

Nagendra

Mobile application developer with 9+ years of experience in both Native and Hybrid Mobile applications.

%d bloggers like this: