diff --git a/src/plugin/__tests__/__snapshots__/withIosSourcemaps.test.ts.snap b/src/plugin/__tests__/__snapshots__/withIosSourcemaps.test.ts.snap index 10660e4..6aa2c72 100644 --- a/src/plugin/__tests__/__snapshots__/withIosSourcemaps.test.ts.snap +++ b/src/plugin/__tests__/__snapshots__/withIosSourcemaps.test.ts.snap @@ -1,49 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`withIosSourcemaps on pristine project adds script to upload sourcemaps to Datadog 1`] = ` -""if [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\nexport SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map\\n +exports[`withIosSourcemaps on pristine project adds script to upload sourcemaps to Datadog 1`] = `""if [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\nexport SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map\\n \\n\\nif [[ -z \\"$DATADOG_CI_EXEC\\" ]]; then\\n DATADOG_CI_EXEC=\\"$(\\"$NODE_BINARY\\" --print \\"require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')\\")\\";\\n \\n # Check if the file exists and is executable\\n if [[ -x \\"$DATADOG_CI_EXEC\\" ]]; then\\n export DATADOG_CI_EXEC;\\n else\\n echo \\"Error: DATADOG_CI_EXEC does not exist or is not executable\\";\\n exit 1;\\n fi\\nfi\\n\\n\\n$DATADOG_CI_EXEC react-native xcode \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n\\n\\n""`; -if [[ -z "$DATADOG_CI_EXEC" ]]; then - export DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")" -fi +exports[`withIosSourcemaps on pristine project adds script to upload sourcemaps to Datadog with custom service name 1`] = `""if [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\nexport SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map\\n \\n\\nif [[ -z \\"$DATADOG_CI_EXEC\\" ]]; then\\n DATADOG_CI_EXEC=\\"$(\\"$NODE_BINARY\\" --print \\"require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')\\")\\";\\n \\n # Check if the file exists and is executable\\n if [[ -x \\"$DATADOG_CI_EXEC\\" ]]; then\\n export DATADOG_CI_EXEC;\\n else\\n echo \\"Error: DATADOG_CI_EXEC does not exist or is not executable\\";\\n exit 1;\\n fi\\nfi\\n\\n\\n$DATADOG_CI_EXEC react-native xcode \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n --service com.company.app\\n\\n""`; +exports[`withIosSourcemaps on projects implementing Sentry adds script to upload sourcemaps to Datadog 1`] = `""export SENTRY_PROPERTIES=sentry.properties\\nexport EXTRA_PACKAGER_ARGS=\\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\\"\\nif [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\n\`node --print \\"require.resolve('@sentry/cli/package.json').slice(0, -13) + '/bin/sentry-cli'\\"\` react-native xcode --force-foreground \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n\\n\\n \\n\\nif [[ -z \\"$DATADOG_CI_EXEC\\" ]]; then\\n DATADOG_CI_EXEC=\\"$(\\"$NODE_BINARY\\" --print \\"require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')\\")\\";\\n \\n # Check if the file exists and is executable\\n if [[ -x \\"$DATADOG_CI_EXEC\\" ]]; then\\n export DATADOG_CI_EXEC;\\n else\\n echo \\"Error: DATADOG_CI_EXEC does not exist or is not executable\\";\\n exit 1;\\n fi\\nfi\\n\\n\\n$DATADOG_CI_EXEC react-native xcode \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n""`; -$DATADOG_CI_EXEC react-native xcode \`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"\` -\\n\\n"" -`; - -exports[`withIosSourcemaps on pristine project adds script to upload sourcemaps to Datadog with custom service name 1`] = ` -""if [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\nexport SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map\\n - -if [[ -z "$DATADOG_CI_EXEC" ]]; then - export DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")" -fi - - -$DATADOG_CI_EXEC react-native xcode \`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"\` - --service com.company.app\\n\\n"" -`; - -exports[`withIosSourcemaps on projects implementing Sentry adds script to upload sourcemaps to Datadog 1`] = ` -""export SENTRY_PROPERTIES=sentry.properties\\nexport EXTRA_PACKAGER_ARGS=\\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\\"\\nif [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\n\`node --print \\"require.resolve('@sentry/cli/package.json').slice(0, -13) + '/bin/sentry-cli'\\"\` react-native xcode --force-foreground \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n\\n\\n - -if [[ -z "$DATADOG_CI_EXEC" ]]; then - export DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")" -fi - - -$DATADOG_CI_EXEC react-native xcode \`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"\` -"" -`; - -exports[`withIosSourcemaps on projects implementing Sentry adds script to upload sourcemaps to Datadog with custom service name 1`] = ` -""export SENTRY_PROPERTIES=sentry.properties\\nexport EXTRA_PACKAGER_ARGS=\\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\\"\\nif [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\n\`node --print \\"require.resolve('@sentry/cli/package.json').slice(0, -13) + '/bin/sentry-cli'\\"\` react-native xcode --force-foreground \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n\\n\\n - -if [[ -z "$DATADOG_CI_EXEC" ]]; then - export DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")" -fi - - -$DATADOG_CI_EXEC react-native xcode \`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"\` - --service com.company.app"" -`; +exports[`withIosSourcemaps on projects implementing Sentry adds script to upload sourcemaps to Datadog with custom service name 1`] = `""export SENTRY_PROPERTIES=sentry.properties\\nexport EXTRA_PACKAGER_ARGS=\\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\\"\\nif [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\n source \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\n\\n# The project root by default is one level up from the ios directory\\nexport PROJECT_ROOT=\\"$PROJECT_DIR\\"/..\\n\\nif [[ \\"$CONFIGURATION\\" = *Debug* ]]; then\\n export SKIP_BUNDLING=1\\nfi\\n\`node --print \\"require.resolve('@sentry/cli/package.json').slice(0, -13) + '/bin/sentry-cli'\\"\` react-native xcode --force-foreground \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n\\n\\n \\n\\nif [[ -z \\"$DATADOG_CI_EXEC\\" ]]; then\\n DATADOG_CI_EXEC=\\"$(\\"$NODE_BINARY\\" --print \\"require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')\\")\\";\\n \\n # Check if the file exists and is executable\\n if [[ -x \\"$DATADOG_CI_EXEC\\" ]]; then\\n export DATADOG_CI_EXEC;\\n else\\n echo \\"Error: DATADOG_CI_EXEC does not exist or is not executable\\";\\n exit 1;\\n fi\\nfi\\n\\n\\n$DATADOG_CI_EXEC react-native xcode \`\\"$NODE_BINARY\\" --print \\"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\\"\`\\n --service com.company.app""`; diff --git a/src/plugin/common/exports.ts b/src/plugin/common/exports.ts index 13a2b83..df55478 100644 --- a/src/plugin/common/exports.ts +++ b/src/plugin/common/exports.ts @@ -1,7 +1,16 @@ export const IOS_SOURCEMAP_FILE_EXPORT = "export SOURCEMAP_FILE=$DERIVED_FILE_DIR/main.jsbundle.map"; + export const IOS_DATADOG_CI_EXPORT = ` if [[ -z "$DATADOG_CI_EXEC" ]]; then - export DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")" + DATADOG_CI_EXEC="$("$NODE_BINARY" --print "require('path').resolve(require('path').dirname(require.resolve('@datadog/datadog-ci/package.json')), '../../.bin/datadog-ci')")"; + + # Check if the file exists and is executable + if [[ -x "$DATADOG_CI_EXEC" ]]; then + export DATADOG_CI_EXEC; + else + echo "Error: DATADOG_CI_EXEC does not exist or is not executable"; + exit 1; + fi fi `; diff --git a/src/plugin/common/utils.ts b/src/plugin/common/utils.ts new file mode 100644 index 0000000..7bf8748 --- /dev/null +++ b/src/plugin/common/utils.ts @@ -0,0 +1,10 @@ +export const escapeStringForIOSBuildPhase = (str: string) => { + return ( + str + .replace(/\\/g, "\\\\") // Escape backslashes + .replace(/"/g, '\\"') // Escape double quotes + // .replace(/\$/g, '\\$') // Escape dollar signs + .replace(/\n/g, "\\n") + ); // Replace newlines with \n + // .replace(/`/g, '\\`'); // Escape backticks +}; diff --git a/src/plugin/withIosDsyms/withIosDsyms.ts b/src/plugin/withIosDsyms/withIosDsyms.ts index 122bda5..a6cdd7a 100644 --- a/src/plugin/withIosDsyms/withIosDsyms.ts +++ b/src/plugin/withIosDsyms/withIosDsyms.ts @@ -29,20 +29,19 @@ const withIosDsyms: ConfigPlugin = (config) => { { shellScript: `set -e - if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then - source "$PODS_ROOT/../.xcode.env" - fi - if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then - source "$PODS_ROOT/../.xcode.env.local" - fi - - if [[ -z "$NODE_BINARY" ]]; then - echo "ERROR: NODE_BINARY env variable is not set" - fi - - ${IOS_DATADOG_CI_EXPORT} - - $DATADOG_CI_EXEC dsyms upload $DWARF_DSYM_FOLDER_PATH +if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then + source "$PODS_ROOT/../.xcode.env" +fi + +if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then + source "$PODS_ROOT/../.xcode.env.local" +fi + +if [[ -z "$NODE_BINARY" ]]; then + echo "ERROR: NODE_BINARY env variable is not set" +fi +${IOS_DATADOG_CI_EXPORT} +$DATADOG_CI_EXEC dsyms upload $DWARF_DSYM_FOLDER_PATH `, shellPath: "/bin/sh", } diff --git a/src/plugin/withIosSourcemaps/withIosSourcemaps.ts b/src/plugin/withIosSourcemaps/withIosSourcemaps.ts index 632f420..f40d783 100644 --- a/src/plugin/withIosSourcemaps/withIosSourcemaps.ts +++ b/src/plugin/withIosSourcemaps/withIosSourcemaps.ts @@ -11,13 +11,14 @@ import { IOS_DATADOG_CI_EXPORT, IOS_SOURCEMAP_FILE_EXPORT, } from "../common/exports"; +import { escapeStringForIOSBuildPhase } from "../common/utils"; import { SourceMapUploadOptions } from "../getErrorTrackingPluginsFromOptions"; -const DATADOG_XCODE_COMMAND = ` +const DATADOG_XCODE_COMMAND = escapeStringForIOSBuildPhase(` ${IOS_DATADOG_CI_EXPORT} $DATADOG_CI_EXEC react-native xcode \`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"\` -`; +`); const getDatadogXCodeCommand = ( serviceName: SourceMapUploadOptions["serviceName"] ) =>