Skip to content

Commit 8a96dee

Browse files
committed
add release script
Signed-off-by: Sam Spycher <samspycher@users.noreply.github.com>
1 parent 90e8701 commit 8a96dee

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed

release.sh

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
#!/usr/bin/env bash
2+
3+
# Script to manage a multi-step release process:
4+
# 1. If current version is X.Y.Z-SNAPSHOT:
5+
# - Calculates release version X.Y.Z
6+
# - Sets version to X.Y.Z, commits, and pushes this commit.
7+
# 2. Calculates suggested next snapshot (e.g., X.Y.(Z+1)-SNAPSHOT).
8+
# 3. Prompts developer for the actual next snapshot version (with suggestion as default).
9+
# 4. Validates the developer's input (must be higher semver, must end in -SNAPSHOT).
10+
# 5. Sets version to the chosen snapshot, commits (DOES NOT PUSH this commit).
11+
# 6. Instructs user to:
12+
# a) Create GitHub release/tag for X.Y.Z (pointing to the pushed release commit).
13+
# b) After GitHub release actions complete, manually push the second (snapshot) commit.
14+
15+
set -e # Exit immediately if a command exits with a non-zero status.
16+
17+
# --- Check for required commands ---
18+
if ! command -v mvn &>/dev/null; then
19+
echo "Error: mvn (Maven) command not found. Please install Maven and ensure it's in your PATH."
20+
exit 1
21+
fi
22+
23+
if ! command -v git &>/dev/null; then
24+
echo "Error: git command not found. Please install Git and ensure it's in your PATH."
25+
exit 1
26+
fi
27+
28+
# --- Helper function to compare semver versions (simplified: A > B) ---
29+
# Returns 0 if v1 > v2, 1 otherwise.
30+
# Assumes versions are like X.Y.Z or X.Y.Z-SNAPSHOT. Ignores -SNAPSHOT for gt comparison.
31+
version_gt() {
32+
local v1=${1%-SNAPSHOT} # remove -SNAPSHOT if present
33+
local v2=${2%-SNAPSHOT} # remove -SNAPSHOT if present
34+
35+
IFS='.' read -r -a v1_parts <<<"$v1"
36+
IFS='.' read -r -a v2_parts <<<"$v2"
37+
38+
# Pad with zeros if parts are missing (e.g. 0.1 vs 0.1.0)
39+
for i in 0 1 2; do
40+
v1_parts[i]=${v1_parts[i]:-0}
41+
v2_parts[i]=${v2_parts[i]:-0}
42+
done
43+
44+
for i in 0 1 2; do
45+
if ((v1_parts[i] > v2_parts[i])); then
46+
return 0 # v1 > v2
47+
fi
48+
if ((v1_parts[i] < v2_parts[i])); then
49+
return 1 # v1 < v2
50+
fi
51+
done
52+
return 1 # v1 == v2, so not strictly greater
53+
}
54+
55+
# --- Get Current State ---
56+
CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
57+
if [ -z "${CURRENT_VERSION}" ]; then
58+
echo "Error: Could not determine current project version using Maven."
59+
exit 1
60+
fi
61+
echo "Current project version: ${CURRENT_VERSION}"
62+
63+
# --- Validate Current Version and Arguments ---
64+
if [[ "${CURRENT_VERSION}" != *"-SNAPSHOT" ]]; then
65+
echo "Error: Current version (${CURRENT_VERSION}) is not a SNAPSHOT version."
66+
echo "This script must be run on a SNAPSHOT version to prepare a release."
67+
echo "If a release was just made, you might need to push the latest (snapshot) commit manually."
68+
exit 1
69+
fi
70+
71+
if [ ! -z "$1" ]; then
72+
echo "Error: This script does not accept arguments."
73+
echo " The release version is calculated, and the next snapshot version will be prompted."
74+
exit 1
75+
fi
76+
77+
RELEASE_VERSION=${CURRENT_VERSION%-SNAPSHOT} # Remove -SNAPSHOT
78+
COMMIT_MSG_RELEASE="prepare release ${RELEASE_VERSION}"
79+
80+
echo "Calculated release version: ${RELEASE_VERSION}"
81+
82+
# --- Confirmation for Phase 1 (Prepare Release) ---
83+
echo
84+
echo "-------------------- ACTION SUMMARY (Phase 1/2) --------------------"
85+
echo "Current version is SNAPSHOT (${CURRENT_VERSION})."
86+
echo "1. Will set version to RELEASE: ${RELEASE_VERSION}"
87+
echo " Will commit changes with message: \"${COMMIT_MSG_RELEASE}\""
88+
echo "2. Will create an annotated tag: '${RELEASE_VERSION}' for this commit."
89+
echo "3. Will PUSH this commit AND the tag ('${RELEASE_VERSION}') to the remote repository."
90+
echo "-------------------------------------------------------------------"
91+
echo
92+
93+
read -p "Do you want to proceed with Phase 1 (Prepare, Tag, and Push Release)? (y/N): " confirmation
94+
if [[ ! "$confirmation" =~ ^[Yy]$ ]]; then
95+
echo "Operation cancelled by user."
96+
exit 0
97+
fi
98+
99+
# --- Execute Phase 1 Actions ---
100+
101+
# 1. Check for uncommitted changes
102+
if ! git diff --quiet HEAD --; then
103+
echo "Error: Uncommitted changes detected. Please commit or stash them first."
104+
exit 1
105+
fi
106+
107+
# 2. Set version to RELEASE_VERSION
108+
echo "Setting POM versions to ${RELEASE_VERSION}... (This may take a moment)"
109+
mvn versions:set -DnewVersion="${RELEASE_VERSION}" -DprocessAllModules=true -DgenerateBackupPoms=false
110+
111+
# 3. Commit the release version change
112+
echo "Staging pom.xml files for release commit..."
113+
find . -name pom.xml -type f -exec git add {} +
114+
echo "Committing release version change: \"${COMMIT_MSG_RELEASE}\" ..."
115+
git commit -m "${COMMIT_MSG_RELEASE}"
116+
echo "Release version ${RELEASE_VERSION} committed."
117+
118+
# 4. Create an annotated tag for the release
119+
echo "Creating annotated tag '${RELEASE_VERSION}'..."
120+
git tag -a "${RELEASE_VERSION}" -m "Release ${RELEASE_VERSION}"
121+
echo "Tag '${RELEASE_VERSION}' created."
122+
123+
# 5. Push the release commit and the tag
124+
echo "Pushing release commit and tag ('${RELEASE_VERSION}') to remote..."
125+
git push --follow-tags
126+
echo "Release commit and tag pushed successfully."
127+
echo "-------------------------------------------------------------------"
128+
echo
129+
130+
# --- Phase 2: Prepare Next Development Snapshot ---
131+
132+
# Calculate SUGGESTED_NEXT_SNAPSHOT_VERSION (e.g., from 0.1.1 to 0.1.2-SNAPSHOT)
133+
IFS='.' read -r -a VERSION_PARTS <<<"${RELEASE_VERSION}"
134+
MAJOR_VERSION=${VERSION_PARTS[0]}
135+
MINOR_VERSION=${VERSION_PARTS[1]}
136+
PATCH_VERSION=${VERSION_PARTS[2]}
137+
138+
if [ -z "$PATCH_VERSION" ]; then # Should not happen if RELEASE_VERSION was valid
139+
echo "Error: Could not parse patch version from ${RELEASE_VERSION}."
140+
echo "Ensure version is in format X.Y.Z."
141+
exit 1
142+
fi
143+
144+
NEXT_PATCH_VERSION=$((PATCH_VERSION + 1))
145+
SUGGESTED_NEXT_SNAPSHOT_VERSION="${MAJOR_VERSION}.${MINOR_VERSION}.${NEXT_PATCH_VERSION}-SNAPSHOT"
146+
147+
# Prompt for next snapshot version
148+
echo
149+
echo "-------------------- ACTION SUMMARY (Phase 2/2) --------------------"
150+
echo "The release version ${RELEASE_VERSION} has been committed and pushed."
151+
echo
152+
echo "Now, let's prepare for the next development iteration."
153+
NEXT_SNAPSHOT_VERSION=""
154+
while true; do
155+
printf "Enter the next snapshot version (e.g., %s): " "${SUGGESTED_NEXT_SNAPSHOT_VERSION}"
156+
read USER_NEXT_SNAPSHOT_VERSION
157+
158+
if [ -z "${USER_NEXT_SNAPSHOT_VERSION}" ]; then
159+
USER_NEXT_SNAPSHOT_VERSION="${SUGGESTED_NEXT_SNAPSHOT_VERSION}"
160+
echo "No input provided, using suggested: ${USER_NEXT_SNAPSHOT_VERSION}"
161+
fi
162+
163+
# Ensure it ends with -SNAPSHOT
164+
if [[ "${USER_NEXT_SNAPSHOT_VERSION}" != *"-SNAPSHOT" ]]; then
165+
echo "Warning: The version '${USER_NEXT_SNAPSHOT_VERSION}' does not end with -SNAPSHOT. Appending it."
166+
USER_NEXT_SNAPSHOT_VERSION="${USER_NEXT_SNAPSHOT_VERSION}-SNAPSHOT"
167+
echo "Updated to: ${USER_NEXT_SNAPSHOT_VERSION}"
168+
fi
169+
170+
# Validate semver is greater
171+
if version_gt "${USER_NEXT_SNAPSHOT_VERSION}" "${RELEASE_VERSION}"; then
172+
NEXT_SNAPSHOT_VERSION=${USER_NEXT_SNAPSHOT_VERSION}
173+
break
174+
else
175+
echo "Error: Next snapshot version ('${USER_NEXT_SNAPSHOT_VERSION%-SNAPSHOT}') must be greater than the release version ('${RELEASE_VERSION}')."
176+
echo "Please provide a valid higher version."
177+
# Reset suggested for next loop iteration if user input was bad
178+
SUGGESTED_NEXT_SNAPSHOT_VERSION=${USER_NEXT_SNAPSHOT_VERSION}
179+
fi
180+
done
181+
182+
COMMIT_MSG_NEXT_DEV="prepare for next development iteration (${NEXT_SNAPSHOT_VERSION})"
183+
184+
echo
185+
echo "Will set version to NEXT SNAPSHOT: ${NEXT_SNAPSHOT_VERSION}"
186+
echo "Will commit changes with message: \"${COMMIT_MSG_NEXT_DEV}\""
187+
echo "IMPORTANT: This commit will NOT be pushed by the script."
188+
echo "-------------------------------------------------------------------"
189+
echo
190+
191+
read -p "Do you want to proceed with Phase 2 (Prepare Next Snapshot locally)? (y/N): " confirmation_phase2
192+
if [[ ! "$confirmation_phase2" =~ ^[Yy]$ ]]; then
193+
echo "Operation cancelled by user before Phase 2."
194+
exit 0
195+
fi
196+
197+
# Set version to NEXT_SNAPSHOT_VERSION
198+
echo "Setting POM versions to ${NEXT_SNAPSHOT_VERSION}... (This may take a moment)"
199+
mvn versions:set -DnewVersion="${NEXT_SNAPSHOT_VERSION}" -DprocessAllModules=true -DgenerateBackupPoms=false
200+
201+
# Commit the next snapshot version change
202+
echo "Staging pom.xml files for next development iteration commit..."
203+
find . -name pom.xml -type f -exec git add {} +
204+
echo "Committing next snapshot version change: \"${COMMIT_MSG_NEXT_DEV}\" ..."
205+
git commit -m "${COMMIT_MSG_NEXT_DEV}"
206+
echo "Next snapshot version ${NEXT_SNAPSHOT_VERSION} committed locally."
207+
208+
# Output Final Instructions
209+
echo
210+
echo "----------------------------- ACTION REQUIRED ------------------------------"
211+
echo "Local repository updated. Two commits were involved:"
212+
echo " 1. \"${COMMIT_MSG_RELEASE}\" (version ${RELEASE_VERSION}) - This commit AND the tag '${RELEASE_VERSION}' WERE PUSHED."
213+
echo " 2. \"${COMMIT_MSG_NEXT_DEV}\" (version ${NEXT_SNAPSHOT_VERSION}) - This commit IS LOCAL."
214+
echo
215+
echo "NEXT STEPS:"
216+
echo "1. Go to GitHub. The tag '${RELEASE_VERSION}' has been pushed."
217+
echo " - A GitHub Release might have been automatically created from this tag, or you may need to"
218+
echo " draft and publish a new release using the '${RELEASE_VERSION}' tag."
219+
echo " - Add release notes as appropriate."
220+
echo " - Wait for any automated release build/deployment processes triggered by this tag/release to complete successfully."
221+
echo
222+
echo "2. AFTER the GitHub release is published and any associated CI/CD is successful, push the local snapshot commit:"
223+
echo " git push"
224+
echo " (This will push the commit \"${COMMIT_MSG_NEXT_DEV}\" for version ${NEXT_SNAPSHOT_VERSION})"
225+
echo "---------------------------------------------------------------------------"

0 commit comments

Comments
 (0)