mirror of
https://github.com/cryptoadvance/specter-desktop.git
synced 2026-08-13 12:33:29 +02:00
* fix release_helper lazy gl property * make osx build script work with pyenv --------- Co-authored-by: Manolis <moneymanolis@protonmail.com>
404 lines
15 KiB
Bash
Executable file
404 lines
15 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
# We start in the directory where this script is located
|
|
cd "$( dirname "${BASH_SOURCE[0]}" )/."
|
|
source build-common.sh
|
|
cd ..
|
|
# Now in project-root
|
|
|
|
# Overriding this function
|
|
function create_virtualenv_for_pyinstaller {
|
|
# This currently assumes to be run with: Python 3.10.11
|
|
# Important: pyinstaller needs a Python binary with shared library files
|
|
# With pyenv, for example, you get this like so: env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.10.4
|
|
# Use pyenv if set as environment variable
|
|
if [ $USE_PYENV_FOR_SPECTER_BUILD = true ]; then
|
|
echo "Trying to use pyenv ..."
|
|
if ! command -v pyenv >/dev/null 2>&1; then
|
|
echo "Error: pyenv is not available. Please make sure pyenv is installed and configured properly." >&2
|
|
exit 1
|
|
fi
|
|
### This is usually in .zshrc, putting it in .bashrc didn't work ###
|
|
export PYENV_ROOT="$HOME/.pyenv"
|
|
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
|
|
eval "$(pyenv init -)"
|
|
### this needs the pyenv-virtualenv plugin. If you don't have it:
|
|
### git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
|
|
eval "$(pyenv virtualenv-init -)"
|
|
### ------------------------------------------------------------ ###
|
|
PYTHON_VERSION=3.10.11
|
|
export PYENV_VERSION=$PYTHON_VERSION
|
|
echo "Setting PYENV_VERSION to 3.10.11, using pyenv-virtualenv to create the buildenv..."
|
|
echo " --> Deleting .buildenv"
|
|
pyenv uninstall -f .buildenv
|
|
rm -rf "$HOME/.pyenv/versions/$PYTHON_VERSION/envs/.buildenv"
|
|
pyenv virtualenv 3.10.11 .buildenv
|
|
pyenv activate .buildenv
|
|
else
|
|
echo "pyenv is not available. Using system Python version."
|
|
if [ -d .buildenv ]; then
|
|
echo " --> Deleting .buildenv"
|
|
rm -rf .buildenv
|
|
fi
|
|
virtualenv .buildenv
|
|
source .buildenv/bin/activate
|
|
fi
|
|
pip3 install -e ".[test]"
|
|
}
|
|
|
|
# Overriding this function to deal with the x86 special case
|
|
function make_hash_if_necessary {
|
|
cd pyinstaller/electron
|
|
echo " --> calculate the hash of the binary for download"
|
|
specterd_plt_filename=../dist/${specterd_filename}
|
|
# early exit
|
|
if [[ "$make_hash" != 'True' ]]; then
|
|
node ./set-version $version
|
|
return 0
|
|
fi
|
|
|
|
# We need to set-versions for two specterd, one arm and one intel.
|
|
# arm64 one
|
|
node ./set-version $version ${specterd_plt_filename}
|
|
# Download and check the intel one
|
|
# this needs some env-vars to be set
|
|
rm -rf signing_dir/*
|
|
PYTHONPATH=../.. python3 -m utils.release_helper downloadgithub
|
|
ret_code=$?
|
|
if [ $ret_code -ne 0 ]; then
|
|
echo "Downloading and verifying x64 specterd failed with exit code $ret_code"
|
|
exit $ret_code
|
|
fi
|
|
if [[ ! -f ./signing_dir/specterd-${version}-osx_x64.zip ]]; then
|
|
echo "Downloading and verifying x64 specterd failed as the file does not seem to be there"
|
|
exit 1
|
|
fi
|
|
rm -f /tmp/specterd
|
|
unzip ./signing_dir/specterd-${version}-osx_x64.zip -d /tmp
|
|
node ./set-version $version /tmp/specterd x64
|
|
echo " Hashes in version-data.json $(cat ./version-data.json | jq -r '.sha256')"
|
|
echo " Hash of file $(sha256sum ${specterd_plt_filename} )"
|
|
echo " Hash of x64 file $(sha256sum /tmp/specterd )"
|
|
cd ../..
|
|
}
|
|
|
|
function macos_code_sign {
|
|
# prerequisites for this:
|
|
# in short:
|
|
# * make sure you have a proper app-specific password on https://appleid.apple.com/account/manage
|
|
# * collect some information via scrun altool --list-providers -u "<yourAppleID>"
|
|
# * create profile via xcrun notarytool store-credentials --apple-id "<YourAppleID>" --password "app-specific-pw" --team-id "seeFromAbove"
|
|
# * Call the profile: SpecterProfile
|
|
# For details see:
|
|
# * https://www.youtube.com/watch?v=2xJcMzoi0EI
|
|
# * https://blog.dgunia.de/2022/09/01/switching-from-altool-to-notarytool/
|
|
# * https://scriptingosx.com/2021/07/notarize-a-command-line-tool-with-notarytool/
|
|
# This creates a ZIP archive from the app package (using the ditto command).
|
|
# This ZIP archive is then used to upload the app to the Apple notarization service via xcrun notarytool (formerly xcrun altool)
|
|
# After the app has been uploaded to the Apple servers and notarized, the ZIP archive is not used again.
|
|
# The function uses the xcrun stapler command to attach the notarization result to the app, and then exits.
|
|
|
|
# docs:
|
|
# https://help.apple.com/itc/apploader/#/apdATD1E53-D1E1A1303-D1E53A1126
|
|
# https://keith.github.io/xcode-man-pages/altool.1.html
|
|
cd pyinstaller/electron
|
|
echo ' --> Attempting to code sign...'
|
|
specterimg_filename_fqfn=dist/${dist_mac_folder_name}/${specterimg_filename}.app
|
|
echo " executing: ditto -c -k --keepParent "${specterimg_filename_fqfn}" dist/${specterimg_filename}.zip"
|
|
|
|
ditto -c -k --keepParent "${specterimg_filename_fqfn}" dist/${specterimg_filename}.zip
|
|
# upload
|
|
echo ' uploading for notarisation ... '
|
|
|
|
output_json=$(xcrun notarytool submit dist/${specterimg_filename}.zip --apple-id "kneunert@gmail.com" --keychain-profile "SpecterProfile" --output-format json --wait )
|
|
|
|
|
|
# parsing the requestuuid which we'll need to track progress
|
|
requestuuid=$(echo $output_json | jq -r '.id')
|
|
status=$(echo $output_json | jq -r '.status')
|
|
echo "Request ID: $requestuuid"
|
|
if [ "$status" = "Invalid" ]; then
|
|
mkdir -p signing_logs
|
|
echo "issues with notarisation"
|
|
xcrun notarytool log ${requestuuid} --keychain-profile SpecterProfile | tee ./signing_logs/${app_name}_${timestamp}_${requestuuid}.log
|
|
exit 1
|
|
fi
|
|
|
|
# The stapler somehow "staples" the result of the notarisation in to your app
|
|
# see e.g. https://stackoverflow.com/questions/58817903/how-to-download-notarized-files-from-apple
|
|
echo " --> Staple the file dist/${dist_mac_folder_name}/${specterimg_filename}.app"
|
|
xcrun stapler staple "dist/${dist_mac_folder_name}/${specterimg_filename}.app"
|
|
echo ' Successfully Stapled the file'
|
|
cd ../..
|
|
}
|
|
|
|
|
|
function sub_help {
|
|
cat << EOF
|
|
|
|
### Quick overview
|
|
: <<'END_COMMENT'
|
|
What do you need to sign the Specter app with Apple's notary service?
|
|
- An Apple Developer account
|
|
- You must create a signing certificate in your developer account, which will be used to sign your app.
|
|
- This certificate must be stored in your keychain on your Mac.
|
|
- When you create a signing certificate in your developer account, you will be asked to specify a password for the certificate.
|
|
- You can store this password in the keychain, too, so that it - and thus the certificate - can be accessed automatically during the signing process. Like so:
|
|
xcrun altool --store-password-in-keychain-item AC_PASSWORD -u '<your apple id>' -p apassword
|
|
- As seen above, you need the the xcrun command line tool: This tool is also used to upload your app to the notary service and check the status of the notarization process.
|
|
|
|
In summary, to sign a macOS app with Apple's notary service, you need an Apple Developer account, a signing certificate, a password for your keychain, the app package to be signed, and the xcrun command line tool.
|
|
END_COMMENT
|
|
|
|
### Prerequisites
|
|
# brew install gmp # to prevent module 'embit.util' has no attribute 'ctypes_secp256k1'
|
|
# brew install jq
|
|
# npm install --global create-dmg
|
|
|
|
### Trouble shooting
|
|
# If you have the common issue "errSecInternalComponent" while signing the code:
|
|
# https://medium.com/@ceyhunkeklik/how-to-fix-ios-application-code-signing-error-4818bd331327
|
|
|
|
# create-dmg issue? Note that there are 2 create-dmg scripts out there. We use:
|
|
# https://github.com/sindresorhus/create-dmg
|
|
|
|
The different "tasks" are now somehow separated from one another.
|
|
We have:
|
|
* make-hash is rather a flag for the electron-build to incorporate the hash of the specterd
|
|
* specterd will trigger the pyinstaller build of the specterd
|
|
* electron will build the electron-app
|
|
* sign will upload the electron-app to the Apple notary service and get it back notarized
|
|
* upload will upload all the binary artifacts to the github-release-page. This includes the creation of the hash-files
|
|
and the gnupg signing
|
|
|
|
### Trouble shooting (Legacy)
|
|
# Currently, only MacOS Catalina is supported to build the dmg-file
|
|
# Therefore we expect xcode 12.1 (according to google)
|
|
# After installation of xcode: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
|
# otherwise you get xcrun: error: unable to find utility "altool", not a developer tool or in PATH
|
|
# catalina might have a a too old version of bash. You need at least 4.0 or so
|
|
# 3.2 is too low definitely
|
|
# brew install bash
|
|
|
|
# Example-call:
|
|
./utils/build-osx.sh --debug --version v1.10.0-pre23 --appleid "Kim Neunert (FWV59JHV83)" --mail "kim@specter.solutions" make-hash specterd electron sign upload
|
|
EOF
|
|
}
|
|
|
|
appleid=""
|
|
|
|
while [[ $# -gt 0 ]]
|
|
do
|
|
arg="$1"
|
|
case $arg in
|
|
"" | "-h" | "--help")
|
|
sub_help
|
|
exit 0
|
|
shift
|
|
;;
|
|
--debug)
|
|
set -x
|
|
DEBUG=true
|
|
shift
|
|
;;
|
|
--version)
|
|
version=$2
|
|
shift
|
|
shift
|
|
;;
|
|
--appleid)
|
|
appleid=$2
|
|
shift
|
|
shift
|
|
;;
|
|
--mail)
|
|
mail=$2
|
|
shift
|
|
shift
|
|
;;
|
|
specterd)
|
|
build_specterd=True
|
|
shift
|
|
;;
|
|
make-hash)
|
|
make_hash=True
|
|
shift
|
|
;;
|
|
electron)
|
|
build_electron=True
|
|
shift
|
|
;;
|
|
sign)
|
|
build_sign=True
|
|
shift
|
|
;;
|
|
package)
|
|
build_package=True
|
|
shift
|
|
;;
|
|
upload)
|
|
upload=True
|
|
shift
|
|
;;
|
|
help)
|
|
sub_help
|
|
shift
|
|
;;
|
|
*)
|
|
shift
|
|
sub_${arg} $@ && ret=0 || ret=$?
|
|
if [ "$ret" = 127 ]; then
|
|
echo "Error: '$arg' is not a known subcommand." >&2
|
|
echo " Run '$progname --help' for a list of known subcommands." >&2
|
|
exit 1
|
|
else
|
|
exit $ret_value
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
echo " --> This build got triggered for version $version"
|
|
|
|
echo $version > pyinstaller/version.txt
|
|
|
|
configure
|
|
|
|
if [[ "$build_specterd" = "True" ]]; then
|
|
create_virtualenv_for_pyinstaller
|
|
build_pypi_pckgs_and_install
|
|
install_build_requirements
|
|
cleanup
|
|
building_app
|
|
fi
|
|
|
|
if [[ "$make_hash" = "True" ]]; then
|
|
# Making the hash only makes sense on a arm arch
|
|
if [[ "$ARCH" != "arm64" ]]; then
|
|
echo "ERROR: make-hash target should be only called on an arm64 machine on a mac"
|
|
exit 1
|
|
fi
|
|
make_hash_if_necessary
|
|
fi
|
|
|
|
if [[ "$build_electron" = "True" ]]; then
|
|
# Making the hash only makes sense on a arm arch
|
|
if [[ "$ARCH" != "arm64" ]]; then
|
|
echo "ERROR: electron target should be only called on an arm64 machine on a mac"
|
|
exit 1
|
|
fi
|
|
prepare_npm
|
|
npm i
|
|
if [[ "${appleid}" == '' ]]
|
|
then
|
|
echo "`jq '.build.mac.identity=null' package.json`" > package.json
|
|
else
|
|
echo "`jq '.build.mac.identity="'"${appleid}"'"' package.json`" > package.json
|
|
fi
|
|
building_electron_app
|
|
fi
|
|
|
|
if [[ "$build_sign" = "True" ]]; then
|
|
# if [ "$(uname -m)" = "arm64" ]; then
|
|
# dist_mac_folder_name=${dist_mac_folder_name}-arm64
|
|
# fi
|
|
if [[ "$appleid" != '' ]]; then
|
|
macos_code_sign
|
|
else
|
|
echo "WARNING: Forgot to add the appleid ?!"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [[ "$build_package" = "True" ]]; then
|
|
echo " --> Preparing the release"
|
|
mkdir -p release
|
|
rm -rf release/*
|
|
|
|
# The specterd-zipfile from specterd
|
|
if [[ -f pyinstaller/dist/${specterd_filename} ]]; then
|
|
echo " --> Making the release-zip for specterd"
|
|
pushd pyinstaller/dist # to not preserve folder structure
|
|
zip ../../release/${specterd_filename}-${version}-osx_${ARCH}.zip ${specterd_filename}
|
|
popd
|
|
fi
|
|
|
|
# The dmg image file from App
|
|
if [[ -d pyinstaller/electron/dist/${dist_mac_folder_name}/${specterimg_filename}.app ]]; then
|
|
rm -f pyinstaller/electron/dist/*.dmg
|
|
echo " --> Creating dmg"
|
|
create-dmg pyinstaller/electron/dist/${dist_mac_folder_name}/${specterimg_filename}.app --identity="Developer ID Application: ${appleid}" pyinstaller/electron/dist
|
|
# create-dmg doesn't create the prepending "v" to the version
|
|
node_comp_version=$(python3 -c "print('$version'[1:])")
|
|
mv "pyinstaller/electron/dist/${specterimg_filename} ${node_comp_version}.dmg" dist/${specterimg_filename}-${version}.dmg
|
|
echo " --> Copying img file dist/${specterimg_filename}-${version}.dmg"
|
|
cp dist/${specterimg_filename}-${version}.dmg release/${specterimg_filename}-${version}.dmg
|
|
else
|
|
echo "WARNING: Skipping packaging for electron App"
|
|
echo "No pyinstaller/electron/dist/${dist_mac_folder_name}/${specterimg_filename}.app has been found."
|
|
fi
|
|
|
|
file=./release/${specterd_filename}-${version}-osx_${ARCH}.zip
|
|
if [[ -f $file ]]; then
|
|
echo -n " FYI : "
|
|
sha256sum $file
|
|
fi
|
|
file=./release/${specterimg_filename}-${version}.dmg
|
|
if [[ -f $file ]]; then
|
|
echo -n " FIY : "
|
|
sha256sum $file
|
|
fi
|
|
fi
|
|
|
|
if [ "$app_name" != "specter" ]; then
|
|
# "early" exit
|
|
if [[ "$upload" = "True" ]]; then
|
|
echo "no upload for app_name $app_name"
|
|
exit 1
|
|
fi
|
|
exit
|
|
fi
|
|
|
|
if [[ "$upload" = "True" ]]; then
|
|
echo " --> gpg-signing the hashes and uploading"
|
|
. ../../specter_gh_upload.sh # A simple file looks like: export GH_BIN_UPLOAD_PW=...(GH token)
|
|
export CI_COMMIT_TAG=$version
|
|
if [[ -z "$CI_PROJECT_ROOT_NAMESPACE" ]]; then
|
|
echo "WARNING: Why is CI_PROJECT_ROOT_NAMESPACE not set? Setting to cryptoadvance"
|
|
export CI_PROJECT_ROOT_NAMESPACE=cryptoadvance
|
|
fi
|
|
echo " This build: version: $version gh-project: $CI_PROJECT_ROOT_NAMESPACE"
|
|
|
|
specterd_zip_fqfn=./release/specterd-${version}-osx_${ARCH}.zip
|
|
echo " Checking for file $specterd_zip_fqfn"
|
|
if [[ -f $specterd_zip_fqfn ]]; then
|
|
python3 ./utils/github.py upload $specterd_zip_fqfn
|
|
else
|
|
echo " WARNING: not uploading as it does not exist: $specterd_zip_fqfn"
|
|
fi
|
|
|
|
specter_dmg_fqfn=./release/Specter-${version}.dmg
|
|
echo " Checking for file $specter_dmg_fqfn"
|
|
if [[ -f $specter_dmg_fqfn ]]; then
|
|
python3 ./utils/github.py upload $specter_dmg_fqfn
|
|
else
|
|
echo " WARNING: not uploading as it does not exist: $specter_dmg_fqfn"
|
|
fi
|
|
|
|
cd release
|
|
# Maybe we have some SHA256SUMS files from other runs lying around. We don't want to shasum them
|
|
rm -f SHA256SUMS*
|
|
sha256sum * > SHA256SUMS-macos_${ARCH}
|
|
python3 ../utils/github.py upload SHA256SUMS-macos_${ARCH}
|
|
# The GPG comman below has a timeout. If that's reached, the script will interrupt. So let's make some noise
|
|
say "Hello?! Your overlord is speaking! You're now allowed to sign the binary!"
|
|
echo "Just in case you missed the timeout, those three last commands are missing:"
|
|
echo "cd release"
|
|
echo "gpg --detach-sign --armor SHA256SUMS-macos_${ARCH}"
|
|
echo "python3 ../utils/github.py upload SHA256SUMS-macos_${ARCH}.asc"
|
|
|
|
gpg --detach-sign --armor SHA256SUMS-macos_${ARCH}
|
|
python3 ../utils/github.py upload SHA256SUMS-macos_${ARCH}.asc
|
|
fi
|
|
|