mirror of
https://github.com/fergalmoran/picard.git
synced 2026-01-09 01:54:00 +00:00
A libwebp vulnerarbility allows arbitrary code execution when loading a manipulated image. Disable the Qt webp imageformat plugin for binary builds for macOS and Windows for now. WebP images still can be loaded and saved, but they will not be displayed.
155 lines
5.9 KiB
Bash
Executable File
155 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
if [ -z "$TRAVIS_TAG" ] && [ -n "$TRAVIS_OSX_IMAGE" ]; then
|
|
python3 setup.py patch_version --platform="osx.$TRAVIS_OSX_IMAGE"
|
|
fi
|
|
VERSION=$(python3 -c 'import picard; print(picard.__version__)')
|
|
|
|
MACOS_VERSION=$(sw_vers -productVersion)
|
|
MACOS_VERSION_MAJOR=${MACOS_VERSION%.*}
|
|
MACOS_VERSION_MAJOR=${MACOS_VERSION_MAJOR%.*}
|
|
MACOS_VERSION_MINOR=${MACOS_VERSION#*.}
|
|
MACOS_VERSION_MINOR=${MACOS_VERSION_MINOR%.*}
|
|
|
|
echo "Building Picard..."
|
|
rm -rf dist build locale
|
|
python3 setup.py clean
|
|
python3 setup.py build
|
|
python3 setup.py build_ext -i
|
|
pyinstaller --noconfirm --clean picard.spec
|
|
|
|
CODESIGN=0
|
|
NOTARIZE=0
|
|
KEYCHAIN_PATH=picard.keychain
|
|
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
|
|
CERTIFICATE_NAME="MetaBrainz Foundation Inc."
|
|
CERTIFICATE_FILE=scripts/package/appledev.p12
|
|
|
|
if [ -f "$CERTIFICATE_FILE" ] && [ -n "$CODESIGN_MACOS_P12_PASSWORD" ]; then
|
|
echo "Preparing code signing certificate..."
|
|
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
security set-keychain-settings "$KEYCHAIN_PATH" # Ensure keychain stays unlocked
|
|
security list-keychains -d user -s "$KEYCHAIN_PATH"
|
|
security default-keychain -s "$KEYCHAIN_PATH"
|
|
security import "$CERTIFICATE_FILE" -k "$KEYCHAIN_PATH" -P "$CODESIGN_MACOS_P12_PASSWORD" -T /usr/bin/codesign
|
|
# The line below is necessary when building on Sierra.
|
|
# See https://stackoverflow.com/q/39868578
|
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
|
security find-identity -p codesigning # For debugging
|
|
CODESIGN=1
|
|
fi
|
|
|
|
# Submit app for notarization on macOS >= 10.14
|
|
if { [ "$MACOS_VERSION_MAJOR" -eq 10 ] && [ "$MACOS_VERSION_MINOR" -ge 14 ]; } || [ "$MACOS_VERSION_MAJOR" -ge 11 ]; then
|
|
NOTARIZE=1
|
|
fi
|
|
|
|
cd dist
|
|
|
|
echo "Create and sign app bundle..."
|
|
APP_BUNDLE="MusicBrainz Picard.app"
|
|
ditto -rsrc --arch x86_64 "$APP_BUNDLE" "$APP_BUNDLE.tmp"
|
|
rm -r "$APP_BUNDLE"
|
|
mv "$APP_BUNDLE.tmp" "$APP_BUNDLE"
|
|
|
|
# Fix placing text files in Resources instead of Contents to avoid signatures ending up in extended attributes.
|
|
# This fixes the signature breaking if extended attributes get removed or modified.
|
|
# Fixes https://tickets.metabrainz.org/browse/PICARD-1943 and related issues.
|
|
echo "Fixing location of Qt5 translation resources for code signing..."
|
|
if [[ -d "$APP_BUNDLE/Contents/MacOS/PyQt5/Qt5/" ]]; then
|
|
QT5_DIR=Qt5
|
|
else # For older PyQt5 installs
|
|
QT5_DIR=Qt
|
|
fi
|
|
mkdir "$APP_BUNDLE/Contents/Resources/$QT5_DIR/"
|
|
mv "$APP_BUNDLE/Contents/MacOS/PyQt5/$QT5_DIR/translations" "$APP_BUNDLE/Contents/Resources/$QT5_DIR/"
|
|
pushd "$APP_BUNDLE/Contents/MacOS/PyQt5/$QT5_DIR/"
|
|
ln -s "../../../Resources/$QT5_DIR/translations" .
|
|
popd
|
|
|
|
# Mitigate libwebp vulnerability allowing for arbitrary code execution (CVE-2023-4863).
|
|
# Disable the Qt webp imageformat plugin.
|
|
rm "$APP_BUNDLE/Contents/MacOS/PyQt5/$QT5_DIR/plugins/imageformats/libqwebp.dylib"
|
|
|
|
if [ "$CODESIGN" = '1' ]; then
|
|
# Enable hardened runtime if app will get notarized
|
|
if [ "$NOTARIZE" = "1" ]; then
|
|
codesign --verbose --deep --force \
|
|
--options runtime \
|
|
--entitlements ../scripts/package/entitlements.plist \
|
|
--keychain "$KEYCHAIN_PATH" --sign "$CERTIFICATE_NAME" \
|
|
"$APP_BUNDLE"
|
|
../scripts/package/macos-notarize-app.sh "$APP_BUNDLE"
|
|
codesign --verbose --deep --verbose --strict=all --check-notarization "$APP_BUNDLE"
|
|
else
|
|
codesign --verify --verbose --deep --force \
|
|
--keychain "$KEYCHAIN_PATH" --sign "$CERTIFICATE_NAME" \
|
|
"$APP_BUNDLE"
|
|
fi
|
|
fi
|
|
|
|
# Only test the app if it was codesigned, otherwise execution likely fails
|
|
if [ "$CODESIGN" = '1' ]; then
|
|
echo "Verify Picard executable works and required dependencies are bundled..."
|
|
VERSIONS=$("$APP_BUNDLE/Contents/MacOS/picard-run" --long-version --no-crash-dialog)
|
|
echo "$VERSIONS"
|
|
ASTRCMP_REGEX="astrcmp C"
|
|
[[ $VERSIONS =~ $ASTRCMP_REGEX ]] || (echo "Failed: Build does not include astrcmp C" && false)
|
|
LIBDISCID_REGEX="libdiscid [0-9]+\.[0-9]+\.[0-9]+"
|
|
[[ $VERSIONS =~ $LIBDISCID_REGEX ]] || (echo "Failed: Build does not include libdiscid" && false)
|
|
"$APP_BUNDLE/Contents/MacOS/fpcalc" -version
|
|
fi
|
|
|
|
echo "Package app bundle into DMG image..."
|
|
if [ -n "$MACOSX_DEPLOYMENT_TARGET" ]; then
|
|
DMG="MusicBrainz-Picard-${VERSION}-macOS-${MACOSX_DEPLOYMENT_TARGET}.dmg"
|
|
else
|
|
DMG="MusicBrainz-Picard-${VERSION}.dmg"
|
|
fi
|
|
mkdir staging
|
|
mv "$APP_BUNDLE" staging/
|
|
# Offer a link to /Applications for easy installation
|
|
ln -s /Applications staging/Applications
|
|
|
|
set +e
|
|
# workaround hdiutil: create failed - Resource busy
|
|
ATTEMPTS=5
|
|
DELAY=5
|
|
for i in $(seq $ATTEMPTS); do
|
|
hdiutil create -verbose -volname "MusicBrainz Picard $VERSION" \
|
|
-srcfolder staging -ov -format UDBZ "$DMG"
|
|
ret=$?
|
|
[ "$ret" -eq 0 ] && break
|
|
echo "hdutil failed with exit code $ret ($i/$ATTEMPTS), retrying in $DELAY seconds"
|
|
sleep $DELAY
|
|
done
|
|
if [ "$ret" -ne 0 ]; then
|
|
echo "hdiutil failed too many times, exiting..."
|
|
exit "$ret"
|
|
fi
|
|
set -e
|
|
|
|
[ "$CODESIGN" = '1' ] && codesign --verify --verbose \
|
|
--keychain "$KEYCHAIN_PATH" --sign "$CERTIFICATE_NAME" "$DMG"
|
|
md5 -r "$DMG"
|
|
|
|
if [ -n "$UPLOAD_OSX" ]; then
|
|
echo "Preparing to upload $DMG..."
|
|
# make upload failures non fatal
|
|
set +e
|
|
# Set $AWS_ARTIFACTS_BUCKET, $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY for AWS S3 upload to work
|
|
if [ -n "$AWS_ARTIFACTS_BUCKET" ] && [ -n "$AWS_ACCESS_KEY_ID" ]; then
|
|
pip3 install --upgrade awscli
|
|
aws s3 cp --acl public-read "$DMG" "s3://${AWS_ARTIFACTS_BUCKET}/${TRAVIS_REPO_SLUG}/${TRAVIS_BUILD_NUMBER}/$DMG"
|
|
echo "Package uploaded to https://s3.${AWS_DEFAULT_REGION}.amazonaws.com/${AWS_ARTIFACTS_BUCKET}/${TRAVIS_REPO_SLUG}/${TRAVIS_BUILD_NUMBER}/${DMG// /%20}"
|
|
else
|
|
# Fall back to transfer.sh
|
|
curl -v --retry 6 --retry-delay 10 --max-time 180 --upload-file "$DMG" https://transfer.sh/
|
|
fi
|
|
set -e
|
|
# Required for a newline between the outputs
|
|
echo -e "\n"
|
|
fi
|