-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathcompute-version.sh
More file actions
executable file
·202 lines (174 loc) · 5.88 KB
/
Copy pathcompute-version.sh
File metadata and controls
executable file
·202 lines (174 loc) · 5.88 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
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/bin/env bash
# Copyright 2026, Datadog, Inc
# Compute the profiler version from git tags.
#
# Usage:
# utils/compute-version.sh [--release] [--major|--minor|--patch]
# [--branch-suffix <branch>]
#
# Without --release: prints the snapshot version for HEAD.
# With --release: prints the release version (no -SNAPSHOT suffix).
#
# Version rules:
# main → most recent tag v_X.Y.Z → X.(Y+1).0-SNAPSHOT
# release/X.Y._ → most recent tag v_X.Y.Z → X.Y.(Z+1)-SNAPSHOT
# other branches → same bump as main + -<branch>-SNAPSHOT suffix
# tag commit → X.Y.Z (no bump)
#
# Exit 1 if no version tags are reachable from HEAD.
set -euo pipefail
# Resolve repo root by walking up from CWD (no git command needed, so
# this works even when git's "dubious ownership" check would block
# git rev-parse --show-toplevel in CI containers).
REPO_ROOT="."
dir="$(pwd)"
while [ "$dir" != "/" ] && [ ! -d "$dir/.git" ]; do
dir=$(dirname "$dir")
done
if [ -d "$dir/.git" ]; then
REPO_ROOT="$dir"
fi
# Use -c safe.directory for all git commands so they work regardless of
# ownership (CI containers may have a different owner than the runner user).
# This does NOT modify global git config.
GIT="git -c safe.directory=$REPO_ROOT"
RELEASE=false
BUMP_TYPE=""
BRANCH_SUFFIX=""
usage() {
cat <<EOF
Usage: $0 [--release] [--major|--minor|--patch] [--branch-suffix <branch>]
Options:
--release Print the release version (strip -SNAPSHOT)
--major Major bump (implies --release)
--minor Minor bump (implies --release)
--patch Patch bump (implies --release)
--branch-suffix <branch> Append -<branch>-SNAPSHOT for non-main branches
--help Show this help
EOF
}
while [ $# -gt 0 ]; do
case "$1" in
--release) RELEASE=true; shift ;;
--major) RELEASE=true; BUMP_TYPE="major"; shift ;;
--minor) RELEASE=true; BUMP_TYPE="minor"; shift ;;
--patch) RELEASE=true; BUMP_TYPE="patch"; shift ;;
--branch-suffix) BRANCH_SUFFIX="${2:-}"; shift 2 ;;
--help) usage; exit 0 ;;
*) echo "ERROR: unknown argument: $1" >&2; usage >&2; exit 1 ;;
esac
done
# --- Detect tag build (short-circuit) ---------------------------------------
if [[ "${CI_COMMIT_TAG:-}" =~ ^v_([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
echo "${BASH_REMATCH[1]}"
exit 0
fi
# GitHub Actions tag push: GITHUB_REF_TYPE=tag, GITHUB_REF_NAME=v_X.Y.Z
if [ "${GITHUB_REF_TYPE:-}" = "tag" ] && [[ "${GITHUB_REF_NAME:-}" =~ ^v_([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
echo "${BASH_REMATCH[1]}"
exit 0
fi
# --- Detect current branch --------------------------------------------------
branch=""
if [ -n "${CI_COMMIT_BRANCH:-}" ]; then
branch="$CI_COMMIT_BRANCH"
elif [ -n "${GITHUB_REF_NAME:-}" ] && [ "${GITHUB_REF_TYPE:-}" != "tag" ]; then
branch="$GITHUB_REF_NAME"
else
branch=$($GIT -C "$REPO_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
fi
# --- Find most recent reachable tag -----------------------------------------
# Determine tag filter: on release/X.Y._ branches, only consider tags
# matching that series (v_X.Y.*) to prevent a merged mainline tag from
# producing a wrong-series version.
tag_filter='v_*'
if [[ "$branch" =~ ^release/([0-9]+)\.([0-9]+)\._$ ]]; then
release_major="${BASH_REMATCH[1]}"
release_minor="${BASH_REMATCH[2]}"
tag_filter="v_${release_major}.${release_minor}.*"
fi
# Portable version sort: works on both GNU and BSD sort (macOS).
# sort -t. -k1,1n -k2,2n -k3,3n splits on '.' and sorts numerically.
version_sort() {
sort -t. -k1,1n -k2,2n -k3,3n
}
# Disable pipefail/errexit for git commands that may fail in unusual
# CI environments (detached HEAD, shallow clones, etc.)
set +e
latest_tag=$($GIT -C "$REPO_ROOT" tag --merged HEAD --list "$tag_filter" 2>/dev/null | sed 's/^v_//' | version_sort | tail -1)
# Fallback: if --merged fails (e.g. detached HEAD in some CI environments),
# use all tags sorted by version — the most recent one is almost certainly
# reachable from HEAD in practice.
if [ -z "$latest_tag" ]; then
latest_tag=$($GIT -C "$REPO_ROOT" tag --list "$tag_filter" 2>/dev/null | sed 's/^v_//' | version_sort | tail -1)
fi
set -e
if [ -z "$latest_tag" ]; then
echo "ERROR: no version tags (v_*) reachable from HEAD" >&2
echo " REPO_ROOT=$REPO_ROOT" >&2
echo " CWD=$(pwd)" >&2
echo " GIT=$GIT" >&2
echo " All tags:" >&2
$GIT -C "$REPO_ROOT" tag --list 2>&1 | head -20 >&2
echo " .git exists: $([ -d "$REPO_ROOT/.git" ] && echo yes || echo no)" >&2
exit 1
fi
IFS=. read -r major minor patch <<<"$latest_tag"
# --- Determine bump type -----------------------------------------------------
is_release_branch=false
if [[ "$branch" =~ ^release/([0-9]+)\.([0-9]+)\._$ ]]; then
is_release_branch=true
fi
if [ -z "$BUMP_TYPE" ]; then
if [ "$is_release_branch" = "true" ]; then
BUMP_TYPE="patch"
else
BUMP_TYPE="minor"
fi
fi
# --- Apply bump with rollover ------------------------------------------------
case "$BUMP_TYPE" in
major)
major=$((major + 1))
minor=0
patch=0
;;
minor)
if [ "$minor" -ge 99 ]; then
major=$((major + 1))
minor=0
else
minor=$((minor + 1))
fi
patch=0
;;
patch)
if [ "$patch" -ge 99 ]; then
if [ "$minor" -ge 99 ]; then
major=$((major + 1))
minor=0
else
minor=$((minor + 1))
fi
patch=0
else
patch=$((patch + 1))
fi
;;
*)
echo "ERROR: unknown bump type: $BUMP_TYPE" >&2
exit 1
;;
esac
version="$major.$minor.$patch"
# --- Assemble version string -------------------------------------------------
if [ "$RELEASE" = "true" ]; then
echo "$version"
else
if [ -n "$BRANCH_SUFFIX" ] && [ "$branch" != "main" ] && [ "$is_release_branch" = "false" ]; then
sanitized_branch=$(echo "$BRANCH_SUFFIX" | tr '/' '_')
echo "${version}-${sanitized_branch}-SNAPSHOT"
else
echo "${version}-SNAPSHOT"
fi
fi