File size: 7,968 Bytes
6b0231d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | #! /usr/bin/env bash
# Copyright 2020, Mark Callow
# SPDX-License-Identifier: Apache-2.0
# Generate release notes from git log.
#
# mkrelnotes [-b] [-c] [-d] [-e] [-l] [-p <preface> [-t] <previous release tag> <release name>
#
# <previous release tag> is the name of the tag identifying the previous
# release. <this release> is the name to be given to the tag for the upcoming
# release. N.B. this tag cannot be created until after ther release notes
# have been generated and checked in. The release notes will include changes
# in the two-dot commit range <previous release tag>..HEAD.
#
# <preface> is inserted between the title and the detailed change list
# that is extracted with git log. It should be used to summarize
# new features and known issues using level 3 (###) headings for those
# sections.
#
# If -b is specified build system changes will be included in the
# release notes.
#
# If -c is specified any previous $RELNOTES_FILE will be appended, with the
# title lines stripped, to the release notes generated here, thus enabling
# cumulative release notes. Otherwise any previous $RELNOTES_FILE file is
# replaced.
#
# If -d is specified details of the changes will be included, otherwise only
# the summary is shown.
#
# If -e is specified changes to `external` packages will be included in the
# release notes.
#
# If -l is specified changes to the load test apps will be included in the
# release notes.
#
# If -i is specified the release notes will be built interactively. That is,
# for each change the user will be asked if it should be included.
#
# If -t is specified changes to the tests will be included in the release notes
# otherwise they are omitted.
# Depth of this script relative to the project root
depth=..
RELNOTES_FILE="RELEASE_NOTES.md"
# The author name in a commit message comes from whatever the user
# has set as user.name in their git config. It usually has no relation
# to their GitHub username so putting an @ before it has no meaning.
#
SUMMARY_FORMAT_W_AUTH="* %s (%h) (%an)"
SUMMARY_FORMAT="* %s (%h)"
function commit_summary() {
local hash=$1
local summary
local prjson
pr=$(git log --oneline -n 1 $hash | grep -o -E "\(#[0-9]+\)" | grep -o -E "[0-9]+")
# Even in PR's the commit has the full name of the user as known to GitHub,
# not their GitHub username. We want to use the GitHub username so there will
# be a link back to the person. We can retrieve this by requesting detailed
# info from GitHub via HTTPS.
summary=$(git log --pretty="$SUMMARY_FORMAT" -n 1 $hash)
if [ -z "$pr" ]; then
cmtjson="$(curl --netrc https://api.github.com/repos/KhronosGroup/KTX-Software/commits/$hash 2>/dev/null)"
author="$(echo $cmtjson | jq -r -e '.author.login')"
else
prjson="$(curl --netrc https://api.github.com/repos/KhronosGroup/KTX-Software/pulls/$pr 2>/dev/null)"
author="$(echo $prjson | jq -r -e '.user.login')"
fi
summary+=" (@$author)"
# \_ avoids confusion with _ for italics.
echo "$summary" | sed -e 's/_/\\_/g'
if [ -n "$includeDetails" ]; then
body="$(git log --pretty="%b" -n 1 $hash | sed -E 's/^(.+)/ \1/')"
if [ -n "$body" ]; then
echo ""
# Remove CR which some multi-line commit bodies contain for unknown
# reasons.
echo "$body" | tr -d \\r | sed -e 's/_/\\_/g'
fi
fi
}
function revisions_in () {
local range=$1; shift
git rev-list $range $*
}
function log() {
local part=$1; shift
local log
for rev in $(revisions_in "$range" $*); do
if [ -n "$interactive" ]; then
git log -1 $rev > /dev/tty
processed=0
while [ $processed -eq 0 ]; do
echo "Include this change? [d,i,s,?] ?" > /dev/tty
read -n 1 opt
echo "" > /dev/tty
case $opt in
d)
git show --pretty=oneline $rev > /dev/tty
;;
[is])
processed=1
;;
?)
echo "d - show diff of this commit" > /dev/tty
echo "i - include this commit." > /dev/tty
echo "s - skip this commit." > /dev/tty
echo "? - display this help message." > /dev/tty
;;
*)
echo "Unknown option: $opt. Try again." > /dev/tty
;;
esac
done
case $opt in
i)
log+="$(commit_summary $rev)"
;;
esac
else
log+="$(commit_summary $rev)"
fi
# For reasons I do not understand I have been completely unable to prevent
# trailing newlines from being removed from the output of commit_summary
# so resorting to ANSI-C quoting to insert some new lines between summaries.
log+=$'\n\n'
done
if [ -n "$log" ]; then
echo "### $part"
echo
echo "$log"
echo
fi
}
function usage() {
cat << EOU
Usage: $0 [-b] [-c] [-d] [-i] [-p <preface>] [-t] <previous release tag> <release name>"
Options:
-b Include build system changes.
-c Make cumulative release notes.
-d Include details of changes. If absent only the summary is shown.
-e Include changes to `external` packages.
-i Interactively select the changes to include.
-l Include changes to load test apps. Ignored if -t specified.
-p <preface>
Include the file <preface> before the list of changes.
-t Include test changes.
EOU
}
while true; do
case $1 in
-b) includeBuildSystem="true"; shift ;;
-c) cumulative="true"; shift;;
-d) includeDetails="true"; shift ;;
-e) includeExternal="true"; shift ;;
-i) interactive="true"; shift;;
-l) includeLoadtests="true"; shift ;;
-p) preface=$2; shift 2 ;;
-t) includeTests="true"; shift ;;
-*) usage; exit 1 ;;
*) break ;;
esac
done
if [ $# -ne 2 ]; then
echo "$0: Need previous release tag and this release name, e.g. 'v4.0.0 v4.0.1'."
exit 1
else
range=$1..
lastrel=$1
thisrel=$2
fi
#if [ $# -ne 1 ]; then
# echo '$0: Need a two-dot revision range, e.g, `v4.0.0..v4.0.1`.'
# exit 1
#else
# range=$1
# if ! [[ $range =~ ([[:alnum:][:punct:]]+)\.\.([[:alnum:]][[:alnum:][:punct:]]*)? ]]; then
# echo "$0: <revision range> is not a two-dot range."
# exit 1
# else
# lastrel=${BASH_REMATCH[1]}
# thisrel=${BASH_REMATCH[2]}
# if [ -z "$lastrel" ]; then
# lastrel=HEAD
# fi
# fi
#fi
# Change to the project root
cd $(dirname $0)/$depth
SAVED_RELNOTES_FILE="${RELNOTES_FILE%.md}-$lastrel.md"
# Save or remove old relnotes.
if [ -f $RELNOTES_FILE ]; then
if [ -z "$cumulative" ]; then
rm $RELNOTES_FILE;
else
mv $RELNOTES_FILE $SAVED_RELNOTES_FILE
fi
fi
# Read preface file before cd.
if [ -n "$preface" ]; then
PREFACE=$(cat $preface)
fi
lib=$(log libktx lib)
tools=$(log Tools tools)
js_binding=$(log "JS Bindings" interface/js_binding)
java_binding=$(log "Java Bindings" interface/java_binding)
python_binding=$(log "Python Bindings" interface/python_binding)
if [ -n "$includeBuildSystem" ]; then
build=$(log "Build Scripts and CMake files" scripts $(find . \( -path ./build -o -path ./.git -o -path ./external -o -path ./other_include \) -prune -false -o -name CMakeLists.txt -o -name '*.cmake'))
fi
if [ -n "$includeExternal" ]; then
external=$(log "External Package Dependencies" external)
fi
if [ -n "$includeTests" ]; then
tests=$(log "Tests" tests)
elif [ -n "$includeLoadtests" ]; then
loadtests=$(log "Load test apps" tests/loadtests)
fi
cat > $RELNOTES_FILE <<- EOF
$(date '+<!-- Copyright %Y, The Khronos Group Inc. -->')
<!-- SPDX-License-Identifier: Apache-2.0 -->
Release Notes
=============
## Version ${thisrel#v}
$PREFACE
### Changes since $lastrel (by part)
$lib
$tools
$js_binding
$java_binding
$python_binding
$external
$tests
$loadtests
$build
EOF
if [ -f $SAVED_RELNOTES_FILE ]; then
awk '! /Release Notes/ && ! /======/ && ! /<!-- Copyright/ && ! /<!-- SPDX/ {print}' $SAVED_RELNOTES_FILE >> $RELNOTES_FILE
rm $SAVED_RELNOTES_FILE
fi
|