Skip to content

Commit 93c3f5e

Browse files
committed
chore: added script that makes releases.
1 parent 5f8b67f commit 93c3f5e

File tree

2 files changed

+340
-0
lines changed

2 files changed

+340
-0
lines changed

Manifest

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# This file lists every file that should be included in a release, one file
2+
# per line. Every file listed must be placed in the project's git repository.
3+
# If a filename refers to a directory, that directory is included as a whole.
4+
# Relative paths are interpreted as relative to the root of that repository.
5+
# Empty lines and lines that start with a '#' are ignored.
6+
7+
pandoc-zotxt.lua
8+
README.md
9+
man/man1/pandoc-zotxt.lua.1.gz
10+
share/lua/5.4/lunajson.lua
11+
share/lua/5.4/lunajson

scripts/make-release.sh

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
#!/bin/sh
2+
# release.sh - Make a release.
3+
# See -h for details.
4+
# 2021, Odin Kroeger
5+
# shellcheck disable=2015
6+
7+
set -Cefu
8+
9+
10+
# CONSTANTS
11+
# =========
12+
13+
SCRIPT_NAME="$(basename "$0")" && [ "$SCRIPT_NAME" ] || {
14+
printf '%s: failed to determine basename.\n' "$0" >&2
15+
exit 69
16+
}
17+
readonly SCRIPT_NAME
18+
19+
20+
REPO="$(git rev-parse --show-toplevel)" && [ "$REPO" ] || {
21+
printf '%s: failed to determine root directory of repository.\n' \
22+
"$SCRIPT_NAME" >&2
23+
exit 69
24+
}
25+
readonly REPO
26+
27+
28+
# FUNCTIONS
29+
# =========
30+
31+
# shellcheck disable=2059
32+
warn() (
33+
exec >&2
34+
printf '%s: ' "$SCRIPT_NAME"
35+
printf -- "$@"
36+
echo
37+
)
38+
39+
panic() {
40+
__panic_status=69
41+
OPTIND=1 OPTARG='' __panic_opt=
42+
while getopts s: __panic_opt
43+
do
44+
case $__panic_opt in
45+
(s) __panic_status="$OPTARG" ;;
46+
(*) return 70
47+
esac
48+
done
49+
shift $((OPTIND - 1))
50+
warn "${@-something went wrong.}"
51+
exit "$__panic_status"
52+
}
53+
54+
cleanup() {
55+
__cleanup_status=$?
56+
set +e
57+
trap '' EXIT HUP INT TERM
58+
[ "${RELEASE-}" ] && [ -d "$RELEASE" ] &&
59+
rm -rf "$RELEASE"
60+
[ "${RELEASES-}" ] && [ -d "$RELEASES" ] &&
61+
rmdir "$RELEASES" 2>/dev/null
62+
if [ "${CLEANUP-}" ]
63+
then
64+
eval "$CLEANUP"
65+
unset CLEANUP
66+
fi
67+
kill -15 -$$ 2>/dev/null
68+
wait
69+
exit "$__cleanup_status"
70+
}
71+
72+
int() {
73+
trap '' HUP INT TERM
74+
exit $((${1:?} + 128))
75+
}
76+
77+
catch() {
78+
SIG="${1:?}"
79+
}
80+
81+
trapf() {
82+
[ $# -gt 1 ] || return 0
83+
__trapf_func="$1"
84+
shift
85+
case $1 in
86+
(0) __trapf_cond=EXIT ;;
87+
(*) __trapf_cond="$(kill -l "$1")" && [ "$__trapf_cond" ] ||
88+
panic -s 70 '%s: not a signal number.' "$1"
89+
esac
90+
# shellcheck disable=2064
91+
trap "$__trapf_func $1" "$__trapf_cond"
92+
shift
93+
trapf "$__trapf_func" "$@"
94+
unset __trapf_func __trapf_cond
95+
}
96+
97+
98+
# DEFAULTS
99+
# =======
100+
101+
# FIXME
102+
MANIFEST="$REPO/Manifest"
103+
104+
# FIXME
105+
RELEASES="$REPO/dist"
106+
107+
108+
# ARGUMENTS
109+
# =========
110+
111+
filter=
112+
OPTIND=1 OPTARG='' opt=
113+
while getopts m:f:d:h opt
114+
do
115+
case $opt in
116+
(f) filter="$OPTARG" ;;
117+
(m) MANIFEST="$OPTARG" ;;
118+
(d) RELEASES="$OPTARG" ;;
119+
(h) exec cat <<EOF
120+
$SCRIPT_NAME - Make a release
121+
122+
Synopsis:
123+
$SCRIPT_NAME [-d DIR] [-f FILTER] [-m MANIFEST]
124+
$SCRIPT_NAME -h
125+
126+
Options:
127+
-d DIR Save releases in DIR (default: ${RELEASES#"$REPO/"}).
128+
-f FILTER The Lua filter. Only needed if there is more
129+
than one Lua script in the Manifest.
130+
-m MANIDEST The Manifest file (default: ${MANIFEST#"$REPO/"})
131+
-h Show this help screen.
132+
EOF
133+
;;
134+
(*) exit 70
135+
esac
136+
done
137+
shift $((OPTIND - 1))
138+
[ $# -gt 0 ] && panic -s 64 'too many operands.'
139+
140+
[ -f "$MANIFEST" ] || panic -s 66 '%s: no such file.' "$MANIFEST"
141+
142+
if ! [ "$filter" ]
143+
then
144+
n=0
145+
while read -r fname || [ "$fname" ]
146+
do
147+
case $fname in ('#'*|'')
148+
continue
149+
esac
150+
case $fname in (*.lua)
151+
filter="$fname" n=$((n + 1))
152+
esac
153+
done <"$MANIFEST"
154+
case $n in
155+
(0) panic 'no Lua script in Manifest.' ;;
156+
(1) : ;;
157+
(*) panic 'too many Lua scripts in Manifest, use -f.'
158+
esac
159+
case $filter in
160+
(/*) : ;;
161+
(*) filter="$REPO/$filter"
162+
esac
163+
fi
164+
165+
[ -f "$filter" ] || panic -s 66 '%s: no such file.'
166+
167+
168+
# INIT
169+
# ====
170+
171+
cd -P "$REPO" || exit 69
172+
trap cleanup EXIT
173+
trapf int 1 2 15
174+
mkdir -p "$RELEASES" || exit 69
175+
176+
# MAIN
177+
# ====
178+
179+
warn 'verifying branch ...'
180+
181+
[ "$(git branch --show-current)" = main ] ||
182+
panic 'not on "main" branch.'
183+
184+
warn 'verifying version number ...'
185+
186+
tag="$( git tag --sort=-version:refname |
187+
grep -E '^v' |
188+
sed 's/^v//; q;')" &&
189+
[ "$tag" ] ||
190+
panic 'failed to derive version from tag.'
191+
192+
release="$(sed -n 's/-- *@release *//p;' "$filter")" && [ "$release" ] ||
193+
panic '%s: failed to parse @release.' "${filter#"$REPO/"}"
194+
195+
vers="$(sed -n "s/^ *VERSION *= *['\"]\([^'\"]*\)['\"].*/\1/p;" "$filter")" &&
196+
[ "$vers" ] ||
197+
panic '%s: failed to parse VERSION.' "${filter#"$REPO/"}"
198+
199+
[ "$tag" = "$release" ] ||
200+
panic -s 65 '%s: @release %s does not match tag v%s.' \
201+
"${filter#"$REPO/"}" "$release" "$tag"
202+
203+
[ "$tag" = "$vers" ] ||
204+
panic -s 65 '%s: VERSION %s does not match tag v%s.' \
205+
"${filter#"$REPO/"}" "$vers" "$tag"
206+
207+
while read -r fname || [ "$fname" ]
208+
do
209+
case $fname in
210+
('#'*|'') continue ;;
211+
(*[Rr][Ee][Aa][Dd][Mm][Ee]*)
212+
grep --fixed-strings --quiet "$tag" "$fname" ||
213+
panic -s 65 '%s: does not reference v%s.' \
214+
"${fname#"$REPO/"}" "$tag"
215+
esac
216+
done <"$MANIFEST"
217+
218+
warn 'running tests ...'
219+
220+
make test >/dev/null 2>&1 ||
221+
panic 'at least one test failed.'
222+
make test -e SCRIPT="$filter" >/dev/null 2>&1 ||
223+
panic 'at least one real-world test failed.'
224+
225+
name="$(basename "$REPO")" && [ "$name" ] ||
226+
panic '%s: failed to determine basename.' "$REPO"
227+
228+
warn 'packing release ...'
229+
230+
RELEASE=
231+
release="$RELEASES/$name-$tag"
232+
trapf catch 1 2 15
233+
set +e
234+
mkdir "$release" && readonly RELEASE="$release"
235+
err=$?
236+
set -e
237+
trapf int 1 2 15
238+
[ "${SIG-}" ] && int "$SIG"
239+
SIG=
240+
[ "$err" -eq 0 ] || exit 69
241+
unset release
242+
243+
lineno=0
244+
# shellcheck disable=2094
245+
while read -r fname || [ "$fname" ]
246+
do
247+
lineno=$((lineno + 1))
248+
case $fname in ('#'*|'')
249+
continue
250+
esac
251+
case $fname in
252+
("/$REPO"|"/$REPO/*") : ;;
253+
(/*) panic -s 65 '%s: line %d: %s: not within %s.' \
254+
"$MANIFEST" "$lineno" "$fname" "$REPO" ;;
255+
(*) fname="$REPO/$fname" ;;
256+
esac
257+
[ -e "$fname" ] ||
258+
panic -s 66 '%s: line %d: %s: no such file or directory.' \
259+
"$MANIFEST" "$lineno" "$fname"
260+
dirname="$(dirname "$fname")" && [ "$dirname" ] ||
261+
panic '%s: line %d: %s: failed to get directory.' \
262+
"$MANIFEST" "$lineno" "$fname"
263+
mkdir -p "$RELEASE/${dirname#"$REPO"}"
264+
if [ -d "$fname" ]
265+
then cp -a "$fname/" "$RELEASE/${fname#"$REPO"}"
266+
else cp "$fname" "$RELEASE/${fname#"$REPO"}"
267+
fi
268+
done <"$MANIFEST"
269+
270+
cd -P "$RELEASES"
271+
272+
TAR="$RELEASES/$name-$tag.tgz"
273+
readonly TAR
274+
trapf catch 1 2 15
275+
set +e
276+
: >"$TAR" && CLEANUP="rm -f \"\$TAR\"; ${CLEANUP-}"
277+
err=$?
278+
set -e
279+
trapf int 1 2 15
280+
[ "${SIG-}" ] && int "$SIG"
281+
SIG=
282+
[ "$err" -eq 0 ] || exit 69
283+
tar --create --gzip --file "$TAR" "$name-$tag"
284+
285+
ZIP="$RELEASES/$name-$tag.zip"
286+
readonly ZIP
287+
trapf catch 1 2 15
288+
set +e
289+
[ -e "$ZIP" ] && panic '%s: exists.' "$ZIP"
290+
zip --grow --recurse-paths --test --quiet "$ZIP" "$name-$tag" &&
291+
CLEANUP="rm -f \"\$ZIP\"; ${CLEANUP-}"
292+
err=$?
293+
set -e
294+
trapf int 1 2 15
295+
[ "${SIG-}" ] && int "$SIG"
296+
SIG=
297+
[ "$err" -eq 0 ] || exit 69
298+
299+
n=0
300+
for file in "$TAR" "$ZIP"
301+
do
302+
n=$((n + 1)) signature="$file.sig"
303+
eval "FILE_$n=\"$signature\""
304+
readonly "FILE_$n"
305+
trapf catch 1 2 15
306+
set +e
307+
: >"$signature" &&
308+
CLEANUP="rm -f \"\$FILE_$n\"; ${CLEANUP-}"
309+
err=$?
310+
set -e
311+
trapf int 1 2 15
312+
[ "${SIG-}" ] && int "$SIG"
313+
SIG=
314+
[ "$err" -eq 0 ] || exit 69
315+
gpg --detach-sign --output - "$file" >>"$signature"
316+
done
317+
318+
warn 'pushing v%s to github ...' "$tag"
319+
320+
git push origin "v$tag"
321+
322+
warn 'drafting release ...'
323+
324+
pre=
325+
case $tag in (*[a-z]*)
326+
pre=--prerelease ;;
327+
esac
328+
329+
gh release create --draft $pre "$RELEASES/$name-$tag."*

0 commit comments

Comments
 (0)