diff --git a/Manifest b/Manifest new file mode 100644 index 0000000..8f2e6a7 --- /dev/null +++ b/Manifest @@ -0,0 +1,11 @@ +# This file lists every file that should be included in a release, one file +# per line. Every file listed must be placed in the project's git repository. +# If a filename refers to a directory, that directory is included as a whole. +# Relative paths are interpreted as relative to the root of that repository. +# Empty lines and lines that start with a '#' are ignored. + +pandoc-zotxt.lua +README.md +man/man1/pandoc-zotxt.lua.1.gz +share/lua/5.4/lunajson.lua +share/lua/5.4/lunajson \ No newline at end of file diff --git a/scripts/make-release.sh b/scripts/make-release.sh new file mode 100644 index 0000000..c4b2113 --- /dev/null +++ b/scripts/make-release.sh @@ -0,0 +1,329 @@ +#!/bin/sh +# release.sh - Make a release. +# See -h for details. +# 2021, Odin Kroeger +# shellcheck disable=2015 + +set -Cefu + + +# CONSTANTS +# ========= + +SCRIPT_NAME="$(basename "$0")" && [ "$SCRIPT_NAME" ] || { + printf '%s: failed to determine basename.\n' "$0" >&2 + exit 69 +} +readonly SCRIPT_NAME + + +REPO="$(git rev-parse --show-toplevel)" && [ "$REPO" ] || { + printf '%s: failed to determine root directory of repository.\n' \ + "$SCRIPT_NAME" >&2 + exit 69 +} +readonly REPO + + +# FUNCTIONS +# ========= + +# shellcheck disable=2059 +warn() ( + exec >&2 + printf '%s: ' "$SCRIPT_NAME" + printf -- "$@" + echo +) + +panic() { + __panic_status=69 + OPTIND=1 OPTARG='' __panic_opt= + while getopts s: __panic_opt + do + case $__panic_opt in + (s) __panic_status="$OPTARG" ;; + (*) return 70 + esac + done + shift $((OPTIND - 1)) + warn "${@-something went wrong.}" + exit "$__panic_status" +} + +cleanup() { + __cleanup_status=$? + set +e + trap '' EXIT HUP INT TERM + [ "${RELEASE-}" ] && [ -d "$RELEASE" ] && + rm -rf "$RELEASE" + [ "${RELEASES-}" ] && [ -d "$RELEASES" ] && + rmdir "$RELEASES" 2>/dev/null + if [ "${CLEANUP-}" ] + then + eval "$CLEANUP" + unset CLEANUP + fi + kill -15 -$$ 2>/dev/null + wait + exit "$__cleanup_status" +} + +int() { + trap '' HUP INT TERM + exit $((${1:?} + 128)) +} + +catch() { + SIG="${1:?}" +} + +trapf() { + [ $# -gt 1 ] || return 0 + __trapf_func="$1" + shift + case $1 in + (0) __trapf_cond=EXIT ;; + (*) __trapf_cond="$(kill -l "$1")" && [ "$__trapf_cond" ] || + panic -s 70 '%s: not a signal number.' "$1" + esac + # shellcheck disable=2064 + trap "$__trapf_func $1" "$__trapf_cond" + shift + trapf "$__trapf_func" "$@" + unset __trapf_func __trapf_cond +} + + +# DEFAULTS +# ======= + +# FIXME +MANIFEST="$REPO/Manifest" + +# FIXME +RELEASES="$REPO/dist" + + +# ARGUMENTS +# ========= + +filter= +OPTIND=1 OPTARG='' opt= +while getopts m:f:d:h opt +do + case $opt in + (f) filter="$OPTARG" ;; + (m) MANIFEST="$OPTARG" ;; + (d) RELEASES="$OPTARG" ;; + (h) exec cat </dev/null 2>&1 || + panic 'at least one test failed.' +make test -e SCRIPT="$filter" >/dev/null 2>&1 || + panic 'at least one real-world test failed.' + +name="$(basename "$REPO")" && [ "$name" ] || + panic '%s: failed to determine basename.' "$REPO" + +warn 'packing release ...' + +RELEASE= +release="$RELEASES/$name-$tag" +trapf catch 1 2 15 +set +e +mkdir "$release" && readonly RELEASE="$release" +err=$? +set -e +trapf int 1 2 15 +[ "${SIG-}" ] && int "$SIG" +SIG= +[ "$err" -eq 0 ] || exit 69 +unset release + +lineno=0 +# shellcheck disable=2094 +while read -r fname || [ "$fname" ] +do + lineno=$((lineno + 1)) + case $fname in ('#'*|'') + continue + esac + case $fname in + ("/$REPO"|"/$REPO/*") : ;; + (/*) panic -s 65 '%s: line %d: %s: not within %s.' \ + "$MANIFEST" "$lineno" "$fname" "$REPO" ;; + (*) fname="$REPO/$fname" ;; + esac + [ -e "$fname" ] || + panic -s 66 '%s: line %d: %s: no such file or directory.' \ + "$MANIFEST" "$lineno" "$fname" + dirname="$(dirname "$fname")" && [ "$dirname" ] || + panic '%s: line %d: %s: failed to get directory.' \ + "$MANIFEST" "$lineno" "$fname" + mkdir -p "$RELEASE/${dirname#"$REPO"}" + if [ -d "$fname" ] + then cp -a "$fname/" "$RELEASE/${fname#"$REPO"}" + else cp "$fname" "$RELEASE/${fname#"$REPO"}" + fi +done <"$MANIFEST" + +cd -P "$RELEASES" + +TAR="$RELEASES/$name-$tag.tgz" +readonly TAR +trapf catch 1 2 15 +set +e +: >"$TAR" && CLEANUP="rm -f \"\$TAR\"; ${CLEANUP-}" +err=$? +set -e +trapf int 1 2 15 +[ "${SIG-}" ] && int "$SIG" +SIG= +[ "$err" -eq 0 ] || exit 69 +tar --create --gzip --file "$TAR" "$name-$tag" + +ZIP="$RELEASES/$name-$tag.zip" +readonly ZIP +trapf catch 1 2 15 +set +e +[ -e "$ZIP" ] && panic '%s: exists.' "$ZIP" +zip --grow --recurse-paths --test --quiet "$ZIP" "$name-$tag" && + CLEANUP="rm -f \"\$ZIP\"; ${CLEANUP-}" +err=$? +set -e +trapf int 1 2 15 +[ "${SIG-}" ] && int "$SIG" +SIG= +[ "$err" -eq 0 ] || exit 69 + +n=0 +for file in "$TAR" "$ZIP" +do + n=$((n + 1)) signature="$file.sig" + eval "FILE_$n=\"$signature\"" + readonly "FILE_$n" + trapf catch 1 2 15 + set +e + : >"$signature" && + CLEANUP="rm -f \"\$FILE_$n\"; ${CLEANUP-}" + err=$? + set -e + trapf int 1 2 15 + [ "${SIG-}" ] && int "$SIG" + SIG= + [ "$err" -eq 0 ] || exit 69 + gpg --detach-sign --output - "$file" >>"$signature" +done + +warn 'pushing v%s to github ...' "$tag" + +git push origin "v$tag" + +warn 'drafting release ...' + +pre= +case $tag in (*[a-z]*) + pre=--prerelease ;; +esac + +gh release create --draft $pre "$RELEASES/$name-$tag."*