diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index acfcc8b79..2286f1807 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,16 +16,32 @@ jobs: with: fetch-depth: 0 - - name: Find last tag - id: last_tag - run: echo "::set-output name=tag::$(git describe --tags --abbrev=0 || echo 'v0.0.0')" + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 - - name: Get second latest tag - id: second_tag + - name: Install dependencies + run: npm install -g gen-git-log + + - name: Find Last Tag + id: last_tag run: | + Tags=$(git tag --list --sort=-version:refname) + + # 获取倒数第一个标签 + FRIEST_LATEST_TAG=$(echo "$Tags" | awk 'NR==1 {print $1; exit}') + # 获取倒数第二个标签 - SECOND_LATEST_TAG=$(git tag --list --sort=-version:refname | awk 'NR==2 {print $1; exit}') + SECOND_LATEST_TAG=$(echo "$Tags" | awk 'NR==1 {print $2; exit}') + + # 如果没有倒数第一个标签,则输出为空字符串 + if [[ -z "$FRIEST_LATEST_TAG" ]]; then + echo "::set-output name=tag_last::v1.0.0" + else + echo "::set-output name=tag_last::$FRIEST_LATEST_TAG" + fi # 如果没有倒数第二个标签,则输出为空字符串 if [[ -z "$SECOND_LATEST_TAG" ]]; then @@ -35,7 +51,9 @@ jobs: fi - name: Generate Release Notes - run: ./bin/genlog.sh -m tag -f ${{ steps.second_tag.outputs.tag_cmd }} -v ${{ steps.last_tag.outputs.tag }} + run: | + newTag=${{ steps.last_tag.outputs.tag_last }} + git-log -m tag -f ${{ steps.last_tag.outputs.tag_cmd }} -v ${newTag#1} - name: Create Release id: create_release @@ -43,8 +61,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.TOKEN }} with: - tag_name: ${{ steps.last_tag.outputs.tag }} - release_name: Release ${{ steps.last_tag.outputs.tag }} - body_path: log/${{steps.last_tag.outputs.tag}}.md + tag_name: ${{ steps.last_tag.outputs.tag_last }} + release_name: Release ${{ steps.last_tag.outputs.tag_last }} + body_path: log/${{steps.last_tag.outputs.tag_last}}.md draft: false prerelease: false \ No newline at end of file diff --git a/bin/genlog.sh b/bin/genlog.sh deleted file mode 100644 index d59c949c5..000000000 --- a/bin/genlog.sh +++ /dev/null @@ -1,529 +0,0 @@ -#!/bin/bash - -# commit 类型 键 -TYPE_MAP=(feat fix refactor style docs chore build ci pref test) -# commit 类型 值 -TYPE_TITLE_MAP=(新增 修改 重构 样式 文档 其他 构建 持续集成 优化 测试) -# 当前日期+时间 -NOW=$(date "+%F %H:%M") -# 起始日期 -SINCE="last.Monday" -# 终止日期 -UNTIL=$(date +%F) -# 是否覆盖文件,默认否 -FOUCE=0 -# 首行是否为生成日期,默认否 -PRINT_TIME=0 -# 输出目录 -OUTPUT_DIR="log" -# 是否已设置作者, 默认否 -HAS_SET_AUTHOR=0 - -# function,去除字符串两头空格 -trim() { - trimmed=$1 - # https://blog.csdn.net/dongwuming/article/details/50605911 - # 从变量$string的结尾, 删除最长匹配$substring的子串 - trimmed=${trimmed%% } - # 从变量$string的开头, 删除最长匹配$substring的子串 - trimmed=${trimmed## } - # TODO 首部空格无法全部移除 - trimmed=${trimmed## } - echo $trimmed - # 移除全部空格 - # echo ${trimmed// /} -} - -# function,是否应该强制生成文件 -shouldFouceResolve() { - # 输出文件已存在 & 不强制生成 则提示并退出 - if [ -e $OUTPUT -a $FOUCE -eq 0 ]; then - echo "${OUTPUT} already exists! \n - Please update package.json or remove log file or add '-f' follow the command!\n - " - exit 1 - fi -} -# function,首行是否应该输出生成日期 -shouldPrintTime() { - if [ $PRINT_TIME -eq 1 ]; then - echo "> Generated on ${NOW} By [Gen-Git-Log](https://www.npmjs.com/package/gen-git-log)\n" - - case $MODE in - branch) - # 分支模式 - TITLE="${TARGET}...${SOURCE}" - ;; - tag) - # 标签模式 - TITLE="${TARGET}...$(getVersion)" - ;; - esac - - if [ ! -z $TITLE ]; then - # 如果TITLE赋值则组装输出 - TITLE="## [${TITLE}](${REMOTE}/compare/${TITLE})" - echo $TITLE - fi - fi -} -# function,获取版本 -getVersion() { - # 判断是否自定义版本 - if [ -z $VERSION ]; then - # 未传入版本 - VERSION=v1.0.0 - fi - trim $VERSION -} -# function,生成输出文件路径 -generateOutPutPath() { - # 输出文件路径,默认“v版本.md” - echo "${OUTPUT_DIR}/$(getVersion).md" -} -# 生成指定SOURCE TARGET tag差异记录 -genSingleTagLog() { - SOU=$1 - TAR=$2 - - if [ ! "$3"x = "0"x ]; then - if [ $SOU = HEAD ]; then - # 如果是与最新HEAD对比则将HEAD设为version - TIT="## [$(getVersion)](${REMOTE}/compare/${TAR}...$(getVersion))" - else - TIT="## [${SOU}](${REMOTE}/compare/${TAR}...${SOU})" - fi - echo - echo - echo "${TIT} ($(git -C "${REPO}" log -1 --format=%ad --date=short $SOU))" - fi - - # 直接使用分支比对查找所有匹配 log - GIT_PAGER=$(git -C "${REPO}" log --no-merges --reverse --format="${LOG_FORMAT}" "$SOU...$TAR") - - if [ ! -z "$GIT_PAGER" ]; then - # 字符串分隔符 - IFS="*" - # 分割字符串为数组 - singleTagArr=($GIT_PAGER) - # 还原分割符,否则会导致if判断失效 - IFS="" - # 循环处理数组 - for s in ${singleTagArr[@]}; do - # 去除字符串两头空格 - s=$(trim $s) - # 判断字符串非空 - if [ ! -z $s ]; then - # 替换全角冒号 - s=${s/:/:} - # 循环commit 类型 - for type in ${TYPE_MAP[@]}; do - # 组织正则 - reg="${type}:" - # 判断commit类型 - if [[ ${s} == *"${reg}"* ]]; then - # 裁剪字符串 - s=${s##*${reg}} - s=${s%@*} - # 移除空格 - s=$(trim $s) - # 动态数组变量赋值 - eval COMMIT_${type}='(${COMMIT_'${type}'[*]} $s)' - break - fi - done - fi - done - - # 处理数据 - typeIndex=0 - for type in ${TYPE_MAP[@]}; do - # 拷贝数组 - eval type='(${COMMIT_'${type}'[*]})' - - # 判断数组是否含有元素 - if [ ${#type[*]} != 0 ]; then - echo "#### ${TYPE_TITLE_MAP[$typeIndex]}" - - for i in ${type[@]}; do - echo "* ${i}" - done - echo - fi - let typeIndex++ - done - fi -} - -# 生成tag -genTagLog() { - LOG_FORMAT="$FORMAT_DEFAULT @%ae" - - OUTPUT=$(generateOutPutPath) - - shouldFouceResolve - - # 获取最新标签 - LASTEST_TAG=$(git -C "${REPO}" describe --tags $(git -C "${REPO}" rev-list --tags --max-count=1)) - - if [ -z $SOURCE ]; then - SOURCE="HEAD" - fi - if [ -z $TARGET ]; then - TARGET=$LASTEST_TAG - fi - - case $1 in - copy) - # 如果传参为 copy 则将结果输出至剪切板 - genSingleTagLog $SOURCE $TARGET 0 | pbcopy - ;; - release-note) - # 如果传参为 release-note 则将结果直接输出 - genSingleTagLog $SOURCE master 0 - ;; - *) - ( - shouldPrintTime - genSingleTagLog $SOURCE $TARGET 0 - ) >$OUTPUT - ;; - esac -} - -# 传参覆盖默认值 -while getopts "m:a:s:u:S:T:r:v:ftd:h" arg; do - case $arg in - m) - # 模式 - MODE=$OPTARG - ;; - a) - # 作者 - AUTHOR=$OPTARG - # 已设置作者 - HAS_SET_AUTHOR=1 - ;; - s) - # 起始日期 - SINCE=$OPTARG - ;; - u) - # 终止日期 - UNTIL=$OPTARG - ;; - S) - # 源分支/标签 - SOURCE=$OPTARG - ;; - T) - # 目标分支/标签 - TARGET=$OPTARG - ;; - r) - # Git 仓库本地路径 - REPO=$OPTARG - ;; - v) - # 自定义版本 - VERSION=$OPTARG - ;; - f) - # 强制覆盖文件 - FOUCE=1 - ;; - t) - # 首行输出生成日期 - PRINT_TIME=1 - ;; - d) - # 输出目录路径 - OUTPUT_DIR=$OPTARG - ;; - h) - echo " - Usage:\n - git-log [options]\n - - Options:\n - -m 生成模式 默认:无(周报),可选:branch(分支比对)、tag(标签比对)、changelog(汇总日志) - -a 想要过滤的作者 默认:$(git config user.name) - -s 起始日期 默认:上周一,格式:2018-01-01 - -u 终止日期 默认:当天,格式:2018-01-01 - -S 源分支/标签 默认:无,比对模式:当前分支/最近标签 - -T 目标分支/标签 默认:无,比对模式:当前分支/当前HEAD - -r Git 仓库本地路径 默认:当前目录 - -v 版本号 默认:无,比对模式:仓库路径下 package.json 中 VERSION 字段值 - -f 覆盖文件 默认:否,不需要传值 - -t log 首行为生成日期 默认:否,不需要传值 - -d log 输出目录 默认:仓库路径下 log 文件夹 - " - exit 2 - ;; - ?) - echo "unknown argument" - exit 3 - ;; - esac -done - -# 判断是否需要设置默认作者 -if [ $HAS_SET_AUTHOR -eq 0 ]; then - # 没有设置过则使用默认作者 - AUTHOR=$(git -C "${REPO}" config user.name) -fi - -# 获取远程仓库地址 -REMOTE=$(git -C "${REPO}" remote -v) -REMOTE=${REMOTE#*git@} -if [ ${REMOTE:0:6}x = "origin"x ]; then - # 如果是origin开头认为是http(s)协议checkout下来的,否则是ssh - REMOTE=${REMOTE#*origin} - REMOTE=${REMOTE%%.git *} -else - REMOTE=${REMOTE%%.git *} - REMOTE="http://${REMOTE/://}" -fi - -REMOTE=$(trim $REMOTE) -# 格式化 https://ruby-china.org/topics/939 -# %H: commit hash -# %h: 短commit hash -# %an: 提交人名字 -# %ae: 提交人邮箱 -# %cr: 提交日期, 相对格式(1 day ago) -# %d: ref名称 -# %s: commit信息标题 -# %cd: 提交日期 (--date= 制定的格式) -FORMAT_DEFAULT=" * %s ([%h](${REMOTE}/commit/%H)) " - -# 判断是否指定仓库路径重写输出目录路径 -if [ -z $REPO ]; then - OUTPUT_DIR="./${OUTPUT_DIR}" -else - OUTPUT_DIR="${REPO}/${OUTPUT_DIR}" -fi - -# 指定目录路径不存在则创建 -if [ ! -e $OUTPUT_DIR ]; then - mkdir $OUTPUT_DIR -fi - -# 判断提交人,设定输出路径 -if [ -z $AUTHOR ]; then - # 提交人为空 - LOG_FORMAT="$FORMAT_DEFAULT <%an>" - - # 输出文件路径,默认“当前日期.md” - OUTPUT="${OUTPUT_DIR}/$(date +%F).md" -else - # 有提交人 - LOG_FORMAT="$FORMAT_DEFAULT - %cr" - - # 输出文件路径,默认“提交人名.md” - OUTPUT="${OUTPUT_DIR}/${AUTHOR}.md" -fi - -# 默认分支为当前分支 -CURRENT_BRANCH=$(git -C "${REPO}" rev-parse --abbrev-ref HEAD) - -case $MODE in -branch) - LOG_FORMAT="$FORMAT_DEFAULT @%ae" - - OUTPUT=$(generateOutPutPath) - - shouldFouceResolve - - if [ -z $SOURCE ]; then - SOURCE=$CURRENT_BRANCH - fi - if [ -z $TARGET ]; then - TARGET=$CURRENT_BRANCH - fi - - # 直接使用分支比对查找所有匹配 log - GIT_PAGER=$(git -C "${REPO}" log "$SOURCE...$TARGET" --no-merges --reverse --format="${LOG_FORMAT}") - - ( - shouldPrintTime - - if [ ! -z "$GIT_PAGER" ]; then - # 字符串分隔符 - IFS="*" - # 分割字符串为数组 - arr=($GIT_PAGER) - # 还原分割符,否则会导致if判断失效 - IFS="" - # 循环处理数组 - for s in ${arr[@]}; do - # 去除字符串两头空格 - s=$(trim $s) - # 判断字符串非空 - if [ ! -z $s ]; then - # 替换全角冒号 - s=${s/:/:} - # 循环commit 类型 - for type in ${TYPE_MAP[@]}; do - # 组织正则 - reg="${type}:" - # 判断commit类型 - if [[ ${s} == *"${reg}"* ]]; then - # 裁剪字符串 - s=${s##*${reg}} - s=${s%@*} - # 移除空格 - s=$(trim $s) - # 动态数组变量赋值 - eval COMMIT_${type}='(${COMMIT_'${type}'[*]} $s)' - break - fi - done - fi - done - - # 处理数据 - typeIndex=0 - for type in ${TYPE_MAP[@]}; do - # 拷贝数组 - eval type='(${COMMIT_'${type}'[*]})' - - # 判断数组是否含有元素 - if [ ${#type[*]} != 0 ]; then - echo "#### ${TYPE_TITLE_MAP[$typeIndex]}" - - for i in ${type[@]}; do - echo "* ${i}" - done - echo - fi - let typeIndex++ - done - else - echo "${SOURCE}...${TARGET} 分支无差异" - fi - ) >$OUTPUT - ;; -tag) - genTagLog - ;; -changelog) - if [ -z $REPO ]; then - OUTPUT="./CHANGELOG.md" - else - OUTPUT="${REPO}/CHANGELOG.md" - fi - - LOG_FORMAT="$FORMAT_DEFAULT @%ae" - - shouldFouceResolve - - # 标签列表 - TAG_LIST=$(git -C "${REPO}" tag) - - # 字符串分隔符 - IFS="v" - # 分割字符串为数组 - arr=($TAG_LIST) - # 还原分割符,否则会导致if判断失效 - IFS="" - # 第一次提交commit, 取duan hash - LAST_TAG=$(git -C "${REPO}" rev-list --reverse HEAD | head -1) - LAST_TAG=${LAST_TAG:0:6} - FIRST_TAG="HEAD" - - len=$((${#arr[@]} - 1)) - - ( - # 循环处理数组 - for ((i = $len; i > 0; i--)); do - s=${arr[$i]} - # 去除字符串两头空格 - s=v$(trim $s) - # 判断字符串非空 - if [ ! -z $s ]; then - # 不知道为什么一定要缓存一下,否则$s值错乱 - TEMP=$s - echo $(genSingleTagLog $FIRST_TAG $s) - FIRST_TAG=$TEMP - fi - done - - genSingleTagLog $FIRST_TAG $LAST_TAG - ) >$OUTPUT - ;; -publish) - # 发布模式 - # 站在要发布分支上 - # 同步代码 - # 修改version - # 执行该命令 - # 根据版本号生成log文件 - genTagLog - # 添加所有文件到暂存区 - git -C "${REPO}" add --all - # 生成commit - git -C "${REPO}" commit -m "chore: publish version $(getVersion)" - - # ***********目前大部分项目不允许使用命令行操作master代码,以下代码暂时废弃************** # - # 用户确认目标分支 https://ask.helplib.com/bash/post_113951 - # BRANCH="master" - # read -p"Target branch: master. (y: confirm; n: enter the target branch; c: cancel) " -n 1 -r - # echo "\n" - - # case $REPLY in - # y) - # ;; - # n) - # read -p"Please enter the target branch (For example, master): " -r - # BRANCH=$REPLY - # ;; - # *) - # echo "canceled" - # exit 5 - # ;; - # esac - # 切到branch - # git -C "${REPO}" checkout $BRANCH - # 合并分支到branch - # git -C "${REPO}" merge $CURRENT_BRANCH - # 生成tag - # git -C "${REPO}" tag -a "$(getVersion)" -m "" - # 推送tag - # git -C "${REPO}" push origin --tags - # 推送代码 - git -C "${REPO}" push origin - # 复制release note到剪切板 - pbcopy <$OUTPUT - # 完成 - echo "Push success, Release note has been copied!" - ;; -copy) - genTagLog "copy" - echo "Log has been copied to the clipboard" - exit 6 - ;; -release-note) - genTagLog "release-note" - exit 0 - ;; -*) - shouldFouceResolve - - ( - shouldPrintTime - # 先根据起始及终止时间查找符合条件的log并且把日期格式化后输出 - # 之后遍历所有输出的日期,在根据日期查询当天内的log进行打印 - git -C "${REPO}" log --since="${SINCE}" --until="${UNTIL}" --format="%cd" --date=short | sort -u | while read DATE; do - GIT_PAGER=$(git -C "${REPO}" log --no-merges --reverse --format="${LOG_FORMAT}" --since="${DATE} 00:00:00" --until="${DATE} 23:59:59" --author="${AUTHOR}") - if [ ! -z "$GIT_PAGER" ]; then - echo "[${DATE}]" - echo "${GIT_PAGER}" - echo - fi - done - ) >$OUTPUT - ;; -esac - -echo "Log has been written to '${OUTPUT}'"