github.com/vpayno/adventofcode-2022-golang-workspace@v0.0.0-20230605190011-dbafed5593de/scripts/git-release-notes (about) 1 #!/bin/bash 2 3 declare mode="${1:-latest}" 4 declare release_message="${2:-}" 5 6 git_get_tags() { 7 local tag="${1:-}" 8 9 if [[ -z ${tag} ]]; then 10 git tag | sort -Vr | grep -E '^v[[:digit:]]+[.][[:digit:]]+[.][[:digit:]]+$' 11 else 12 git tag | sort -Vr | grep -E '^v[[:digit:]]+[.][[:digit:]]+[.][[:digit:]]+$' | grep -A 1 "${tag}" 13 fi 14 } # git_get_tags() 15 16 git_get_tag_previous() { 17 local tag="${1:-}" 18 19 git_get_tags "${tag}" | head -n 2 | tail -n 1 20 } # git_get_tag_previous() 21 22 git_get_tag_latest() { 23 local tag="${1:-}" 24 25 git_get_tags "${tag}" | head -n 1 26 } # git_get_tag_latest() 27 28 git_cl() { 29 local tag="${1:-}" 30 31 local tag_previous 32 local tag_latest 33 local git_ref 34 35 if [[ ${tag} =~ ^v0.0.0\^$ ]]; then 36 git_ref="${tag}" 37 elif [[ ${tag} =~ ^release-(short|full:.*)$ ]]; then 38 git_ref="$(git_get_tags | head -n 1)..HEAD" 39 else 40 tag_previous="$(git_get_tag_previous "${tag}")" 41 tag_latest="$(git_get_tag_latest "${tag}")" 42 43 git_ref="${tag_previous}..${tag_latest}" 44 fi 45 46 git log --pretty=format:' - %s' --abbrev-commit --decorate "${git_ref}" 47 } # git_cl() 48 49 get_release_heading() { 50 local tag="${1:-}" 51 local mode="${2:-}" 52 53 local heading_start="##" 54 local heading_end="" 55 56 if [[ ${mode%%:*} =~ ^all|release-full$ ]]; then 57 heading_start="<h2>" 58 heading_end="</h2>" 59 fi 60 61 if [[ ${tag%%:*} =~ ^release-short$ ]]; then 62 printf "release: %s\n" "${release_message}" 63 return 64 elif [[ ${tag%%:*} =~ ^release-full$ ]]; then 65 git log --pretty=format:"${heading_start} [%as] " --abbrev-commit --decorate -n 1 "${tag//release-*/HEAD}" 66 printf "Release %s: %s\n%s\n" "${tag##*:}" "${release_message}" "${heading_end}" 67 return 68 fi 69 70 git log --pretty=format:"${heading_start} [%as] " --abbrev-commit --decorate -n 1 "${tag//release-*/HEAD}" 71 72 if [[ ${tag} == v0.0.0^ ]]; then 73 printf "Release v0.0.0: initial release\n" 74 else 75 git_cl "${tag%%:*}" | head -n 1 | sed -r -e 's/^ - release: (v[[:digit:]]+[.][[:digit:]]+[.][[:digit:]]+) (- )?/Release \1: /g' 76 fi 77 78 printf "%s\n" "${heading_end}" 79 } 80 81 filter_commits() { 82 grep -v -e 'Initial commit' -e 'Merge pull request' 83 } # filter_commits() 84 85 get_release_body() { 86 local tag="${1:-}" 87 88 local -a sections 89 90 mapfile -t sections < <(git_cl "${tag}" | grep -v -E "^ - release: " | filter_commits | awk '{ print $2 }' | tr -d ":" | sort -Vu) 91 92 for section in "${sections[@]}"; do 93 printf "\n" 94 printf -- "### %s\n" "${section,,}" 95 printf "\n" 96 git_cl "${tag}" | grep -v -E "^ - release: " | filter_commits | sort -k 2,2 -V | grep -- "- ${section}: " | sed -r -e 's/^ - [[:alpha:]].*: /- /g' | sort -V 97 done 98 } 99 100 create_release_notes() { 101 local mode="${1}" 102 103 local first="true" 104 local -a tags 105 local open_fold_flag=" open" 106 107 if [[ ${mode} == latest ]]; then 108 mapfile -t tags < <(git_get_tag_latest) 109 elif [[ ${mode} == release-short ]]; then 110 mapfile -t tags < <(printf "%s\n" "${mode}") 111 elif [[ ${mode%%:*} == release-full ]]; then 112 printf "# %s Release Notes\n" '"Powerful Cli Applications in Go" Workspace' 113 printf "\n" 114 115 mapfile -t tags < <(printf "%s\n" "${mode}"; git_get_tags | sort -Vr) 116 elif [[ ${mode} =~ ^v[0-9]+[.][0-9]+[.][0-9]+$ ]]; then 117 if ! git tag | grep -q -E "^${mode##*:}$"; then 118 printf "ERROR: tag [%s] doesn't exist!\n" "${mode}" 119 exit 1 120 fi 121 122 mapfile -t tags < <(printf "%s\n" "${mode}") 123 else 124 printf "# %s Release Notes\n" '"Powerful Cli Applications in Go" Workspace' 125 printf "\n" 126 127 mapfile -t tags < <(git_get_tags | sort -Vr) 128 fi 129 130 for tag in "${tags[@]}"; do 131 if [[ ${tag} == v0.0.0 ]]; then 132 tag="${tag}^" 133 fi 134 135 if "${first}"; then 136 first="false" 137 else 138 printf "\n" 139 fi 140 141 [[ ${mode} =~ ^all|release-full:v.*$ ]] && printf "<details%s>\n <summary>\n" "${open_fold_flag}" 142 get_release_heading "${tag}" "${mode}" 143 [[ ${mode} =~ ^all|release-full:v.*$ ]] && printf " </summary>\n" 144 get_release_body "${tag}" "${mode}" 145 [[ ${mode} =~ ^all|release-full:v.*$ ]] && printf "\n</details>\n" 146 147 open_fold_flag="" 148 done 149 150 { 151 printf "Running misspell -w CHANGELOG.md...\n" 152 misspell -w CHANGELOG*.md 153 printf "done\n" 154 } 1>&2 155 } # create_release_notes() 156 157 if [[ ${mode} =~ ^(|latest|release-(short|full:v[0-9]+[.][0-9]+[.][0-9]+)|all|v[0-9]+[.][0-9]+[.][0-9]+)$ ]]; then 158 create_release_notes "${mode}" 159 else 160 printf "Usage: %s ^(|latest|release-(short|full:[0-9]+[.][0-9]+[.][0-9]+)|all|v[0-9]+[.][0-9]+[.][0-9]+)$\n" "$0" 161 exit 1 162 fi