spiegel-keyman/resources/shellHelperFunctions.sh

349 lines
No EOL
11 KiB
Bash
Executable file

#!/bin/bash
_shf_base_dir=$(dirname "$BASH_SOURCE")/..
# Designed to determine which set of browsers should be available for local testing,
# based upon the current system OS.
get_builder_OS ( ) {
# Default value, since it's the most general case/configuration to detect.
os_id="linux"
# Subject to change with future improvements.
if [[ "${OSTYPE}" = "darwin"* ]]; then
os_id="mac"
elif [[ "${OSTYPE}" = "msys" ]]; then
os_id="win"
elif [[ "${OSTYPE}" = "cygwin" ]]; then
os_id="win"
fi
}
# Allows for a quick macOS check for those scripts requiring a macOS environment.
verify_on_mac() {
if [[ "${OSTYPE}" != "darwin"* ]]; then
fail "This build script will only run in a Mac environment."
exit 1
fi
}
# The list of valid projects that our build scripts ought expect.
projects=("android" "ios" "linux" "lmlayer" "mac" "web" "windows")
# Used to validate a specified 'project' parameter.
verify_project() {
match=false
for proj in ${projects[@]}
do
if [ $proj = $1 ]; then
match=true
fi
done
if [ $match = false ]; then
fail "Invalid project specified!"
fi
}
# The list of valid platforms that our build scripts ought expect.
platforms=("android" "ios" "linux" "lmlayer" "mac" "web" "desktop" "developer")
# Used to validate a specified 'platform' parameter.
verify_platform() {
match=false
for proj in ${platforms[@]}
do
if [ $proj = $1 ]; then
match=true
fi
done
if [ $match = false ]; then
fail "Invalid platform specified!"
fi
}
# Gets the folder containing each platform's history.md file, which is also the base folder for most of the platforms.
# Sets $platform_folder accordingly.
get_platform_folder() {
verify_platform $1
if [[ $1 = "desktop" || $1 = "developer" ]]; then
platform_folder="$_shf_base_dir/windows/src/$1"
elif [[ $1 = "lmlayer" ]]; then
platform_folder="common/predictive-text"
else
platform_folder="$_shf_base_dir/$1"
fi
}
# The following allows coloring of warning and error lines, but only works if there's a
# terminal attached, so not on the build machine.
if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]]; then
ERROR_RED=$(tput setaf 1)
SUCCESS_GREEN=$(tput setaf 2)
WARNING_YELLOW=$(tput setaf 3)
NORMAL=$(tput sgr0)
TERM_HEADING=$(tput setaf 4)
else
ERROR_RED=
SUCCESS_GREEN=
WARNING_YELLOW=
NORMAL=
TERM_HEADING=
fi
echo_heading() {
echo "${TERM_HEADING}$*${NORMAL}"
}
fail() {
FAILURE_MSG="$1"
if [[ "$FAILURE_MSG" == "" ]]; then
FAILURE_MSG="Unknown failure"
fi
echo "${ERROR_RED}$FAILURE_MSG${NORMAL}"
exit 1
}
warn() { echo "${WARNING_YELLOW}$*${NORMAL}"; }
displayInfo() {
if [ "$QUIET" != true ]; then
while [[ $# -gt 0 ]] ; do
echo $1
shift # past argument
done
fi
}
assertFileExists() {
if ! [ -f $1 ]; then
fail "Build failed: missing $1"
fi
}
assertDirExists() {
if ! [ -d $1 ]; then
fail "Build failed: missing $1"
fi
}
assertValidVersionNbr()
{
if [[ "$1" == "" || ! "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
fail "Specified version not valid: '$1'. Version should be in the form Major.Minor.BuildCounter"
fi
}
assertValidPRVersionNbr()
{
if [[ "$1" == "" || ! "$1" =~ ^[0-9]+\.[0-9]+\.pull\.[0-9]+$ ]]; then
fail "Specified version not valid: '$1'. Version should be in the form Major.Minor.pull.BuildCounter"
fi
}
dl_info_display_usage() {
echo "Used to create a metadata file needed on the download site"
echo "for it to connect to the download.keyman.com API functions."
echo
echo "usage: write-download_info <name> <filepath> <version> <tier> <platform>"
echo
echo " name Specifies the user-friendly name of the product represented by the file."
echo " filepath Specifies the path and file in need of a .download_info metadata file."
echo " version Specifies the build version number, which should be in the"
echo " form Major.Minor.BuildCounter"
echo " tier Specifies tier (typically one of: alpha, beta, stable)."
echo " platform Specifies the target platforms for the file."
echo " (Should be one of: android, ios, mac, web, windows)"
echo
echo "The resulting .downloadinfo file will be automatically placed in the same directory"
echo "as the originally-specified file."
exit 1
}
write_download_info() {
#Process file & path information.
PRODUCT_NAME="$1"
BASE_PATH="$2"
KM_VERSION="$3"
KM_TIER="$4"
KM_PLATFORM="$5"
verify_project "$KM_PLATFORM"
BASE_DIR=$(dirname "${BASE_PATH}")
BASE_FILE=$(basename "${BASE_PATH}");
if ([ -h "${BASE_DIR}" ]) then
while([ -h "${BASE_DIR}" ]) do BASE_PATH=`readlink "${BASE_DIR}"`;
done
fi
assertFileExists "$2"
pushd . > /dev/null
cd `dirname ${BASE_DIR}` > /dev/null
BASE_PATH=`pwd`;
popd > /dev/null
DEST_DIR="$BASE_DIR"
#Process version parameter.
assertValidVersionNbr "$3"
KM_BLD_COUNTER="$((${KM_VERSION##*.}))"
if [ "$KM_VERSION" = "" ]; then
fail "Required -version parameter not specified!"
fi
if [ "$KM_TIER" = "" ]; then
fail "Required -tier parameter not specified!"
fi
DOWNLOAD_INFO_FILEPATH="${BASE_PATH}/${BASE_FILE}.download_info"
if [[ ! -f "${BASE_PATH}/${BASE_FILE}" ]]; then
fail "Cannot compute file size or MD5 for non-existent DMG file: ${BASE_PATH}/${BASE_FILE}"
fi
FILE_EXTENSION="${BASE_FILE##*.}"
FILE_SIZE=$(stat -f"%z" "${BASE_PATH}/${BASE_FILE}")
MD5_HASH=$(md5 -q "${BASE_PATH}/${BASE_FILE}")
if [[ -f "$DOWNLOAD_INFO_FILEPATH" ]]; then
warn "Overwriting $DOWNLOAD_INFO_FILEPATH"
fi
echo { > "$DOWNLOAD_INFO_FILEPATH"
echo " \"name\": \"${PRODUCT_NAME}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"version\": \"${KM_VERSION}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"date\": \"$(date "+%Y-%m-%d")\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"platform\": \"${KM_PLATFORM}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"stability\": \"${KM_TIER}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"file\": \"${BASE_FILE}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"md5\": \"${MD5_HASH}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"type\": \"${FILE_EXTENSION}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"build\": \"${KM_BLD_COUNTER}\"," >> "$DOWNLOAD_INFO_FILEPATH"
echo " \"size\": \"${FILE_SIZE}\"" >> "$DOWNLOAD_INFO_FILEPATH"
echo } >> "$DOWNLOAD_INFO_FILEPATH"
}
# set_version sets the file version on mac/ios projects
set_version ( ) {
PRODUCT_PATH=$1
if [ $VERSION ]; then
if [ $2 ]; then # $2 = product name.
echo "Setting version numbers in $2 to $VERSION."
fi
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $VERSION" "$PRODUCT_PATH/Info.plist"
/usr/libexec/Plistbuddy -c "Set CFBundleShortVersionString $VERSION" "$PRODUCT_PATH/Info.plist"
fi
}
# Uses npm to set the current package version (package.json).
#
# NOTE: this must be invoked exclusively on the CI system!
#
# Usage:
#
# set_npm_version VERSION_WITH_TIER
#
set_npm_version () {
local version=$1
# We use --no-git-tag-version because our CI system controls version numbering and
# already tags releases. We also want to have the version of this match the
# release of Keyman Developer -- these two versions should be in sync. Because this
# is a large repo with multiple projects and build systems, it's better for us that
# individual build systems don't take too much ownership of git tagging. :)
npm --no-git-tag-version --allow-same-version version "$version" || fail "Could not set package version to $version."
}
# Initializes use of the npm `lerna` package within the repo.
init_lerna() {
if [ "${KEYMAN_ROOT}" = "" ]; then
fail "KEYMAN_ROOT not defined; cannot bootstrap repo's dependencies"
fi
# At its base, lerna does use an npm-friendly package.json. Installing that allows the base lerna install to work.
# We already changed directory in the parent script.
npm install --no-optional
# Now that it exists, we can run the following command locally. (Otherwise, npx will temporarily download everything again, each time!)
# npm run lerna bootstrap
}
# Accepts an optional parameter.
# #1 - when set to 'false', only ensures that `npm` and `node` are accessible; does not install dependencies.
#
# Designed for use with the projects/packages we have (manually) listed in the base folder's lerna.json.
verify_npm_setup () {
if [ $# != 0 ]; then
fetch_deps=$1
else
fetch_deps=true
fi
# Check if Node.JS/npm is installed.
type npm >/dev/null ||\
fail "Build environment setup error detected! Please ensure Node.js is installed!"
if [ $fetch_deps = true ]; then
WORKING_DIRECTORY=`pwd`
cd "$KEYMAN_ROOT"
# Ensure the repo's base resources are installed. (This ensures the local `lerna` install is available.)
npm install --no-optional
# Use lerna to ensure repo-internal dependencies are all properly linked
# while also installing external dependencies. Also propagates lerna into
# each project that can use it (once added as a dev-dependency there)
#
# `lerna` will only affect the packages listed the file lerna.json at the repo's base.
# The "packages" entry therein is MANUALLY managed, not automatic. Anything not listed
# therein will not be affected by `lerna` commands.
#
# Calls repo's base package 'bootstrap' script, performing the needed `lerna bootstrap -- --no-optional` command.
get_builder_OS
# https://github.com/lerna/lerna/issues/789 - there seems to sometimes be a concurrency issue when
# bootstrapping on macOS.
if [ ${os_id} == 'mac' ]; then
# --concurrency=1 is a modification on the lerna command, not for forwarding through the bootstrap command.
# It's a bit tricky.
npm run lerna -- bootstrap --concurrency=1 -- --no-optional
else
npm run bootstrap
fi
# Alternatively, without the specific script:
# npx lerna bootstrap -- --no-optional # ONLY SAFE AT REPO'S BASE (otherwise, temporarily re-downloads `lerna`!)
# - or -
# npm run lerna -- bootstrap -- -- --no-optional # Possible to use within sub-packages with proper setup. (See below.)
# Note: calling the above WITHOUT changing directories to $KEYMAN_ROOT will re-download lerna.
#
# Instead, configuring each package like this:
#
# "scripts": {
# "lerna": "cd ../ && npm run lerna --"
# },
#
# and calling this:
# npm run lerna bootstrap -- -- --no-optional
# will suffice.
#
# (The cd ../ will make the base repo's package.json the default for npm lookups.)
# (The double '--' is required due to the nested `npm run lerna` call, to ensure the parameters are properly passed through.)
if [ $? -ne 0 ]; then
# restore original working directory
cd "$WORKING_DIRECTORY"
fail "Build environment setup error detected! Please ensure Node.js is installed!"
else
# restore original working directory
cd "$WORKING_DIRECTORY"
fi
fi
}