diff --git a/.forgejo/workflows/build_release.yml b/.forgejo/workflows/build_release.yml index d6ca6c232..26ed46418 100755 --- a/.forgejo/workflows/build_release.yml +++ b/.forgejo/workflows/build_release.yml @@ -112,18 +112,138 @@ jobs: git fetch --no-tags --depth=1 "https://github.com/${upstream_repo}.git" "$upstream_base" || true fi + use_fork_merge_split=0 + log_range="" if [ -n "$upstream_base" ] && git cat-file -e "${upstream_base}^{commit}" 2>/dev/null; then - commit_logs="$(git log --pretty=format:'- %s (@%an)' "${upstream_base}..HEAD")" + use_fork_merge_split=1 elif [ -n "$previous_tag" ]; then - commit_logs="$(git log --pretty=format:'- %s (@%an)' "${previous_tag}..HEAD")" + log_range="${previous_tag}..HEAD" + fi + + commit_log_file="$(mktemp /tmp/komikku-commit-logs.XXXXXX)" + declare -a new_lines fix_lines improve_lines other_lines + + bucket_for_subject() { + local s="$1" + local b=other + shopt -s nocasematch + local r_feat r_feature r_add r_fix r_perf r_refactor r_chore r_docs r_style r_test r_ci r_build r_improve + r_feat='^feat\([^)]*\):' + r_feature='^feature\([^)]*\):' + r_add='^add\([^)]*\):' + r_fix='^fix\([^)]*\):' + r_perf='^perf\([^)]*\):' + r_refactor='^refactor\([^)]*\):' + r_chore='^chore\([^)]*\):' + r_docs='^docs\([^)]*\):' + r_style='^style\([^)]*\):' + r_test='^test\([^)]*\):' + r_ci='^ci\([^)]*\):' + r_build='^build\([^)]*\):' + r_improve='^improve\([^)]*\):' + if [[ "$s" =~ ^feat: ]] || [[ "$s" =~ $r_feat ]]; then b=new + elif [[ "$s" =~ ^feature: ]] || [[ "$s" =~ $r_feature ]]; then b=new + elif [[ "$s" =~ ^add: ]] || [[ "$s" =~ $r_add ]]; then b=new + elif [[ "$s" =~ ^fix: ]] || [[ "$s" =~ $r_fix ]]; then b=fix + elif [[ "$s" =~ ^perf: ]] || [[ "$s" =~ $r_perf ]]; then b=improve + elif [[ "$s" =~ ^refactor: ]] || [[ "$s" =~ $r_refactor ]]; then b=improve + elif [[ "$s" =~ ^chore: ]] || [[ "$s" =~ $r_chore ]]; then b=improve + elif [[ "$s" =~ ^docs: ]] || [[ "$s" =~ $r_docs ]]; then b=improve + elif [[ "$s" =~ ^style: ]] || [[ "$s" =~ $r_style ]]; then b=improve + elif [[ "$s" =~ ^test: ]] || [[ "$s" =~ $r_test ]]; then b=improve + elif [[ "$s" =~ ^ci: ]] || [[ "$s" =~ $r_ci ]]; then b=improve + elif [[ "$s" =~ ^build: ]] || [[ "$s" =~ $r_build ]]; then b=improve + elif [[ "$s" =~ ^improve: ]] || [[ "$s" =~ $r_improve ]]; then b=improve + fi + shopt -u nocasematch + printf '%s' "$b" + } + + clear_buckets() { + new_lines=() fix_lines=() improve_lines=() other_lines=() + } + + fill_buckets_from_git() { + local rev_range="$1" + shift + while IFS= read -r line || [ -n "${line:-}" ]; do + [ -z "${line:-}" ] && continue + subject="${line%%$'\x1f'*}" + author="${line#*$'\x1f'}" + entry="- ${subject} (@${author})" + case "$(bucket_for_subject "$subject")" in + new) new_lines+=("$entry") ;; + fix) fix_lines+=("$entry") ;; + improve) improve_lines+=("$entry") ;; + *) other_lines+=("$entry") ;; + esac + done < <(git log "$@" --pretty=tformat:'%s%x1f%an' "$rev_range") + } + + emit_buckets_from_arrays() { + local any=0 + if [ ${#new_lines[@]} -gt 0 ]; then + printf '%s\n' "##### New" "" + printf '%s\n' "${new_lines[@]}" + printf '\n' + any=1 + fi + if [ ${#fix_lines[@]} -gt 0 ]; then + printf '%s\n' "##### Fix" "" + printf '%s\n' "${fix_lines[@]}" + printf '\n' + any=1 + fi + if [ ${#improve_lines[@]} -gt 0 ]; then + printf '%s\n' "##### Improve" "" + printf '%s\n' "${improve_lines[@]}" + printf '\n' + any=1 + fi + if [ ${#other_lines[@]} -gt 0 ]; then + printf '%s\n' "##### Other" "" + printf '%s\n' "${other_lines[@]}" + printf '\n' + any=1 + fi + [ "$any" -eq 1 ] + } + + if [ "$use_fork_merge_split" -eq 1 ]; then + { + printf '%s\n' "#### Fork changes" "" + clear_buckets + fill_buckets_from_git "${upstream_base}..HEAD" --no-merges + if [ ${#new_lines[@]} -eq 0 ] && [ ${#fix_lines[@]} -eq 0 ] && [ ${#improve_lines[@]} -eq 0 ] && [ ${#other_lines[@]} -eq 0 ]; then + printf '%s\n' "_No direct commits in this range._" "" + else + emit_buckets_from_arrays + fi + + clear_buckets + fill_buckets_from_git "${upstream_base}..HEAD" --merges + if [ ${#new_lines[@]} -gt 0 ] || [ ${#fix_lines[@]} -gt 0 ] || [ ${#improve_lines[@]} -gt 0 ] || [ ${#other_lines[@]} -gt 0 ]; then + printf '%s\n' "#### Merge commits" "" + emit_buckets_from_arrays + printf '\n' + fi + } > "${commit_log_file}" + elif [ -n "$log_range" ]; then + clear_buckets + fill_buckets_from_git "$log_range" + { + if emit_buckets_from_arrays; then + : + else + printf '%s\n' "##### Other" "" "- Initial release" "" + fi + } > "${commit_log_file}" else - commit_logs='- Initial release' + printf '%s\n' "##### Other" "" "- Initial release" "" > "${commit_log_file}" fi # Do not pass multiline commit text via step outputs / env (breaks some Forgejo/act_runner # runners before the shell starts — empty logs). Only pass a temp file path. - commit_log_file="$(mktemp /tmp/komikku-commit-logs.XXXXXX)" - printf '%s\n' "$commit_logs" > "${commit_log_file}" echo "COMMIT_LOG_FILE=${commit_log_file}" >> "${GITHUB_ENV}" - name: Set up Gradle @@ -395,7 +515,7 @@ jobs: fi commit_logs="$(printf '%s' "$commit_logs" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" if [ -z "$commit_logs" ]; then - commit_logs="- Initial release" + commit_logs=$'##### Other\n\n- Initial release\n' fi full_changelog="" @@ -412,12 +532,6 @@ jobs: printf '%s\n' \ "#### What's Changed" \ "" \ - "##### New" \ - "" \ - "##### Improve" \ - "" \ - "##### Fix" \ - "" \ "${commit_logs}" \ "" \ "##### Based on" \