Update bump-version.sh to use semantic build versions

This commit is contained in:
Leendert de Borst
2025-08-06 12:10:19 +02:00
parent e10ef4bd75
commit 3af46c80fa
+256 -95
View File
@@ -3,10 +3,59 @@
# Check if running with bash
if [ -z "$BASH_VERSION" ]; then
echo "Error: This script must be run with bash"
echo "Usage: bash $0"
echo "Usage: bash $0 [--build-only]"
exit 1
fi
# Initialize variables
BUILD_ONLY=false
MARKETING_UPDATE=false
# Function to generate semantic build number
# Format: MMmmppXX where MM=major, mm=minor, pp=patch, XX=build
generate_semantic_build_number() {
local major=$1
local minor=$2
local patch=$3
local build_increment=$4
# Pad with zeros and create build number
local major_padded=$(printf "%02d" $major)
local minor_padded=$(printf "%02d" $minor)
local patch_padded=$(printf "%02d" $patch)
local build_padded=$(printf "%02d" $build_increment)
local semantic_build="${major_padded}${minor_padded}${patch_padded}${build_padded}"
# Remove leading zeros for App Store compatibility
echo $((10#$semantic_build))
}
# Function to extract build increment from semantic build number
extract_build_increment() {
local semantic_build=$1
local version_major=$2
local version_minor=$3
local version_patch=$4
# Pad the semantic build number to 8 digits with leading zeros
local padded_build=$(printf "%08d" $semantic_build)
# Generate the version prefix
local version_prefix=$(printf "%02d%02d%02d" $version_major $version_minor $version_patch)
# Check if the build number starts with the expected version prefix
if [[ $padded_build == $version_prefix* ]]; then
# Extract the last 2 digits as the build increment
local build_increment=${padded_build: -2}
# Remove leading zeros
echo $((10#$build_increment))
else
# If version changed, reset to 0
echo 0
fi
}
# Function to read and validate semantic version
read_semver() {
# Get current version from server
@@ -28,23 +77,42 @@ read_semver() {
done
}
# Function to handle build number bump
handle_build_number() {
# Function to handle semantic build number bump
handle_semantic_build_number() {
local current_build=$1
local project_name=$2
local new_build=$((current_build + 1))
local version_major=$3
local version_minor=$4
local version_patch=$5
local is_marketing_update=$6
read -p "$project_name ($current_build). Enter new build number [$new_build]: " input
# Extract current build increment from semantic build
local current_increment=$(extract_build_increment "$current_build" "$version_major" "$version_minor" "$version_patch")
# Determine suggested increment based on update type
local suggested_increment
if [[ "$is_marketing_update" == true ]]; then
# For marketing version updates, suggest 0 as we're starting fresh
suggested_increment=0
read -p "$project_name ($current_build) - Enter new build increment [$suggested_increment]: " input
if [[ -z "$input" || "$input" =~ ^[Yy]$ ]]; then
echo $new_build
else
if [[ "$input" =~ ^[0-9]+$ ]]; then
echo $input
else
echo "Invalid input. Using default increment."
echo $new_build
# For build-only updates, suggest increment + 1
suggested_increment=$((current_increment + 1))
read -p "$project_name ($current_build) - (Increment: $current_increment) - Enter new build increment [$suggested_increment]: " input
fi
if [[ -z "$input" ]]; then
input=$suggested_increment
fi
if [[ "$input" =~ ^[0-9]+$ ]]; then
if [[ $input -gt 99 ]]; then
input=99
fi
generate_semantic_build_number "$version_major" "$version_minor" "$version_patch" "$input"
else
generate_semantic_build_number "$version_major" "$version_minor" "$version_patch" "$suggested_increment"
fi
}
@@ -115,7 +183,6 @@ get_safari_version() {
}
# Check current versions
echo "Checking current versions..."
server_version=$(get_server_version)
browser_wxt_version=$(get_browser_extension_version)
browser_package_version=$(get_browser_extension_package_json_version)
@@ -162,11 +229,37 @@ for project in "${!versions[@]}"; do
fi
done
# Print current versions
echo -e "\nCurrent versions:"
for project in "${!versions[@]}"; do
echo "${display_names[$project]}: ${versions[$project]}"
done
# This script is used to bump version numbers across the AliasVault codebase.
# It can update both marketing versions (e.g. 1.2.3) and build numbers for app stores.
# Marketing versions are used for new feature releases and bug fixes.
# Build numbers are used for internal testing, translations, and misc updates.
# Ask user what they want to do
echo ""
echo "--------------------------------"
echo "AliasVault version bump tool"
echo "* This tool updates version numbers across the AliasVault codebase"
echo "--------------------------------"
echo ""
echo "What would you like to do?"
echo ""
echo "1) [Public release] Prepare new public release (marketing version + app store build numbers)"
echo "2) [Internal release] New internal app store build (app store build numbers only, e.g. for testing translations)"
echo ""
read -p "Enter your choice: " choice
case $choice in
1)
MARKETING_UPDATE=true
;;
2)
BUILD_ONLY=true
;;
*)
echo "Invalid choice. Exiting."
exit 1
;;
esac
# If versions are not equal, ask for confirmation
if [[ "$all_equal" == false ]]; then
@@ -184,75 +277,100 @@ if [[ "$all_equal" == false ]]; then
fi
fi
# Read new version
echo -e "\nEnter new version:"
read_semver
if [[ "$BUILD_ONLY" == true ]]; then
# Use existing version
version=$first_version
major=$(echo $version | cut -d. -f1)
minor=$(echo $version | cut -d. -f2)
patch=$(echo $version | cut -d. -f3)
elif [[ "$MARKETING_UPDATE" == true ]]; then
# Print current versions
echo ""
echo "--------------------------------"
echo "Current versions"
echo "--------------------------------"
for project in "${!versions[@]}"; do
echo "${display_names[$project]}: ${versions[$project]}"
done
# Extract major, minor, patch from version
major=$(echo $version | cut -d. -f1)
minor=$(echo $version | cut -d. -f2)
patch=$(echo $version | cut -d. -f3)
# Read new version
echo ""
echo "--------------------------------"
echo "Update marketing versions"
echo "--------------------------------"
read_semver
# Update server version
echo -e "\nUpdating server version..."
update_version "../apps/server/Shared/AliasVault.Shared.Core/AppInfo.cs" \
"public const int VersionMajor = [0-9]\+;" \
"public const int VersionMajor = $major;"
update_version "../apps/server/Shared/AliasVault.Shared.Core/AppInfo.cs" \
"public const int VersionMinor = [0-9]\+;" \
"public const int VersionMinor = $minor;"
update_version "../apps/server/Shared/AliasVault.Shared.Core/AppInfo.cs" \
"public const int VersionPatch = [0-9]\+;" \
"public const int VersionPatch = $patch;"
# Extract major, minor, patch from version
major=$(echo $version | cut -d. -f1)
minor=$(echo $version | cut -d. -f2)
patch=$(echo $version | cut -d. -f3)
# Update browser extension version
echo "Updating browser extension version..."
update_version "../apps/browser-extension/wxt.config.ts" \
"version: \"[0-9]\+\.[0-9]\+\.[0-9]\+\"," \
"version: \"$version\","
# Update server version
echo -e "\nUpdating server version..."
update_version "../apps/server/Shared/AliasVault.Shared.Core/AppInfo.cs" \
"public const int VersionMajor = [0-9][0-9]*;" \
"public const int VersionMajor = $major;"
update_version "../apps/server/Shared/AliasVault.Shared.Core/AppInfo.cs" \
"public const int VersionMinor = [0-9][0-9]*;" \
"public const int VersionMinor = $minor;"
update_version "../apps/server/Shared/AliasVault.Shared.Core/AppInfo.cs" \
"public const int VersionPatch = [0-9][0-9]*;" \
"public const int VersionPatch = $patch;"
# Update package.json version
echo "Updating package.json version..."
update_version "../apps/browser-extension/package.json" \
"\"version\": \"[0-9]\+\.[0-9]\+\.[0-9]\+\"," \
"\"version\": \"$version\","
# Update browser extension version
echo "Updating browser extension version..."
update_version "../apps/browser-extension/wxt.config.ts" \
"version: \"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"," \
"version: \"$version\","
# Update browser extension AppInfo.ts version
echo "Updating browser extension AppInfo.ts version..."
update_version "../apps/browser-extension/src/utils/AppInfo.ts" \
"public static readonly VERSION = '[0-9]\+\.[0-9]\+\.[0-9]\+';" \
"public static readonly VERSION = '$version';"
# Update package.json version
echo "Updating package.json version..."
update_version "../apps/browser-extension/package.json" \
"\"version\": \"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"," \
"\"version\": \"$version\","
# Update generic mobile app version
echo "Updating mobile app version..."
update_version "../apps/mobile-app/utils/AppInfo.ts" \
"public static readonly VERSION = '[0-9]\+\.[0-9]\+\.[0-9]\+';" \
"public static readonly VERSION = '$version';"
update_version "../apps/mobile-app/app.json" \
"\"version\": \"[0-9]\+\.[0-9]\+\.[0-9]\+\"," \
"\"version\": \"$version\","
# Update browser extension AppInfo.ts version
echo "Updating browser extension AppInfo.ts version..."
update_version "../apps/browser-extension/src/utils/AppInfo.ts" \
"public static readonly VERSION = '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*';" \
"public static readonly VERSION = '$version';"
# Update generic mobile app version
echo "Updating mobile app version..."
update_version "../apps/mobile-app/utils/AppInfo.ts" \
"public static readonly VERSION = '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*';" \
"public static readonly VERSION = '$version';"
update_version "../apps/mobile-app/app.json" \
"\"version\": \"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"," \
"\"version\": \"$version\","
# Update iOS app version
echo "Updating iOS app version..."
update_version "../apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj" \
"MARKETING_VERSION = [0-9]\+\.[0-9]\+\.[0-9]\+;" \
"MARKETING_VERSION = $version;"
# Update iOS app version
echo "Updating iOS app version..."
update_version "../apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj" \
"MARKETING_VERSION = [0-9]\+\.[0-9]\+\.[0-9]\+;" \
"MARKETING_VERSION = $version;"
# Update Android app version
echo "Updating Android app version..."
update_version "../apps/mobile-app/android/app/build.gradle" \
"versionName \"[0-9]\+\.[0-9]\+\.[0-9]\+\"" \
"versionName \"$version\""
# Update Android app version
echo "Updating Android app version..."
update_version "../apps/mobile-app/android/app/build.gradle" \
"versionName \"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\"" \
"versionName \"$version\""
# Update Safari extension version
echo "Updating Safari extension version..."
update_version "../apps/browser-extension/safari-xcode/AliasVault/AliasVault.xcodeproj/project.pbxproj" \
"MARKETING_VERSION = [0-9]\+\.[0-9]\+\.[0-9]\+;" \
"MARKETING_VERSION = $version;"
# Update Safari extension version
echo "Updating Safari extension version..."
update_version "../apps/browser-extension/safari-xcode/AliasVault/AliasVault.xcodeproj/project.pbxproj" \
"MARKETING_VERSION = [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*;" \
"MARKETING_VERSION = $version;"
fi
# Handle build numbers
echo -e "\nIncrementing build numbers..."
# Handle build numbers with semantic versioning
echo ""
echo "--------------------------------"
echo "Update semantic build numbers (for App Store releases)"
echo "--------------------------------"
printf "Example for version %d.%d.%d: \"%02d%02d%02d00\" → %d (leading zeros removed)\n" $major $minor $patch $major $minor $patch $((10#$(printf "%02d%02d%02d00" $major $minor $patch)))
echo "> Breakdown: $(printf "%02d" $major) (major) $(printf "%02d" $minor) (minor) $(printf "%02d" $patch) (patch) 00 (build)"
echo ""
# Read current build numbers
current_ios_build=$(grep -A1 "CURRENT_PROJECT_VERSION" ../apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj | grep "CURRENT_PROJECT_VERSION = [0-9]\+;" | head -n1 | tr -d ';' | tr -d ' ' | cut -d'=' -f2 | grep -E '^[0-9]+$')
@@ -273,47 +391,90 @@ if [ -z "$current_safari_build" ]; then
exit 1
fi
# Handle iOS build number with semantic versioning
# Handle iOS build number
new_ios_build=$(handle_build_number "$current_ios_build" "iOS Mobile App")
new_ios_build=$(handle_semantic_build_number "$current_ios_build" "iOS Mobile App" "$major" "$minor" "$patch" "$MARKETING_UPDATE")
update_version "../apps/mobile-app/ios/AliasVault.xcodeproj/project.pbxproj" \
"CURRENT_PROJECT_VERSION = [0-9]\+;" \
"CURRENT_PROJECT_VERSION = $new_ios_build;" \
"iOS Mobile App"
# Handle Android build number
new_android_build=$(handle_build_number "$current_android_build" "Android App")
new_android_build=$(handle_semantic_build_number "$current_android_build" "Android App" "$major" "$minor" "$patch" "$MARKETING_UPDATE")
update_version "../apps/mobile-app/android/app/build.gradle" \
"versionCode [0-9]\+" \
"versionCode $new_android_build" \
"Android App"
# Handle Safari build number
new_safari_build=$(handle_build_number "$current_safari_build" "Safari Extension")
new_safari_build=$(handle_semantic_build_number "$current_safari_build" "Safari Extension" "$major" "$minor" "$patch" "$MARKETING_UPDATE")
update_version "../apps/browser-extension/safari-xcode/AliasVault/AliasVault.xcodeproj/project.pbxproj" \
"CURRENT_PROJECT_VERSION = [0-9]\+;" \
"CURRENT_PROJECT_VERSION = $new_safari_build;" \
"Safari Extension"
# Show reminders
echo -e "\n"
echo "--------------------------------"
echo "IMPORTANT REMINDERS:"
echo "Reminders (!):"
echo "--------------------------------"
# Install.sh reminder
echo "• If you've made changes to install.sh since the last release, remember to update its @version in the header to match this release version ($version)."
if [[ "$MARKETING_UPDATE" == true ]]; then
# Install.sh reminder (only for version changes)
echo "• If you've made changes to install.sh since the last release, remember to update its @version in the header to match this release version ($version)."
# Changelog reminder
echo "Add changelogs for new version $version to the /fastlane directory:"
echo " - iOS: fastlane/metadata/ios/[lang]/changelogs/$(echo $new_ios_build | cut -d. -f1-2).txt"
echo " - Android: fastlane/metadata/android/[lang]/changelogs/$(echo $new_android_build | cut -d. -f1-2).txt"
echo " - Browser Extension: fastlane/metadata/browser-extension/[lang]/changelogs/$version.txt"
# Create empty changelog files and remind about them
echo "Creating empty changelog files for version $version in the /fastlane directory..."
echo "--------------------------------"
read -p "Press Enter to continue..."
# Create iOS changelog files
if [ -d "../fastlane/metadata/ios" ]; then
for lang_dir in ../fastlane/metadata/ios/*/; do
if [ -d "$lang_dir" ]; then
lang=$(basename "$lang_dir")
changelog_dir="$lang_dir/changelogs"
mkdir -p "$changelog_dir"
touch "$changelog_dir/$new_ios_build.txt"
fi
done
fi
echo -e "\nAll build numbers have been updated successfully!"
echo "New version: $version"
echo "New iOS mobile app build: $new_ios_build"
echo "New Android build: $new_android_build"
echo "New Safari extension build: $new_safari_build"
# Create Android changelog files
if [ -d "../fastlane/metadata/android" ]; then
for lang_dir in ../fastlane/metadata/android/*/; do
if [ -d "$lang_dir" ]; then
lang=$(basename "$lang_dir")
changelog_dir="$lang_dir/changelogs"
mkdir -p "$changelog_dir"
touch "$changelog_dir/$new_android_build.txt"
fi
done
fi
# Create Browser Extension changelog files
if [ -d "../fastlane/metadata/browser-extension" ]; then
for lang_dir in ../fastlane/metadata/browser-extension/*/; do
if [ -d "$lang_dir" ]; then
lang=$(basename "$lang_dir")
changelog_dir="$lang_dir/changelogs"
mkdir -p "$changelog_dir"
touch "$changelog_dir/$version.txt"
fi
done
fi
echo ""
echo "• Please fill in the changelog content in the created files:"
echo " - iOS: fastlane/metadata/ios/[lang]/changelogs/$new_ios_build.txt"
echo " - Android: fastlane/metadata/android/[lang]/changelogs/$new_android_build.txt"
echo " - Browser Extension: fastlane/metadata/browser-extension/[lang]/changelogs/$version.txt"
elif [[ "$BUILD_ONLY" == true ]]; then
echo " Marketing version remained at: $version"
echo " Only build numbers were incremented"
fi
if [[ "$BUILD_ONLY" == true ]]; then
echo -e "\n✅ Build-only update completed!"
elif [[ "$MARKETING_UPDATE" == true ]]; then
echo -e "\n✅ Marketing version and build update completed!"
else
echo -e "\n✅ Update completed!"
fi