release.sh 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #!/bin/bash
  2. # Interactive release script
  3. # Usage: ./release.sh
  4. # Exit immediately if a command exits with a non-zero status
  5. set -e
  6. # Function to display error messages
  7. error_exit() {
  8. echo "❌ ERROR: $1" >&2
  9. exit 1
  10. }
  11. # Function to display success messages
  12. success_message() {
  13. echo "✅ SUCCESS: $1"
  14. }
  15. # Function to display info messages
  16. info_message() {
  17. echo "ℹ️ INFO: $1"
  18. }
  19. # Function to display section headers
  20. section_header() {
  21. echo ""
  22. echo "================================================"
  23. echo "$1"
  24. echo "================================================"
  25. }
  26. # Function to increment version based on user choice
  27. increment_version() {
  28. local current_version="$1"
  29. local choice="$2"
  30. # Split version into parts
  31. IFS='.' read -ra VERSION_PARTS <<< "$current_version"
  32. local major=${VERSION_PARTS[0]}
  33. local minor=${VERSION_PARTS[1]}
  34. local patch=${VERSION_PARTS[2]}
  35. case $choice in
  36. 1)
  37. # Increment major, reset minor and patch to 0
  38. major=$((major + 1))
  39. minor=0
  40. patch=0
  41. ;;
  42. 2)
  43. # Increment minor, reset patch to 0
  44. minor=$((minor + 1))
  45. patch=0
  46. ;;
  47. 3)
  48. # Increment patch only
  49. patch=$((patch + 1))
  50. ;;
  51. *)
  52. error_exit "Invalid choice: $choice"
  53. ;;
  54. esac
  55. echo "$major.$minor.$patch"
  56. }
  57. # Function to update package.json version
  58. update_package_json() {
  59. local version="$1"
  60. local package_file="package.json"
  61. if [ ! -f "$package_file" ]; then
  62. error_exit "package.json not found in current directory"
  63. fi
  64. info_message "Updating version in $package_file to $version"
  65. # Update version using sed (macOS compatible)
  66. if [[ "$OSTYPE" == "darwin"* ]]; then
  67. sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"$version\"/" "$package_file"
  68. else
  69. sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$version\"/" "$package_file"
  70. fi
  71. # Verify the change
  72. local new_version=$(grep -m 1 '"version":' "$package_file" | awk -F '"' '{print $4}')
  73. if [ "$new_version" = "$version" ]; then
  74. success_message "package.json version updated to $version"
  75. else
  76. error_exit "Failed to update package.json version"
  77. fi
  78. }
  79. # Function to update version in public/webConfigApi.js
  80. update_webconfig_version() {
  81. local version="$1"
  82. local webconfig_file="public/webConfigApi.js"
  83. if [ ! -f "$webconfig_file" ]; then
  84. info_message "$webconfig_file not found. Skipping version update."
  85. return 0
  86. fi
  87. info_message "Updating version in $webconfig_file to $version"
  88. # Update version using sed (macOS compatible)
  89. if [[ "$OSTYPE" == "darwin"* ]]; then
  90. sed -i '' "s/version: '[^']*'/version: '$version'/" "$webconfig_file"
  91. sed -i '' "s/\/\/ 版本: [^ ]*/\/\/ 版本: $version/" "$webconfig_file"
  92. else
  93. sed -i "s/version: '[^']*'/version: '$version'/" "$webconfig_file"
  94. sed -i "s/\/\/ 版本: [^ ]*/\/\/ 版本: $version/" "$webconfig_file"
  95. fi
  96. # Verify the change
  97. if grep -q "version: '$version'" "$webconfig_file"; then
  98. success_message "$webconfig_file version updated to $version"
  99. else
  100. error_exit "Failed to update $webconfig_file version"
  101. fi
  102. }
  103. section_header "🚀 Interactive Release Process"
  104. # Step 1: Check if we are on dev or main branch
  105. info_message "Checking current branch..."
  106. CURRENT_BRANCH=$(git branch --show-current)
  107. if [ "$CURRENT_BRANCH" != "dev" ] && [ "$CURRENT_BRANCH" != "main" ]; then
  108. error_exit "Must be on 'dev' or 'main' branch. Current branch: $CURRENT_BRANCH. Please switch to dev or main branch first."
  109. fi
  110. success_message "Currently on $CURRENT_BRANCH branch"
  111. # Step 2: Check for uncommitted changes
  112. info_message "Checking for uncommitted changes..."
  113. if [ -n "$(git status --porcelain)" ]; then
  114. echo "⚠️ WARNING: You have uncommitted changes:"
  115. git status --short
  116. read -p "Do you want to continue anyway? (y/n): " -n 1 -r
  117. echo
  118. if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  119. error_exit "Please commit or stash your changes before release"
  120. fi
  121. fi
  122. success_message "Working directory is clean or user confirmed to continue"
  123. # Step 3: Fetch latest changes from remote
  124. info_message "Fetching latest changes from remote..."
  125. git fetch origin || error_exit "Failed to fetch from remote"
  126. success_message "Fetched latest changes from remote"
  127. # Step 4: Check if local branch is behind remote
  128. info_message "Checking if local $CURRENT_BRANCH branch is up to date..."
  129. LOCAL_COMMIT=$(git rev-parse $CURRENT_BRANCH)
  130. REMOTE_COMMIT=$(git rev-parse origin/$CURRENT_BRANCH)
  131. if [ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]; then
  132. info_message "Local $CURRENT_BRANCH branch is behind remote. Pulling latest changes..."
  133. git pull origin $CURRENT_BRANCH || error_exit "Failed to pull latest changes from origin/$CURRENT_BRANCH"
  134. success_message "Successfully pulled latest changes"
  135. else
  136. success_message "Local $CURRENT_BRANCH branch is up to date"
  137. fi
  138. # Step 5: Get current version and display version selection menu
  139. info_message "Getting current version..."
  140. # Get current version from package.json
  141. CURRENT_VERSION=$(grep -m 1 '"version":' package.json | awk -F '"' '{print $4}')
  142. if [ -z "$CURRENT_VERSION" ]; then
  143. error_exit "Could not determine current version from package.json"
  144. fi
  145. # Split current version into parts for display
  146. IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION"
  147. MAJOR=${VERSION_PARTS[0]}
  148. MINOR=${VERSION_PARTS[1]}
  149. PATCH=${VERSION_PARTS[2]}
  150. section_header "Version Selection"
  151. echo "📦 Current version: $CURRENT_VERSION"
  152. echo ""
  153. echo "Please select which version number to increment:"
  154. echo ""
  155. echo "1) Major version (${MAJOR}.${MINOR}.${PATCH} → $((MAJOR + 1)).0.0)"
  156. echo " Use for: Breaking changes, major new features"
  157. echo ""
  158. echo "2) Minor version (${MAJOR}.${MINOR}.${PATCH} → ${MAJOR}.$((MINOR + 1)).0)"
  159. echo " Use for: New features, backward-compatible changes"
  160. echo ""
  161. echo "3) Patch version (${MAJOR}.${MINOR}.${PATCH} → ${MAJOR}.${MINOR}.$((PATCH + 1)))"
  162. echo " Use for: Bug fixes, small improvements"
  163. echo ""
  164. # Get user choice
  165. while true; do
  166. read -p "Enter your choice (1-3): " -n 1 -r
  167. echo
  168. case $REPLY in
  169. [1-3])
  170. CHOICE=$REPLY
  171. break
  172. ;;
  173. *)
  174. echo "❌ Invalid choice. Please enter 1, 2, or 3."
  175. ;;
  176. esac
  177. done
  178. # Calculate new version
  179. NEW_VERSION=$(increment_version "$CURRENT_VERSION" "$CHOICE")
  180. VERSION_TAG="v$NEW_VERSION"
  181. section_header "Release Confirmation"
  182. echo "📋 Release Summary:"
  183. echo " Current version: $CURRENT_VERSION"
  184. echo " New version: $NEW_VERSION"
  185. echo " Tag to create: $VERSION_TAG"
  186. echo ""
  187. # Final confirmation
  188. read -p "Do you want to proceed with the release? (y/n): " -n 1 -r
  189. echo
  190. if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  191. info_message "Release cancelled by user"
  192. exit 0
  193. fi
  194. # Step 6: Verify the tag doesn't already exist
  195. info_message "Checking if tag $VERSION_TAG already exists..."
  196. if git rev-parse "$VERSION_TAG" >/dev/null 2>&1; then
  197. error_exit "Tag $VERSION_TAG already exists. This should not happen as we generated it automatically."
  198. fi
  199. success_message "Tag $VERSION_TAG is available"
  200. section_header "Executing Release"
  201. # Step 7: Update version files and timestamp
  202. info_message "Updating version files and build timestamp..."
  203. update_package_json "$NEW_VERSION"
  204. update_webconfig_version "$NEW_VERSION"
  205. success_message "All version files and timestamp updated"
  206. # Step 9: Commit all changes
  207. info_message "Committing version updates, timestamp changes, and generated config..."
  208. git add package.json public/webConfigApi.js
  209. git commit -m "chore: bump version to $NEW_VERSION and update timestamp for release $VERSION_TAG" || error_exit "Failed to commit changes"
  210. success_message "Version, timestamp, and config changes committed"
  211. # Step 10: Create the tag at the new commit
  212. info_message "Creating tag $VERSION_TAG..."
  213. git tag -a "$VERSION_TAG" -m "Release $VERSION_TAG" || error_exit "Failed to create tag"
  214. success_message "Tag $VERSION_TAG created at current commit"
  215. # Step 11: Push changes and tag to remote
  216. info_message "Pushing changes and tag to remote..."
  217. git push origin $CURRENT_BRANCH || error_exit "Failed to push changes to remote"
  218. git push origin "$VERSION_TAG" || error_exit "Failed to push tag to remote"
  219. success_message "Changes and tag pushed to remote"
  220. # Step 12: Execute package.sh for final build and packaging (if exists)
  221. if [ -f "bash/package.sh" ]; then
  222. info_message "Executing package.sh script for final build and packaging..."
  223. chmod +x bash/package.sh
  224. bash/package.sh || error_exit "Package script failed"
  225. success_message "Package script executed successfully"
  226. else
  227. info_message "bash/package.sh not found, skipping build packaging"
  228. fi
  229. section_header "🎉 Release Completed Successfully!"
  230. echo "✅ Tag $VERSION_TAG has been created and pushed to remote"
  231. echo "✅ Version updated from $CURRENT_VERSION to $NEW_VERSION"
  232. echo "✅ Files updated: package.json, public/webConfigApi.js"
  233. echo "✅ Commit: $(git rev-parse HEAD)"
  234. echo ""
  235. echo "You can now view the release at:"
  236. echo "🔗 https://sg-git.pwtk.cc/ka-cn/pwtk-admin-web/releases"