Repository navigation
Expand file tree
/
Copy pathnext-version.sh
More file actions
executable file
·57 lines (52 loc) · 1.83 KB
/
Copy pathnext-version.sh
File metadata and controls
executable file
·57 lines (52 loc) · 1.83 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
#!/usr/bin/env bash
# Prints the next SemVer (without "v") derived from conventional-commit subjects since the highest v* tag.
#
# feat: → minor
# "!" after the type, or a
# "BREAKING CHANGE:" footer → major
# anything else → patch (every push to main is a release)
# no tag yet → 0.1.0
#
# Usage: next-version.sh [-C <repo>] [--current]
# --current print the highest existing tag instead (0.0.0 when there is none)
set -euo pipefail
dir="."
current_only=false
while [[ $# -gt 0 ]]; do
case "$1" in
-C) dir="$2"; shift 2 ;;
--current) current_only=true; shift ;;
-h|--help) sed -n '2,12p' "$0"; exit 0 ;;
*) echo "usage: $0 [-C dir] [--current]" >&2; exit 2 ;;
esac
done
g() { git -C "$dir" "$@"; }
# Highest tag by version sort, not the nearest one in history: a tag on a merged branch must still count.
current="$(g tag -l 'v[0-9]*.[0-9]*.[0-9]*' | sed 's/^v//' | sort -V | tail -n1)"
if $current_only; then
echo "${current:-0.0.0}"
exit 0
fi
if [[ -z "$current" ]]; then
echo "0.1.0"
exit 0
fi
range="v${current}..HEAD"
bump="patch"
major_re='^[a-z]+(\([^)]*\))?!: '
minor_re='^feat(\([^)]*\))?: '
while IFS= read -r subject; do
if [[ "$subject" =~ $major_re ]]; then bump="major"; break; fi
if [[ "$subject" =~ $minor_re ]]; then bump="minor"; fi
done < <(g log --format=%s "$range")
if [[ "$bump" != "major" ]]; then
# Captured first: grep -q exiting early would SIGPIPE git log, and pipefail would read that as "no match".
bodies="$(g log --format=%b "$range")"
if grep -q '^BREAKING CHANGE:' <<<"$bodies"; then bump="major"; fi
fi
IFS=. read -r major minor patch <<< "$current"
case "$bump" in
major) echo "$((major + 1)).0.0" ;;
minor) echo "${major}.$((minor + 1)).0" ;;
patch) echo "${major}.${minor}.$((patch + 1))" ;;
esac