Repository navigation
Expand file tree
/
Copy pathrelease-notes.sh
More file actions
executable file
·67 lines (63 loc) · 2.53 KB
/
Copy pathrelease-notes.sh
File metadata and controls
executable file
·67 lines (63 loc) · 2.53 KB
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
#!/usr/bin/env bash
# Prints the body of the GitHub Release for <tag>: the summary section of the
# bump PR that release.sh merged as <tag>'s commit, then GitHub's generated
# notes, then <install notes>, dist's install instructions. If no PR was merged
# as that commit (say, a tag pushed by hand), or its body has no summary
# section, the body is the generated notes and the install instructions alone.
#
# Usage: scripts/release-notes.sh <tag> <install notes>
#
# release-notes.yml runs it in a checkout of <tag> once the Release is
# published. It builds the body from its inputs and the PR, never from the
# Release's current body, so running it again gives the same body.
set -euo pipefail
# So a failure inside $(…) stops the script too.
shopt -s inherit_errexit
main() {
if [ "$#" -ne 2 ]; then
echo "usage: release-notes.sh <tag> <install notes>" >&2
exit 2
fi
local commit summary
commit=$(git rev-parse --verify "$1^{commit}")
# In an if, so failing to read the PR falls back rather than stopping the
# script and leaving the Release with dist's body.
if ! summary=$(bump_summary "$commit"); then
echo "release-notes: warning: could not read the bump PR, so the body has no summary" >&2
summary=
fi
if [ -n "${summary//[[:space:]]/}" ]; then
printf '%s\n\n' "$summary"
fi
gh api 'repos/{owner}/{repo}/releases/generate-notes' -f tag_name="$1" --jq .body
printf '\n%s\n' "$2"
}
# bump_summary <commit>
# The summary section of the body of the PR merged as <commit>, or nothing.
# GitHub lists every PR the commit belongs to, including one whose head it
# is, so only a PR whose merge commit it is counts.
bump_summary() {
local number
# Errors are returned explicitly, as the caller's if turns errexit off.
number=$(gh api "repos/{owner}/{repo}/commits/$1/pulls" \
--jq '.[] | "\(.merge_commit_sha) \(.number)"' |
awk -v commit="$1" '$1 == commit && !number { number = $2 } END { print number }') ||
return
if [ -n "$number" ]; then
gh pr view "$number" --json body --jq .body | summary_section
fi
}
# summary_section
# The lines of the PR body on stdin between the markers release.sh's pr_body
# writes around the summary, or nothing if either marker is missing.
summary_section() {
awk '
{ sub(/\r$/, "") }
$0 == "<!-- release-summary:end -->" && inside { printf "%s", text; inside = 0; done = 1 }
inside { text = text $0 "\n" }
$0 == "<!-- release-summary:start -->" && !done { inside = 1 }'
}
# Only when run, so the tests can source the script and call its functions.
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
main "$@"
fi