#!/bin/bash # Interactive release script # Usage: ./release.sh # Exit immediately if a command exits with a non-zero status set -e # Function to display error messages error_exit() { echo "❌ ERROR: $1" >&2 exit 1 } # Function to display success messages success_message() { echo "✅ SUCCESS: $1" } # Function to display info messages info_message() { echo "â„šī¸ INFO: $1" } # Function to display section headers section_header() { echo "" echo "================================================" echo "$1" echo "================================================" } # Function to increment version based on user choice increment_version() { local current_version="$1" local choice="$2" # Split version into parts IFS='.' read -ra VERSION_PARTS <<<"$current_version" local major=${VERSION_PARTS[0]} local minor=${VERSION_PARTS[1]} local patch=${VERSION_PARTS[2]} case $choice in 1) # Increment major, reset minor and patch to 0 major=$((major + 1)) minor=0 patch=0 ;; 2) # Increment minor, reset patch to 0 minor=$((minor + 1)) patch=0 ;; 3) # Increment patch only patch=$((patch + 1)) ;; *) error_exit "Invalid choice: $choice" ;; esac echo "$major.$minor.$patch" } # Function to update package.json version update_package_json() { local version="$1" local package_file="package.json" if [ ! -f "$package_file" ]; then error_exit "package.json not found in current directory" fi info_message "Updating version in $package_file to $version" # Update version using sed (macOS compatible) if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"$version\"/" "$package_file" else sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$version\"/" "$package_file" fi # Verify the change local new_version=$(grep -m 1 '"version":' "$package_file" | awk -F '"' '{print $4}') if [ "$new_version" = "$version" ]; then success_message "package.json version updated to $version" else error_exit "Failed to update package.json version" fi } section_header "🚀 Interactive Release Process" # Step 1: Check if we are on dev or master branch info_message "Checking current branch..." CURRENT_BRANCH=$(git branch --show-current) if [ "$CURRENT_BRANCH" != "dev" ] && [ "$CURRENT_BRANCH" != "master" ]; then error_exit "Must be on 'dev' or 'master' branch. Current branch: $CURRENT_BRANCH. Please switch to dev or master branch first." fi success_message "Currently on $CURRENT_BRANCH branch" # Step 2: Check for uncommitted changes info_message "Checking for uncommitted changes..." if [ -n "$(git status --porcelain)" ]; then echo "âš ī¸ WARNING: You have uncommitted changes:" git status --short read -p "Do you want to continue anyway? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then error_exit "Please commit or stash your changes before release" fi fi success_message "Working directory is clean or user confirmed to continue" # Step 3: Fetch latest changes from remote info_message "Fetching latest changes from remote..." git fetch origin || error_exit "Failed to fetch from remote" success_message "Fetched latest changes from remote" # Step 4: Check if local branch is behind remote info_message "Checking if local $CURRENT_BRANCH branch is up to date..." LOCAL_COMMIT=$(git rev-parse $CURRENT_BRANCH) REMOTE_COMMIT=$(git rev-parse origin/$CURRENT_BRANCH) if [ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]; then info_message "Local $CURRENT_BRANCH branch is behind remote. Pulling latest changes..." git pull origin $CURRENT_BRANCH || error_exit "Failed to pull latest changes from origin/$CURRENT_BRANCH" success_message "Successfully pulled latest changes" else success_message "Local $CURRENT_BRANCH branch is up to date" fi # Step 5: Get current version and display version selection menu info_message "Getting current version..." # Get current version from package.json CURRENT_VERSION=$(grep -m 1 '"version":' package.json | awk -F '"' '{print $4}') if [ -z "$CURRENT_VERSION" ]; then error_exit "Could not determine current version from package.json" fi # Split current version into parts for display IFS='.' read -ra VERSION_PARTS <<<"$CURRENT_VERSION" MAJOR=${VERSION_PARTS[0]} MINOR=${VERSION_PARTS[1]} PATCH=${VERSION_PARTS[2]} section_header "Version Selection" echo "đŸ“Ļ Current version: $CURRENT_VERSION" echo "" echo "Please select which version number to increment:" echo "" echo "1) Major version (${MAJOR}.${MINOR}.${PATCH} → $((MAJOR + 1)).0.0)" echo " Use for: Breaking changes, major new features" echo "" echo "2) Minor version (${MAJOR}.${MINOR}.${PATCH} → ${MAJOR}.$((MINOR + 1)).0)" echo " Use for: New features, backward-compatible changes" echo "" echo "3) Patch version (${MAJOR}.${MINOR}.${PATCH} → ${MAJOR}.${MINOR}.$((PATCH + 1)))" echo " Use for: Bug fixes, small improvements" echo "" # Get user choice while true; do read -p "Enter your choice (1-3): " -n 1 -r echo case $REPLY in [1-3]) CHOICE=$REPLY break ;; *) echo "❌ Invalid choice. Please enter 1, 2, or 3." ;; esac done # Calculate new version NEW_VERSION=$(increment_version "$CURRENT_VERSION" "$CHOICE") VERSION_TAG="v$NEW_VERSION" section_header "Release Confirmation" echo "📋 Release Summary:" echo " Current version: $CURRENT_VERSION" echo " New version: $NEW_VERSION" echo " Tag to create: $VERSION_TAG" echo "" # Final confirmation read -p "Do you want to proceed with the release? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then info_message "Release cancelled by user" exit 0 fi # Step 6: Verify the tag doesn't already exist info_message "Checking if tag $VERSION_TAG already exists..." if git rev-parse "$VERSION_TAG" >/dev/null 2>&1; then error_exit "Tag $VERSION_TAG already exists. This should not happen as we generated it automatically." fi success_message "Tag $VERSION_TAG is available" section_header "Executing Release" # Step 7: Update version in package.json info_message "Updating version in package.json..." update_package_json "$NEW_VERSION" success_message "Version updated in package.json" # Step 8: Stage and commit changes info_message "Staging and committing version update..." git add package.json || error_exit "Failed to stage package.json" git commit -m "chore: bump version to $NEW_VERSION for release $VERSION_TAG" || error_exit "Failed to commit changes" success_message "Version change committed" # Step 10: Create the tag at the new commit info_message "Creating tag $VERSION_TAG..." git tag -a "$VERSION_TAG" -m "Release $VERSION_TAG" || error_exit "Failed to create tag" success_message "Tag $VERSION_TAG created at current commit" # Step 11: Push changes and tag to remote info_message "Pushing changes and tag to remote..." git push origin $CURRENT_BRANCH || error_exit "Failed to push changes to remote" git push origin "$VERSION_TAG" || error_exit "Failed to push tag to remote" success_message "Changes and tag pushed to remote" section_header "🎉 Release Completed Successfully!" echo "✅ Tag $VERSION_TAG has been created and pushed to remote" echo "✅ Version updated from $CURRENT_VERSION to $NEW_VERSION" echo "✅ Commit: $(git rev-parse HEAD)" echo "" echo "Jenkins will automatically deploy to Cloudflare Pages." echo "🔗 Production: https://tg-live-game.pwtk-dev.work"