mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-26 09:35:52 +00:00
- Fix unbound variable errors in install-node.sh and node-path-setup.sh - Add release-progress.sh for visual release monitoring - Add release-health-check.sh for comprehensive pre-release validation - Add check-node-simple.sh as a simpler, more robust Node.js checker - Create release-improved.sh with better state tracking and progress indicators - Update release-state.sh with better timestamp tracking These improvements address issues encountered during beta.13 release: - Node.js detection failures due to unbound variables - Lack of visibility into release progress - No clear way to resume interrupted releases - Missing pre-flight validation
335 lines
No EOL
9.4 KiB
Bash
Executable file
335 lines
No EOL
9.4 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
# Improved release script with better state tracking and progress indicators
|
|
#
|
|
# This script automates the entire release process for VibeTunnel:
|
|
# 1. Pre-flight checks
|
|
# 2. Clean build directory
|
|
# 3. Set version
|
|
# 4. Build application
|
|
# 5. Sign and notarize
|
|
# 6. Create DMG and ZIP
|
|
# 7. Create GitHub release
|
|
# 8. Update appcast
|
|
# 9. Commit and push
|
|
#
|
|
|
|
set -eo pipefail
|
|
|
|
# Script directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$SCRIPT_DIR/.."
|
|
|
|
# Source required scripts
|
|
source "$SCRIPT_DIR/release-state.sh"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Progress tracking
|
|
STEP_START_TIME=""
|
|
|
|
start_step() {
|
|
local step_num=$1
|
|
local step_name=$2
|
|
STEP_START_TIME=$(date +%s)
|
|
echo ""
|
|
echo -e "${BLUE}📋 Step $step_num/9: $step_name...${NC}"
|
|
update_step "$step_num" "in_progress"
|
|
}
|
|
|
|
complete_step() {
|
|
local step_num=$1
|
|
local step_name=$2
|
|
local duration=$(($(date +%s) - STEP_START_TIME))
|
|
echo -e "${GREEN}✅ $step_name completed (${duration}s)${NC}"
|
|
update_step "$step_num" "completed"
|
|
}
|
|
|
|
fail_step() {
|
|
local step_num=$1
|
|
local step_name=$2
|
|
local error_msg=$3
|
|
echo -e "${RED}❌ $step_name failed: $error_msg${NC}"
|
|
update_step "$step_num" "failed"
|
|
exit 1
|
|
}
|
|
|
|
# Show progress with timeout warnings
|
|
show_progress() {
|
|
local operation=$1
|
|
local timeout_warning=${2:-300} # Default 5 minutes
|
|
local start_time=$(date +%s)
|
|
local warned=false
|
|
|
|
while true; do
|
|
local elapsed=$(($(date +%s) - start_time))
|
|
|
|
# Show timeout warning
|
|
if [[ $elapsed -gt $timeout_warning ]] && [[ "$warned" == "false" ]]; then
|
|
echo -e "${YELLOW}⏰ $operation is taking longer than expected (>${timeout_warning}s)...${NC}"
|
|
warned=true
|
|
fi
|
|
|
|
# Check if process is still running
|
|
if ! jobs %1 &>/dev/null; then
|
|
break
|
|
fi
|
|
|
|
# Update progress indicator
|
|
printf "."
|
|
sleep 5
|
|
done
|
|
echo "" # New line after dots
|
|
}
|
|
|
|
# Parse command line arguments
|
|
RELEASE_TYPE=""
|
|
RELEASE_NUMBER=""
|
|
DRY_RUN=false
|
|
RESUME=false
|
|
SHOW_STATUS=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
--resume)
|
|
RESUME=true
|
|
shift
|
|
;;
|
|
--status)
|
|
SHOW_STATUS=true
|
|
shift
|
|
;;
|
|
stable|beta|alpha|rc)
|
|
RELEASE_TYPE=$1
|
|
shift
|
|
if [[ $# -gt 0 && ! "$1" =~ ^-- ]]; then
|
|
RELEASE_NUMBER=$1
|
|
shift
|
|
fi
|
|
;;
|
|
*)
|
|
echo -e "${RED}❌ Unknown argument: $1${NC}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Show status if requested
|
|
if [[ "$SHOW_STATUS" == "true" ]]; then
|
|
show_release_status
|
|
exit 0
|
|
fi
|
|
|
|
# Main release process
|
|
if [[ "$RESUME" == "true" ]]; then
|
|
echo -e "${BLUE}📋 Resuming release${NC}"
|
|
# Load state and continue from last step
|
|
if [[ ! -f "$PROJECT_ROOT/.release-state.json" ]]; then
|
|
echo -e "${RED}❌ No release state found to resume${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if release is stale (>2 hours old)
|
|
LAST_UPDATED=$(jq -r '.last_updated // empty' "$PROJECT_ROOT/.release-state.json")
|
|
if [[ -n "$LAST_UPDATED" ]]; then
|
|
LAST_TIMESTAMP=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$LAST_UPDATED" +%s 2>/dev/null || date -d "$LAST_UPDATED" +%s)
|
|
CURRENT_TIMESTAMP=$(date +%s)
|
|
AGE=$((CURRENT_TIMESTAMP - LAST_TIMESTAMP))
|
|
|
|
if [[ $AGE -gt 7200 ]]; then # 2 hours
|
|
echo -e "${YELLOW}⚠️ Release state is over 2 hours old${NC}"
|
|
echo "Continue anyway? (y/n): "
|
|
read -r response
|
|
if [[ "$response" != "y" ]]; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
CURRENT_STEP=$(get_current_step)
|
|
echo "Resuming from step $CURRENT_STEP..."
|
|
else
|
|
# Validate release type and number
|
|
if [[ -z "$RELEASE_TYPE" ]]; then
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$RELEASE_TYPE" != "stable" ]] && [[ -z "$RELEASE_NUMBER" ]]; then
|
|
echo -e "${RED}❌ Error: Pre-release number is required for $RELEASE_TYPE releases${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Initialize state
|
|
RELEASE_VERSION=$(get_release_version "$RELEASE_TYPE" "$RELEASE_NUMBER")
|
|
BUILD_NUMBER=$(get_build_number)
|
|
TAG_NAME="v$RELEASE_VERSION"
|
|
|
|
init_state "$RELEASE_TYPE" "$RELEASE_VERSION" "$BUILD_NUMBER" "$TAG_NAME"
|
|
CURRENT_STEP=1
|
|
fi
|
|
|
|
# Execute steps based on current progress
|
|
echo -e "${BLUE}🚀 VibeTunnel Release Process${NC}"
|
|
echo "=================================="
|
|
|
|
# Step 1: Pre-flight check
|
|
if [[ $(get_current_step) -le 1 ]]; then
|
|
start_step 1 "Pre-flight check"
|
|
|
|
# Run the preflight check
|
|
if ! "$SCRIPT_DIR/preflight-check.sh"; then
|
|
fail_step 1 "Pre-flight check" "Pre-flight checks failed"
|
|
fi
|
|
|
|
complete_step 1 "Pre-flight check"
|
|
fi
|
|
|
|
# Step 2: Clean build
|
|
if [[ $(get_current_step) -le 2 ]]; then
|
|
start_step 2 "Clean build directory"
|
|
|
|
"$SCRIPT_DIR/clean.sh" || fail_step 2 "Clean build" "Failed to clean build directory"
|
|
|
|
complete_step 2 "Clean build directory"
|
|
fi
|
|
|
|
# Step 3: Set version
|
|
if [[ $(get_current_step) -le 3 ]]; then
|
|
start_step 3 "Set version"
|
|
|
|
# Version should already be set in version.xcconfig
|
|
echo "Version: $RELEASE_VERSION"
|
|
echo "Build: $BUILD_NUMBER"
|
|
|
|
complete_step 3 "Set version"
|
|
fi
|
|
|
|
# Step 4: Build application
|
|
if [[ $(get_current_step) -le 4 ]]; then
|
|
start_step 4 "Build application"
|
|
|
|
# Build with progress tracking
|
|
(
|
|
export CI=${CI:-false}
|
|
export SKIP_NODE_CHECK=${SKIP_NODE_CHECK:-false}
|
|
export IS_PRERELEASE_BUILD=$([[ "$RELEASE_TYPE" != "stable" ]] && echo "true" || echo "false")
|
|
"$SCRIPT_DIR/build.sh" --configuration Release
|
|
) &
|
|
|
|
show_progress "Building application" 600 # 10 minute warning
|
|
wait $! || fail_step 4 "Build application" "Build failed"
|
|
|
|
complete_step 4 "Build application"
|
|
fi
|
|
|
|
# Step 5: Sign and notarize
|
|
if [[ $(get_current_step) -le 5 ]]; then
|
|
start_step 5 "Sign and notarize"
|
|
|
|
APP_PATH="$PROJECT_ROOT/build/Build/Products/Release/VibeTunnel.app"
|
|
|
|
# Sign and notarize with progress tracking
|
|
"$SCRIPT_DIR/sign-and-notarize.sh" "$APP_PATH" &
|
|
show_progress "Notarization" 600 # 10 minute warning
|
|
wait $! || fail_step 5 "Sign and notarize" "Notarization failed"
|
|
|
|
# Update artifact path
|
|
update_artifact "app_path" "$APP_PATH"
|
|
|
|
complete_step 5 "Sign and notarize"
|
|
fi
|
|
|
|
# Step 6: Create DMG and ZIP
|
|
if [[ $(get_current_step) -le 6 ]]; then
|
|
start_step 6 "Create DMG and ZIP"
|
|
|
|
DMG_PATH="$PROJECT_ROOT/build/VibeTunnel-$RELEASE_VERSION.dmg"
|
|
ZIP_PATH="$PROJECT_ROOT/build/VibeTunnel-$RELEASE_VERSION.zip"
|
|
|
|
# Create DMG
|
|
"$SCRIPT_DIR/create-dmg.sh" "$APP_PATH" || fail_step 6 "Create DMG" "DMG creation failed"
|
|
|
|
# Create ZIP
|
|
"$SCRIPT_DIR/create-zip.sh" "$APP_PATH" || fail_step 6 "Create ZIP" "ZIP creation failed"
|
|
|
|
# Update artifact paths
|
|
update_artifact "dmg_path" "$DMG_PATH"
|
|
update_artifact "zip_path" "$ZIP_PATH"
|
|
|
|
complete_step 6 "Create DMG and ZIP"
|
|
fi
|
|
|
|
# Step 7: GitHub release
|
|
if [[ $(get_current_step) -le 7 ]]; then
|
|
start_step 7 "GitHub release"
|
|
|
|
# Generate release notes
|
|
RELEASE_NOTES=$("$SCRIPT_DIR/generate-release-notes.sh" "$RELEASE_VERSION")
|
|
|
|
# Create GitHub release
|
|
gh release create "$TAG_NAME" \
|
|
--title "VibeTunnel $RELEASE_VERSION" \
|
|
--notes "$RELEASE_NOTES" \
|
|
$([[ "$RELEASE_TYPE" != "stable" ]] && echo "--prerelease") \
|
|
"$DMG_PATH" \
|
|
"$ZIP_PATH" || fail_step 7 "GitHub release" "Failed to create GitHub release"
|
|
|
|
complete_step 7 "GitHub release"
|
|
fi
|
|
|
|
# Step 8: Update appcast
|
|
if [[ $(get_current_step) -le 8 ]]; then
|
|
start_step 8 "Update appcast"
|
|
|
|
# Sign DMG for Sparkle
|
|
export SPARKLE_ACCOUNT="VibeTunnel"
|
|
SPARKLE_SIG=$(sign_update -f "$PROJECT_ROOT/private/sparkle_ed_private_key" "$DMG_PATH" --account VibeTunnel | grep -o 'sparkle:edSignature="[^"]*"' | cut -d'"' -f2)
|
|
|
|
if [[ -z "$SPARKLE_SIG" ]]; then
|
|
fail_step 8 "Update appcast" "Failed to sign DMG for Sparkle"
|
|
fi
|
|
|
|
# Update artifact
|
|
update_artifact "sparkle_signature" "$SPARKLE_SIG"
|
|
|
|
# Update appcast file
|
|
"$SCRIPT_DIR/update-appcast.sh" "$RELEASE_VERSION" "$BUILD_NUMBER" "$SPARKLE_SIG" || fail_step 8 "Update appcast" "Failed to update appcast"
|
|
|
|
complete_step 8 "Update appcast"
|
|
fi
|
|
|
|
# Step 9: Commit and push
|
|
if [[ $(get_current_step) -le 9 ]]; then
|
|
start_step 9 "Commit and push"
|
|
|
|
# Add and commit appcast changes
|
|
git add ../appcast*.xml
|
|
git commit -m "Update appcast for v$RELEASE_VERSION" || true # Ignore if no changes
|
|
git push || fail_step 9 "Commit and push" "Failed to push changes"
|
|
|
|
complete_step 9 "Commit and push"
|
|
fi
|
|
|
|
# Clean up state file on success
|
|
rm -f "$PROJECT_ROOT/.release-state.json"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}🎉 Release $RELEASE_VERSION completed successfully!${NC}"
|
|
echo ""
|
|
echo "Release artifacts:"
|
|
echo " - GitHub: https://github.com/amantus-ai/vibetunnel/releases/tag/$TAG_NAME"
|
|
echo " - DMG: $DMG_PATH"
|
|
echo " - ZIP: $ZIP_PATH"
|
|
echo ""
|
|
echo "Users on the $([[ "$RELEASE_TYPE" == "stable" ]] && echo "stable" || echo "pre-release") channel will receive the update via Sparkle." |