Skip to content

Instantly share code, notes, and snippets.

@masonicGIT
Last active September 21, 2016 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masonicGIT/a613b12aa4ddeb7c3907a9802963d4e9 to your computer and use it in GitHub Desktop.
Save masonicGIT/a613b12aa4ddeb7c3907a9802963d4e9 to your computer and use it in GitHub Desktop.
## Electron build & sign utility script
#
# Requirements:
# - ITMS transporter
# - Application Loader
#
#
# 1. Set all necessary variables below (APP, APP_KEY, INSTALLER_KEY, BUNDLE_ID)
# 2. Run the electron packager on your node application folder.
#
# APP_KEY - "3rd Party Mac Developer Application: Adam Smith (2U14V9M123)"
# INSTALLER_KEY - "3rd Party Mac Developer Installer: Adam Smith (2U11V1M123)"
# BUNDLE_ID - This must be the App ID from your apple developer portal
# APP_NAME - The name of your application
APP_KEY=""
INSTALLER_KEY=""
BUNDLE_ID="org.voluntary.bitmarkets"
APP_NAME="Bitmarkets.app"
#
# 3. Run the script with the following:
#
# bash build.sh <path to application> <app-version> <electron version>
#
##
## Set the necessary command-line arguments
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]
then
echo "Please set your apple developer path to your .app folder, your app version, and your preferred electron version"
echo "bash build.sh <path-to-.app> <app build version> <electron version>"
exit 1
fi
APP=${APP_NAME%.*}
PRODUCTION_FOLDER="Production"
PROD_APP="$PRODUCTION_FOLDER/$APP_NAME"
RESULT_PATH="$PRODUCTION_FOLDER/$APP.pkg"
PROD_APP_FOLDER="$PRODUCTION_FOLDER/$APP_NAME/Contents/Resources/app"
FRAMEWORKS_PATH="$PROD_APP/Contents/Frameworks"
ALTOOL="/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
if [ -d "Bitmarkets-mas-x64" ] ; then
echo "Removing existing mas directory"
rm -rf Bitmarkets-mas-x64
fi
electron-packager $1 --name="bitmarkets" --platform=mas --arch=x64 --version $3 --overwrite --app-bundle-id=$BUNDLE_ID --build-version=$2
# --------------------------------------------------------------------
# Create a Production folder and copy the electron app folder into it.
# --------------------------------------------------------------------
eval rm -rf $PRODUCTION_FOLDER
mkdir $PRODUCTION_FOLDER
echo "► Removed old Production folder"
mv Bitmarkets-mas-x64/Bitmarkets.app $PRODUCTION_FOLDER/
rm -rf Bitmarkets-mas-x64
echo "► Copied app to Production"
# --------------------------------------------------------------------
# Run the node script bundle.js to package up all the JS source
# files into one file (bundle.js).
# --------------------------------------------------------------------
node bundle_js.js "$PROD_APP_FOLDER/source" "$PROD_APP_FOLDER/bundle.js"
echo "► Bundled javascript"
# --------------------------------------------------------------------
# Run bundle_css.js which does the same for the css files (into bundle.css).
# --------------------------------------------------------------------
node bundle_css.js "$PROD_APP_FOLDER/source" "$PROD_APP_FOLDER/bundle.css"
echo "► Bundled css"
# --------------------------------------------------------------------
# Run uglifyjs on bundle.js to produce bundle.min.js.
# --------------------------------------------------------------------
uglifyjs "$PROD_APP_FOLDER/bundle.js" --keep-fnames -c -o "$PROD_APP_FOLDER/bundle.min.js" 2> /dev/null
cp "$PROD_APP_FOLDER/bundle.js" "$PROD_APP_FOLDER/bundle.min.js"
echo "► Minified javascript"
# --------------------------------------------------------------------
# Removes unneeded files
# --------------------------------------------------------------------
rm "$PROD_APP_FOLDER/bundle.js"
rm -rf "$PROD_APP_FOLDER/source"
echo "► Removed unminified js"
rm "$PROD_APP_FOLDER/index.html"
mv "$PROD_APP_FOLDER/index_release.html" "$PROD_APP_FOLDER/index.html"
echo "► Switching to production index.html"
# ----------------------------------
find "$PROD_APP" -name "*.o" -type f -delete
echo "► Removed any .o files"
# ----------------------------------
rm $PROD_APP_FOLDER/node_modules/*/*.markdown
rm $PROD_APP_FOLDER/node_modules/*/*.md
rm $PROD_APP_FOLDER/node_modules/*/LICENSE.txt
rm $PROD_APP_FOLDER/node_modules/*/license
rm $PROD_APP_FOLDER/node_modules/*/test.js
rm $PROD_APP_FOLDER/node_modules/*/Makefile
rm -Rf $PROD_APP_FOLDER/node_modules/*/examples
rm -Rf $PROD_APP_FOLDER/node_modules/*/example
rm -Rf $PROD_APP_FOLDER/node_modules/*/test
echo "► Removed unneeded node_module stuff"
find $PROD_APP_FOLDER/node_modules/* -name 'bin' -exec rm -rf {} \; 2> /dev/null
rm -rf $PROD_APP_FOLDER/node_modules/.bin
find $PROD_APP_FOLDER/node_modules/* -name '.bin' -exec rm -rf {} \; 2> /dev/null
echo "► Remove all bin folders ( per codesign requirements )"
rm -Rf "$PROD_APP/Contents/Resources/app/node_modules/electron-prebuilt/dist/Electron.app"
echo "► Removed node_modules/electron-prebuilt/dist/Electron.app"
# --------------------------------------------------------------------
# Remove some unneeded frameworks.
# advice from http://www.saschawise.com/blog/2015/08/12/electron-for-the-mac-app-store.html
# --------------------------------------------------------------------
rm -rf "$PROD_APP/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/crashpad_handler"
rm -rf "$PROD_APP/Contents/Frameworks/Electron Framework.framework/Libraries/ffmpegsumo.so"
rm -rf "$PROD_APP/Contents/Frameworks/Squirrel.framework/Versions/A/Resources/ShipIt"
# ----------------------------------------------------
# Locate the frameworks, apps, and dynamic libraries
# ----------------------------------------------------
FRAMEWORKS=""
FRAMEWORKS_DIR="${FRAMEWORKS_PATH}"
if [ -d "$FRAMEWORKS_DIR" ] ; then
FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.app" -or -name "*.dylib" | sed -e "s/\(.*framework^dylib\)/\1\/Versions\/A\//" | sed 's#/*$##')
RESULT=$?
if [[ $RESULT != 0 ]] ; then
echo "► Encountered an error while scanning for frameworks"
exit 1
fi
FRAMEWORKS="${FRAMEWORKS}"
fi
echo "► Scanned for frameworks apps and dynamic libs"
# ---------------------------------------------------------
# Locate the nested .node files in the node_modules folder
# ---------------------------------------------------------
if [ -d "$PROD_APP_FOLDER" ] ; then
NODEITEMS=$(find "$PROD_APP_FOLDER/node_modules" -name "*.node")
RESULT=$?
if [[ $RESULT != 0 ]] ; then
echo "► Encountered an error while scanning for .node files"
exit 1
fi
FRAMEWORKS="${FRAMEWORKS}"$'\n'"${NODEITEMS}"
fi
echo "► Locating nested .node modules"
# --------------------------------------------------------------
# Handle the case where there are spaces in the framework name
# --------------------------------------------------------------
SAVED_IFS=$IFS
IFS=$(echo -en "\n\b")
echo "► Set internal field separator"
ROOT_DIR=$PWD
for FRAMEWORK in $FRAMEWORKS;
do
eval cd "${FRAMEWORKS_PATH}"
if [[ $FRAMEWORK == *"framework" ]] ; then
# Strip out the period and everything after it
PACKAGE=${FRAMEWORK%.*}
# Strip out everythinge before the framework name
PACKAGE=${PACKAGE#*/*/*/*/}
# Insert escape characters before the whitespace
PACKAGERAW=$PACKAGE
PACKAGE=${PACKAGE// /\\ }
PACKAGE_FOLDER="${PACKAGE}.framework"
# Insert escape characters before the whitespaces for the framework paths
FRAMEWORK=${FRAMEWORK// /\\ }
# Set the Versions/A symlink
eval cd "${PACKAGE_FOLDER}"
eval rm -rf "Versions/Current"
eval cd "Versions"; ln -s A Current
cd ..;
eval rm "${PACKAGE}"
ln -s Versions/Current/"${PACKAGERAW}" "${PACKAGERAW}"
eval rm -rf Resources
ln -s Versions/Current/Resources Resources
if [ -d "${FRAMEWORK}/Libraries" ]; then
eval rm -rf Libraries
ln -s Versions/Current/Libraries Libraries
fi
cd ..;
fi
cd $ROOT_DIR
done
echo "► Set all symlinks"
# --------------------------------------------------------------------
# Try to fix the bundle ids of the linked frameworks to keep Apple code signing happy.
# --------------------------------------------------------------------
sed -i "" -e "s|com\.github\.electron\.framework|$BUNDLE_ID|g" $PROD_APP/Contents/Frameworks/Electron\ Framework.framework/Resources/Info.plist
sed -i "" -e "s|org\.voluntary\.bitmarkets\.helper\.EH|$BUNDLE_ID|g" $PROD_APP/Contents/Frameworks/Bitmarkets\ Helper\ EH.app/Contents/Info.plist
sed -i "" -e "s|org\.voluntary\.bitmarkets\.helper\.NP|$BUNDLE_ID|g" $PROD_APP/Contents/Frameworks/Bitmarkets\ Helper\ NP.app/Contents/Info.plist
sed -i "" -e "s|org\.voluntary\.bitmarkets\.helper|$BUNDLE_ID|g" $PROD_APP/Contents/Frameworks/Bitmarkets\ Helper.app/Contents/Info.plist
echo "► Fixed all bundle ids"
# -----------------------------------------------------------------------------
# Sign all the items in the ITEMS array - Frameworks, dynamic libraries, .node
# -----------------------------------------------------------------------------
for FRAMEWORK in $FRAMEWORKS;
do
if [[ $FRAMEWORK == *"Helper"* ]]
then
PACKAGE=${FRAMEWORK%.*}
PACKAGE=${PACKAGE#*/*/*/*/}
PACKAGERAW=$PACKAGE
codesign --force --deep --verify --verbose --entitlements 'child.plist' --sign "$APP_KEY" "$FRAMEWORK/Contents/MacOS/$PACKAGERAW"
fi
codesign --force --deep --verify --verbose --entitlements 'child.plist' --sign "$APP_KEY" "$FRAMEWORK"
RESULT=$?
if [[ $RESULT != 0 ]] ; then
echo "► Failed to sign '${FRAMEWORK}'"
IFS=$SAVED_IFS
exit 1
fi
done
echo "► All frameworks and apps successfully signed"
codesign --force --verify --deep --verbose=4 --entitlements 'child.plist' --sign "$APP_KEY" "$PROD_APP/Contents/MacOS/Bitmarkets"
RESULT=$?
if [[ $RESULT != 0 ]] ; then
echo "► Failed to sign Electron executable"
IFS=$SAVED_IFS
exit 1
fi
echo "► Signed the electron executable"
codesign --verbose=4 --force --verify -fs "$APP_KEY" -i ${BUNDLE_ID} --entitlements 'parent.plist' "$PROD_APP"
echo "► Signed application"
codesign --deep-verify -vv --strict "$PROD_APP"
codesign -dvvv "$PROD_APP"
RESULT=$?
if [[ $RESULT != 0 ]] ; then
echo "► Failed to sign '${PROD_APP}'"
exit 1
fi
echo "► Verified app with codesign"
chmod -R 777 "$PROD_APP"
echo "► Reset app permissions"
productbuild --component "$PROD_APP" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
echo "► Built signed .pkg"
echo "► ✅ ✅ ✅ ✅ ---------- Build completed and signed ------------- ✅ ✅ ✅ ✅ "
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment