From e8746babe4e83bb253bbbd575790bf2442ee67c1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 28 Mar 2026 12:23:31 +0000 Subject: [PATCH] feat: add version bump script (bump-version.sh) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agnostic version bump tool that finds all version strings in the project and updates them together. Usage: ./bump-version.sh # interactive menu ./bump-version.sh patch # 0.9.0 → 0.9.1 ./bump-version.sh minor # 0.9.0 → 0.10.0 ./bump-version.sh major # 0.9.0 → 1.0.0 ./bump-version.sh 1.2.3 # set to specific version Finds versions in JSON files ("version": "X.Y.Z") and HTML/JS files (vX.Y.Z). Excludes node_modules and dist directories. https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- bump-version.sh | 193 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100755 bump-version.sh diff --git a/bump-version.sh b/bump-version.sh new file mode 100755 index 0000000..64e730d --- /dev/null +++ b/bump-version.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# +# Version Bump Script +# +# Finds all version numbers in the project, shows them, and lets you +# bump the patch/minor/major or enter a custom version. +# +# Works with any project that has version strings in JSON files, +# HTML files, or other text files. +# +# Usage: +# ./bump-version.sh # interactive — shows versions, asks what to do +# ./bump-version.sh 1.2.3 # set all versions to 1.2.3 +# ./bump-version.sh patch # bump patch: 0.9.0 → 0.9.1 +# ./bump-version.sh minor # bump minor: 0.9.0 → 0.10.0 +# ./bump-version.sh major # bump major: 0.9.0 → 1.0.0 +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Find all files containing version-like strings +# Looks for patterns like "version": "X.Y.Z" or "v X.Y.Z" or "Version X.Y.Z" +find_version_files() { + # JSON files with "version": "X.Y.Z" + grep -rlE '"version":\s*"[0-9]+\.[0-9]+\.[0-9]+"' --include='*.json' . 2>/dev/null | grep -v node_modules | grep -v dist || true + # HTML/JS files with version display strings like "v1.2.3" or "v 1.2.3" + grep -rlE ' v[0-9]+\.[0-9]+\.[0-9]+' --include='*.html' --include='*.js' . 2>/dev/null | grep -v node_modules | grep -v dist || true +} + +# Extract version from a file +get_version_from_file() { + local file="$1" + # Try JSON "version": "X.Y.Z" first + local ver=$(grep -oP '"version":\s*"\K[0-9]+\.[0-9]+\.[0-9]+' "$file" 2>/dev/null | head -1) + if [ -n "$ver" ]; then + echo "$ver" + return + fi + # Try "vX.Y.Z" or "Version X.Y.Z" pattern + ver=$(grep -oP '[vV]ersion[" ]*\K[0-9]+\.[0-9]+\.[0-9]+' "$file" 2>/dev/null | head -1) + if [ -n "$ver" ]; then + echo "$ver" + return + fi + # Try " vX.Y.Z" (e.g. "Silent Send v0.9.0") + ver=$(grep -oP ' v\K[0-9]+\.[0-9]+\.[0-9]+' "$file" 2>/dev/null | head -1) + if [ -n "$ver" ]; then + echo "$ver" + return + fi +} + +# Get the most common version across all files (the "current" version) +get_current_version() { + local versions="" + while IFS= read -r file; do + [ -z "$file" ] && continue + local ver=$(get_version_from_file "$file") + if [ -n "$ver" ]; then + versions="$versions $ver" + fi + done <<< "$(find_version_files)" + + # Return the most common version + echo "$versions" | tr ' ' '\n' | sort | uniq -c | sort -rn | head -1 | awk '{print $2}' +} + +# Show all version occurrences +show_versions() { + echo -e "${CYAN}Files with version strings:${NC}" + echo "" + while IFS= read -r file; do + [ -z "$file" ] && continue + local ver=$(get_version_from_file "$file") + if [ -n "$ver" ]; then + local rel="${file#./}" + echo -e " ${GREEN}$ver${NC} $rel" + fi + done <<< "$(find_version_files)" + echo "" +} + +# Replace version in all files +replace_version() { + local old="$1" + local new="$2" + + echo -e "${YELLOW}Replacing $old → $new${NC}" + echo "" + + while IFS= read -r file; do + [ -z "$file" ] && continue + local ver=$(get_version_from_file "$file") + if [ "$ver" = "$old" ]; then + # Replace in JSON files: "version": "X.Y.Z" + sed -i "s/\"version\": \"$old\"/\"version\": \"$new\"/" "$file" 2>/dev/null + # Replace display strings: vX.Y.Z or Version X.Y.Z + sed -i "s/\(ersion[\" ]*\)$old/\1$new/g" "$file" 2>/dev/null + # Replace vX.Y.Z standalone + sed -i "s/v$old/v$new/g" "$file" 2>/dev/null + + local rel="${file#./}" + echo -e " ${GREEN}✓${NC} $rel" + fi + done <<< "$(find_version_files)" + + echo "" + echo -e "${GREEN}Done! All versions set to $new${NC}" +} + +# Bump a version component +bump_version() { + local ver="$1" + local part="$2" + + IFS='.' read -r major minor patch <<< "$ver" + + case "$part" in + major) echo "$((major + 1)).0.0" ;; + minor) echo "$major.$((minor + 1)).0" ;; + patch) echo "$major.$minor.$((patch + 1))" ;; + esac +} + +# --- Main --- + +CURRENT=$(get_current_version) + +if [ -z "$CURRENT" ]; then + echo -e "${RED}No version strings found in the project.${NC}" + exit 1 +fi + +# Handle command-line argument +if [ -n "$1" ]; then + case "$1" in + patch|minor|major) + NEW=$(bump_version "$CURRENT" "$1") + show_versions + replace_version "$CURRENT" "$NEW" + exit 0 + ;; + [0-9]*) + show_versions + replace_version "$CURRENT" "$1" + exit 0 + ;; + *) + echo "Usage: $0 [patch|minor|major|X.Y.Z]" + exit 1 + ;; + esac +fi + +# Interactive mode +show_versions + +echo -e "Current version: ${GREEN}$CURRENT${NC}" +echo "" +echo " [1] Bump patch: $CURRENT → $(bump_version "$CURRENT" patch)" +echo " [2] Bump minor: $CURRENT → $(bump_version "$CURRENT" minor)" +echo " [3] Bump major: $CURRENT → $(bump_version "$CURRENT" major)" +echo " [4] Enter custom version" +echo " [q] Quit" +echo "" +read -p "Choice: " choice + +case "$choice" in + 1) NEW=$(bump_version "$CURRENT" patch) ;; + 2) NEW=$(bump_version "$CURRENT" minor) ;; + 3) NEW=$(bump_version "$CURRENT" major) ;; + 4) + read -p "Enter version: " NEW + if ! [[ "$NEW" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo -e "${RED}Invalid version format. Use X.Y.Z${NC}" + exit 1 + fi + ;; + q|Q|"") echo "Cancelled."; exit 0 ;; + *) echo -e "${RED}Invalid choice.${NC}"; exit 1 ;; +esac + +replace_version "$CURRENT" "$NEW"