Skip to content

Instantly share code, notes, and snippets.

@aparajita
Last active June 1, 2021 05:40
Show Gist options
  • Save aparajita/3194e0ce1a01b6fe7d74c33c9578927e to your computer and use it in GitHub Desktop.
Save aparajita/3194e0ce1a01b6fe7d74c33c9578927e to your computer and use it in GitHub Desktop.
Script to notarize a 4D plugin
#!/usr/bin/env bash
#
# $1 - Source plugin path, must be on a local filesystem
#
# DEPENDENCIES
#
# This script relies on jq, a JSON parser. You can download
# it at https://stedolan.github.io/jq, or install via package
# managers such as brew or apt.
#
#
# HOW TO USE
#
# To use this script, you need to set three environment variables.
# The easiest way to do this is to export them from .bashrc or .zshrc,
# depending on which shell you use. Add these three lines to your
# shell's rc file (without the leading #):
#
# export AC_USER=
# export AC_PASSWORD=
# export AC_PROVIDER=
#
# Now you will set the values after "=".
#
# AC_USER
# Your App Store Connect username, usually your Apple ID email address.
#
# AC_PASSWORD
# The password to your App Store Connect account. Note that you must create
# an app-specific password to use with this script:
#
# - Log in to appleid.apple.com
# - Click "Generate Password..." under "APP-SPECIFIC PASSWORDS" in the
# - Enter "codesign"
# - Copy the generated password
# - Open a terminal and execute this (<user> is the value you use
# for AC_USER, <password> is the copied password):
#
# xcrun altool --store-password-in-keychain-item codesign \
# -u "<user>" -p "<password>"
#
# Once you have done all this, set the value of AC_PASSWORD to
# @keychain:codesign. Then reload your shell so AC_USER and AC_PASSWORD are
# available globally.
#
# AC_PROVIDER
# If you are not part of multiple teams in App Store Connect, ignore this.
#
# If you are part of multiple teams in App Store Connect, you must tell
# Apple under which team (provider) you are signing a plugin. To get the correct
# value to use, open a terminal and execute:
#
# xcrun altool --list-providers -u "$AC_USER" -p "$AC_PASSWORD"
#
# You will get a list of the teams (providers) you belong to. Copy the value
# in the ProviderShortName (NOT ProviderName) column for the team you want to
# sign your plugin under. Then set the value of AC_PROVIDER to the value you
# just copied and reload your shell.
#
# Setup
#
RED='\033[00;31m'
GREEN='\033[00;32m'
END='\033[0m'
notify() {
echo -e "${GREEN}${1}${END}"
}
fail() {
echo -e "${RED}${1}${END}"
exit 1
}
pluginPath="$1"
# If pluginPath is a symbolic link, resolve it
if [ -L "$pluginPath" ]; then
pluginPath=$(readlink "$pluginPath")
notify "* Resolved path to:"
echo -e "$pluginPath\n"
fi
bundleName=$(basename "$pluginPath")
pluginName=${bundleName%.bundle}
#
# Sign the plugin bundle
#
identity=$(security find-identity -p codesigning -v | egrep 'Developer ID Application[^"]+' -o)
notify "* Signing $bundleName...\n"
xattr -cr "$pluginPath"
codesign --verbose --deep --timestamp --force --sign "$identity" "$pluginPath"
notify "\n* Checking signature...\n"
if ! codesign --verify --verbose=2 --deep --strict "$pluginPath"; then
exit $?
fi
if ! check-signature "$pluginPath"; then
exit $?
fi
#
# Make a zip for submission
#
tempDir=$(mktemp -d "/tmp/$pluginName.XXXX" || fail "Could not create temp dir for zip")
zipPath="$tempDir/$pluginName.zip"
notify "\n* Creating zip..."
ditto -c -k --keepParent "$pluginPath" "$zipPath" || rm -rf "$tempDir"
notify "* zip created at $zipPath"
#
# Submit the zip
#
notify "* Submitting zip...\n"
dateTime=$(date "+%Y%m%d%H%M%S")
bundleId=$(plutil -convert json -r -o - -- "$pluginPath"/Contents/Info.plist | grep CFBundleIdentifier | awk -F ' : ' '{ print $2 }' | tr -d '",')
if [[ -n "$AC_PROVIDER" ]]; then
provider="--asc-provider $AC_PROVIDER"
else
provider=""
fi
notarizeResponse=$(xcrun altool --notarize-app \
--file "$zipPath" \
--primary-bundle-id "$bundleId.$dateTime" \
--username "$AC_USER" \
--password "$AC_PASSWORD" \
--output-format json \
$provider)
uuid=$(echo "$notarizeResponse" | jq -M '."notarization-upload".RequestUUID' | tr -d '"')
echo "uuid = $uuid"
rm -rf "$tempDir"
notify "\n* Deleted zip"
notify "\n* Waiting for result of notarization..."
statusResponse=""
until [[ "$statusResponse" == "success" ]]; do
sleep 30
statusResponse=$(xcrun altool --notarization-info "$uuid" \
--username "$AC_USER" \
--password "$AC_PASSWORD" \
--asc-provider "$AC_PROVIDER" \
--output-format json \
| jq -M '."notarization-info".Status' \
| tr -d '"')
echo "$(date "+%H:%M:%S") $statusResponse"
done
notify "\n* Plugin notarized, stapling...\n"
xcrun stapler staple "$pluginPath"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment