From bce3d0d6d7153535798296c8036bb74a3bc969e2 Mon Sep 17 00:00:00 2001 From: Limon Date: Tue, 28 Feb 2017 13:44:26 +0800 Subject: [PATCH] add release.sh --- release.sh | 459 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100755 release.sh diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..213aa35 --- /dev/null +++ b/release.sh @@ -0,0 +1,459 @@ +#!/bin/bash + +BGreen='\033[1;32m' +Default='\033[0;m' + +podName="" +version="" +podspecFilePath="" +homepage="" +httpsRepo="" +oldVersion="" +confirmed="n" + +getPodInfo() { + + for file in ./* + do + if test -f $file + then + if [[ $file == *".podspec"* ]]; then + filename=`basename $file` + podName=${filename%.podspec*} + podspecFilePath="./${podName}.podspec" + fi + fi + done + + while read line; do + line=${line//[[:blank:]]/} + if [[ $line == *".homepage="* ]]; then + homepage=${line##*='"'} + homepage=${homepage%'"'} + fi + if [[ $line == *".source="* ]]; then + httpsRepo=${line##*git=>'"'} + httpsRepo=${httpsRepo%'"'*} + fi + # 截取旧版本号 + if [[ $line == *"s.version"*"="* ]]; then + oldVersion=${line##*=} + oldVersion=${oldVersion#*\"} + oldVersion=${oldVersion%\"} + oldVersion=${oldVersion#*\'} + oldVersion=${oldVersion%\'} + fi + done < $podspecFilePath +} + +getVersion() { + read -p "Enter New Version: " version + + if test -z "$version"; then + getVersion + fi +} + +updateVersion() { + + # update .podspec file + while read line; do + if [[ $line == *"s.version"*"="* ]]; then + newLine=${line/$oldVersion/$version} + sed -i '' "s#$line#$newLine#" "$podspecFilePath" + fi + done < $podspecFilePath + + # update README.md file + while read line; do + if [[ $line == *"pod"*"${oldVersion}"* ]]; then + newLine=${line/$oldVersion/$version} + sed -i '' "s#$line#$newLine#" "./README.md" + fi + if [[ $line == *"github"*"${podName}"*"${oldVersion}"* ]]; then + newLine=${line/$oldVersion/$version} + sed -i '' "s#${line}#${newLine}#" "./README.md" + fi + done < "./README.md" + + # update Xcode project + updateProjectVersion --version=$version --target=$podName + # ./update_version.sh --version=$version --target=$podName +} + +getInfomation() { + getVersion + + echo -e "\n${Default}================================================" + echo -e " Pod Name : ${BGreen}${podName}${Default}" + echo -e " Version : ${BGreen}${version}${Default}" + echo -e " HTTPS Repo : ${BGreen}${httpsRepo}${Default}" + echo -e " Home Page URL : ${BGreen}${homepage}${Default}" + echo -e "================================================\n" +} + +########### Compare newVersion and oldVersion ############### +compareVersion() { + ## @file version_compare + ## Compare [semantic] versions in Bash, comparable to PHP's version_compare function. + # ------------------------------------------------------------------ + ## @author Mark Carver + ## @copyright MIT + ## @version 1.0.0 + ## @see http://php.net/manual/en/function.version-compare.php + + APP_NAME=$(basename ${0}) + APP_VERSION="1.0.0" + + # Version compare + function version_compare () { + # Default to a failed comparison result. + local -i result=1; + + # Ensure there are two versions to compare. + [ $# -lt 2 ] || [ -z "${1}" ] || [ -z "${2}" ] && echo "${FUNCNAME[0]} requires a minimum of two arguments to compare versions." &>/dev/stderr && return ${result} + + # Determine the operation to perform, if any. + local op="${3}" + + # Convert passed versions into values for comparison. + local v1=$(version_compare_convert ${1}) + local v2=$(version_compare_convert ${2}) + + # Immediately return when comparing version equality (which doesn't require sorting). + if [ -z "${op}" ]; then + [ "${v1}" == "${v2}" ] && echo 0 && return; + else + if [ "${op}" == "!=" ] || [ "${op}" == "<>" ] || [ "${op}" == "ne" ]; then + if [ "${v1}" != "${v2}" ]; then let result=0; fi; + return ${result}; + elif [ "${op}" == "=" ] || [ "${op}" == "==" ] || [ "${op}" == "eq" ]; then + if [ "${v1}" == "${v2}" ]; then let result=0; fi; + return ${result}; + elif [ "${op}" == "le" ] || [ "${op}" == "<=" ] || [ "${op}" == "ge" ] || [ "${op}" == ">=" ] && [ "${v1}" == "${v2}" ]; then + if [ "${v1}" == "${v2}" ]; then let result=0; fi; + return ${result}; + fi + fi + + # If we get to this point, the versions should be different. + # Immediately return if they're the same. + [ "${v1}" == "${v2}" ] && return ${result} + + local sort='sort' + + # If only one version has a pre-release label, reverse sorting so + # the version without one can take precedence. + [[ "${v1}" == *"-"* ]] && [[ "${v2}" != *"-"* ]] || [[ "${v2}" == *"-"* ]] && [[ "${v1}" != *"-"* ]] && sort="${sort} -r" + + # Sort the versions. + local -a sorted=($(printf "%s\n%s" "${v1}" "${v2}" | ${sort})) + + # No operator passed, indicate which direction the comparison leans. + if [ -z "${op}" ]; then + if [ "${v1}" == "${sorted[0]}" ]; then echo -1; else echo 1; fi + return + fi + + case "${op}" in + "<" | "lt" | "<=" | "le") if [ "${v1}" == "${sorted[0]}" ]; then let result=0; fi;; + ">" | "gt" | ">=" | "ge") if [ "${v1}" == "${sorted[1]}" ]; then let result=0; fi;; + esac + + return ${result} + } + + # Converts a version string to an integer that is used for comparison purposes. + function version_compare_convert () { + local version="${@}" + + # Remove any build meta information as it should not be used per semver spec. + version="${version%+*}" + + # Extract any pre-release label. + local prerelease + [[ "${version}" = *"-"* ]] && prerelease=${version##*-} + [ -n "${prerelease}" ] && prerelease="-${prerelease}" + + version="${version%%-*}" + + # Separate version (minus pre-release label) into an array using periods as the separator. + local OLDIFS=${IFS} && local IFS=. && version=(${version%-*}) && IFS=${OLDIFS} + + # Unfortunately, we must use sed to strip of leading zeros here. + local major=$(echo ${version[0]:=0} | sed 's/^0*//') + local minor=$(echo ${version[1]:=0} | sed 's/^0*//') + local patch=$(echo ${version[2]:=0} | sed 's/^0*//') + local build=$(echo ${version[3]:=0} | sed 's/^0*//') + + # Combine the version parts and pad everything with zeros, except major. + printf "%s%04d%04d%04d%s\n" "${major}" "${minor}" "${patch}" "${build}" "${prerelease}" + } + + # Color Support + # See: http://unix.stackexchange.com/a/10065 + if test -t 1; then + ncolors=$(tput colors) + if test -n "$ncolors" && test $ncolors -ge 8; then + bold="$(tput bold)" && underline="$(tput smul)" && standout="$(tput smso)" && normal="$(tput sgr0)" + black="$(tput setaf 0)" && red="$(tput setaf 1)" && green="$(tput setaf 2)" && yellow="$(tput setaf 3)" + blue="$(tput setaf 4)" && magenta="$(tput setaf 5)" && cyan="$(tput setaf 6)" && white="$(tput setaf 7)" + fi + fi + + function version_compare_usage { + echo "${bold}${APP_NAME} (${APP_VERSION})${normal}" + echo "Compare [semantic] versions in Bash, comparable to PHP's version_compare function." + echo + echo "${bold}Usage:${normal}" + echo " ${APP_NAME} [-hV] ${cyan} ${normal} [${cyan}${normal}]" + echo + echo "${bold}Required arguments:${normal}" + echo " - ${cyan}${normal}: First version number to compare." + echo " - ${cyan}${normal}: Second version number to compare." + echo + echo "${bold}Optional arguments:${normal}" + echo " - ${cyan}${normal}: When this argument is provided, it will test for a particular" + echo " relationship. This argument is case-sensitive, values should be lowercase." + echo " Possible operators are:" + echo " ${bold}=, ==, eq${normal} (equal)" + echo " ${bold}>, gt${normal} (greater than)" + echo " ${bold}>=, ge${normal} (greater than or equal)" + echo " ${bold}<, lt${normal} (less than)" + echo " ${bold}<=, le${normal} (less than or equal)" + echo " ${bold}!=, <>, ne${normal} (not equal)" + echo + echo "${bold}Return Value:${normal}" + echo " There are two distinct operation modes for ${APP_NAME}. It's solely based" + echo " on whether or not the ${cyan}${normal} argument was provided:" + echo + echo " - When ${cyan}${normal} IS provided, ${APP_NAME} will return either a 0 or 1" + echo " exit code (no output printed to /dev/stdout) based on the result of the ${cyan}${normal}" + echo " relationship between the versions. This is particularly useful in cases where" + echo " testing versions can, historically, be quite cumbersome:" + echo + echo " ${magenta}! ${APP_NAME} \${version1} \${version2} \">\" && echo \"You have not met the minimum version requirements.\" && exit 1${normal}" + echo + echo " You can, of course, opt for the more traditional/verbose conditional" + echo " block in that suites your fancy:" + echo + echo " ${magenta}${APP_NAME} \${version1} \${version2}" + echo " if [ \$? -gt 0 ]; then" + echo " echo \"You have not met the minimum version requirements.\"" + echo " exit 1" + echo " fi${normal}" + echo + echo " - When ${cyan}${normal} is NOT provided, ${APP_NAME} will output (print to /dev/stdout):" + echo " -1: ${cyan}${normal} is lower than ${cyan}${normal}" + echo " 0: ${cyan}${normal} and ${cyan}${normal} are equal" + echo " 1: ${cyan}${normal} is lower than ${cyan}${normal}" + echo + echo " This mode is primarily only ever helpful when there is a need to determine the" + echo " relationship between two versions and provide logic for all three states:" + echo + echo " ${magenta}ret=\$(${APP_NAME} \${version1} \${version2})" + echo " if [ \"\${ret}\" == \"-1\" ]; then" + echo " # Do some logic here." + echo " elif [ \"\${ret}\" == \"0\" ]; then" + echo " # Do some logic here." + echo " else" + echo " # Do some logic here." + echo " fi${normal}" + echo + echo " While there are use cases for both modes, it's recommended that you provide an" + echo " ${cyan}${normal} argument to reduce any logic whenever possible." + echo + echo "${bold}Options:${normal}" + echo " ${bold}-h${normal} Display this help and exit." + echo " ${bold}-V${normal} Display version information and exit." +} + +# Do not continue if sourced. +[[ ${0} != "$BASH_SOURCE" ]] && return + +# Process options. +while getopts ":hV" opt; do + case $opt in + h) version_compare_usage && exit;; + V) echo "${APP_VERSION}" && exit;; + \?|*) echo "${red}${APP_NAME}: illegal option: -- ${OPTARG}${normal}" >&2 && echo && version_compare_usage && exit 64;; + esac +done +shift $((OPTIND-1)) # Remove parsed options. + +# Allow script to be invoked as a CLI "command" by proxying arguments to the internal function. +[ $# -gt 0 ] && version_compare ${@} + +} + +########### Update Xocde Info.plist ############### +updateProjectVersion() { + # Link: + # ./update-version.sh --version=1.2.9 --build=95 --target=MonkeyKing + + # We use PlistBuddy to handle the Info.plist values. Here we define where it lives. + plistBuddy="/usr/libexec/PlistBuddy" + + BGreen='\033[1;32m' + + # Parse input variables and update settings. + for i in "$@"; do + case $i in + -h|--help) + echo "usage: sh version-update.sh [options...]\n" + echo "Options: (when provided via the CLI, these will override options set within the script itself)" + echo " --build= Apply the given value to the build number (CFBundleVersion) for the project." + echo "-p, --plist= Use the specified plist file as the source of truth for version details." + echo " --version= Apply the given value to the marketing version (CFBundleShortVersionString) for the project." + echo "-x, --xcodeproj= Use the specified Xcode project file to gather plist names." + echo "-x, --target= Use the specified Xcode project target to gather plist names." + echo "\nFor more detailed information on the use of these variables, see the script source." + exit 1 + ;; + -x=*|--xcodeproj=*) + xcodeproj="${i#*=}" + shift + ;; + -p=*|--plist=*) + plist="${i#*=}" + shift + ;; + --target=*) + specified_target="${i#*=}" + shift + ;; + --build=*) + specified_build="${i#*=}" + shift + ;; + --version=*) + specified_version="${i#*=}" + shift + ;; + *) + ;; + esac + done + + # Locate the xcodeproj. + # If we've specified a xcodeproj above, we'll simply use that instead. + if [[ -z ${xcodeproj} ]]; then + xcodeproj=$(find . -depth 1 -name "*.xcodeproj" | sed -e 's/^\.\///g') + fi + + # Check that the xcodeproj file we've located is valid, and warn if it isn't. + # This could also indicate an issue with the code used to automatically locate the xcodeproj file. + # If you're encountering this and the file exists, ensure that ${xcodeproj} contains the correct + # path, or use the "--xcodeproj" variable to provide an accurate location. + if [[ ! -f "${xcodeproj}/project.pbxproj" ]]; then + echo "${BASH_SOURCE}:${LINENO}: error: Could not locate the xcodeproj file \"${xcodeproj}\"." + exit 1 + else + echo "Xcode Project: \"${xcodeproj}\"" + fi + + # Find unique references to Info.plist files in the project + projectFile="${xcodeproj}/project.pbxproj" + plists=$(grep "^\s*INFOPLIST_FILE.*$" "${projectFile}" | sed -Ee 's/^[[:space:]]+INFOPLIST_FILE[[:space:]*=[[:space:]]*["]?([^"]+)["]?;$/\1/g' | sort | uniq) + + # Attempt to guess the plist based on the list we have. + # If we've specified a plist above, we'll simply use that instead. + if [[ -z ${plist} ]]; then + while read -r thisPlist; do + if [[ $thisPlist == *"${specified_target}"* ]]; then + plist=$thisPlist + fi + done <<< "${plists}" + fi + + # Check that the plist file we've located is valid, and warn if it isn't. + # This could also indicate an issue with the code used to match plist files in the xcodeproj file. + # If you're encountering this and the file exists, ensure that ${plists} contains _ONLY_ filenames. + if [[ ! -f ${plist} ]]; then + echo "${BASH_SOURCE}:${LINENO}: error: Could not locate the plist file \"${plist}\"." + exit 1 + else + echo "Source Info.plist: \"${plist}\"" + fi + + # Find the current build number in the main Info.plist + mainBundleVersion=$("${plistBuddy}" -c "Print CFBundleVersion" "${plist}") + mainBundleShortVersionString=$("${plistBuddy}" -c "Print CFBundleShortVersionString" "${plist}") + echo "Current project version is ${mainBundleShortVersionString} (${mainBundleVersion})." + + # If the user specified a marketing version (via "--version"), we overwrite the version from the source of truth. + if [[ ! -z ${specified_version} ]]; then + mainBundleShortVersionString=${specified_version} + echo "Applying specified marketing version (${specified_version})..." + fi + + if [[ ! -z ${specified_build} ]]; then + mainBundleVersion=${specified_build} + echo "Applying specified build number (${specified_build})..." + fi + + # Update all of the Info.plist files we discovered + while read -r thisPlist; do + # Find out the current version + thisBundleVersion=$("${plistBuddy}" -c "Print CFBundleVersion" "${thisPlist}") + thisBundleShortVersionString=$("${plistBuddy}" -c "Print CFBundleShortVersionString" "${thisPlist}") + # Update the CFBundleVersion if needed + if [[ ${thisBundleVersion} != ${mainBundleVersion} ]]; then + echo -e "${BGreen}Updating \"${thisPlist}\" with build ${mainBundleVersion}..." + "${plistBuddy}" -c "Set :CFBundleVersion ${mainBundleVersion}" "${thisPlist}" + fi + # Update the CFBundleShortVersionString if needed + if [[ ${thisBundleShortVersionString} != ${mainBundleShortVersionString} ]]; then + echo -e "${BGreen}Updating \"${thisPlist}\" with marketing version ${mainBundleShortVersionString}..." + "${plistBuddy}" -c "Set :CFBundleShortVersionString ${mainBundleShortVersionString}" "${thisPlist}" + git add "${thisPlist}" + fi + echo -e "${BGreen}Current \"${thisPlist}\" version is ${mainBundleShortVersionString} (${mainBundleVersion})." + done <<< "${plist}" +} + +########### 开始 ############### + +getPodInfo + +echo -e "\n" + +echo "Current Version: ${oldVersion}" + +while [ "$confirmed" != "y" -a "$confirmed" != "Y" ] +do + if [ "$confirmed" == "n" -o "$confirmed" == "N" ]; then + getInfomation + fi + read -p "confirm? (y/n):" confirmed +done + +! compareVersion $version $oldVersion ">" && echo "Invalid version. $version <= $oldVersion" && exit 1 + +updateVersion + +echo "" + +echo "--------------------------------------------------------------------------------" + +echo "" + +git add "${podspecFilePath}" +git add "./README.md" +git commit -m "[$podName] update version $version" +git push + +git tag "${version}" +git push --tags + +echo "" + +echo "--------------------------------------------------------------------------------" +echo "Start pod trunk push \"${podName}.podspec\" --allow-warnings" + +pod trunk push "${podName}.podspec" --allow-warnings + +echo -e "\n" + +say "finished" +echo "finished"