-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrelease.sh
More file actions
executable file
·189 lines (152 loc) · 4.01 KB
/
Copy pathrelease.sh
File metadata and controls
executable file
·189 lines (152 loc) · 4.01 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
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
#!/bin/bash
set -eo pipefail
shopt -s extglob
version=$1
awk-in-place () {
local tmpfile=$(mktemp)
local original="$1"
shift
cp "$original" "$tmpfile"
awk "$@" <"$tmpfile" >"$original"
rm "$tmpfile"
}
check-changes () {
if git ls-files --exclude-standard --other | grep . >/dev/null ; then
echo 'Found untracked files:' >&2
git ls-files --exclude-standard --other | sed -e 's/^/ /' >&2
echo >&2
echo 'Please commit changes before proceeding.' >&2
return 1
fi
git diff --color --exit-code HEAD || {
echo >&2
echo 'Please commit changes before proceeding.' >&2
return 1
}
}
crate-names () {
cargo metadata --format-version 1 --no-deps | jq -r '.packages[].name'
}
branch-name () {
git rev-parse --abbrev-ref HEAD
}
auto-pr () {
local branch_name="$(branch-name)"
if [[ "$(branch-name)" = main ]] ; then
echo "Cannot auto-pr on main branch." >&2
return 1
fi
pr_url=$((gh pr view --json url,closed 2>/dev/null || true) \
| jq -r 'select(.closed | not) | .url')
if [[ "$pr_url" ]] ; then
echo "Found existing PR: $pr_url"
echo
else
# Create a PR
gh pr create --fill-verbose --title "$1"
fi
gh pr merge --disable-auto --delete-branch
sleep 3
gh pr checks --watch --fail-fast
git checkout main
git pull
git merge --ff-only "$branch_name"
git push origin HEAD
git branch -d "$branch_name"
git push origin --delete "$branch_name"
}
confirm () {
local prompt="$1"
local answer
read -n 1 -p "${prompt} [yN] " answer
case $answer in
[yY]*) echo ;; # Continue
*) echo ; echo Canceling. >&2 ; exit 1 ;;
esac
}
case $version in
+([0-9]).+([0-9]).+([0-9])*) ;; # Good
*) echo "Usage $0 VERSION" >&2 ; exit 1 ;;
esac
command -v gh &>/dev/null || {
echo "gh not installed (https://cli.github.com)" >&2
exit 1
}
command -v jq &>/dev/null || {
echo "jq not installed (https://jqlang.org)" >&2
exit 1
}
command -v parse-changelog &>/dev/null || {
echo "parse-changelog not installed (https://github.com/taiki-e/parse-changelog)" >&2
exit 1
}
if [[ "$(branch-name)" = main ]] ; then
git switch -c "release-$version"
fi
check-changes
echo 'Making sure version is correct.'
awk-in-place Cargo.toml '
/^version *=/ && !done {
sub(/"[0-9.]+"/, "\"'$version'\"")
done=1
}
{ print }'
# Fix docs.rs links in README, if present
echo 'Updating links in README.md'
for name in $(crate-names) ; do
awk-in-place README.md '{
sub(/https:\/\/docs\.rs\/'"$name"'\/[0-9]+.[0-9]+.[0-9]+\//, \
"https://docs.rs/'"$name"'/'$version'/")
print
}'
done
cargo check --quiet
# Do semver checks only if there is a version on crates.io to compare to.
# FIXME: can’t tell if crates.io search failed for another reason.
main_crate_name=$(crate-names | head -1)
if (cd / && cargo info "$main_crate_name" &>/dev/null) ; then
echo 'Doing semantic versioning checks'
cargo semver-checks || { echo ; confirm 'Release anyway?' ; }
fi
awk-in-place CHANGELOG.md '
/^## / && !done {
$0 = "## Release '$version' ('$(date +%Y-%m-%d)')"
done=1
}
{ print }'
# Confirm changelog
changelog=$(mktemp)
{
echo "## Release ${version}"
echo
parse-changelog CHANGELOG.md "$version"
} >"$changelog"
cat "$changelog"
echo
confirm 'Release notes displayed above. Continue?'
# Commit version bump if necessary.
check-changes &>/dev/null || {
git add -u
git commit --cleanup=verbatim --file - <<EOF
Release ${version}
$(parse-changelog CHANGELOG.md "$version")
EOF
}
check-changes
git tag --force --sign --file "$changelog" --cleanup=verbatim "v${version}"
git push --force --tags origin HEAD
auto-pr "Release ${version}"
cargo publish
awk-in-place CHANGELOG.md '
/^## Release/ && !done {
print "## main branch\n"
done=1
}
{ print }'
git switch -c post-release
git add CHANGELOG.md
git diff --staged
confirm 'Commit with message "Prepping CHANGELOG.md for development."?'
git commit -m 'Prepping CHANGELOG.md for development.'
git push --force origin HEAD
auto-pr "Prepping CHANGELOG.md for development"