mirror of
https://github.com/m1k1o/neko.git
synced 2026-11-03 00:11:48 -06:00
111 lines
2.9 KiB
Bash
Executable File
111 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: utils/release.sh <major|minor|patch> [--push]
|
|
|
|
Bumps the client and core package versions together, commits the release, and
|
|
creates an annotated vX.Y.Z tag. The tag is shared by the backend and client
|
|
release workflows. By default, prints the command to push the branch and tag.
|
|
Pass --push to push both atomically to origin.
|
|
EOF
|
|
}
|
|
|
|
if [[ ${1:-} == --help || ${1:-} == -h ]]; then
|
|
usage
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $# -lt 1 || $# -gt 2 ]]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
bump=$1
|
|
case "$bump" in
|
|
major|minor|patch) ;;
|
|
*)
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
push=0
|
|
if [[ $# -eq 2 ]]; then
|
|
if [[ $2 != --push ]]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
push=1
|
|
fi
|
|
|
|
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
root=$(git -C "$script_dir" rev-parse --show-toplevel 2>/dev/null) || {
|
|
printf 'Error: run this script from inside a git repository.\n' >&2
|
|
exit 1
|
|
}
|
|
cd "$root"
|
|
|
|
if [[ -n $(git status --porcelain) ]]; then
|
|
printf 'Error: working tree must be clean before releasing.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
branch=$(git branch --show-current)
|
|
if [[ -z $branch ]]; then
|
|
printf 'Error: release from a branch, not a detached HEAD.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $push -eq 1 ]] && ! git remote get-url origin >/dev/null 2>&1; then
|
|
printf 'Error: remote "origin" is not configured.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
client_version=$(node -p "require('./client/package.json').version")
|
|
core_version=$(node -p "require('./client/core/package.json').version")
|
|
if [[ $client_version != "$core_version" ]]; then
|
|
printf 'Error: client version (%s) and core version (%s) differ.\n' "$client_version" "$core_version" >&2
|
|
exit 1
|
|
fi
|
|
|
|
next_version=$(node - "$client_version" "$bump" <<'NODE'
|
|
const [, , version, bump] = process.argv
|
|
const match = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/.exec(version)
|
|
if (!match) throw new Error(`Expected a stable semver version, got ${version}`)
|
|
|
|
let [major, minor, patch] = match.slice(1).map(BigInt)
|
|
if (bump === 'major') [major, minor, patch] = [major + 1n, 0n, 0n]
|
|
if (bump === 'minor') [minor, patch] = [minor + 1n, 0n]
|
|
if (bump === 'patch') patch += 1n
|
|
console.log(`${major}.${minor}.${patch}`)
|
|
NODE
|
|
)
|
|
tag="v$next_version"
|
|
|
|
if git rev-parse --verify --quiet "refs/tags/$tag" >/dev/null; then
|
|
printf 'Error: tag %s already exists locally.\n' "$tag" >&2
|
|
exit 1
|
|
fi
|
|
|
|
(cd "$root/client" && npm version "$next_version" --no-git-tag-version)
|
|
(cd "$root/client/core" && npm version "$next_version" --no-git-tag-version)
|
|
|
|
git add -- \
|
|
client/package.json \
|
|
client/package-lock.json \
|
|
client/core/package.json \
|
|
client/core/package-lock.json
|
|
git commit -m "release: $tag"
|
|
git tag --annotate "$tag" --message "Release $tag"
|
|
|
|
push_command=(git push --atomic origin "HEAD:refs/heads/$branch" "refs/tags/$tag")
|
|
if [[ $push -eq 1 ]]; then
|
|
"${push_command[@]}"
|
|
else
|
|
printf '\nRelease %s created locally. To push the release commit and tag, run:\n ' "$tag"
|
|
printf '%q ' "${push_command[@]}"
|
|
printf '\n'
|
|
fi
|