diff --git a/update/bump-version.sh b/update/bump-version.sh index 52e0557db..626d323b4 100755 --- a/update/bump-version.sh +++ b/update/bump-version.sh @@ -1,132 +1,204 @@ -#!/bin/bash - -set -e +#!/usr/bin/env bash + +show_help() { + echo "-tag [new_tag]" + echo " new tag shall be in format of ^\\d+\\.\\d+\\.\\d+$ and greater than the current one or \$basetag" + echo "-basetag [basetag name]" + echo " specify the base tag (which shall be in format of ^\\d+\\.\\d+\\.\\d+$), default to be the latest number format tag name" + echo "-updatelog" + echo " update CHANGELOG.md if this switch is used" + echo "-h" + echo " show help info" +} -invalid_args() { - echo "Usage: $(basename $0) |major|minor|patch" - exit 1 +get_old_version() { + local filePath=$1 + local version + version=$(grep -E 'VERSION_(MAJOR|MINOR|PATCH)=' "$filePath") + declare -A version_map + + version_map[major]=$(echo "$version" | grep -oP 'VERSION_MAJOR=\K\d+') + version_map[minor]=$(echo "$version" | grep -oP 'VERSION_MINOR=\K\d+') + version_map[patch]=$(echo "$version" | grep -oP 'VERSION_PATCH=\K\d+') + version_map[str]="${version_map[major]}.${version_map[minor]}.${version_map[patch]}" + + echo "${version_map[major]}" + echo "${version_map[minor]}" + echo "${version_map[patch]}" + echo "${version_map[str]}" } -match_line() { - grep --quiet --fixed-strings "$@" +parse_new_version() { + local new_version=$1 + declare -A version + + if [[ $new_version =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + version[major]=${BASH_REMATCH[1]} + version[minor]=${BASH_REMATCH[2]} + version[patch]=${BASH_REMATCH[3]} + fi + + echo "${version[major]}" + echo "${version[minor]}" + echo "${version[patch]}" } -get_current_version() { - local file="$1" - local keyword="$2" - local line="$(grep --fixed-strings "set ${keyword}=" "${file}")" - local pattern='set '"${keyword}"'=([0-9]+)' - if [[ "${line}" =~ $pattern ]]; then - echo ${BASH_REMATCH[1]} +update_changelog() { + local new_tag=$1 + local old_tag=$2 + local commits + commits=$(git log "$old_tag..HEAD" --pretty=format:"%s ([%an](https://github.com/rime/weasel/commit/%H))") + + declare -A groupedCommits + declare -A groupedTitle + groupedTitle=( + [build]="Builds" + [ci]="Continuous Integration" + [fix]="Bug Fixes" + [feat]="Features" + [docs]="Documents" + [style]="Code Style" + [refactor]="Code Refactor" + [test]="Tests" + [chore]="Chores" + [commit]="Commits" + ) + + # 启用不区分大小写的匹配 + shopt -s nocasematch + + while IFS= read -r commit; do + if [[ $commit =~ ^(build|ci|fix|feat|docs|style|refactor|test|chore)(\([^\)]+\))?: ]]; then + prefix=${BASH_REMATCH[1],,} # 提取前缀并转小写 + groupedCommits[$prefix]+="$commit"$'\n' else - echo 0 + groupedCommits["commit"]+="$commit"$'\n' fi -} - -old_major=$(get_current_version build.bat VERSION_MAJOR) -old_minor=$(get_current_version build.bat VERSION_MINOR) -old_patch=$(get_current_version build.bat VERSION_PATCH) - -old_version="${old_major}.${old_minor}.${old_patch}" - -new_version=$1 - -new_major=$old_major -new_minor=$old_minor -new_patch=$old_patch - -version_pattern='([0-9]+)\.([0-9]+)\.([0-9]+)' - -if [[ $new_version =~ $version_pattern ]]; then - new_major=${BASH_REMATCH[1]} - new_minor=${BASH_REMATCH[2]} - new_patch=${BASH_REMATCH[3]} -elif [[ $new_version = 'major' ]]; then - ((++new_major)) - new_minor=0 - new_patch=0 -elif [[ $new_version = 'minor' ]]; then - ((++new_minor)) - new_patch=0 -elif [[ $new_version = 'patch' ]]; then - ((++new_patch)) -else - invalid_args -fi + done <<< "$commits" -new_version="${new_major}.${new_minor}.${new_patch}" -echo "updating ${old_version} => ${new_version}" + # 禁用不区分大小写的匹配 + shopt -u nocasematch -update_version_number() { - local file="$1" - local variable="$2" - local old_value="$3" - local new_value="$4" - if [[ "${old_value}" == "${new_value}" ]]; then - return + local changelog="" + for group in "${!groupedCommits[@]}"; do + if [[ -n ${groupedCommits[$group]} ]]; then + changelog+=$'\n'"#### ${groupedTitle[$group]}"$'\n' + changelog+="${groupedCommits[$group]}" fi - sed -i'~' "s/set ${variable}=[0-9]*/set ${variable}=${new_value}/" "${file}" - rm "${file}~" + done + + local currentDateTime + currentDateTime=$(date "+%Y-%m-%d") + local fileContent + fileContent=$("$'\n' + contentAdd+="## [$new_tag](https://github.com/rime/weasel/compare/$old_tag...$new_tag)($currentDateTime)"$'\n' + contentAdd+="$changelog" + contentAdd=$"$contentAdd"$'\n' + + echo "$contentAdd" + echo "$contentAdd$fileContent" > CHANGELOG.md +} + +faild_exit() { + echo + echo "Orz :( bump version failed!" + echo "we will revert the modification by command git checkout . " + echo + git checkout . + exit 1 } -update_version_number build.bat VERSION_MAJOR $old_major $new_major -update_version_number build.bat VERSION_MINOR $old_minor $new_minor -update_version_number build.bat VERSION_PATCH $old_patch $new_patch -update_version_number xbuild.bat VERSION_MAJOR $old_major $new_major -update_version_number xbuild.bat VERSION_MINOR $old_minor $new_minor -update_version_number xbuild.bat VERSION_PATCH $old_patch $new_patch - -if [[ $OSTYPE =~ darwin ]]; then - L_BOUND='[[:<:]]' - R_BOUND='[[:>:]]' -else - L_BOUND='\<' - R_BOUND='\>' +while [[ $# -gt 0 ]]; do + case $1 in + -tag) + tag="$2" + shift + ;; + -basetag) + basetag="$2" + shift + ;; + -updatelog) + updatelog=true + ;; + -h) + show_help + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac + shift +done + +if ! [[ -f weasel.sln && -d .git ]]; then + echo "Current directory is: $(pwd), it's not the weasel root directory" + echo "please run 'update/bump_version.sh' with parameters under the weasel root in bash" + exit 1 fi -SEP='\([,.]\)' +if [[ ! $tag =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Tag name does not match rule '^\\d+\\.\\d+\\.\\d+$'" + echo "Please recheck it" + exit 1 +fi -version_pattern="${L_BOUND}${old_major}${SEP}${old_minor}${SEP}${old_patch}${R_BOUND}" -replacement=${new_major}'\1'${new_minor}'\2'${new_patch} +old_version=($(get_old_version "build.bat")) +new_version=($(parse_new_version "$tag")) -update_version_string() { - local file="$1" - sed -i'~' "s/${version_pattern}/${replacement}/g" "${file}" - rm "${file}~" -} +if [[ -z "$basetag" ]]; then + basetag=${old_version[3]} +fi -update_pub_date() { - local file="$1" - local today=$(date -R) - sed -i'~' "s/[^<]*/${today}/" "${file}" - rm "${file}~" -} +if [[ ! $basetag =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Basetag format is not correct, it shall be in format of '^\\d+\\.\\d+\\.\\d+$'" + echo "Please recheck it" + exit 1 +fi -# prerequisite: -# cargo install clog-cli -update_changelog() { - local version="$1" - clog --from-latest-tag \ - --changelog CHANGELOG.md \ - --repository https://github.com/rime/weasel \ - --setversion "${version}" -} +if [[ "$tag" == "${old_version[3]}" ]]; then + echo "The new tag: $tag is the same as the old one: ${old_version[3]}" + exit 1 +elif [[ "$tag" < "${old_version[3]}" ]]; then + echo "$tag is older than ${old_version[3]}, please recheck your target version" + exit 1 +fi + +echo "Bumping version to $tag ..." +currentDateTime=$(date --rfc-2822) + +# update appcast xml files +sed -i "s|${old_version[3]}|$tag|g" ./update/appcast.xml || faild_exit +sed -i "s|[^<]*|$currentDateTime|g" ./update/appcast.xml || faild_exit +echo "update/appcast.xml updated" + +sed -i "s|${old_version[3]}|$tag|g" ./update/testing-appcast.xml || faild_exit +sed -i "s|[^<]*|$currentDateTime|g" ./update/testing-appcast.xml || faild_exit +echo "update/testing-appcast.xml updated" + +# update bat files +sed -i "s/VERSION_MAJOR=${old_version[0]}/VERSION_MAJOR=${new_version[0]}/g" ./build.bat || faild_exit +sed -i "s/VERSION_MINOR=${old_version[1]}/VERSION_MINOR=${new_version[1]}/g" ./build.bat || faild_exit +sed -i "s/VERSION_PATCH=${old_version[2]}/VERSION_PATCH=${new_version[2]}/g" ./build.bat || faild_exit +echo "build.bat updated" + +sed -i "s/VERSION_MAJOR=${old_version[0]}/VERSION_MAJOR=${new_version[0]}/g" ./xbuild.bat || faild_exit +sed -i "s/VERSION_MINOR=${old_version[1]}/VERSION_MINOR=${new_version[1]}/g" ./xbuild.bat || faild_exit +sed -i "s/VERSION_PATCH=${old_version[2]}/VERSION_PATCH=${new_version[2]}/g" ./xbuild.bat || faild_exit +echo "xbuild.bat updated" + +if [[ $updatelog ]]; then + update_changelog "$tag" "$basetag" || faild_exit + git add CHANGELOG.md + echo "CHANGELOG.md updated" +fi -update_version_string update/testing-appcast.xml -update_version_string update/appcast.xml -update_pub_date update/testing-appcast.xml -update_pub_date update/appcast.xml - -# changelog manually, so disable this -#update_changelog "${new_version}" -#${VISUAL:-${EDITOR:-nano}} CHANGELOG.md -#match_line "## ${new_version} " CHANGELOG.md || ( -# echo >&2 "CHANGELOG.md has no changes for version ${new_version}." -# exit 1 -#) -#bash update/write-release-notes.sh - -release_message="chore(release): ${new_version} :tada:" -release_tag="${new_version}" -git commit --all --message "${release_message}" -git tag --annotate "${release_tag}" --message "${release_message}" +release_message="chore(release): $tag :tada:" +release_tag="$tag" +git add update/*.xml build.bat xbuild.bat +git commit -m "$release_message" +git tag -a "$release_tag" -m "$release_message"